aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/tools
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-12-20 14:26:54 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-12-20 14:26:54 +0000
commit9a199699c2fd227dae8c1ff60a70c819e9d4fdfe (patch)
tree1953a1b292c4637ca2a5ede1494d3a5b84cccac3 /contrib/llvm/tools
parent2cab237b5dbfe1b3e9c7aa7a3c02d2b98fcf7462 (diff)
parent461a67fa15370a9ec88f8f8a240bf7c123bb2029 (diff)
Notes
Diffstat (limited to 'contrib/llvm/tools')
-rw-r--r--contrib/llvm/tools/clang/include/clang-c/Index.h58
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTContext.h394
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h14
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTUnresolvedSet.h25
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTVector.h53
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/AttrIterator.h37
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/BaseSubobject.h24
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/BuiltinTypes.def3
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h93
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h71
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/CharUnits.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/CommentVisitor.h12
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DataCollection.h65
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Decl.h667
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclBase.h286
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h534
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclContextInternals.h29
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h77
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h40
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclLookups.h23
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h658
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclOpenMP.h20
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h480
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclVisitor.h19
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h135
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DependentDiagnostic.h30
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Expr.h81
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h900
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h477
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ExternalASTMerger.h139
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h103
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/GlobalDecl.h29
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/LexicallyOrderedRecursiveASTVisitor.h164
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h60
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/OpenMPClause.h1582
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/OperationKinds.def10
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/OperationKinds.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h101
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/QualTypeNames.h (renamed from contrib/llvm/tools/clang/include/clang/Tooling/Core/QualTypeNames.h)25
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/RecordLayout.h48
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h76
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h68
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Stmt.h425
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/StmtDataCollectors.td242
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/StmtGraphTraits.h27
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h60
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/StmtOpenMP.h122
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/StmtVisitor.h46
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h76
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/TemplateName.h73
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Type.h1152
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h237
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/TypeNodes.def3
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/UnresolvedSet.h20
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/VTTBuilder.h44
-rw-r--r--contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchers.h858
-rw-r--r--contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersInternal.h248
-rw-r--r--contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersMacros.h45
-rw-r--r--contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Parser.h31
-rw-r--r--contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Registry.h16
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Consumed.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Dominators.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/LiveVariables.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/PostOrderCFGView.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafety.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h24
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/AnalysisDeclContext.h (renamed from contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h)24
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/BodyFarm.h (renamed from contrib/llvm/tools/clang/lib/Analysis/BodyFarm.h)11
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/CFG.h356
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/CallGraph.h93
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/CloneDetection.h245
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h26
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Support/BumpVector.h53
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/AddressSpaces.h32
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/AlignedAllocation.h44
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/AllDiagnostics.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Attr.td566
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/AttrDocs.td198
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Attributes.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Builtins.def515
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Builtins.h7
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAArch64.def9
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAMDGPU.def3
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsARM.def1
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsHexagon.def222
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsNVPTX.def48
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def128
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86_64.def8
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/CharInfo.h42
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Cuda.h7
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DeclNodes.td59
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h8
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticASTKinds.td9
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCrossTUKinds.td18
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td50
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticError.h61
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td82
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h43
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td47
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticOptions.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td47
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticRefactoringKinds.td34
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td336
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSerializationKinds.td41
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h92
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/LLVM.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/LangOptions.def13
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h7
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Module.h81
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/OpenCLExtensions.def4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.def8
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.def1
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/OperatorPrecedence.h9
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/SanitizerBlacklist.h15
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/SanitizerSpecialCaseList.h54
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.def20
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h32
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h105
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/SourceManagerInternals.h22
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h1
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/SyncScope.h154
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h76
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TargetOptions.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def18
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h3
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/VirtualFileSystem.h28
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/X86Target.def232
-rw-r--r--contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenABITypes.h9
-rw-r--r--contrib/llvm/tools/clang/include/clang/CodeGen/ConstantInitFuture.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/CodeGen/ModuleBuilder.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/CrossTU/CrossTUDiagnostic.h29
-rw-r--r--contrib/llvm/tools/clang/include/clang/CrossTU/CrossTranslationUnit.h159
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td50
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/CLCompatOptions.td7
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Compilation.h14
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Distro.h11
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Driver.h12
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Job.h8
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Options.td418
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/SanitizerArgs.h20
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h69
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/XRayArgs.h1
-rw-r--r--contrib/llvm/tools/clang/include/clang/Format/Format.h144
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h20
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def26
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h7
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/CommandLineSourceLoc.h46
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h13
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h15
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/LangStandard.h28
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def17
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/PrecompiledPreamble.h92
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticBuffer.h5
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h3
-rw-r--r--contrib/llvm/tools/clang/include/clang/Index/IndexDataConsumer.h3
-rw-r--r--contrib/llvm/tools/clang/include/clang/Index/IndexSymbol.h3
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h126
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/HeaderSearchOptions.h89
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/Lexer.h127
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h1
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/MacroArgs.h22
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h88
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/ModuleLoader.h31
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/ModuleMap.h75
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/MultipleIncludeOpt.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h40
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/PTHLexer.h25
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/PTHManager.h42
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/Pragma.h29
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h70
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h294
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h47
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/PreprocessorOptions.h55
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h111
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/VariadicMacroSupport.h226
-rw-r--r--contrib/llvm/tools/clang/include/clang/Parse/ParseAST.h7
-rw-r--r--contrib/llvm/tools/clang/include/clang/Parse/Parser.h106
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h44
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteConsumer.h34
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteOptions.h17
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h55
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Lookup.h25
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Overload.h30
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Ownership.h3
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Scope.h11
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Sema.h237
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/SemaInternal.h3
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h420
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h341
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h117
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ContinuousRangeMap.h34
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ModuleManager.h77
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td17
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Analyses.def5
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h17
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h (renamed from contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h)6
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h17
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h7
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h8
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h8
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h50
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h17
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h11
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h12
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h10
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h9
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/ASTDiff/ASTDiff.h127
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/ASTDiff/ASTDiffInternal.h48
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/CommonOptionsParser.h50
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabase.h39
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Core/Replacement.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Execution.h175
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/ASTSelection.h155
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/AtomicChange.h44
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Extract/Extract.h53
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h12
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringAction.h64
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringActionRule.h74
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h123
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringActionRules.h94
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringActionRulesInternal.h158
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringDiagnostic.h30
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringOption.h64
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringOptionVisitor.h62
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringOptions.h58
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringResultConsumer.h52
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringRuleContext.h90
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/RenamingAction.h52
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/SymbolName.h49
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/SymbolOccurrences.h91
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h14
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h12
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/StandaloneExecution.h97
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/ToolExecutorPluginRegistry.h24
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Tooling.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/module.modulemap22
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTContext.cpp687
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp157
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp601
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTStructuralEquivalence.cpp15
-rw-r--r--contrib/llvm/tools/clang/lib/AST/CXXABI.h13
-rw-r--r--contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp72
-rw-r--r--contrib/llvm/tools/clang/lib/AST/CommentSema.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DataCollection.cpp50
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Decl.cpp634
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclBase.cpp60
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp189
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp20
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp101
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp181
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp150
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp27
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Expr.cpp114
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp233
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp139
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExprObjC.cpp12
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExternalASTMerger.cpp398
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp190
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Linkage.h159
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Mangle.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp25
-rw-r--r--contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp27
-rw-r--r--contrib/llvm/tools/clang/lib/AST/NSAPI.cpp1
-rw-r--r--contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp118
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ODRHash.cpp67
-rw-r--r--contrib/llvm/tools/clang/lib/AST/OpenMPClause.cpp81
-rw-r--r--contrib/llvm/tools/clang/lib/AST/QualTypeNames.cpp (renamed from contrib/llvm/tools/clang/lib/Tooling/Core/QualTypeNames.cpp)13
-rw-r--r--contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp9
-rw-r--r--contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp38
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Stmt.cpp78
-rw-r--r--contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp17
-rw-r--r--contrib/llvm/tools/clang/lib/AST/StmtOpenMP.cpp49
-rw-r--r--contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp150
-rw-r--r--contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp42
-rw-r--r--contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp24
-rw-r--r--contrib/llvm/tools/clang/lib/AST/TemplateName.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Type.cpp304
-rw-r--r--contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp131
-rw-r--r--contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp154
-rw-r--r--contrib/llvm/tools/clang/lib/AST/VTTBuilder.cpp24
-rw-r--r--contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp21
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchersInternal.cpp329
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Marshallers.h120
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Parser.cpp43
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Registry.cpp60
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/AnalysisDeclContext.cpp38
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/BodyFarm.cpp366
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/CFG.cpp449
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/CallGraph.cpp38
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/CloneDetection.cpp155
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/CocoaConventions.cpp13
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/Consumed.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/LiveVariables.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/ReachableCode.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/ScanfFormatString.cpp9
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/ThreadSafety.cpp21
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyCommon.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyTIL.cpp1
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/UninitializedValues.cpp17
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Builtins.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Cuda.cpp24
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp46
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/FileManager.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp76
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Module.cpp30
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp66
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/OperatorPrecedence.cpp1
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/SanitizerBlacklist.cpp27
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/SanitizerSpecialCaseList.cpp64
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp66
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp31
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets.cpp9511
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets.h51
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/AArch64.cpp537
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/AArch64.h167
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/AMDGPU.cpp373
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/AMDGPU.h322
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/ARM.cpp1064
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/ARM.h256
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/AVR.cpp320
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/AVR.h184
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/BPF.cpp25
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/BPF.h94
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Hexagon.cpp158
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Hexagon.h128
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Lanai.cpp67
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Lanai.h92
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Le64.cpp39
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Le64.h64
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/MSP430.cpp34
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/MSP430.h92
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Mips.cpp252
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Mips.h397
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/NVPTX.cpp199
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/NVPTX.h132
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Nios2.cpp56
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Nios2.h147
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/OSTargets.cpp139
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/OSTargets.h725
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/PNaCl.cpp30
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/PNaCl.h87
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/PPC.cpp544
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/PPC.h368
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/SPIR.cpp33
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/SPIR.h127
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Sparc.cpp197
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/Sparc.h270
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/SystemZ.cpp118
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/SystemZ.h145
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/TCE.cpp35
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/TCE.h123
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/WebAssembly.cpp96
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/WebAssembly.h148
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/X86.cpp1518
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/X86.h801
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/XCore.cpp38
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets/XCore.h82
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Version.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp57
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/XRayLists.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp115
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGAtomic.cpp306
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp335
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGBuilder.h7
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp1521
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCXX.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.h21
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp93
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp177
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCoroutine.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp157
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h11
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp42
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp89
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp45
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp735
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp19
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp108
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp1227
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp135
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp36
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp27
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.cpp71
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.h21
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp856
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h106
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp362
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.h31
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp37
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp50
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp964
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp38
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGValue.h70
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenABITypes.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp65
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp224
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h278
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp390
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h100
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.cpp173
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.cpp265
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.h200
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypeCache.h5
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp16
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h5
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/ConstantEmitter.h178
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.cpp366
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.h2
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp110
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp116
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/ModuleBuilder.cpp13
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/SanitizerMetadata.cpp9
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp639
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.h60
-rw-r--r--contrib/llvm/tools/clang/lib/CrossTU/CrossTranslationUnit.cpp269
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Compilation.cpp97
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Distro.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Driver.cpp147
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Job.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp166
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp212
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/AMDGPU.cpp60
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/AMDGPU.h20
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Ananas.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/AArch64.cpp22
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/ARM.cpp50
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/ARM.h7
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Mips.cpp102
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Mips.h4
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.cpp12
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.h1
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/X86.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/BareMetal.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/BareMetal.h1
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Bitrig.cpp190
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Bitrig.h79
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Clang.cpp2426
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Clang.h4
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/CloudABI.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/CommonArgs.cpp238
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/CommonArgs.h7
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/CrossWindows.cpp45
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Cuda.cpp281
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Cuda.h28
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Darwin.cpp750
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Darwin.h79
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/DragonFly.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/FreeBSD.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/FreeBSD.h3
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Fuchsia.cpp44
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Fuchsia.h7
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Gnu.cpp221
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Hexagon.cpp98
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Hexagon.h4
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Linux.cpp26
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/MSVC.cpp47
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/MinGW.cpp43
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/MinGW.h4
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Minix.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/NaCl.cpp16
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/NetBSD.cpp30
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/NetBSD.h3
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/OpenBSD.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/PS4CPU.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Solaris.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/WebAssembly.cpp45
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/WebAssembly.h2
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/XRayArgs.cpp18
-rw-r--r--contrib/llvm/tools/clang/lib/Format/BreakableToken.cpp528
-rw-r--r--contrib/llvm/tools/clang/lib/Format/BreakableToken.h317
-rw-r--r--contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.cpp745
-rw-r--r--contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.h75
-rw-r--r--contrib/llvm/tools/clang/lib/Format/Format.cpp195
-rw-r--r--contrib/llvm/tools/clang/lib/Format/FormatInternal.h83
-rw-r--r--contrib/llvm/tools/clang/lib/Format/FormatToken.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/Format/FormatToken.h167
-rw-r--r--contrib/llvm/tools/clang/lib/Format/FormatTokenLexer.cpp88
-rw-r--r--contrib/llvm/tools/clang/lib/Format/FormatTokenLexer.h4
-rw-r--r--contrib/llvm/tools/clang/lib/Format/NamespaceEndCommentsFixer.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/Format/NamespaceEndCommentsFixer.h2
-rw-r--r--contrib/llvm/tools/clang/lib/Format/SortJavaScriptImports.cpp16
-rw-r--r--contrib/llvm/tools/clang/lib/Format/TokenAnalyzer.cpp40
-rw-r--r--contrib/llvm/tools/clang/lib/Format/TokenAnalyzer.h47
-rw-r--r--contrib/llvm/tools/clang/lib/Format/TokenAnnotator.cpp265
-rw-r--r--contrib/llvm/tools/clang/lib/Format/TokenAnnotator.h5
-rw-r--r--contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.cpp259
-rw-r--r--contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.h11
-rw-r--r--contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.cpp320
-rw-r--r--contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.h43
-rw-r--r--contrib/llvm/tools/clang/lib/Format/UsingDeclarationsSorter.cpp91
-rw-r--r--contrib/llvm/tools/clang/lib/Format/UsingDeclarationsSorter.h2
-rw-r--r--contrib/llvm/tools/clang/lib/Format/WhitespaceManager.cpp33
-rw-r--r--contrib/llvm/tools/clang/lib/Format/WhitespaceManager.h8
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp64
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp74
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp168
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp23
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp26
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp1
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp108
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/MultiplexConsumer.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/PrecompiledPreamble.cpp261
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp24
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/Rewrite/FrontendActions.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteObjC.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticBuffer.cpp37
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp143
-rw-r--r--contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp17
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/__clang_cuda_cmath.h23
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/__clang_cuda_intrinsics.h146
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/__clang_cuda_math_forward_declares.h8
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/__clang_cuda_runtime_wrapper.h36
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/arm64intr.h49
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx2intrin.h12
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512bwintrin.h556
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512cdintrin.h5
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512dqintrin.h38
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512fintrin.h669
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512vlbwintrin.h1005
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512vlcdintrin.h10
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512vldqintrin.h54
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512vlintrin.h1010
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512vpopcntdqvlintrin.h99
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/cetintrin.h93
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/clflushoptintrin.h2
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/clwbintrin.h52
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/cuda_wrappers/algorithm2
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/cuda_wrappers/new51
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/emmintrin.h12
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/float.h14
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/fma4intrin.h44
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/fmaintrin.h48
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/immintrin.h13
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/intrin.h6
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/opencl-c.h666
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/stdbool.h5
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/unwind.h78
-rw-r--r--contrib/llvm/tools/clang/lib/Index/CodegenNameGenerator.cpp39
-rw-r--r--contrib/llvm/tools/clang/lib/Index/CommentToXML.cpp1
-rw-r--r--contrib/llvm/tools/clang/lib/Index/IndexBody.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/Index/IndexDecl.cpp36
-rw-r--r--contrib/llvm/tools/clang/lib/Index/IndexSymbol.cpp38
-rw-r--r--contrib/llvm/tools/clang/lib/Index/IndexTypeSourceInfo.cpp13
-rw-r--r--contrib/llvm/tools/clang/lib/Index/IndexingAction.cpp22
-rw-r--r--contrib/llvm/tools/clang/lib/Index/IndexingContext.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp74
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp87
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/Lexer.cpp463
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp57
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp51
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp36
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp148
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp206
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp142
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp89
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/Pragma.cpp54
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp49
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp95
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PreprocessorLexer.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/TokenConcatenation.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp296
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp160
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp72
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp35
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp58
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp28
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp146
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp12
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp24
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp225
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp36
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/Parser.cpp41
-rw-r--r--contrib/llvm/tools/clang/lib/Rewrite/HTMLRewrite.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp38
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp28
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/Sema.cpp183
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp69
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp19
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp1257
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp124
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCoroutine.cpp51
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp707
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp407
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp774
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp212
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp689
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp124
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp65
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp49
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp164
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp44
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp107
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp16
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp1971
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp316
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp83
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp83
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp12
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp144
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp182
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp38
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp110
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp181
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaType.cpp517
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/TreeTransform.h155
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h3
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp688
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp90
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h92
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp46
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp250
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp83
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp26
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp59
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/MultiOnDiskHashTable.h69
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp54
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp43
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CloneChecker.cpp12
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp57
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp33
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeleteWithNonVirtualDtorChecker.cpp153
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp19
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp17
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp73
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp140
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCContainersASTChecker.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp35
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp148
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp312
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp51
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp425
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp43
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp85
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp96
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CallEvent.cpp34
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp142
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp64
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp314
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/IssueHash.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp294
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp13
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PrettyStackTraceLocationContext.h2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ProgramState.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp107
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp44
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SVals.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp27
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Store.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp12
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/ASTDiff/ASTDiff.cpp1021
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/ArgumentsAdjusters.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/CommonOptionsParser.cpp122
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/CompilationDatabase.cpp53
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Core/Replacement.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Execution.cpp105
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Refactoring/ASTSelection.cpp453
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Refactoring/ASTSelectionRequirements.cpp48
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Refactoring/AtomicChange.cpp188
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Refactoring/Extract/Extract.cpp199
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp112
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Refactoring/Extract/SourceExtraction.h52
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Refactoring/RefactoringActions.cpp114
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/RenamingAction.cpp197
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/SymbolOccurrences.cpp37
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp54
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp298
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/StandaloneExecution.cpp91
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Tooling.cpp16
-rw-r--r--contrib/llvm/tools/clang/tools/clang-format/ClangFormat.cpp41
-rw-r--r--contrib/llvm/tools/clang/tools/driver/cc1as_main.cpp9
-rw-r--r--contrib/llvm/tools/clang/tools/driver/driver.cpp37
-rw-r--r--contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp395
-rw-r--r--contrib/llvm/tools/clang/utils/TableGen/ClangDataCollectorsEmitter.cpp18
-rw-r--r--contrib/llvm/tools/clang/utils/TableGen/TableGen.cpp6
-rw-r--r--contrib/llvm/tools/clang/utils/TableGen/TableGenBackends.h2
729 files changed, 63130 insertions, 33727 deletions
diff --git a/contrib/llvm/tools/clang/include/clang-c/Index.h b/contrib/llvm/tools/clang/include/clang-c/Index.h
index 3b5ea9fa539ba..587008a7210b1 100644
--- a/contrib/llvm/tools/clang/include/clang-c/Index.h
+++ b/contrib/llvm/tools/clang/include/clang-c/Index.h
@@ -32,7 +32,7 @@
* compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
*/
#define CINDEX_VERSION_MAJOR 0
-#define CINDEX_VERSION_MINOR 43
+#define CINDEX_VERSION_MINOR 45
#define CINDEX_VERSION_ENCODE(major, minor) ( \
((major) * 10000) \
@@ -334,6 +334,16 @@ CINDEX_LINKAGE void clang_CXIndex_setGlobalOptions(CXIndex, unsigned options);
CINDEX_LINKAGE unsigned clang_CXIndex_getGlobalOptions(CXIndex);
/**
+ * \brief Sets the invocation emission path option in a CXIndex.
+ *
+ * The invocation emission path specifies a path which will contain log
+ * files for certain libclang invocations. A null value (default) implies that
+ * libclang invocations are not logged..
+ */
+CINDEX_LINKAGE void
+clang_CXIndex_setInvocationEmissionPathOption(CXIndex, const char *Path);
+
+/**
* \defgroup CINDEX_FILES File manipulation routines
*
* @{
@@ -394,6 +404,21 @@ CINDEX_LINKAGE CXFile clang_getFile(CXTranslationUnit tu,
const char *file_name);
/**
+ * \brief Retrieve the buffer associated with the given file.
+ *
+ * \param tu the translation unit
+ *
+ * \param file the file for which to retrieve the buffer.
+ *
+ * \param size [out] if non-NULL, will be set to the size of the buffer.
+ *
+ * \returns a pointer to the buffer in memory that holds the contents of
+ * \p file, or a NULL pointer when the file is not loaded.
+ */
+CINDEX_LINKAGE const char *clang_getFileContents(CXTranslationUnit tu,
+ CXFile file, size_t *size);
+
+/**
* \brief Returns non-zero if the \c file1 and \c file2 point to the same file,
* or they are both NULL.
*/
@@ -2837,6 +2862,22 @@ enum CXLanguageKind {
CINDEX_LINKAGE enum CXLanguageKind clang_getCursorLanguage(CXCursor cursor);
/**
+ * \brief Describe the "thread-local storage (TLS) kind" of the declaration
+ * referred to by a cursor.
+ */
+enum CXTLSKind {
+ CXTLS_None = 0,
+ CXTLS_Dynamic,
+ CXTLS_Static
+};
+
+/**
+ * \brief Determine the "thread-local storage (TLS) kind" of the declaration
+ * referred to by a cursor.
+ */
+CINDEX_LINKAGE enum CXTLSKind clang_getCursorTLSKind(CXCursor cursor);
+
+/**
* \brief Returns the translation unit that a cursor originated from.
*/
CINDEX_LINKAGE CXTranslationUnit clang_Cursor_getTranslationUnit(CXCursor);
@@ -3115,8 +3156,9 @@ enum CXTypeKind {
CXType_ObjCSel = 29,
CXType_Float128 = 30,
CXType_Half = 31,
+ CXType_Float16 = 32,
CXType_FirstBuiltin = CXType_Void,
- CXType_LastBuiltin = CXType_Half,
+ CXType_LastBuiltin = CXType_Float16,
CXType_Complex = 100,
CXType_Pointer = 101,
@@ -4276,6 +4318,12 @@ CINDEX_LINKAGE CXString clang_Cursor_getMangling(CXCursor);
CINDEX_LINKAGE CXStringSet *clang_Cursor_getCXXManglings(CXCursor);
/**
+ * \brief Retrieve the CXStrings representing the mangled symbols of the ObjC
+ * class interface or implementation at the cursor.
+ */
+CINDEX_LINKAGE CXStringSet *clang_Cursor_getObjCManglings(CXCursor);
+
+/**
* @}
*/
@@ -4419,6 +4467,12 @@ CINDEX_LINKAGE unsigned clang_CXXMethod_isStatic(CXCursor C);
CINDEX_LINKAGE unsigned clang_CXXMethod_isVirtual(CXCursor C);
/**
+ * \brief Determine if a C++ record is abstract, i.e. whether a class or struct
+ * has a pure virtual member function.
+ */
+CINDEX_LINKAGE unsigned clang_CXXRecord_isAbstract(CXCursor C);
+
+/**
* \brief Determine if an enum declaration refers to a scoped enum.
*/
CINDEX_LINKAGE unsigned clang_EnumDecl_isScoped(CXCursor C);
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h b/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h
index 703f588c56635..a5d080035df00 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h
@@ -1,4 +1,4 @@
-//===--- ASTContext.h - Context to hold long-lived AST nodes ----*- C++ -*-===//
+//===- ASTContext.h - Context to hold long-lived AST nodes ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,10 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
/// \brief Defines the clang::ASTContext interface.
-///
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ASTCONTEXT_H
@@ -19,8 +19,8 @@
#include "clang/AST/CanonicalType.h"
#include "clang/AST/CommentCommandTraits.h"
#include "clang/AST/Decl.h"
-#include "clang/AST/DeclarationName.h"
#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclarationName.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/PrettyPrinter.h"
@@ -30,32 +30,32 @@
#include "clang/AST/Type.h"
#include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/Linkage.h"
-#include "clang/Basic/LLVM.h"
-#include "clang/Basic/Module.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SanitizerBlacklist.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
+#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/XRayLists.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
-#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
-#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/TinyPtrVector.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/AlignOf.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
@@ -65,7 +65,6 @@
#include <cstdint>
#include <iterator>
#include <memory>
-#include <new>
#include <string>
#include <type_traits>
#include <utility>
@@ -75,50 +74,72 @@ namespace llvm {
struct fltSemantics;
-} // end namespace llvm
+} // namespace llvm
namespace clang {
+class APValue;
class ASTMutationListener;
class ASTRecordLayout;
class AtomicExpr;
class BlockExpr;
+class BuiltinTemplateDecl;
class CharUnits;
class CXXABI;
+class CXXConstructorDecl;
+class CXXMethodDecl;
+class CXXRecordDecl;
class DiagnosticsEngine;
class Expr;
+class MangleContext;
class MangleNumberingContext;
class MaterializeTemporaryExpr;
-class TargetInfo;
-// Decls
-class MangleContext;
+class MemberSpecializationInfo;
+class Module;
+class ObjCCategoryDecl;
+class ObjCCategoryImplDecl;
+class ObjCContainerDecl;
+class ObjCImplDecl;
+class ObjCImplementationDecl;
+class ObjCInterfaceDecl;
class ObjCIvarDecl;
+class ObjCMethodDecl;
class ObjCPropertyDecl;
+class ObjCPropertyImplDecl;
+class ObjCProtocolDecl;
+class ObjCTypeParamDecl;
+class Preprocessor;
+class Stmt;
+class StoredDeclsMap;
+class TemplateDecl;
+class TemplateParameterList;
+class TemplateTemplateParmDecl;
+class TemplateTypeParmDecl;
class UnresolvedSetIterator;
-class UsingDecl;
class UsingShadowDecl;
+class VarTemplateDecl;
class VTableContextBase;
namespace Builtin {
- class Context;
+class Context;
-} // end namespace Builtin
+} // namespace Builtin
enum BuiltinTemplateKind : int;
namespace comments {
- class FullComment;
+class FullComment;
-} // end namespace comments
+} // namespace comments
struct TypeInfo {
- uint64_t Width;
- unsigned Align;
+ uint64_t Width = 0;
+ unsigned Align = 0;
bool AlignIsRequired : 1;
- TypeInfo() : Width(0), Align(0), AlignIsRequired(false) {}
+ TypeInfo() : AlignIsRequired(false) {}
TypeInfo(uint64_t Width, unsigned Align, bool AlignIsRequired)
: Width(Width), Align(Align), AlignIsRequired(AlignIsRequired) {}
};
@@ -126,7 +147,7 @@ struct TypeInfo {
/// \brief Holds long-lived AST nodes (such as types and decls) that can be
/// referred to throughout the semantic analysis of a file.
class ASTContext : public RefCountedBase<ASTContext> {
- ASTContext &this_() { return *this; }
+ friend class NestedNameSpecifier;
mutable SmallVector<Type *, 0> Types;
mutable llvm::FoldingSet<ExtQuals> ExtQualNodes;
@@ -143,6 +164,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
mutable llvm::FoldingSet<DependentSizedArrayType> DependentSizedArrayTypes;
mutable llvm::FoldingSet<DependentSizedExtVectorType>
DependentSizedExtVectorTypes;
+ mutable llvm::FoldingSet<DependentAddressSpaceType>
+ DependentAddressSpaceTypes;
mutable llvm::FoldingSet<VectorType> VectorTypes;
mutable llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes;
mutable llvm::ContextualFoldingSet<FunctionProtoType, ASTContext&>
@@ -187,8 +210,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
///
/// This set is managed by the NestedNameSpecifier class.
mutable llvm::FoldingSet<NestedNameSpecifier> NestedNameSpecifiers;
- mutable NestedNameSpecifier *GlobalNestedNameSpecifier;
- friend class NestedNameSpecifier;
+ mutable NestedNameSpecifier *GlobalNestedNameSpecifier = nullptr;
/// \brief A cache mapping from RecordDecls to ASTRecordLayouts.
///
@@ -199,7 +221,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
ObjCLayouts;
/// \brief A cache from types to size and alignment information.
- typedef llvm::DenseMap<const Type *, struct TypeInfo> TypeInfoMap;
+ using TypeInfoMap = llvm::DenseMap<const Type *, struct TypeInfo>;
mutable TypeInfoMap MemoizedTypeInfo;
/// \brief A cache mapping from CXXRecordDecls to key functions.
@@ -233,7 +255,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
public:
CanonicalTemplateTemplateParm(TemplateTemplateParmDecl *Parm)
- : Parm(Parm) { }
+ : Parm(Parm) {}
TemplateTemplateParmDecl *getParam() const { return Parm; }
@@ -249,32 +271,32 @@ class ASTContext : public RefCountedBase<ASTContext> {
getCanonicalTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTP) const;
/// \brief The typedef for the __int128_t type.
- mutable TypedefDecl *Int128Decl;
+ mutable TypedefDecl *Int128Decl = nullptr;
/// \brief The typedef for the __uint128_t type.
- mutable TypedefDecl *UInt128Decl;
+ mutable TypedefDecl *UInt128Decl = nullptr;
/// \brief The typedef for the target specific predefined
/// __builtin_va_list type.
- mutable TypedefDecl *BuiltinVaListDecl;
+ mutable TypedefDecl *BuiltinVaListDecl = nullptr;
/// The typedef for the predefined \c __builtin_ms_va_list type.
- mutable TypedefDecl *BuiltinMSVaListDecl;
+ mutable TypedefDecl *BuiltinMSVaListDecl = nullptr;
/// \brief The typedef for the predefined \c id type.
- mutable TypedefDecl *ObjCIdDecl;
+ mutable TypedefDecl *ObjCIdDecl = nullptr;
/// \brief The typedef for the predefined \c SEL type.
- mutable TypedefDecl *ObjCSelDecl;
+ mutable TypedefDecl *ObjCSelDecl = nullptr;
/// \brief The typedef for the predefined \c Class type.
- mutable TypedefDecl *ObjCClassDecl;
+ mutable TypedefDecl *ObjCClassDecl = nullptr;
/// \brief The typedef for the predefined \c Protocol class in Objective-C.
- mutable ObjCInterfaceDecl *ObjCProtocolClassDecl;
+ mutable ObjCInterfaceDecl *ObjCProtocolClassDecl = nullptr;
/// \brief The typedef for the predefined 'BOOL' type.
- mutable TypedefDecl *BOOLDecl;
+ mutable TypedefDecl *BOOLDecl = nullptr;
// Typedefs which may be provided defining the structure of Objective-C
// pseudo-builtins
@@ -298,42 +320,42 @@ class ASTContext : public RefCountedBase<ASTContext> {
mutable IdentifierInfo *TypePackElementName = nullptr;
QualType ObjCConstantStringType;
- mutable RecordDecl *CFConstantStringTagDecl;
- mutable TypedefDecl *CFConstantStringTypeDecl;
+ mutable RecordDecl *CFConstantStringTagDecl = nullptr;
+ mutable TypedefDecl *CFConstantStringTypeDecl = nullptr;
mutable QualType ObjCSuperType;
QualType ObjCNSStringType;
/// \brief The typedef declaration for the Objective-C "instancetype" type.
- TypedefDecl *ObjCInstanceTypeDecl;
+ TypedefDecl *ObjCInstanceTypeDecl = nullptr;
/// \brief The type for the C FILE type.
- TypeDecl *FILEDecl;
+ TypeDecl *FILEDecl = nullptr;
/// \brief The type for the C jmp_buf type.
- TypeDecl *jmp_bufDecl;
+ TypeDecl *jmp_bufDecl = nullptr;
/// \brief The type for the C sigjmp_buf type.
- TypeDecl *sigjmp_bufDecl;
+ TypeDecl *sigjmp_bufDecl = nullptr;
/// \brief The type for the C ucontext_t type.
- TypeDecl *ucontext_tDecl;
+ TypeDecl *ucontext_tDecl = nullptr;
/// \brief Type for the Block descriptor for Blocks CodeGen.
///
/// Since this is only used for generation of debug info, it is not
/// serialized.
- mutable RecordDecl *BlockDescriptorType;
+ mutable RecordDecl *BlockDescriptorType = nullptr;
/// \brief Type for the Block descriptor for Blocks CodeGen.
///
/// Since this is only used for generation of debug info, it is not
/// serialized.
- mutable RecordDecl *BlockDescriptorExtendedType;
+ mutable RecordDecl *BlockDescriptorExtendedType = nullptr;
/// \brief Declaration for the CUDA cudaConfigureCall function.
- FunctionDecl *cudaConfigureCallDecl;
+ FunctionDecl *cudaConfigureCallDecl = nullptr;
/// \brief Keeps track of all declaration attributes.
///
@@ -363,12 +385,19 @@ class ASTContext : public RefCountedBase<ASTContext> {
};
llvm::DenseMap<Module*, PerModuleInitializers*> ModuleInitializers;
+ ASTContext &this_() { return *this; }
+
public:
/// \brief A type synonym for the TemplateOrInstantiation mapping.
- typedef llvm::PointerUnion<VarTemplateDecl *, MemberSpecializationInfo *>
- TemplateOrSpecializationInfo;
+ using TemplateOrSpecializationInfo =
+ llvm::PointerUnion<VarTemplateDecl *, MemberSpecializationInfo *>;
private:
+ friend class ASTDeclReader;
+ friend class ASTReader;
+ friend class ASTWriter;
+ friend class CXXRecordDecl;
+
/// \brief A mapping to contain the template or declaration that
/// a variable declaration describes or was instantiated from,
/// respectively.
@@ -438,7 +467,7 @@ private:
/// Since most C++ member functions aren't virtual and therefore
/// don't override anything, we store the overridden functions in
/// this map on the side rather than within the CXXMethodDecl structure.
- typedef llvm::TinyPtrVector<const CXXMethodDecl*> CXXMethodVector;
+ using CXXMethodVector = llvm::TinyPtrVector<const CXXMethodDecl *>;
llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector> OverriddenMethods;
/// \brief Mapping from each declaration context to its corresponding
@@ -454,18 +483,18 @@ private:
/// \brief Mapping that stores parameterIndex values for ParmVarDecls when
/// that value exceeds the bitfield size of ParmVarDeclBits.ParameterIndex.
- typedef llvm::DenseMap<const VarDecl *, unsigned> ParameterIndexTable;
+ using ParameterIndexTable = llvm::DenseMap<const VarDecl *, unsigned>;
ParameterIndexTable ParamIndices;
- ImportDecl *FirstLocalImport;
- ImportDecl *LastLocalImport;
+ ImportDecl *FirstLocalImport = nullptr;
+ ImportDecl *LastLocalImport = nullptr;
TranslationUnitDecl *TUDecl;
- mutable ExternCContextDecl *ExternCContext;
- mutable BuiltinTemplateDecl *MakeIntegerSeqDecl;
- mutable BuiltinTemplateDecl *TypePackElementDecl;
+ mutable ExternCContextDecl *ExternCContext = nullptr;
+ mutable BuiltinTemplateDecl *MakeIntegerSeqDecl = nullptr;
+ mutable BuiltinTemplateDecl *TypePackElementDecl = nullptr;
- /// \brief The associated SourceManager object.a
+ /// \brief The associated SourceManager object.
SourceManager &SourceMgr;
/// \brief The language options used to create the AST associated with
@@ -494,19 +523,14 @@ private:
CXXABI *createCXXABI(const TargetInfo &T);
/// \brief The logical -> physical address space map.
- const LangAS::Map *AddrSpaceMap;
+ const LangASMap *AddrSpaceMap = nullptr;
/// \brief Address space map mangling must be used with language specific
/// address spaces (e.g. OpenCL/CUDA)
bool AddrSpaceMapMangling;
- friend class ASTDeclReader;
- friend class ASTReader;
- friend class ASTWriter;
- friend class CXXRecordDecl;
-
- const TargetInfo *Target;
- const TargetInfo *AuxTarget;
+ const TargetInfo *Target = nullptr;
+ const TargetInfo *AuxTarget = nullptr;
clang::PrintingPolicy PrintingPolicy;
public:
@@ -515,31 +539,33 @@ public:
Builtin::Context &BuiltinInfo;
mutable DeclarationNameTable DeclarationNames;
IntrusiveRefCntPtr<ExternalASTSource> ExternalSource;
- ASTMutationListener *Listener;
+ ASTMutationListener *Listener = nullptr;
/// \brief Contains parents of a node.
- typedef llvm::SmallVector<ast_type_traits::DynTypedNode, 2> ParentVector;
+ using ParentVector = llvm::SmallVector<ast_type_traits::DynTypedNode, 2>;
/// \brief Maps from a node to its parents. This is used for nodes that have
/// pointer identity only, which are more common and we can save space by
/// only storing a unique pointer to them.
- typedef llvm::DenseMap<const void *,
- llvm::PointerUnion4<const Decl *, const Stmt *,
- ast_type_traits::DynTypedNode *,
- ParentVector *>> ParentMapPointers;
+ using ParentMapPointers =
+ llvm::DenseMap<const void *,
+ llvm::PointerUnion4<const Decl *, const Stmt *,
+ ast_type_traits::DynTypedNode *,
+ ParentVector *>>;
/// Parent map for nodes without pointer identity. We store a full
/// DynTypedNode for all keys.
- typedef llvm::DenseMap<
- ast_type_traits::DynTypedNode,
- llvm::PointerUnion4<const Decl *, const Stmt *,
- ast_type_traits::DynTypedNode *, ParentVector *>>
- ParentMapOtherNodes;
+ using ParentMapOtherNodes =
+ llvm::DenseMap<ast_type_traits::DynTypedNode,
+ llvm::PointerUnion4<const Decl *, const Stmt *,
+ ast_type_traits::DynTypedNode *,
+ ParentVector *>>;
/// Container for either a single DynTypedNode or for an ArrayRef to
/// DynTypedNode. For use with ParentMap.
class DynTypedNodeList {
- typedef ast_type_traits::DynTypedNode DynTypedNode;
+ using DynTypedNode = ast_type_traits::DynTypedNode;
+
llvm::AlignedCharArrayUnion<ast_type_traits::DynTypedNode,
ArrayRef<DynTypedNode>> Storage;
bool IsSingleNode;
@@ -548,6 +574,7 @@ public:
DynTypedNodeList(const DynTypedNode &N) : IsSingleNode(true) {
new (Storage.buffer) DynTypedNode(N);
}
+
DynTypedNodeList(ArrayRef<DynTypedNode> A) : IsSingleNode(false) {
new (Storage.buffer) ArrayRef<DynTypedNode>(A);
}
@@ -626,13 +653,14 @@ public:
template <typename T> T *Allocate(size_t Num = 1) const {
return static_cast<T *>(Allocate(Num * sizeof(T), alignof(T)));
}
- void Deallocate(void *Ptr) const { }
+ void Deallocate(void *Ptr) const {}
/// Return the total amount of physical memory allocated for representing
/// AST nodes and type information.
size_t getASTAllocatedMemory() const {
return BumpAlloc.getTotalMemory();
}
+
/// Return the total memory used for various side tables.
size_t getSideTableAllocatedMemory() const;
@@ -649,6 +677,7 @@ public:
/// Returns empty type if there is no appropriate target types.
QualType getIntTypeForBitwidth(unsigned DestWidth,
unsigned Signed) const;
+
/// getRealTypeForBitwidth -
/// sets floating point QualTy according to specified bitwidth.
/// Returns empty type if there is no appropriate target types.
@@ -676,7 +705,7 @@ public:
RawCommentList Comments;
/// \brief True if comments are already loaded from ExternalASTSource.
- mutable bool CommentsLoaded;
+ mutable bool CommentsLoaded = false;
class RawCommentAndCacheFlags {
public:
@@ -759,24 +788,24 @@ public:
}
/// \brief Return the documentation comment attached to a given declaration.
- /// Returns NULL if no comment is attached.
+ /// Returns nullptr if no comment is attached.
///
- /// \param OriginalDecl if not NULL, is set to declaration AST node that had
- /// the comment, if the comment we found comes from a redeclaration.
+ /// \param OriginalDecl if not nullptr, is set to declaration AST node that
+ /// had the comment, if the comment we found comes from a redeclaration.
const RawComment *
getRawCommentForAnyRedecl(const Decl *D,
const Decl **OriginalDecl = nullptr) const;
/// Return parsed documentation comment attached to a given declaration.
- /// Returns NULL if no comment is attached.
+ /// Returns nullptr if no comment is attached.
///
- /// \param PP the Preprocessor used with this TU. Could be NULL if
+ /// \param PP the Preprocessor used with this TU. Could be nullptr if
/// preprocessor is not available.
comments::FullComment *getCommentForDecl(const Decl *D,
const Preprocessor *PP) const;
/// Return parsed documentation comment attached to a given declaration.
- /// Returns NULL if no comment is attached. Does not look at any
+ /// Returns nullptr if no comment is attached. Does not look at any
/// redeclarations of the declaration.
comments::FullComment *getLocalCommentForDeclUncached(const Decl *D) const;
@@ -788,16 +817,16 @@ private:
/// \brief Iterator that visits import declarations.
class import_iterator {
- ImportDecl *Import;
+ ImportDecl *Import = nullptr;
public:
- typedef ImportDecl *value_type;
- typedef ImportDecl *reference;
- typedef ImportDecl *pointer;
- typedef int difference_type;
- typedef std::forward_iterator_tag iterator_category;
+ using value_type = ImportDecl *;
+ using reference = ImportDecl *;
+ using pointer = ImportDecl *;
+ using difference_type = int;
+ using iterator_category = std::forward_iterator_tag;
- import_iterator() : Import() {}
+ import_iterator() = default;
explicit import_iterator(ImportDecl *Import) : Import(Import) {}
reference operator*() const { return Import; }
@@ -876,7 +905,7 @@ public:
void setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst, FieldDecl *Tmpl);
// Access to the set of methods overridden by the given C++ method.
- typedef CXXMethodVector::const_iterator overridden_cxx_method_iterator;
+ using overridden_cxx_method_iterator = CXXMethodVector::const_iterator;
overridden_cxx_method_iterator
overridden_methods_begin(const CXXMethodDecl *Method) const;
@@ -884,8 +913,10 @@ public:
overridden_methods_end(const CXXMethodDecl *Method) const;
unsigned overridden_methods_size(const CXXMethodDecl *Method) const;
- typedef llvm::iterator_range<overridden_cxx_method_iterator>
- overridden_method_range;
+
+ using overridden_method_range =
+ llvm::iterator_range<overridden_cxx_method_iterator>;
+
overridden_method_range overridden_methods(const CXXMethodDecl *Method) const;
/// \brief Note that the given C++ \p Method overrides the given \p
@@ -912,7 +943,8 @@ public:
return Import->NextLocalImport;
}
- typedef llvm::iterator_range<import_iterator> import_range;
+ using import_range = llvm::iterator_range<import_iterator>;
+
import_range local_imports() const {
return import_range(import_iterator(FirstLocalImport), import_iterator());
}
@@ -929,6 +961,7 @@ public:
/// and should be visible whenever \p M is visible.
void mergeDefinitionIntoModule(NamedDecl *ND, Module *M,
bool NotifyListeners = true);
+
/// \brief Clean up the merged definition list. Call this if you might have
/// added duplicates into the list.
void deduplicateMergedDefinitonsFor(NamedDecl *ND);
@@ -973,6 +1006,7 @@ public:
CanQualType UnsignedLongLongTy, UnsignedInt128Ty;
CanQualType FloatTy, DoubleTy, LongDoubleTy, Float128Ty;
CanQualType HalfTy; // [OpenCL 6.1.1.1], ARM NEON
+ CanQualType Float16Ty; // C11 extension ISO/IEC TS 18661-3
CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy;
CanQualType Float128ComplexTy;
CanQualType VoidPtrTy, NullPtrTy;
@@ -1067,7 +1101,14 @@ public:
/// The resulting type has a union of the qualifiers from T and the address
/// space. If T already has an address space specifier, it is silently
/// replaced.
- QualType getAddrSpaceQualType(QualType T, unsigned AddressSpace) const;
+ QualType getAddrSpaceQualType(QualType T, LangAS AddressSpace) const;
+
+ /// \brief Remove any existing address space on the type and returns the type
+ /// with qualifiers intact (or that's the idea anyway)
+ ///
+ /// The return type should be T with all prior qualifiers minus the address
+ /// space.
+ QualType removeAddrSpaceQualType(QualType T) const;
/// \brief Apply Objective-C protocol qualifiers to the given type.
/// \param allowOnPointerType specifies if we can apply protocol
@@ -1175,6 +1216,7 @@ public:
/// \brief Return a read_only pipe type for the specified type.
QualType getReadPipeType(QualType T) const;
+
/// \brief Return a write_only pipe type for the specified type.
QualType getWritePipeType(QualType T) const;
@@ -1182,9 +1224,16 @@ public:
/// pointer to blocks.
QualType getBlockDescriptorExtendedType() const;
+ /// Map an AST Type to an OpenCLTypeKind enum value.
+ TargetInfo::OpenCLTypeKind getOpenCLTypeKind(const Type *T) const;
+
+ /// Get address space for OpenCL type.
+ LangAS getOpenCLTypeAddrSpace(const Type *T) const;
+
void setcudaConfigureCallDecl(FunctionDecl *FD) {
cudaConfigureCallDecl = FD;
}
+
FunctionDecl *getcudaConfigureCallDecl() {
return cudaConfigureCallDecl;
}
@@ -1192,7 +1241,6 @@ public:
/// Returns true iff we need copy/dispose helpers for the given type.
bool BlockRequiresCopying(QualType Ty, const VarDecl *D);
-
/// Returns true, if given type has a known lifetime. HasByrefExtendedLayout is set
/// to false in this case. If HasByrefExtendedLayout returns true, byref variable
/// has extended lifetime.
@@ -1269,6 +1317,10 @@ public:
Expr *SizeExpr,
SourceLocation AttrLoc) const;
+ QualType getDependentAddressSpaceType(QualType PointeeType,
+ Expr *AddrSpaceExpr,
+ SourceLocation AttrLoc) const;
+
/// \brief Return a K&R style C function type like 'int()'.
QualType getFunctionNoProtoType(QualType ResultTy,
const FunctionType::ExtInfo &Info) const;
@@ -1396,6 +1448,7 @@ public:
QualType Canonical = QualType()) const;
bool ObjCObjectAdoptsQTypeProtocols(QualType QT, ObjCInterfaceDecl *Decl);
+
/// QIdProtocolsAdoptObjCObjectProtocols - Checks that protocols in
/// QT's qualified-id protocol list adopt all protocols in IDecl's list
/// of protocols.
@@ -1426,7 +1479,7 @@ public:
/// \brief C++11 deduction pattern for 'auto &&' type.
QualType getAutoRRefDeductType() const;
- /// \brief C++1z deduced class template specialization type.
+ /// \brief C++17 deduced class template specialization type.
QualType getDeducedTemplateSpecializationType(TemplateName Template,
QualType DeducedType,
bool IsDependent) const;
@@ -1488,6 +1541,11 @@ public:
/// <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
QualType getPointerDiffType() const;
+ /// \brief Return the unique unsigned counterpart of "ptrdiff_t"
+ /// integer type. The standard (C11 7.21.6.1p7) refers to this type
+ /// in the definition of %tu format specifier.
+ QualType getUnsignedPointerDiffType() const;
+
/// \brief Return the unique type for "pid_t" defined in
/// <sys/types.h>. We need this to compute the correct type for vfork().
QualType getProcessIDType() const;
@@ -1581,6 +1639,24 @@ public:
return NSCopyingName;
}
+ CanQualType getNSUIntegerType() const {
+ assert(Target && "Expected target to be initialized");
+ const llvm::Triple &T = Target->getTriple();
+ // Windows is LLP64 rather than LP64
+ if (T.isOSWindows() && T.isArch64Bit())
+ return UnsignedLongLongTy;
+ return UnsignedLongTy;
+ }
+
+ CanQualType getNSIntegerType() const {
+ assert(Target && "Expected target to be initialized");
+ const llvm::Triple &T = Target->getTriple();
+ // Windows is LLP64 rather than LP64
+ if (T.isOSWindows() && T.isArch64Bit())
+ return LongLongTy;
+ return LongTy;
+ }
+
/// Retrieve the identifier 'bool'.
IdentifierInfo *getBoolName() const {
if (!BoolName)
@@ -1865,10 +1941,17 @@ public:
const TemplateArgument &ArgPack) const;
enum GetBuiltinTypeError {
- GE_None, ///< No error
- GE_Missing_stdio, ///< Missing a type from <stdio.h>
- GE_Missing_setjmp, ///< Missing a type from <setjmp.h>
- GE_Missing_ucontext ///< Missing a type from <ucontext.h>
+ /// No error
+ GE_None,
+
+ /// Missing a type from <stdio.h>
+ GE_Missing_stdio,
+
+ /// Missing a type from <setjmp.h>
+ GE_Missing_setjmp,
+
+ /// Missing a type from <ucontext.h>
+ GE_Missing_ucontext
};
/// \brief Return the type for the specified builtin.
@@ -2019,7 +2102,7 @@ public:
getASTObjCImplementationLayout(const ObjCImplementationDecl *D) const;
/// \brief Get our current best idea for the key function of the
- /// given record decl, or NULL if there isn't one.
+ /// given record decl, or nullptr if there isn't one.
///
/// The key function is, according to the Itanium C++ ABI section 5.2.3:
/// ...the first non-pure virtual function that is not inline at the
@@ -2072,6 +2155,10 @@ public:
void CollectInheritedProtocols(const Decl *CDecl,
llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols);
+ /// \brief Return true if the specified type has unique object representations
+ /// according to (C++17 [meta.unary.prop]p9)
+ bool hasUniqueObjectRepresentations(QualType Ty) const;
+
//===--------------------------------------------------------------------===//
// Type Operators
//===--------------------------------------------------------------------===//
@@ -2103,7 +2190,6 @@ public:
bool hasSameType(QualType T1, QualType T2) const {
return getCanonicalType(T1) == getCanonicalType(T2);
}
-
bool hasSameType(const Type *T1, const Type *T2) const {
return getCanonicalType(T1) == getCanonicalType(T2);
}
@@ -2192,7 +2278,7 @@ public:
getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const;
/// \brief Retrieves the default calling convention for the current target.
- CallingConv getDefaultCallingConvention(bool isVariadic,
+ CallingConv getDefaultCallingConvention(bool IsVariadic,
bool IsCXXMethod) const;
/// \brief Retrieves the "canonical" template name that refers to a
@@ -2326,14 +2412,14 @@ public:
return getTargetAddressSpace(Q.getAddressSpace());
}
- unsigned getTargetAddressSpace(unsigned AS) const;
+ unsigned getTargetAddressSpace(LangAS AS) const;
/// Get target-dependent integer value for null pointer which is used for
/// constant folding.
uint64_t getTargetNullPointerValue(QualType QT) const;
- bool addressSpaceMapManglingFor(unsigned AS) const {
- return AddrSpaceMapMangling || AS >= LangAS::FirstTargetAddressSpace;
+ bool addressSpaceMapManglingFor(LangAS AS) const {
+ return AddrSpaceMapMangling || isTargetAddressSpace(AS);
}
private:
@@ -2355,12 +2441,15 @@ public:
bool isObjCIdType(QualType T) const {
return T == getObjCIdType();
}
+
bool isObjCClassType(QualType T) const {
return T == getObjCClassType();
}
+
bool isObjCSelType(QualType T) const {
return T == getObjCSelType();
}
+
bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS,
bool ForCompare);
@@ -2394,9 +2483,30 @@ public:
QualType mergeObjCGCQualifiers(QualType, QualType);
- bool doFunctionTypesMatchOnExtParameterInfos(
- const FunctionProtoType *FromFunctionType,
- const FunctionProtoType *ToFunctionType);
+ /// This function merges the ExtParameterInfo lists of two functions. It
+ /// returns true if the lists are compatible. The merged list is returned in
+ /// NewParamInfos.
+ ///
+ /// \param FirstFnType The type of the first function.
+ ///
+ /// \param SecondFnType The type of the second function.
+ ///
+ /// \param CanUseFirst This flag is set to true if the first function's
+ /// ExtParameterInfo list can be used as the composite list of
+ /// ExtParameterInfo.
+ ///
+ /// \param CanUseSecond This flag is set to true if the second function's
+ /// ExtParameterInfo list can be used as the composite list of
+ /// ExtParameterInfo.
+ ///
+ /// \param NewParamInfos The composite list of ExtParameterInfo. The list is
+ /// empty if none of the flags are set.
+ ///
+ bool mergeExtParameterInfo(
+ const FunctionProtoType *FirstFnType,
+ const FunctionProtoType *SecondFnType,
+ bool &CanUseFirst, bool &CanUseSecond,
+ SmallVectorImpl<FunctionProtoType::ExtParameterInfo> &NewParamInfos);
void ResetObjCLayout(const ObjCContainerDecl *CD);
@@ -2432,12 +2542,13 @@ public:
bool isSentinelNullExpr(const Expr *E);
- /// \brief Get the implementation of the ObjCInterfaceDecl \p D, or NULL if
+ /// \brief Get the implementation of the ObjCInterfaceDecl \p D, or nullptr if
/// none exists.
ObjCImplementationDecl *getObjCImplementation(ObjCInterfaceDecl *D);
- /// \brief Get the implementation of the ObjCCategoryDecl \p D, or NULL if
+
+ /// \brief Get the implementation of the ObjCCategoryDecl \p D, or nullptr if
/// none exists.
- ObjCCategoryImplDecl *getObjCImplementation(ObjCCategoryDecl *D);
+ ObjCCategoryImplDecl *getObjCImplementation(ObjCCategoryDecl *D);
/// \brief Return true if there is at least one \@implementation in the TU.
bool AnyObjCImplementation() {
@@ -2447,6 +2558,7 @@ public:
/// \brief Set the implementation of ObjCInterfaceDecl.
void setObjCImplementation(ObjCInterfaceDecl *IFaceD,
ObjCImplementationDecl *ImplD);
+
/// \brief Set the implementation of ObjCCategoryDecl.
void setObjCImplementation(ObjCCategoryDecl *CatD,
ObjCCategoryImplDecl *ImplD);
@@ -2466,8 +2578,9 @@ public:
/// \brief Set the copy inialization expression of a block var decl.
void setBlockVarCopyInits(VarDecl*VD, Expr* Init);
+
/// \brief Get the copy initialization expression of the VarDecl \p VD, or
- /// NULL if none exists.
+ /// nullptr if none exists.
Expr *getBlockVarCopyInits(const VarDecl* VD);
/// \brief Allocate an uninitialized TypeSourceInfo.
@@ -2636,6 +2749,7 @@ private:
const FieldDecl *Field,
bool includeVBases = true,
QualType *NotEncodedT=nullptr) const;
+
public:
// Adds the encoding of a method parameter or return type.
void getObjCEncodingForMethodParameter(Decl::ObjCDeclQualifier QT,
@@ -2647,11 +2761,19 @@ public:
bool isMSStaticDataMemberInlineDefinition(const VarDecl *VD) const;
enum class InlineVariableDefinitionKind {
- None, ///< Not an inline variable.
- Weak, ///< Weak definition of inline variable.
- WeakUnknown, ///< Weak for now, might become strong later in this TU.
- Strong ///< Strong definition.
+ /// Not an inline variable.
+ None,
+
+ /// Weak definition of inline variable.
+ Weak,
+
+ /// Weak for now, might become strong later in this TU.
+ WeakUnknown,
+
+ /// Strong definition.
+ Strong
};
+
/// \brief Determine whether a definition of this inline variable should
/// be treated as a weak or strong definition. For compatibility with
/// C++14 and before, for a constexpr static data member, if there is an
@@ -2661,6 +2783,9 @@ public:
getInlineVariableDefinitionKind(const VarDecl *VD) const;
private:
+ friend class DeclarationNameTable;
+ friend class DeclContext;
+
const ASTRecordLayout &
getObjCLayout(const ObjCInterfaceDecl *D,
const ObjCImplementationDecl *Impl) const;
@@ -2673,26 +2798,23 @@ private:
// into the datastructures which avoids this mess during deallocation but is
// wasteful of memory, and here we require a lot of error prone book keeping
// in order to track and run destructors while we're tearing things down.
- typedef llvm::SmallVector<std::pair<void (*)(void *), void *>, 16>
- DeallocationFunctionsAndArguments;
+ using DeallocationFunctionsAndArguments =
+ llvm::SmallVector<std::pair<void (*)(void *), void *>, 16>;
DeallocationFunctionsAndArguments Deallocations;
// FIXME: This currently contains the set of StoredDeclMaps used
// by DeclContext objects. This probably should not be in ASTContext,
// but we include it here so that ASTContext can quickly deallocate them.
- llvm::PointerIntPair<StoredDeclsMap*,1> LastSDM;
-
- friend class DeclContext;
- friend class DeclarationNameTable;
-
- void ReleaseDeclContextMaps();
- void ReleaseParentMapEntries();
+ llvm::PointerIntPair<StoredDeclsMap *, 1> LastSDM;
std::unique_ptr<ParentMapPointers> PointerParents;
std::unique_ptr<ParentMapOtherNodes> OtherParents;
std::unique_ptr<VTableContextBase> VTContext;
+ void ReleaseDeclContextMaps();
+ void ReleaseParentMapEntries();
+
public:
enum PragmaSectionFlag : unsigned {
PSF_None = 0,
@@ -2712,27 +2834,26 @@ public:
SectionInfo(DeclaratorDecl *Decl,
SourceLocation PragmaSectionLocation,
int SectionFlags)
- : Decl(Decl),
- PragmaSectionLocation(PragmaSectionLocation),
- SectionFlags(SectionFlags) {}
+ : Decl(Decl), PragmaSectionLocation(PragmaSectionLocation),
+ SectionFlags(SectionFlags) {}
};
llvm::StringMap<SectionInfo> SectionInfos;
};
/// \brief Utility function for constructing a nullary selector.
-static inline Selector GetNullarySelector(StringRef name, ASTContext& Ctx) {
+inline Selector GetNullarySelector(StringRef name, ASTContext &Ctx) {
IdentifierInfo* II = &Ctx.Idents.get(name);
return Ctx.Selectors.getSelector(0, &II);
}
/// \brief Utility function for constructing an unary selector.
-static inline Selector GetUnarySelector(StringRef name, ASTContext& Ctx) {
+inline Selector GetUnarySelector(StringRef name, ASTContext &Ctx) {
IdentifierInfo* II = &Ctx.Idents.get(name);
return Ctx.Selectors.getSelector(1, &II);
}
-} // end namespace clang
+} // namespace clang
// operator new and delete aren't allowed inside namespaces.
@@ -2763,11 +2884,12 @@ static inline Selector GetUnarySelector(StringRef name, ASTContext& Ctx) {
/// @param C The ASTContext that provides the allocator.
/// @param Alignment The alignment of the allocated memory (if the underlying
/// allocator supports it).
-/// @return The allocated memory. Could be NULL.
+/// @return The allocated memory. Could be nullptr.
inline void *operator new(size_t Bytes, const clang::ASTContext &C,
size_t Alignment) {
return C.Allocate(Bytes, Alignment);
}
+
/// @brief Placement delete companion to the new above.
///
/// This operator is just a companion to the new above. There is no way of
@@ -2800,7 +2922,7 @@ inline void operator delete(void *Ptr, const clang::ASTContext &C, size_t) {
/// @param C The ASTContext that provides the allocator.
/// @param Alignment The alignment of the allocated memory (if the underlying
/// allocator supports it).
-/// @return The allocated memory. Could be NULL.
+/// @return The allocated memory. Could be nullptr.
inline void *operator new[](size_t Bytes, const clang::ASTContext& C,
size_t Alignment = 8) {
return C.Allocate(Bytes, Alignment);
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h b/contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h
index a8eff1a2fcbb5..9395d36d87e58 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h
@@ -22,6 +22,7 @@ namespace clang {
class CXXRecordDecl;
class Decl;
class DeclContext;
+ class Expr;
class FieldDecl;
class FunctionDecl;
class FunctionTemplateDecl;
@@ -35,6 +36,7 @@ namespace clang {
class QualType;
class RecordDecl;
class TagDecl;
+ class ValueDecl;
class VarDecl;
class VarTemplateDecl;
class VarTemplateSpecializationDecl;
@@ -80,13 +82,19 @@ public:
/// \brief A virtual destructor's operator delete has been resolved.
virtual void ResolvedOperatorDelete(const CXXDestructorDecl *DD,
- const FunctionDecl *Delete) {}
+ const FunctionDecl *Delete,
+ Expr *ThisArg) {}
/// \brief An implicit member got a definition.
virtual void CompletedImplicitDefinition(const FunctionDecl *D) {}
- /// \brief A static data member was implicitly instantiated.
- virtual void StaticDataMemberInstantiated(const VarDecl *D) {}
+ /// \brief The instantiation of a templated function or variable was
+ /// requested. In particular, the point of instantiation and template
+ /// specialization kind of \p D may have changed.
+ virtual void InstantiationRequested(const ValueDecl *D) {}
+
+ /// \brief A templated variable's definition was implicitly instantiated.
+ virtual void VariableDefinitionInstantiated(const VarDecl *D) {}
/// \brief A function template's definition was instantiated.
virtual void FunctionDefinitionInstantiated(const FunctionDecl *D) {}
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTUnresolvedSet.h b/contrib/llvm/tools/clang/include/clang/AST/ASTUnresolvedSet.h
index 9078a0e80299c..3693aeccfe14f 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ASTUnresolvedSet.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTUnresolvedSet.h
@@ -1,4 +1,4 @@
-//===-- ASTUnresolvedSet.h - Unresolved sets of declarations ---*- C++ -*-===//
+//===- ASTUnresolvedSet.h - Unresolved sets of declarations -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,14 +16,22 @@
#define LLVM_CLANG_AST_ASTUNRESOLVEDSET_H
#include "clang/AST/ASTVector.h"
+#include "clang/AST/DeclAccessPair.h"
#include "clang/AST/UnresolvedSet.h"
+#include "clang/Basic/Specifiers.h"
+#include <cassert>
+#include <cstdint>
namespace clang {
+class NamedDecl;
+
/// \brief An UnresolvedSet-like class which uses the ASTContext's allocator.
class ASTUnresolvedSet {
+ friend class LazyASTUnresolvedSet;
+
struct DeclsTy : ASTVector<DeclAccessPair> {
- DeclsTy() {}
+ DeclsTy() = default;
DeclsTy(ASTContext &C, unsigned N) : ASTVector<DeclAccessPair>(C, N) {}
bool isLazy() const { return getTag(); }
@@ -32,14 +40,12 @@ class ASTUnresolvedSet {
DeclsTy Decls;
- friend class LazyASTUnresolvedSet;
-
public:
- ASTUnresolvedSet() {}
+ ASTUnresolvedSet() = default;
ASTUnresolvedSet(ASTContext &C, unsigned N) : Decls(C, N) {}
- typedef UnresolvedSetIterator iterator;
- typedef UnresolvedSetIterator const_iterator;
+ using iterator = UnresolvedSetIterator;
+ using const_iterator = UnresolvedSetIterator;
iterator begin() { return iterator(Decls.begin()); }
iterator end() { return iterator(Decls.end()); }
@@ -98,13 +104,14 @@ public:
}
void reserve(ASTContext &C, unsigned N) { Impl.reserve(C, N); }
+
void addLazyDecl(ASTContext &C, uintptr_t ID, AccessSpecifier AS) {
assert(Impl.empty() || Impl.Decls.isLazy());
Impl.Decls.setLazy(true);
- Impl.addDecl(C, reinterpret_cast<NamedDecl*>(ID << 2), AS);
+ Impl.addDecl(C, reinterpret_cast<NamedDecl *>(ID << 2), AS);
}
};
} // namespace clang
-#endif
+#endif // LLVM_CLANG_AST_ASTUNRESOLVEDSET_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTVector.h b/contrib/llvm/tools/clang/include/clang/AST/ASTVector.h
index 717a9e9dff340..80cd6b7007a6d 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ASTVector.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTVector.h
@@ -1,4 +1,4 @@
-//===- ASTVector.h - Vector that uses ASTContext for allocation --*- C++ -*-=//
+//===- ASTVector.h - Vector that uses ASTContext for allocation ---*- C++ -*-=//
//
// The LLVM Compiler Infrastructure
//
@@ -18,22 +18,26 @@
#ifndef LLVM_CLANG_AST_ASTVECTOR_H
#define LLVM_CLANG_AST_ASTVECTOR_H
-#include "clang/AST/AttrIterator.h"
#include "llvm/ADT/PointerIntPair.h"
-#include "llvm/Support/type_traits.h"
#include <algorithm>
+#include <cassert>
#include <cstddef>
#include <cstring>
+#include <iterator>
#include <memory>
+#include <type_traits>
+#include <utility>
namespace clang {
- class ASTContext;
+
+class ASTContext;
template<typename T>
class ASTVector {
private:
- T *Begin, *End;
- llvm::PointerIntPair<T*, 1, bool> Capacity;
+ T *Begin = nullptr;
+ T *End = nullptr;
+ llvm::PointerIntPair<T *, 1, bool> Capacity;
void setEnd(T *P) { this->End = P; }
@@ -45,7 +49,7 @@ protected:
public:
// Default ctor - Initialize to empty.
- ASTVector() : Begin(nullptr), End(nullptr), Capacity(nullptr, false) {}
+ ASTVector() : Capacity(nullptr, false) {}
ASTVector(ASTVector &&O) : Begin(O.Begin), End(O.End), Capacity(O.Capacity) {
O.Begin = O.End = nullptr;
@@ -53,14 +57,15 @@ public:
O.Capacity.setInt(false);
}
- ASTVector(const ASTContext &C, unsigned N)
- : Begin(nullptr), End(nullptr), Capacity(nullptr, false) {
+ ASTVector(const ASTContext &C, unsigned N) : Capacity(nullptr, false) {
reserve(C, N);
}
ASTVector &operator=(ASTVector &&RHS) {
ASTVector O(std::move(RHS));
+
using std::swap;
+
swap(Begin, O.Begin);
swap(End, O.End);
swap(Capacity, O.Capacity);
@@ -74,19 +79,19 @@ public:
}
}
- typedef size_t size_type;
- typedef ptrdiff_t difference_type;
- typedef T value_type;
- typedef T* iterator;
- typedef const T* const_iterator;
+ using size_type = size_t;
+ using difference_type = ptrdiff_t;
+ using value_type = T;
+ using iterator = T *;
+ using const_iterator = const T *;
- typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
- typedef std::reverse_iterator<iterator> reverse_iterator;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+ using reverse_iterator = std::reverse_iterator<iterator>;
- typedef T& reference;
- typedef const T& const_reference;
- typedef T* pointer;
- typedef const T* const_pointer;
+ using reference = T &;
+ using const_reference = const T &;
+ using pointer = T *;
+ using const_pointer = const T *;
// forward iterator creation methods.
iterator begin() { return Begin; }
@@ -175,7 +180,6 @@ public:
size_t capacity() const { return this->capacity_ptr() - Begin; }
/// append - Add the specified range to the end of the SmallVector.
- ///
template<typename in_iter>
void append(const ASTContext &C, in_iter in_start, in_iter in_end) {
size_type NumInputs = std::distance(in_start, in_end);
@@ -195,7 +199,6 @@ public:
}
/// append - Add the specified range to the end of the SmallVector.
- ///
void append(const ASTContext &C, size_type NumInputs, const T &Elt) {
// Grow allocated space if needed.
if (NumInputs > size_type(this->capacity_ptr()-this->end()))
@@ -368,6 +371,7 @@ protected:
const_iterator capacity_ptr() const {
return (iterator) Capacity.getPointer();
}
+
iterator capacity_ptr() { return (iterator)Capacity.getPointer(); }
};
@@ -401,5 +405,6 @@ void ASTVector<T>::grow(const ASTContext &C, size_t MinSize) {
Capacity.setPointer(Begin+NewCapacity);
}
-} // end: clang namespace
-#endif
+} // namespace clang
+
+#endif // LLVM_CLANG_AST_ASTVECTOR_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/AttrIterator.h b/contrib/llvm/tools/clang/include/clang/AST/AttrIterator.h
index fb9b049e5d6b1..56807b4590d37 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/AttrIterator.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/AttrIterator.h
@@ -1,4 +1,4 @@
-//===--- AttrIterator.h - Classes for attribute iteration -------*- C++ -*-===//
+//===- AttrIterator.h - Classes for attribute iteration ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,16 +15,23 @@
#define LLVM_CLANG_AST_ATTRITERATOR_H
#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Casting.h"
+#include <cassert>
+#include <cstddef>
#include <iterator>
namespace clang {
- class ASTContext;
- class Attr;
-}
+
+class ASTContext;
+class Attr;
+
+} // namespace clang
// Defined in ASTContext.h
void *operator new(size_t Bytes, const clang::ASTContext &C,
size_t Alignment = 8);
+
// FIXME: Being forced to not have a default argument here due to redeclaration
// rules on default arguments sucks
void *operator new[](size_t Bytes, const clang::ASTContext &C,
@@ -39,13 +46,13 @@ void operator delete[](void *Ptr, const clang::ASTContext &C, size_t);
namespace clang {
/// AttrVec - A vector of Attr, which is how they are stored on the AST.
-typedef SmallVector<Attr *, 4> AttrVec;
+using AttrVec = SmallVector<Attr *, 4>;
/// specific_attr_iterator - Iterates over a subrange of an AttrVec, only
/// providing attributes that are of a specific type.
template <typename SpecificAttr, typename Container = AttrVec>
class specific_attr_iterator {
- typedef typename Container::const_iterator Iterator;
+ using Iterator = typename Container::const_iterator;
/// Current - The current, underlying iterator.
/// In order to ensure we don't dereference an invalid iterator unless
@@ -67,14 +74,14 @@ class specific_attr_iterator {
}
public:
- typedef SpecificAttr* value_type;
- typedef SpecificAttr* reference;
- typedef SpecificAttr* pointer;
- typedef std::forward_iterator_tag iterator_category;
- typedef std::ptrdiff_t difference_type;
+ using value_type = SpecificAttr *;
+ using reference = SpecificAttr *;
+ using pointer = SpecificAttr *;
+ using iterator_category = std::forward_iterator_tag;
+ using difference_type = std::ptrdiff_t;
- specific_attr_iterator() : Current() { }
- explicit specific_attr_iterator(Iterator i) : Current(i) { }
+ specific_attr_iterator() = default;
+ explicit specific_attr_iterator(Iterator i) : Current(i) {}
reference operator*() const {
AdvanceToNext();
@@ -136,6 +143,6 @@ inline SpecificAttr *getSpecificAttr(const Container& container) {
return nullptr;
}
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_AST_ATTRITERATOR_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/BaseSubobject.h b/contrib/llvm/tools/clang/include/clang/AST/BaseSubobject.h
index 66af023c828e4..fdb7e718fe9e4 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/BaseSubobject.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/BaseSubobject.h
@@ -1,4 +1,4 @@
-//===--- BaseSubobject.h - BaseSubobject class ----------------------------===//
+//===- BaseSubobject.h - BaseSubobject class --------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,12 +15,15 @@
#define LLVM_CLANG_AST_BASESUBOBJECT_H
#include "clang/AST/CharUnits.h"
-#include "clang/AST/DeclCXX.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/Support/type_traits.h"
+#include <cstdint>
+#include <utility>
namespace clang {
+
+class CXXRecordDecl;
+
// BaseSubobject - Uniquely identifies a direct or indirect base class.
// Stores both the base class decl and the offset from the most derived class to
// the base class. Used for vtable and VTT generation.
@@ -32,9 +35,9 @@ class BaseSubobject {
CharUnits BaseOffset;
public:
- BaseSubobject() { }
+ BaseSubobject() = default;
BaseSubobject(const CXXRecordDecl *Base, CharUnits BaseOffset)
- : Base(Base), BaseOffset(BaseOffset) { }
+ : Base(Base), BaseOffset(BaseOffset) {}
/// getBase - Returns the base class declaration.
const CXXRecordDecl *getBase() const { return Base; }
@@ -47,7 +50,7 @@ public:
}
};
-} // end namespace clang
+} // namespace clang
namespace llvm {
@@ -65,7 +68,8 @@ template<> struct DenseMapInfo<clang::BaseSubobject> {
}
static unsigned getHashValue(const clang::BaseSubobject &Base) {
- typedef std::pair<const clang::CXXRecordDecl *, clang::CharUnits> PairTy;
+ using PairTy = std::pair<const clang::CXXRecordDecl *, clang::CharUnits>;
+
return DenseMapInfo<PairTy>::getHashValue(PairTy(Base.getBase(),
Base.getBaseOffset()));
}
@@ -81,6 +85,6 @@ template <> struct isPodLike<clang::BaseSubobject> {
static const bool value = true;
};
-}
+} // namespace llvm
-#endif
+#endif // LLVM_CLANG_AST_BASESUBOBJECT_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/BuiltinTypes.def b/contrib/llvm/tools/clang/include/clang/AST/BuiltinTypes.def
index 181131aba07f7..e4f5f7db2f73c 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/BuiltinTypes.def
+++ b/contrib/llvm/tools/clang/include/clang/AST/BuiltinTypes.def
@@ -133,6 +133,9 @@ FLOATING_TYPE(Double, DoubleTy)
// 'long double'
FLOATING_TYPE(LongDouble, LongDoubleTy)
+// '_Float16'
+FLOATING_TYPE(Float16, HalfTy)
+
// '__float128'
FLOATING_TYPE(Float128, Float128Ty)
diff --git a/contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h b/contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h
index 980608570fd68..11fb229f0c091 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h
@@ -1,4 +1,4 @@
-//===------ CXXInheritance.h - C++ Inheritance ------------------*- C++ -*-===//
+//===- CXXInheritance.h - C++ Inheritance -----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,19 +16,23 @@
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclarationName.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeOrdering.h"
+#include "clang/Basic/Specifiers.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
-#include <cassert>
+#include "llvm/ADT/iterator_range.h"
#include <list>
+#include <memory>
+#include <utility>
namespace clang {
-
-class CXXBaseSpecifier;
-class CXXMethodDecl;
-class CXXRecordDecl;
+
+class ASTContext;
class NamedDecl;
/// \brief Represents an element in a path from a derived class to a
@@ -66,12 +70,12 @@ struct CXXBasePathElement {
/// subobject is being used.
class CXXBasePath : public SmallVector<CXXBasePathElement, 4> {
public:
- CXXBasePath() : Access(AS_public) {}
-
/// \brief The access along this inheritance path. This is only
/// calculated when recording paths. AS_none is a special value
/// used to indicate a path which permits no legal access.
- AccessSpecifier Access;
+ AccessSpecifier Access = AS_public;
+
+ CXXBasePath() = default;
/// \brief The set of declarations found inside this base class
/// subobject.
@@ -113,8 +117,10 @@ public:
/// refer to the same base class subobject of type A (the virtual
/// one), there is no ambiguity.
class CXXBasePaths {
+ friend class CXXRecordDecl;
+
/// \brief The type from which this search originated.
- CXXRecordDecl *Origin;
+ CXXRecordDecl *Origin = nullptr;
/// Paths - The actual set of paths that can be taken from the
/// derived class to the same base class.
@@ -152,15 +158,13 @@ class CXXBasePaths {
CXXBasePath ScratchPath;
/// DetectedVirtual - The base class that is virtual.
- const RecordType *DetectedVirtual;
+ const RecordType *DetectedVirtual = nullptr;
/// \brief Array of the declarations that have been found. This
/// array is constructed only if needed, e.g., to iterate over the
/// results within LookupResult.
std::unique_ptr<NamedDecl *[]> DeclsFound;
- unsigned NumDeclsFound;
-
- friend class CXXRecordDecl;
+ unsigned NumDeclsFound = 0;
void ComputeDeclsFound();
@@ -169,17 +173,16 @@ class CXXBasePaths {
bool LookupInDependent = false);
public:
- typedef std::list<CXXBasePath>::iterator paths_iterator;
- typedef std::list<CXXBasePath>::const_iterator const_paths_iterator;
- typedef NamedDecl **decl_iterator;
+ using paths_iterator = std::list<CXXBasePath>::iterator;
+ using const_paths_iterator = std::list<CXXBasePath>::const_iterator;
+ using decl_iterator = NamedDecl **;
/// BasePaths - Construct a new BasePaths structure to record the
/// paths for a derived-to-base search.
explicit CXXBasePaths(bool FindAmbiguities = true, bool RecordPaths = true,
bool DetectVirtual = true)
- : Origin(), FindAmbiguities(FindAmbiguities), RecordPaths(RecordPaths),
- DetectVirtual(DetectVirtual), DetectedVirtual(nullptr),
- NumDeclsFound(0) {}
+ : FindAmbiguities(FindAmbiguities), RecordPaths(RecordPaths),
+ DetectVirtual(DetectVirtual) {}
paths_iterator begin() { return Paths.begin(); }
paths_iterator end() { return Paths.end(); }
@@ -189,7 +192,8 @@ public:
CXXBasePath& front() { return Paths.front(); }
const CXXBasePath& front() const { return Paths.front(); }
- typedef llvm::iterator_range<decl_iterator> decl_range;
+ using decl_range = llvm::iterator_range<decl_iterator>;
+
decl_range found_decls();
/// \brief Determine whether the path from the most-derived type to the
@@ -231,25 +235,24 @@ public:
/// \brief Uniquely identifies a virtual method within a class
/// hierarchy by the method itself and a class subobject number.
struct UniqueVirtualMethod {
- UniqueVirtualMethod()
- : Method(nullptr), Subobject(0), InVirtualSubobject(nullptr) { }
-
- UniqueVirtualMethod(CXXMethodDecl *Method, unsigned Subobject,
- const CXXRecordDecl *InVirtualSubobject)
- : Method(Method), Subobject(Subobject),
- InVirtualSubobject(InVirtualSubobject) { }
-
/// \brief The overriding virtual method.
- CXXMethodDecl *Method;
+ CXXMethodDecl *Method = nullptr;
/// \brief The subobject in which the overriding virtual method
/// resides.
- unsigned Subobject;
+ unsigned Subobject = 0;
/// \brief The virtual base class subobject of which this overridden
/// virtual method is a part. Note that this records the closest
/// derived virtual base class subobject.
- const CXXRecordDecl *InVirtualSubobject;
+ const CXXRecordDecl *InVirtualSubobject = nullptr;
+
+ UniqueVirtualMethod() = default;
+
+ UniqueVirtualMethod(CXXMethodDecl *Method, unsigned Subobject,
+ const CXXRecordDecl *InVirtualSubobject)
+ : Method(Method), Subobject(Subobject),
+ InVirtualSubobject(InVirtualSubobject) {}
friend bool operator==(const UniqueVirtualMethod &X,
const UniqueVirtualMethod &Y) {
@@ -271,14 +274,16 @@ struct UniqueVirtualMethod {
/// pair is the virtual method that overrides it (including the
/// subobject in which that virtual function occurs).
class OverridingMethods {
- typedef SmallVector<UniqueVirtualMethod, 4> ValuesT;
- typedef llvm::MapVector<unsigned, ValuesT> MapType;
+ using ValuesT = SmallVector<UniqueVirtualMethod, 4>;
+ using MapType = llvm::MapVector<unsigned, ValuesT>;
+
MapType Overrides;
public:
// Iterate over the set of subobjects that have overriding methods.
- typedef MapType::iterator iterator;
- typedef MapType::const_iterator const_iterator;
+ using iterator = MapType::iterator;
+ using const_iterator = MapType::const_iterator;
+
iterator begin() { return Overrides.begin(); }
const_iterator begin() const { return Overrides.begin(); }
iterator end() { return Overrides.end(); }
@@ -287,10 +292,10 @@ public:
// Iterate over the set of overriding virtual methods in a given
// subobject.
- typedef SmallVectorImpl<UniqueVirtualMethod>::iterator
- overriding_iterator;
- typedef SmallVectorImpl<UniqueVirtualMethod>::const_iterator
- overriding_const_iterator;
+ using overriding_iterator =
+ SmallVectorImpl<UniqueVirtualMethod>::iterator;
+ using overriding_const_iterator =
+ SmallVectorImpl<UniqueVirtualMethod>::const_iterator;
// Add a new overriding method for a particular subobject.
void add(unsigned OverriddenSubobject, UniqueVirtualMethod Overriding);
@@ -357,12 +362,12 @@ public:
/// subobject numbers greater than 0 refer to non-virtual base class
/// subobjects of that type.
class CXXFinalOverriderMap
- : public llvm::MapVector<const CXXMethodDecl *, OverridingMethods> { };
+ : public llvm::MapVector<const CXXMethodDecl *, OverridingMethods> {};
/// \brief A set of all the primary bases for a class.
class CXXIndirectPrimaryBaseSet
- : public llvm::SmallSet<const CXXRecordDecl*, 32> { };
+ : public llvm::SmallSet<const CXXRecordDecl*, 32> {};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_AST_CXXINHERITANCE_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h b/contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h
index 25f6172be9b19..6487613200de3 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h
@@ -1,4 +1,4 @@
-//===-- CanonicalType.h - C Language Family Type Representation -*- C++ -*-===//
+//===- CanonicalType.h - C Language Family Type Representation --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,13 +16,29 @@
#define LLVM_CLANG_AST_CANONICALTYPE_H
#include "clang/AST/Type.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/iterator.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
+#include <cassert>
+#include <iterator>
+#include <type_traits>
namespace clang {
template<typename T> class CanProxy;
template<typename T> struct CanProxyAdaptor;
+class CXXRecordDecl;
+class EnumDecl;
+class Expr;
+class IdentifierInfo;
+class ObjCInterfaceDecl;
+class RecordDecl;
+class TagDecl;
+class TemplateTypeParmDecl;
//----------------------------------------------------------------------------//
// Canonical, qualified type template
@@ -46,8 +62,6 @@ template<typename T> struct CanProxyAdaptor;
/// converted to @c CanQual<ReferenceType>. Note that any @c CanQual type can
/// be implicitly converted to a QualType, but the reverse operation requires
/// a call to ASTContext::getCanonicalType().
-///
-///
template<typename T = Type>
class CanQual {
/// \brief The actual, canonical type.
@@ -55,7 +69,7 @@ class CanQual {
public:
/// \brief Constructs a NULL canonical type.
- CanQual() : Stored() { }
+ CanQual() = default;
/// \brief Converting constructor that permits implicit upcasting of
/// canonical type pointers.
@@ -66,12 +80,11 @@ public:
/// \brief Retrieve the underlying type pointer, which refers to a
/// canonical type.
///
- /// The underlying pointer must not be NULL.
+ /// The underlying pointer must not be nullptr.
const T *getTypePtr() const { return cast<T>(Stored.getTypePtr()); }
/// \brief Retrieve the underlying type pointer, which refers to a
- /// canonical type, or NULL.
- ///
+ /// canonical type, or nullptr.
const T *getTypePtrOrNull() const {
return cast_or_null<T>(Stored.getTypePtrOrNull());
}
@@ -125,9 +138,11 @@ public:
bool isConstQualified() const {
return Stored.isLocalConstQualified();
}
+
bool isVolatileQualified() const {
return Stored.isLocalVolatileQualified();
}
+
bool isRestrictQualified() const {
return Stored.isLocalRestrictQualified();
}
@@ -195,7 +210,7 @@ inline bool operator!=(CanQual<T> x, CanQual<U> y) {
}
/// \brief Represents a canonical, potentially-qualified type.
-typedef CanQual<Type> CanQualType;
+using CanQualType = CanQual<Type>;
inline CanQualType Type::getCanonicalTypeUnqualified() const {
return CanQualType::CreateUnsafe(getCanonicalTypeInternal());
@@ -320,7 +335,7 @@ public:
/// than the more typical @c QualType, to propagate the notion of "canonical"
/// through the system.
template<typename T>
-struct CanProxyAdaptor : CanProxyBase<T> { };
+struct CanProxyAdaptor : CanProxyBase<T> {};
/// \brief Canonical proxy type returned when retrieving the members of a
/// canonical type or as the result of the @c CanQual<T>::getAs member
@@ -333,7 +348,7 @@ template<typename T>
class CanProxy : public CanProxyAdaptor<T> {
public:
/// \brief Build a NULL proxy.
- CanProxy() { }
+ CanProxy() = default;
/// \brief Build a proxy to the given canonical type.
CanProxy(CanQual<T> Stored) { this->Stored = Stored; }
@@ -342,7 +357,7 @@ public:
operator CanQual<T>() const { return this->Stored; }
};
-} // end namespace clang
+} // namespace clang
namespace llvm {
@@ -350,8 +365,9 @@ namespace llvm {
/// CanQual<T> to a specific Type class. We're prefer isa/dyn_cast/cast/etc.
/// to return smart pointer (proxies?).
template<typename T>
-struct simplify_type< ::clang::CanQual<T> > {
- typedef const T *SimpleType;
+struct simplify_type< ::clang::CanQual<T>> {
+ using SimpleType = const T *;
+
static SimpleType getSimplifiedValue(::clang::CanQual<T> Val) {
return Val.getTypePtr();
}
@@ -359,19 +375,20 @@ struct simplify_type< ::clang::CanQual<T> > {
// Teach SmallPtrSet that CanQual<T> is "basically a pointer".
template<typename T>
-class PointerLikeTypeTraits<clang::CanQual<T> > {
-public:
- static inline void *getAsVoidPointer(clang::CanQual<T> P) {
+struct PointerLikeTypeTraits<clang::CanQual<T>> {
+ static void *getAsVoidPointer(clang::CanQual<T> P) {
return P.getAsOpaquePtr();
}
- static inline clang::CanQual<T> getFromVoidPointer(void *P) {
+
+ static clang::CanQual<T> getFromVoidPointer(void *P) {
return clang::CanQual<T>::getFromOpaquePtr(P);
}
+
// qualifier information is encoded in the low bits.
enum { NumLowBitsAvailable = 0 };
};
-} // end namespace llvm
+} // namespace llvm
namespace clang {
@@ -389,7 +406,7 @@ struct CanTypeIterator
CanQualType,
typename std::iterator_traits<InputIterator>::difference_type,
CanProxy<Type>, CanQualType> {
- CanTypeIterator() {}
+ CanTypeIterator() = default;
explicit CanTypeIterator(InputIterator Iter)
: CanTypeIterator::iterator_adaptor_base(std::move(Iter)) {}
@@ -487,6 +504,7 @@ struct CanProxyAdaptor<FunctionProtoType>
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasExtParameterInfos)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(
ArrayRef<FunctionProtoType::ExtParameterInfo>, getExtParameterInfos)
+
CanQualType getParamType(unsigned i) const {
return CanQualType::CreateUnsafe(this->getTypePtr()->getParamType(i));
}
@@ -494,8 +512,8 @@ struct CanProxyAdaptor<FunctionProtoType>
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariadic)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getTypeQuals)
- typedef CanTypeIterator<FunctionProtoType::param_type_iterator>
- param_type_iterator;
+ using param_type_iterator =
+ CanTypeIterator<FunctionProtoType::param_type_iterator>;
param_type_iterator param_type_begin() const {
return param_type_iterator(this->getTypePtr()->param_type_begin());
@@ -567,7 +585,8 @@ struct CanProxyAdaptor<ObjCObjectType>
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedId)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClass)
- typedef ObjCObjectPointerType::qual_iterator qual_iterator;
+ using qual_iterator = ObjCObjectPointerType::qual_iterator;
+
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty)
@@ -585,7 +604,8 @@ struct CanProxyAdaptor<ObjCObjectPointerType>
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedIdType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClassType)
- typedef ObjCObjectPointerType::qual_iterator qual_iterator;
+ using qual_iterator = ObjCObjectPointerType::qual_iterator;
+
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty)
@@ -662,7 +682,6 @@ CanProxy<Type> CanTypeIterator<InputIterator>::operator->() const {
return CanProxy<Type>(*this);
}
-}
-
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_AST_CANONICALTYPE_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/CharUnits.h b/contrib/llvm/tools/clang/include/clang/AST/CharUnits.h
index 564c8ec9b9ea0..ddead6046a147 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/CharUnits.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/CharUnits.h
@@ -40,14 +40,14 @@ namespace clang {
typedef int64_t QuantityType;
private:
- QuantityType Quantity;
+ QuantityType Quantity = 0;
explicit CharUnits(QuantityType C) : Quantity(C) {}
public:
/// CharUnits - A default constructor.
- CharUnits() : Quantity(0) {}
+ CharUnits() = default;
/// Zero - Construct a CharUnits quantity of zero.
static CharUnits Zero() {
diff --git a/contrib/llvm/tools/clang/include/clang/AST/CommentVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/CommentVisitor.h
index 21641bfeb89f0..d1cc2d0a4e5e1 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/CommentVisitor.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/CommentVisitor.h
@@ -1,4 +1,4 @@
-//===--- CommentVisitor.h - Visitor for Comment subclasses ------*- C++ -*-===//
+//===- CommentVisitor.h - Visitor for Comment subclasses --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,8 +16,8 @@
namespace clang {
namespace comments {
-template <typename T> struct make_ptr { typedef T *type; };
-template <typename T> struct make_const_ptr { typedef const T *type; };
+template <typename T> struct make_ptr { using type = T *; };
+template <typename T> struct make_const_ptr { using type = const T *; };
template<template <typename> class Ptr, typename ImplClass, typename RetTy=void>
class CommentVisitorBase {
@@ -64,7 +64,7 @@ template<typename ImplClass, typename RetTy=void>
class ConstCommentVisitor :
public CommentVisitorBase<make_const_ptr, ImplClass, RetTy> {};
-} // end namespace comments
-} // end namespace clang
+} // namespace comments
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_AST_COMMENTVISITOR_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DataCollection.h b/contrib/llvm/tools/clang/include/clang/AST/DataCollection.h
new file mode 100644
index 0000000000000..229ac2bd0f22d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/DataCollection.h
@@ -0,0 +1,65 @@
+//===--- DatatCollection.h --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// \brief This file declares helper methods for collecting data from AST nodes.
+///
+/// To collect data from Stmt nodes, subclass ConstStmtVisitor and include
+/// StmtDataCollectors.inc after defining the macros that you need. This
+/// provides data collection implementations for most Stmt kinds. Note
+/// that that code requires some conditions to be met:
+///
+/// - There must be a method addData(const T &Data) that accepts strings,
+/// integral types as well as QualType. All data is forwarded using
+/// to this method.
+/// - The ASTContext of the Stmt must be accessible by the name Context.
+///
+/// It is also possible to override individual visit methods. Have a look at
+/// the DataCollector in lib/Analysis/CloneDetection.cpp for a usage example.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_DATACOLLECTION_H
+#define LLVM_CLANG_AST_DATACOLLECTION_H
+
+#include "clang/AST/ASTContext.h"
+
+namespace clang {
+namespace data_collection {
+
+/// Returns a string that represents all macro expansions that expanded into the
+/// given SourceLocation.
+///
+/// If 'getMacroStack(A) == getMacroStack(B)' is true, then the SourceLocations
+/// A and B are expanded from the same macros in the same order.
+std::string getMacroStack(SourceLocation Loc, ASTContext &Context);
+
+/// Utility functions for implementing addData() for a consumer that has a
+/// method update(StringRef)
+template <class T>
+void addDataToConsumer(T &DataConsumer, llvm::StringRef Str) {
+ DataConsumer.update(Str);
+}
+
+template <class T> void addDataToConsumer(T &DataConsumer, const QualType &QT) {
+ addDataToConsumer(DataConsumer, QT.getAsString());
+}
+
+template <class T, class Type>
+typename std::enable_if<
+ std::is_integral<Type>::value || std::is_enum<Type>::value ||
+ std::is_convertible<Type, size_t>::value // for llvm::hash_code
+ >::type
+addDataToConsumer(T &DataConsumer, Type Data) {
+ DataConsumer.update(StringRef(reinterpret_cast<char *>(&Data), sizeof(Data)));
+}
+
+} // end namespace data_collection
+} // end namespace clang
+
+#endif // LLVM_CLANG_AST_DATACOLLECTION_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Decl.h b/contrib/llvm/tools/clang/include/clang/AST/Decl.h
index 54e6ebcd8af2a..4db0b1ef949ba 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/Decl.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/Decl.h
@@ -1,4 +1,4 @@
-//===--- Decl.h - Classes for representing declarations ---------*- C++ -*-===//
+//===- Decl.h - Classes for representing declarations -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -18,33 +18,58 @@
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/ExternalASTSource.h"
+#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/Redeclarable.h"
#include "clang/AST/Type.h"
+#include "clang/Basic/AddressSpaces.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/Linkage.h"
-#include "clang/Basic/Module.h"
#include "clang/Basic/OperatorKinds.h"
+#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/PragmaKinds.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Basic/Visibility.h"
+#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
-#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/TrailingObjects.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <string>
+#include <utility>
namespace clang {
+
+class ASTContext;
struct ASTTemplateArgumentListInfo;
-class CXXTemporary;
+class Attr;
class CompoundStmt;
class DependentFunctionTemplateSpecializationInfo;
+class EnumDecl;
class Expr;
class FunctionTemplateDecl;
class FunctionTemplateSpecializationInfo;
class LabelStmt;
class MemberSpecializationInfo;
-class NestedNameSpecifier;
+class Module;
+class NamespaceDecl;
class ParmVarDecl;
+class RecordDecl;
class Stmt;
class StringLiteral;
+class TagDecl;
class TemplateArgumentList;
+class TemplateArgumentListInfo;
class TemplateParameterList;
class TypeAliasTemplateDecl;
class TypeLoc;
@@ -58,13 +83,15 @@ class VarTemplateDecl;
/// TypeLoc TL = TypeSourceInfo->getTypeLoc();
/// TL.getStartLoc().print(OS, SrcMgr);
/// @endcode
-///
class TypeSourceInfo {
- QualType Ty;
// Contains a memory block after the class, used for type source information,
// allocated by ASTContext.
friend class ASTContext;
- TypeSourceInfo(QualType ty) : Ty(ty) { }
+
+ QualType Ty;
+
+ TypeSourceInfo(QualType ty) : Ty(ty) {}
+
public:
/// \brief Return the type wrapped by this type source info.
QualType getType() const { return Ty; }
@@ -78,14 +105,16 @@ public:
/// TranslationUnitDecl - The top declaration context.
class TranslationUnitDecl : public Decl, public DeclContext {
- virtual void anchor();
ASTContext &Ctx;
/// The (most recently entered) anonymous namespace for this
/// translation unit, if one has been created.
- NamespaceDecl *AnonymousNamespace;
+ NamespaceDecl *AnonymousNamespace = nullptr;
explicit TranslationUnitDecl(ASTContext &ctx);
+
+ virtual void anchor();
+
public:
ASTContext &getASTContext() const { return Ctx; }
@@ -93,6 +122,7 @@ public:
void setAnonymousNamespace(NamespaceDecl *D) { AnonymousNamespace = D; }
static TranslationUnitDecl *Create(ASTContext &C);
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == TranslationUnit; }
@@ -109,18 +139,18 @@ public:
class PragmaCommentDecl final
: public Decl,
private llvm::TrailingObjects<PragmaCommentDecl, char> {
- virtual void anchor();
-
- PragmaMSCommentKind CommentKind;
-
- friend TrailingObjects;
friend class ASTDeclReader;
friend class ASTDeclWriter;
+ friend TrailingObjects;
+
+ PragmaMSCommentKind CommentKind;
PragmaCommentDecl(TranslationUnitDecl *TU, SourceLocation CommentLoc,
PragmaMSCommentKind CommentKind)
: Decl(PragmaComment, TU, CommentLoc), CommentKind(CommentKind) {}
+ virtual void anchor();
+
public:
static PragmaCommentDecl *Create(const ASTContext &C, TranslationUnitDecl *DC,
SourceLocation CommentLoc,
@@ -143,18 +173,18 @@ public:
class PragmaDetectMismatchDecl final
: public Decl,
private llvm::TrailingObjects<PragmaDetectMismatchDecl, char> {
- virtual void anchor();
-
- size_t ValueStart;
-
- friend TrailingObjects;
friend class ASTDeclReader;
friend class ASTDeclWriter;
+ friend TrailingObjects;
+
+ size_t ValueStart;
PragmaDetectMismatchDecl(TranslationUnitDecl *TU, SourceLocation Loc,
size_t ValueStart)
: Decl(PragmaDetectMismatch, TU, Loc), ValueStart(ValueStart) {}
+ virtual void anchor();
+
public:
static PragmaDetectMismatchDecl *Create(const ASTContext &C,
TranslationUnitDecl *DC,
@@ -189,14 +219,16 @@ public:
/// The declaration at #3 finds it is a redeclaration of \c N::f through
/// lookup in the extern "C" context.
class ExternCContextDecl : public Decl, public DeclContext {
- virtual void anchor();
-
explicit ExternCContextDecl(TranslationUnitDecl *TU)
: Decl(ExternCContext, TU, SourceLocation()),
DeclContext(ExternCContext) {}
+
+ virtual void anchor();
+
public:
static ExternCContextDecl *Create(const ASTContext &C,
TranslationUnitDecl *TU);
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ExternCContext; }
@@ -211,18 +243,19 @@ public:
/// NamedDecl - This represents a decl with a name. Many decls have names such
/// as ObjCMethodDecl, but not \@class, etc.
class NamedDecl : public Decl {
- virtual void anchor();
/// Name - The name of this declaration, which is typically a normal
/// identifier but may also be a special kind of name (C++
/// constructor, Objective-C selector, etc.)
DeclarationName Name;
+ virtual void anchor();
+
private:
NamedDecl *getUnderlyingDeclImpl() LLVM_READONLY;
protected:
NamedDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N)
- : Decl(DK, DC, L), Name(N) { }
+ : Decl(DK, DC, L), Name(N) {}
public:
/// getIdentifier - Get the identifier that names this declaration,
@@ -272,8 +305,7 @@ public:
// FIXME: Remove string version.
std::string getQualifiedNameAsString() const;
- /// getNameForDiagnostic - Appends a human-readable name for this
- /// declaration into the given stream.
+ /// Appends a human-readable name for this declaration into the given stream.
///
/// This is the method invoked by Sema when displaying a NamedDecl
/// in a diagnostic. It does not necessarily produce the same
@@ -339,6 +371,12 @@ public:
return clang::isExternallyVisible(getLinkageInternal());
}
+ /// Determine whether this declaration can be redeclared in a
+ /// different translation unit.
+ bool isExternallyDeclarable() const {
+ return isExternallyVisible() && !getOwningModuleForLinkage();
+ }
+
/// \brief Determines the visibility of this entity.
Visibility getVisibility() const {
return getLinkageAndVisibility().getVisibility();
@@ -349,7 +387,14 @@ public:
/// Kinds of explicit visibility.
enum ExplicitVisibilityKind {
+ /// Do an LV computation for, ultimately, a type.
+ /// Visibility may be restricted by type visibility settings and
+ /// the visibility of template arguments.
VisibilityForType,
+
+ /// Do an LV computation for, ultimately, a non-type declaration.
+ /// Visibility may be restricted by value visibility settings and
+ /// the visibility of template arguments.
VisibilityForValue
};
@@ -412,10 +457,10 @@ inline raw_ostream &operator<<(raw_ostream &OS, const NamedDecl &ND) {
/// location of the statement. For GNU local labels (__label__), the decl
/// location is where the __label__ is.
class LabelDecl : public NamedDecl {
- void anchor() override;
LabelStmt *TheStmt;
StringRef MSAsmName;
- bool MSAsmNameResolved;
+ bool MSAsmNameResolved = false;
+
/// 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.
@@ -423,10 +468,9 @@ class LabelDecl : public NamedDecl {
LabelDecl(DeclContext *DC, SourceLocation IdentL, IdentifierInfo *II,
LabelStmt *S, SourceLocation StartL)
- : NamedDecl(Label, DC, IdentL, II),
- TheStmt(S),
- MSAsmNameResolved(false),
- LocStart(StartL) {}
+ : NamedDecl(Label, DC, IdentL, II), TheStmt(S), LocStart(StartL) {}
+
+ void anchor() override;
public:
static LabelDecl *Create(ASTContext &C, DeclContext *DC,
@@ -446,7 +490,7 @@ public:
return SourceRange(LocStart, getLocation());
}
- bool isMSAsmLabel() const { return MSAsmName.size() != 0; }
+ bool isMSAsmLabel() const { return !MSAsmName.empty(); }
bool isResolvedMSAsmLabel() const { return isMSAsmLabel() && MSAsmNameResolved; }
void setMSAsmLabel(StringRef Name);
StringRef getMSAsmLabel() const { return MSAsmName; }
@@ -464,6 +508,7 @@ class NamespaceDecl : public NamedDecl, public DeclContext,
/// LocStart - The starting location of the source range, pointing
/// to either the namespace or the inline keyword.
SourceLocation LocStart;
+
/// RBraceLoc - The ending location of the source range.
SourceLocation RBraceLoc;
@@ -477,12 +522,16 @@ class NamespaceDecl : public NamedDecl, public DeclContext,
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, NamespaceDecl *PrevDecl);
- typedef Redeclarable<NamespaceDecl> redeclarable_base;
+ using redeclarable_base = Redeclarable<NamespaceDecl>;
+
NamespaceDecl *getNextRedeclarationImpl() override;
NamespaceDecl *getPreviousDeclImpl() override;
NamespaceDecl *getMostRecentDeclImpl() override;
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+
static NamespaceDecl *Create(ASTContext &C, DeclContext *DC,
bool Inline, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
@@ -490,8 +539,9 @@ public:
static NamespaceDecl *CreateDeserialized(ASTContext &C, unsigned ID);
- typedef redeclarable_base::redecl_range redecl_range;
- typedef redeclarable_base::redecl_iterator redecl_iterator;
+ using redecl_range = redeclarable_base::redecl_range;
+ using redecl_iterator = redeclarable_base::redecl_iterator;
+
using redeclarable_base::redecls_begin;
using redeclarable_base::redecls_end;
using redeclarable_base::redecls;
@@ -569,22 +619,21 @@ public:
static NamespaceDecl *castFromDeclContext(const DeclContext *DC) {
return static_cast<NamespaceDecl *>(const_cast<DeclContext*>(DC));
}
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
};
/// ValueDecl - Represent the declaration of a variable (in which case it is
/// an lvalue) a function (in which case it is a function designator) or
/// an enum constant.
class ValueDecl : public NamedDecl {
- void anchor() override;
QualType DeclType;
+ void anchor() override;
+
protected:
ValueDecl(Kind DK, DeclContext *DC, SourceLocation L,
DeclarationName N, QualType T)
: NamedDecl(DK, DC, L, N), DeclType(T) {}
+
public:
QualType getType() const { return DeclType; }
void setType(QualType newType) { DeclType = newType; }
@@ -607,28 +656,23 @@ struct QualifierInfo {
/// The count includes all of the template parameter lists that were matched
/// against the template-ids occurring into the NNS and possibly (in the
/// case of an explicit specialization) a final "template <>".
- unsigned NumTemplParamLists;
+ unsigned NumTemplParamLists = 0;
/// TemplParamLists - A new-allocated array of size NumTemplParamLists,
/// containing pointers to the "outer" template parameter lists.
/// It includes all of the template parameter lists that were matched
/// against the template-ids occurring into the NNS and possibly (in the
/// case of an explicit specialization) a final "template <>".
- TemplateParameterList** TemplParamLists;
+ TemplateParameterList** TemplParamLists = nullptr;
- /// Default constructor.
- QualifierInfo()
- : QualifierLoc(), NumTemplParamLists(0), TemplParamLists(nullptr) {}
+ QualifierInfo() = default;
+ QualifierInfo(const QualifierInfo &) = delete;
+ QualifierInfo& operator=(const QualifierInfo &) = delete;
/// setTemplateParameterListsInfo - Sets info about "outer" template
/// parameter lists.
void setTemplateParameterListsInfo(ASTContext &Context,
ArrayRef<TemplateParameterList *> TPLists);
-
-private:
- // Copy constructor and copy assignment are disabled.
- QualifierInfo(const QualifierInfo&) = delete;
- QualifierInfo& operator=(const QualifierInfo&) = delete;
};
/// \brief Represents a ValueDecl that came out of a declarator.
@@ -640,7 +684,7 @@ class DeclaratorDecl : public ValueDecl {
TypeSourceInfo *TInfo;
};
- llvm::PointerUnion<TypeSourceInfo*, ExtInfo*> DeclInfo;
+ llvm::PointerUnion<TypeSourceInfo *, ExtInfo *> DeclInfo;
/// InnerLocStart - The start of the source range for this declaration,
/// ignoring outer template declarations.
@@ -654,15 +698,18 @@ protected:
DeclaratorDecl(Kind DK, DeclContext *DC, SourceLocation L,
DeclarationName N, QualType T, TypeSourceInfo *TInfo,
SourceLocation StartL)
- : ValueDecl(DK, DC, L, N, T), DeclInfo(TInfo), InnerLocStart(StartL) {
- }
+ : ValueDecl(DK, DC, L, N, T), DeclInfo(TInfo), InnerLocStart(StartL) {}
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+
TypeSourceInfo *getTypeSourceInfo() const {
return hasExtInfo()
? getExtInfo()->TInfo
: DeclInfo.get<TypeSourceInfo*>();
}
+
void setTypeSourceInfo(TypeSourceInfo *TI) {
if (hasExtInfo())
getExtInfo()->TInfo = TI;
@@ -680,6 +727,7 @@ public:
SourceLocation getOuterLocStart() const;
SourceRange getSourceRange() const override LLVM_READONLY;
+
SourceLocation getLocStart() const LLVM_READONLY {
return getOuterLocStart();
}
@@ -704,10 +752,12 @@ public:
unsigned getNumTemplateParameterLists() const {
return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0;
}
+
TemplateParameterList *getTemplateParameterList(unsigned index) const {
assert(index < getNumTemplateParameterLists());
return getExtInfo()->TemplParamLists[index];
}
+
void setTemplateParameterListsInfo(ASTContext &Context,
ArrayRef<TemplateParameterList *> TPLists);
@@ -718,18 +768,12 @@ public:
static bool classofKind(Kind K) {
return K >= firstDeclarator && K <= lastDeclarator;
}
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
};
/// \brief Structure used to store a statement, the constant value to
/// which it was evaluated (if any), and whether or not the statement
/// is an integral constant expression (if known).
struct EvaluatedStmt {
- EvaluatedStmt() : WasEvaluated(false), IsEvaluating(false), CheckedICE(false),
- CheckingICE(false), IsICE(false) { }
-
/// \brief Whether this statement was already evaluated.
bool WasEvaluated : 1;
@@ -751,32 +795,46 @@ struct EvaluatedStmt {
Stmt *Value;
APValue Evaluated;
+
+ EvaluatedStmt() : WasEvaluated(false), IsEvaluating(false), CheckedICE(false),
+ CheckingICE(false), IsICE(false) {}
+
};
/// VarDecl - An instance of this class is created to represent a variable
/// declaration or definition.
class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
public:
- /// getStorageClassSpecifierString - Return the string used to
- /// specify the storage class \p SC.
- ///
- /// It is illegal to call this function with SC == None.
- static const char *getStorageClassSpecifierString(StorageClass SC);
-
/// \brief Initialization styles.
enum InitializationStyle {
- CInit, ///< C-style initialization with assignment
- CallInit, ///< Call-style initialization (C++98)
- ListInit ///< Direct list-initialization (C++11)
+ /// C-style initialization with assignment
+ CInit,
+
+ /// Call-style initialization (C++98)
+ CallInit,
+
+ /// Direct list-initialization (C++11)
+ ListInit
};
/// \brief Kinds of thread-local storage.
enum TLSKind {
- TLS_None, ///< Not a TLS variable.
- TLS_Static, ///< TLS with a known-constant initializer.
- TLS_Dynamic ///< TLS with a dynamic initializer.
+ /// Not a TLS variable.
+ TLS_None,
+
+ /// TLS with a known-constant initializer.
+ TLS_Static,
+
+ /// TLS with a dynamic initializer.
+ TLS_Dynamic
};
+ /// getStorageClassSpecifierString - Return the string used to
+ /// specify the storage class \p SC.
+ ///
+ /// It is illegal to call this function with SC == None.
+ static const char *getStorageClassSpecifierString(StorageClass SC);
+
protected:
// A pointer union of Stmt * and EvaluatedStmt *. When an EvaluatedStmt, we
// have allocated the auxiliary struct of information there.
@@ -785,16 +843,20 @@ protected:
// this as *many* VarDecls are ParmVarDecls that don't have default
// arguments. We could save some space by moving this pointer union to be
// allocated in trailing space when necessary.
- typedef llvm::PointerUnion<Stmt *, EvaluatedStmt *> InitType;
+ using InitType = llvm::PointerUnion<Stmt *, EvaluatedStmt *>;
/// \brief The initializer for this variable or, for a ParmVarDecl, the
/// C++ default argument.
mutable InitType Init;
private:
+ friend class ASTDeclReader;
+ friend class ASTNodeImporter;
+ friend class StmtIteratorBase;
+
class VarDeclBitfields {
- friend class VarDecl;
friend class ASTDeclReader;
+ friend class VarDecl;
unsigned SClass : 3;
unsigned TSCSpec : 2;
@@ -802,10 +864,6 @@ private:
};
enum { NumVarDeclBits = 7 };
- friend class ASTDeclReader;
- friend class StmtIteratorBase;
- friend class ASTNodeImporter;
-
protected:
enum { NumParameterIndexBits = 8 };
@@ -817,8 +875,8 @@ protected:
};
class ParmVarDeclBitfields {
- friend class ParmVarDecl;
friend class ASTDeclReader;
+ friend class ParmVarDecl;
unsigned : NumVarDeclBits;
@@ -850,9 +908,9 @@ protected:
};
class NonParmVarDeclBitfields {
- friend class VarDecl;
- friend class ImplicitParamDecl;
friend class ASTDeclReader;
+ friend class ImplicitParamDecl;
+ friend class VarDecl;
unsigned : NumVarDeclBits;
@@ -912,20 +970,24 @@ protected:
SourceLocation IdLoc, IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo, StorageClass SC);
- typedef Redeclarable<VarDecl> redeclarable_base;
+ using redeclarable_base = Redeclarable<VarDecl>;
+
VarDecl *getNextRedeclarationImpl() override {
return getNextRedeclaration();
}
+
VarDecl *getPreviousDeclImpl() override {
return getPreviousDecl();
}
+
VarDecl *getMostRecentDeclImpl() override {
return getMostRecentDecl();
}
public:
- typedef redeclarable_base::redecl_range redecl_range;
- typedef redeclarable_base::redecl_iterator redecl_iterator;
+ using redecl_range = redeclarable_base::redecl_range;
+ using redecl_iterator = redeclarable_base::redecl_iterator;
+
using redeclarable_base::redecls_begin;
using redeclarable_base::redecls_end;
using redeclarable_base::redecls;
@@ -1030,7 +1092,6 @@ public:
/// inside of functions. It also includes variables inside blocks.
///
/// void foo() { int x; static int y; extern int z; }
- ///
bool isLocalVarDecl() const {
if (getKind() != Decl::Var && getKind() != Decl::Decomposition)
return false;
@@ -1073,9 +1134,14 @@ public:
}
enum DefinitionKind {
- DeclarationOnly, ///< This declaration is only a declaration.
- TentativeDefinition, ///< This declaration is a tentative definition.
- Definition ///< This declaration is definitely a definition.
+ /// This declaration is only a declaration.
+ DeclarationOnly,
+
+ /// This declaration is a tentative definition.
+ TentativeDefinition,
+
+ /// This declaration is definitely a definition.
+ Definition
};
/// \brief Check whether this declaration is a definition. If this could be
@@ -1205,6 +1271,7 @@ public:
InitializationStyle getInitStyle() const {
return static_cast<InitializationStyle>(VarDeclBits.InitStyle);
}
+
/// \brief Whether the initializer is a direct-initializer (list or call).
bool isDirectInit() const {
return getInitStyle() != CInit;
@@ -1222,8 +1289,8 @@ public:
/// definitions one of which needs to be demoted to a declaration to keep
/// the AST invariants.
void demoteThisDefinitionToDeclaration() {
- assert (isThisDeclarationADefinition() && "Not a definition!");
- assert (!isa<ParmVarDecl>(this) && "Cannot demote ParmVarDecls!");
+ assert(isThisDeclarationADefinition() && "Not a definition!");
+ assert(!isa<ParmVarDecl>(this) && "Cannot demote ParmVarDecls!");
NonParmVarDeclBits.IsThisDeclarationADemotedDefinition = 1;
}
@@ -1387,12 +1454,23 @@ public:
/// with pointer to 'this', 'self', '_cmd', virtual table pointers, captured
/// context or something else.
enum ImplicitParamKind : unsigned {
- ObjCSelf, /// Parameter for Objective-C 'self' argument
- ObjCCmd, /// Parameter for Objective-C '_cmd' argument
- CXXThis, /// Parameter for C++ 'this' argument
- CXXVTT, /// Parameter for C++ virtual table pointers
- CapturedContext, /// Parameter for captured context
- Other, /// Other implicit parameter
+ /// Parameter for Objective-C 'self' argument
+ ObjCSelf,
+
+ /// Parameter for Objective-C '_cmd' argument
+ ObjCCmd,
+
+ /// Parameter for C++ 'this' argument
+ CXXThis,
+
+ /// Parameter for C++ virtual table pointers
+ CXXVTT,
+
+ /// Parameter for captured context
+ CapturedContext,
+
+ /// Other implicit parameter
+ Other,
};
/// Create implicit parameter.
@@ -1425,6 +1503,7 @@ public:
ImplicitParamKind getParameterKind() const {
return static_cast<ImplicitParamKind>(NonParmVarDeclBits.ImplicitParamKind);
}
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ImplicitParam; }
@@ -1604,8 +1683,8 @@ private:
unsigned getParameterIndexLarge() const;
};
-/// FunctionDecl - An instance of this class is created to represent a
-/// function declaration or definition.
+/// An instance of this class is created to represent a function declaration or
+/// definition.
///
/// Since a given function can be declared several times in a program,
/// there may be several FunctionDecls that correspond to that
@@ -1631,7 +1710,7 @@ private:
/// ParamInfo - new[]'d array of pointers to VarDecls for the formal
/// parameters of this function. This is null if a prototype or if there are
/// no formals.
- ParmVarDecl **ParamInfo;
+ ParmVarDecl **ParamInfo = nullptr;
LazyDeclStmtPtr Body;
@@ -1640,10 +1719,12 @@ private:
unsigned SClass : 3;
unsigned IsInline : 1;
unsigned IsInlineSpecified : 1;
+
protected:
// This is shared by CXXConstructorDecl, CXXConversionDecl, and
// CXXDeductionGuideDecl.
unsigned IsExplicitSpecified : 1;
+
private:
unsigned IsVirtualAsWritten : 1;
unsigned IsPure : 1;
@@ -1656,7 +1737,7 @@ private:
unsigned HasImplicitReturnZero : 1;
unsigned IsLateTemplateParsed : 1;
unsigned IsConstexpr : 1;
- unsigned InstantiationIsPending:1;
+ unsigned InstantiationIsPending : 1;
/// \brief Indicates if the function uses __try.
unsigned UsesSEHTry : 1;
@@ -1669,6 +1750,15 @@ private:
/// parsing it.
unsigned WillHaveBody : 1;
+protected:
+ /// [C++17] Only used by CXXDeductionGuideDecl. Declared here to avoid
+ /// increasing the size of CXXDeductionGuideDecl by the size of an unsigned
+ /// int as opposed to adding a single bit to FunctionDecl.
+ /// Indicates that the Deduction Guide is the implicitly generated 'copy
+ /// deduction candidate' (is used during overload resolution).
+ unsigned IsCopyDeductionCandidate : 1;
+
+private:
/// \brief End part of this FunctionDecl's source range.
///
/// We could compute the full range in getSourceRange(). However, when we're
@@ -1696,8 +1786,8 @@ private:
DependentFunctionTemplateSpecializationInfo *>
TemplateOrSpecialization;
- /// DNLoc - Provides source/type location info for the
- /// declaration name embedded in the DeclaratorDecl base class.
+ /// Provides source/type location info for the declaration name embedded in
+ /// the DeclaratorDecl base class.
DeclarationNameLoc DNLoc;
/// \brief Specify that this function declaration is actually a function
@@ -1743,33 +1833,38 @@ protected:
bool isConstexprSpecified)
: DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo,
StartLoc),
- DeclContext(DK), redeclarable_base(C), ParamInfo(nullptr), Body(),
- SClass(S), IsInline(isInlineSpecified),
- IsInlineSpecified(isInlineSpecified), IsExplicitSpecified(false),
- IsVirtualAsWritten(false), IsPure(false),
+ DeclContext(DK), redeclarable_base(C), SClass(S),
+ IsInline(isInlineSpecified), IsInlineSpecified(isInlineSpecified),
+ IsExplicitSpecified(false), IsVirtualAsWritten(false), IsPure(false),
HasInheritedPrototype(false), HasWrittenPrototype(true),
IsDeleted(false), IsTrivial(false), IsDefaulted(false),
IsExplicitlyDefaulted(false), HasImplicitReturnZero(false),
IsLateTemplateParsed(false), IsConstexpr(isConstexprSpecified),
- InstantiationIsPending(false),
- UsesSEHTry(false), HasSkippedBody(false), WillHaveBody(false),
- EndRangeLoc(NameInfo.getEndLoc()), TemplateOrSpecialization(),
- DNLoc(NameInfo.getInfo()) {}
+ InstantiationIsPending(false), UsesSEHTry(false), HasSkippedBody(false),
+ WillHaveBody(false), IsCopyDeductionCandidate(false),
+ EndRangeLoc(NameInfo.getEndLoc()), DNLoc(NameInfo.getInfo()) {}
+
+ using redeclarable_base = Redeclarable<FunctionDecl>;
- typedef Redeclarable<FunctionDecl> redeclarable_base;
FunctionDecl *getNextRedeclarationImpl() override {
return getNextRedeclaration();
}
+
FunctionDecl *getPreviousDeclImpl() override {
return getPreviousDecl();
}
+
FunctionDecl *getMostRecentDeclImpl() override {
return getMostRecentDecl();
}
public:
- typedef redeclarable_base::redecl_range redecl_range;
- typedef redeclarable_base::redecl_iterator redecl_iterator;
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+
+ using redecl_range = redeclarable_base::redecl_range;
+ using redecl_iterator = redeclarable_base::redecl_iterator;
+
using redeclarable_base::redecls_begin;
using redeclarable_base::redecls_end;
using redeclarable_base::redecls;
@@ -1826,13 +1921,13 @@ public:
return hasBody(Definition);
}
- /// hasTrivialBody - Returns whether the function has a trivial body that does
- /// not require any specific codegen.
+ /// Returns whether the function has a trivial body that does not require any
+ /// specific codegen.
bool hasTrivialBody() const;
- /// isDefined - Returns true if the function is defined at all, including
- /// a deleted definition. Except for the behavior when the function is
- /// deleted, behaves like hasBody.
+ /// Returns true if the function is defined at all, including a deleted
+ /// definition. Except for the behavior when the function is deleted, behaves
+ /// like hasBody.
bool isDefined(const FunctionDecl *&Definition) const;
virtual bool isDefined() const {
@@ -1851,11 +1946,10 @@ public:
return const_cast<FunctionDecl *>(this)->getDefinition();
}
- /// getBody - Retrieve the body (definition) of the function. The
- /// function body might be in any of the (re-)declarations of this
- /// function. The variant that accepts a FunctionDecl pointer will
- /// set that function declaration to the actual declaration
- /// containing the body (if there is one).
+ /// Retrieve the body (definition) of the function. The function body might be
+ /// in any of the (re-)declarations of this function. The variant that accepts
+ /// a FunctionDecl pointer will set that function declaration to the actual
+ /// declaration containing the body (if there is one).
/// NOTE: For checking if there is a body, use hasBody() instead, to avoid
/// unnecessary AST de-serialization of the body.
Stmt *getBody(const FunctionDecl *&Definition) const;
@@ -1870,15 +1964,13 @@ public:
///
/// This does not determine whether the function has been defined (e.g., in a
/// previous definition); for that information, use isDefined.
- ///
bool isThisDeclarationADefinition() const {
- return IsDeleted || IsDefaulted || Body || IsLateTemplateParsed ||
- WillHaveBody || hasDefiningAttr();
+ return IsDeleted || IsDefaulted || Body || HasSkippedBody ||
+ IsLateTemplateParsed || WillHaveBody || hasDefiningAttr();
}
- /// doesThisDeclarationHaveABody - Returns whether this specific
- /// declaration of the function has a body - that is, if it is a non-
- /// deleted definition.
+ /// Returns whether this specific declaration of the function has a body -
+ /// that is, if it is a non-deleted definition.
bool doesThisDeclarationHaveABody() const {
return Body || IsLateTemplateParsed;
}
@@ -2023,6 +2115,9 @@ public:
/// true through IsAligned.
bool isReplaceableGlobalAllocationFunction(bool *IsAligned = nullptr) const;
+ /// \brief Determine whether this is a destroying operator delete.
+ bool isDestroyingOperatorDelete() const;
+
/// Compute the language linkage.
LanguageLinkage getLanguageLinkage() const;
@@ -2071,8 +2166,9 @@ public:
}
// Iterator access to formal parameters.
- typedef MutableArrayRef<ParmVarDecl *>::iterator param_iterator;
- typedef ArrayRef<ParmVarDecl *>::const_iterator param_const_iterator;
+ using param_iterator = MutableArrayRef<ParmVarDecl *>::iterator;
+ using param_const_iterator = ArrayRef<ParmVarDecl *>::const_iterator;
+
bool param_empty() const { return parameters().empty(); }
param_iterator param_begin() { return parameters().begin(); }
param_iterator param_end() { return parameters().end(); }
@@ -2080,9 +2176,9 @@ public:
param_const_iterator param_end() const { return parameters().end(); }
size_t param_size() const { return parameters().size(); }
- /// getNumParams - Return the number of parameters this function must have
- /// based on its FunctionType. This is the length of the ParamInfo array
- /// after it has been created.
+ /// Return the number of parameters this function must have based on its
+ /// FunctionType. This is the length of the ParamInfo array after it has been
+ /// created.
unsigned getNumParams() const;
const ParmVarDecl *getParamDecl(unsigned i) const {
@@ -2097,10 +2193,9 @@ public:
setParams(getASTContext(), NewParamInfo);
}
- /// getMinRequiredArguments - Returns the minimum number of arguments
- /// needed to call this function. This may be fewer than the number of
- /// function parameters, if some of the parameters have default
- /// arguments (in C++).
+ /// Returns the minimum number of arguments needed to call this function. This
+ /// may be fewer than the number of function parameters, if some of the
+ /// parameters have default arguments (in C++).
unsigned getMinRequiredArguments() const;
QualType getReturnType() const {
@@ -2355,18 +2450,14 @@ public:
static FunctionDecl *castFromDeclContext(const DeclContext *DC) {
return static_cast<FunctionDecl *>(const_cast<DeclContext*>(DC));
}
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
};
-
/// FieldDecl - An instance of this class is created by Sema::ActOnField to
/// represent a member of a struct/union/class.
class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> {
- // FIXME: This can be packed into the bitfields in Decl.
+ unsigned BitField : 1;
unsigned Mutable : 1;
- mutable unsigned CachedFieldIndex : 31;
+ mutable unsigned CachedFieldIndex : 30;
/// The kinds of value we can store in InitializerOrBitWidth.
///
@@ -2376,7 +2467,7 @@ class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> {
/// 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,
+ ISK_NoInit = (unsigned) ICIS_NoInit,
/// The pointer is an (optional due to delayed parsing) Expr*
/// holding the copy-initializer.
@@ -2391,30 +2482,40 @@ class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> {
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 this is a bitfield with a default member initializer, this
+ /// structure is used to represent the two expressions.
+ struct InitAndBitWidth {
+ Expr *Init;
+ Expr *BitWidth;
+ };
+
+ /// \brief Storage for either the bit-width, the in-class initializer, or
+ /// both (via InitAndBitWidth), or the captured variable length array bound.
///
/// 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
+ /// field has an in-class initializer that has not yet been parsed
/// and attached.
+ // FIXME: Tail-allocate this to reduce the size of FieldDecl in the
+ // overwhelmingly common case that we have none of these things.
llvm::PointerIntPair<void *, 2, InitStorageKind> InitStorage;
+
protected:
FieldDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable,
InClassInitStyle InitStyle)
: DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc),
- Mutable(Mutable), CachedFieldIndex(0),
- InitStorage(BW, (InitStorageKind) InitStyle) {
- assert((!BW || InitStyle == ICIS_NoInit) && "got initializer for bitfield");
+ BitField(false), Mutable(Mutable), CachedFieldIndex(0),
+ InitStorage(nullptr, (InitStorageKind) InitStyle) {
+ if (BW)
+ setBitWidth(BW);
}
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+
static FieldDecl *Create(const ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, QualType T,
@@ -2431,10 +2532,7 @@ public:
bool isMutable() const { return Mutable; }
/// \brief Determines whether this field is a bitfield.
- bool isBitField() const {
- return InitStorage.getInt() == ISK_BitWidthOrNothing &&
- InitStorage.getPointer() != nullptr;
- }
+ bool isBitField() const { return BitField; }
/// @brief Determines whether this is an unnamed bitfield.
bool isUnnamedBitfield() const { return isBitField() && !getDeclName(); }
@@ -2446,66 +2544,77 @@ public:
bool isAnonymousStructOrUnion() const;
Expr *getBitWidth() const {
- return isBitField()
- ? static_cast<Expr *>(InitStorage.getPointer())
- : nullptr;
+ if (!BitField)
+ return nullptr;
+ void *Ptr = InitStorage.getPointer();
+ if (getInClassInitStyle())
+ return static_cast<InitAndBitWidth*>(Ptr)->BitWidth;
+ return static_cast<Expr*>(Ptr);
}
+
unsigned getBitWidthValue(const ASTContext &Ctx) const;
/// setBitWidth - Set the bit-field width for this member.
// Note: used by some clients (i.e., do not remove it).
void setBitWidth(Expr *Width) {
- assert(InitStorage.getInt() == ISK_BitWidthOrNothing &&
- InitStorage.getPointer() == nullptr &&
- "bit width, initializer or captured type already set");
- InitStorage.setPointerAndInt(Width, ISK_BitWidthOrNothing);
+ assert(!hasCapturedVLAType() && !BitField &&
+ "bit width or captured type already set");
+ assert(Width && "no bit width specified");
+ InitStorage.setPointer(
+ InitStorage.getInt()
+ ? new (getASTContext())
+ InitAndBitWidth{getInClassInitializer(), Width}
+ : static_cast<void*>(Width));
+ BitField = true;
}
/// removeBitWidth - Remove the bit-field width from this member.
// Note: used by some clients (i.e., do not remove it).
void removeBitWidth() {
assert(isBitField() && "no bitfield width to remove");
- InitStorage.setPointerAndInt(nullptr, ISK_BitWidthOrNothing);
+ InitStorage.setPointer(getInClassInitializer());
+ BitField = false;
}
- /// getInClassInitStyle - Get the kind of (C++11) in-class initializer which
- /// this field has.
+ /// Get the kind of (C++11) default member initializer that this field has.
InClassInitStyle getInClassInitStyle() const {
InitStorageKind storageKind = InitStorage.getInt();
return (storageKind == ISK_CapturedVLAType
? ICIS_NoInit : (InClassInitStyle) storageKind);
}
- /// hasInClassInitializer - Determine whether this member has a C++11 in-class
- /// initializer.
+ /// Determine whether this member has a C++11 default member initializer.
bool hasInClassInitializer() const {
return getInClassInitStyle() != ICIS_NoInit;
}
- /// getInClassInitializer - Get the C++11 in-class initializer for this
- /// member, or null if one has not been set. If a valid declaration has an
- /// in-class initializer, but this returns null, then we have not parsed and
- /// attached it yet.
+ /// Get the C++11 default member initializer for this member, or null if one
+ /// has not been set. If a valid declaration has a default member initializer,
+ /// but this returns null, then we have not parsed and attached it yet.
Expr *getInClassInitializer() const {
- return hasInClassInitializer()
- ? static_cast<Expr *>(InitStorage.getPointer())
- : nullptr;
+ if (!hasInClassInitializer())
+ return nullptr;
+ void *Ptr = InitStorage.getPointer();
+ if (BitField)
+ return static_cast<InitAndBitWidth*>(Ptr)->Init;
+ return static_cast<Expr*>(Ptr);
}
/// setInClassInitializer - Set the C++11 in-class initializer for this
/// member.
void setInClassInitializer(Expr *Init) {
- assert(hasInClassInitializer() &&
- InitStorage.getPointer() == nullptr &&
- "bit width, initializer or captured type already set");
- InitStorage.setPointer(Init);
+ assert(hasInClassInitializer() && !getInClassInitializer());
+ if (BitField)
+ static_cast<InitAndBitWidth*>(InitStorage.getPointer())->Init = Init;
+ else
+ InitStorage.setPointer(Init);
}
/// removeInClassInitializer - Remove the C++11 in-class initializer from this
/// member.
void removeInClassInitializer() {
assert(hasInClassInitializer() && "no initializer to remove");
- InitStorage.setPointerAndInt(nullptr, ISK_BitWidthOrNothing);
+ InitStorage.setPointerAndInt(getBitWidth(), ISK_NoInit);
}
/// \brief Determine whether this member captures the variable length array
@@ -2520,6 +2629,7 @@ public:
InitStorage.getPointer())
: nullptr;
}
+
/// \brief Set the captured variable length array type for this field.
void setCapturedVLAType(const VariableArrayType *VLAType);
@@ -2542,9 +2652,6 @@ public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K >= firstField && K <= lastField; }
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
};
/// EnumConstantDecl - An instance of this object exists for each enum constant
@@ -2554,6 +2661,7 @@ public:
class EnumConstantDecl : public ValueDecl, public Mergeable<EnumConstantDecl> {
Stmt *Init; // an integer constant expression
llvm::APSInt Val; // The value.
+
protected:
EnumConstantDecl(DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType T, Expr *E,
@@ -2561,6 +2669,7 @@ protected:
: ValueDecl(EnumConstant, DC, L, Id, T), Init((Stmt*)E), Val(V) {}
public:
+ friend class StmtIteratorBase;
static EnumConstantDecl *Create(ASTContext &C, EnumDecl *DC,
SourceLocation L, IdentifierInfo *Id,
@@ -2584,8 +2693,6 @@ public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == EnumConstant; }
-
- friend class StmtIteratorBase;
};
/// IndirectFieldDecl - An instance of this class is created to represent a
@@ -2593,7 +2700,6 @@ public:
/// IndirectFieldDecl are always implicit.
class IndirectFieldDecl : public ValueDecl,
public Mergeable<IndirectFieldDecl> {
- void anchor() override;
NamedDecl **Chaining;
unsigned ChainingSize;
@@ -2601,14 +2707,18 @@ class IndirectFieldDecl : public ValueDecl,
DeclarationName N, QualType T,
MutableArrayRef<NamedDecl *> CH);
+ void anchor() override;
+
public:
+ friend class ASTDeclReader;
+
static IndirectFieldDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
QualType T, llvm::MutableArrayRef<NamedDecl *> CH);
static IndirectFieldDecl *CreateDeserialized(ASTContext &C, unsigned ID);
- typedef ArrayRef<NamedDecl *>::const_iterator chain_iterator;
+ using chain_iterator = ArrayRef<NamedDecl *>::const_iterator;
ArrayRef<NamedDecl *> chain() const {
return llvm::makeArrayRef(Chaining, ChainingSize);
@@ -2634,26 +2744,27 @@ public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == IndirectField; }
- friend class ASTDeclReader;
};
/// TypeDecl - Represents a declaration of a type.
-///
class TypeDecl : public NamedDecl {
- void anchor() override;
+ friend class ASTContext;
+
/// TypeForDecl - This indicates the Type object that represents
/// this TypeDecl. It is a cache maintained by
/// ASTContext::getTypedefType, ASTContext::getTagDeclType, and
/// ASTContext::getTemplateTypeParmType, and TemplateTypeParmDecl.
- mutable const Type *TypeForDecl;
+ mutable const Type *TypeForDecl = nullptr;
+
/// LocStart - The start of the source range for this declaration.
SourceLocation LocStart;
- friend class ASTContext;
+
+ void anchor() override;
protected:
TypeDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
SourceLocation StartL = SourceLocation())
- : NamedDecl(DK, DC, L, Id), TypeForDecl(nullptr), LocStart(StartL) {}
+ : NamedDecl(DK, DC, L, Id), LocStart(StartL) {}
public:
// Low-level accessor. If you just want the type defined by this node,
@@ -2677,18 +2788,18 @@ public:
static bool classofKind(Kind K) { return K >= firstType && K <= lastType; }
};
-
/// Base class for declarations which introduce a typedef-name.
class TypedefNameDecl : public TypeDecl, public Redeclarable<TypedefNameDecl> {
- void anchor() override;
- typedef std::pair<TypeSourceInfo*, QualType> ModedTInfo;
- llvm::PointerUnion<TypeSourceInfo*, ModedTInfo*> MaybeModedTInfo;
+ using ModedTInfo = std::pair<TypeSourceInfo *, QualType>;
+ llvm::PointerUnion<TypeSourceInfo *, ModedTInfo *> MaybeModedTInfo;
// FIXME: This can be packed into the bitfields in Decl.
/// If 0, we have not computed IsTransparentTag.
/// Otherwise, IsTransparentTag is (CacheIsTransparentTag >> 1).
mutable unsigned CacheIsTransparentTag : 2;
+ void anchor() override;
+
protected:
TypedefNameDecl(Kind DK, ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
@@ -2696,20 +2807,24 @@ protected:
: TypeDecl(DK, DC, IdLoc, Id, StartLoc), redeclarable_base(C),
MaybeModedTInfo(TInfo), CacheIsTransparentTag(0) {}
- typedef Redeclarable<TypedefNameDecl> redeclarable_base;
+ using redeclarable_base = Redeclarable<TypedefNameDecl>;
+
TypedefNameDecl *getNextRedeclarationImpl() override {
return getNextRedeclaration();
}
+
TypedefNameDecl *getPreviousDeclImpl() override {
return getPreviousDecl();
}
+
TypedefNameDecl *getMostRecentDeclImpl() override {
return getMostRecentDecl();
}
public:
- typedef redeclarable_base::redecl_range redecl_range;
- typedef redeclarable_base::redecl_iterator redecl_iterator;
+ using redecl_range = redeclarable_base::redecl_range;
+ using redecl_iterator = redeclarable_base::redecl_iterator;
+
using redeclarable_base::redecls_begin;
using redeclarable_base::redecls_end;
using redeclarable_base::redecls;
@@ -2724,14 +2839,17 @@ public:
? MaybeModedTInfo.get<ModedTInfo*>()->first
: MaybeModedTInfo.get<TypeSourceInfo*>();
}
+
QualType getUnderlyingType() const {
return isModed()
? MaybeModedTInfo.get<ModedTInfo*>()->second
: MaybeModedTInfo.get<TypeSourceInfo*>()->getType();
}
+
void setTypeSourceInfo(TypeSourceInfo *newType) {
MaybeModedTInfo = newType;
}
+
void setModedTypeSourceInfo(TypeSourceInfo *unmodedTSI, QualType modedTy) {
MaybeModedTInfo = new (getASTContext()) ModedTInfo(unmodedTSI, modedTy);
}
@@ -2817,7 +2935,7 @@ class TagDecl
: public TypeDecl, public DeclContext, public Redeclarable<TagDecl> {
public:
// This is really ugly.
- typedef TagTypeKind TagKind;
+ using TagKind = TagTypeKind;
private:
// FIXME: This can be packed into the bitfields in Decl.
@@ -2850,6 +2968,7 @@ protected:
/// IsScoped - True if this tag declaration is a scoped enumeration. Only
/// possible in C++11 mode.
unsigned IsScoped : 1;
+
/// IsScopedUsingClassTag - If this tag declaration is a scoped enum,
/// then this is true if the scoped enum was declared using the class
/// tag, false if it was declared with the struct tag. No meaning is
@@ -2869,12 +2988,13 @@ protected:
/// Has the full definition of this type been required by a use somewhere in
/// the TU.
unsigned IsCompleteDefinitionRequired : 1;
+
private:
SourceRange BraceRange;
// A struct representing syntactic qualifier info,
// to be used for the (uncommon) case of out-of-line declarations.
- typedef QualifierInfo ExtInfo;
+ using ExtInfo = QualifierInfo;
/// \brief If the (out-of-line) tag declaration name
/// is qualified, it points to the qualifier info (nns and range);
@@ -2906,13 +3026,16 @@ protected:
setPreviousDecl(PrevDecl);
}
- typedef Redeclarable<TagDecl> redeclarable_base;
+ using redeclarable_base = Redeclarable<TagDecl>;
+
TagDecl *getNextRedeclarationImpl() override {
return getNextRedeclaration();
}
+
TagDecl *getPreviousDeclImpl() override {
return getPreviousDecl();
}
+
TagDecl *getMostRecentDeclImpl() override {
return getMostRecentDecl();
}
@@ -2923,8 +3046,12 @@ protected:
void completeDefinition();
public:
- typedef redeclarable_base::redecl_range redecl_range;
- typedef redeclarable_base::redecl_iterator redecl_iterator;
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+
+ using redecl_range = redeclarable_base::redecl_range;
+ using redecl_iterator = redeclarable_base::redecl_iterator;
+
using redeclarable_base::redecls_begin;
using redeclarable_base::redecls_end;
using redeclarable_base::redecls;
@@ -3074,10 +3201,12 @@ public:
unsigned getNumTemplateParameterLists() const {
return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0;
}
+
TemplateParameterList *getTemplateParameterList(unsigned i) const {
assert(i < getNumTemplateParameterLists());
return getExtInfo()->TemplParamLists[i];
}
+
void setTemplateParameterListsInfo(ASTContext &Context,
ArrayRef<TemplateParameterList *> TPLists);
@@ -3088,19 +3217,16 @@ public:
static DeclContext *castToDeclContext(const TagDecl *D) {
return static_cast<DeclContext *>(const_cast<TagDecl*>(D));
}
+
static TagDecl *castFromDeclContext(const DeclContext *DC) {
return static_cast<TagDecl *>(const_cast<DeclContext*>(DC));
}
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
};
/// EnumDecl - Represents an enum. In C++11, enums can be forward-declared
/// with a fixed underlying type, and in C we allow them to be forward-declared
/// with no underlying type as an extension.
class EnumDecl : public TagDecl {
- void anchor() override;
/// IntegerType - This represent the integer type that the enum corresponds
/// to for code generation purposes. Note that the enumerator constants may
/// have a different type than this does.
@@ -3115,8 +3241,7 @@ class EnumDecl : public TagDecl {
/// The underlying type of an enumeration never has any qualifiers, so
/// we can get away with just storing a raw Type*, and thus save an
/// extra pointer when TypeSourceInfo is needed.
-
- llvm::PointerUnion<const Type*, TypeSourceInfo*> IntegerType;
+ llvm::PointerUnion<const Type *, TypeSourceInfo *> IntegerType;
/// PromotionType - The integer type that values of this type should
/// promote to. In C, enumerators are generally of an integer type
@@ -3127,13 +3252,12 @@ class EnumDecl : public TagDecl {
/// \brief If this enumeration is an instantiation of a member enumeration
/// of a class template specialization, this is the member specialization
/// information.
- MemberSpecializationInfo *SpecializationInfo;
+ MemberSpecializationInfo *SpecializationInfo = nullptr;
EnumDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id, EnumDecl *PrevDecl,
bool Scoped, bool ScopedUsingClassTag, bool Fixed)
- : TagDecl(Enum, TTK_Enum, C, DC, IdLoc, Id, PrevDecl, StartLoc),
- SpecializationInfo(nullptr) {
+ : TagDecl(Enum, TTK_Enum, C, DC, IdLoc, Id, PrevDecl, StartLoc) {
assert(Scoped || !ScopedUsingClassTag);
IntegerType = (const Type *)nullptr;
NumNegativeBits = 0;
@@ -3143,9 +3267,13 @@ class EnumDecl : public TagDecl {
IsFixed = Fixed;
}
+ void anchor() override;
+
void setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED,
TemplateSpecializationKind TSK);
public:
+ friend class ASTDeclReader;
+
EnumDecl *getCanonicalDecl() override {
return cast<EnumDecl>(TagDecl::getCanonicalDecl());
}
@@ -3191,9 +3319,9 @@ public:
// enumerator_iterator - Iterates through the enumerators of this
// enumeration.
- typedef specific_decl_iterator<EnumConstantDecl> enumerator_iterator;
- typedef llvm::iterator_range<specific_decl_iterator<EnumConstantDecl>>
- enumerator_range;
+ using enumerator_iterator = specific_decl_iterator<EnumConstantDecl>;
+ using enumerator_range =
+ llvm::iterator_range<specific_decl_iterator<EnumConstantDecl>>;
enumerator_range enumerators() const {
return enumerator_range(enumerator_begin(), enumerator_end());
@@ -3341,17 +3469,15 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Enum; }
-
- friend class ASTDeclReader;
};
-
/// RecordDecl - Represents a struct/union/class. For example:
/// struct X; // Forward declaration, no "body".
/// union Y { int A, B; }; // Has body with members A and B (FieldDecls).
/// This decl will be marked invalid if *any* members are invalid.
-///
class RecordDecl : public TagDecl {
+ friend class DeclContext;
+
// FIXME: This can be packed into the bitfields in Decl.
/// HasFlexibleArrayMember - This is true if this struct ends with a flexible
/// array member (e.g. int X[]) or if this union contains a struct that does.
@@ -3375,7 +3501,6 @@ class RecordDecl : public TagDecl {
/// methods/nested types we allow deserialization of just the fields
/// when needed.
mutable bool LoadedFieldsFromExternalStorage : 1;
- friend class DeclContext;
protected:
RecordDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC,
@@ -3458,6 +3583,7 @@ public:
/// \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();
@@ -3477,8 +3603,8 @@ public:
// Iterator access to field members. The field iterator only visits
// the non-static data members of this class, ignoring any static
// data members, functions, constructors, destructors, etc.
- typedef specific_decl_iterator<FieldDecl> field_iterator;
- typedef llvm::iterator_range<specific_decl_iterator<FieldDecl>> field_range;
+ using field_iterator = specific_decl_iterator<FieldDecl>;
+ using field_range = llvm::iterator_range<specific_decl_iterator<FieldDecl>>;
field_range fields() const { return field_range(field_begin(), field_end()); }
field_iterator field_begin() const;
@@ -3502,7 +3628,7 @@ public:
return K >= firstRecord && K <= lastRecord;
}
- /// isMsStrust - Get whether or not this is an ms_struct which can
+ /// \brief Get whether or not this is an ms_struct which can
/// be turned on with an attribute, pragma, or -mms-bitfields
/// commandline option.
bool isMsStruct(const ASTContext &C) const;
@@ -3522,12 +3648,15 @@ private:
};
class FileScopeAsmDecl : public Decl {
- virtual void anchor();
StringLiteral *AsmString;
SourceLocation RParenLoc;
+
FileScopeAsmDecl(DeclContext *DC, StringLiteral *asmstring,
SourceLocation StartL, SourceLocation EndL)
: Decl(FileScopeAsm, DC, StartL), AsmString(asmstring), RParenLoc(EndL) {}
+
+ virtual void anchor();
+
public:
static FileScopeAsmDecl *Create(ASTContext &C, DeclContext *DC,
StringLiteral *Str, SourceLocation AsmLoc,
@@ -3553,7 +3682,6 @@ public:
/// BlockDecl - This represents a block literal declaration, which is like an
/// unnamed FunctionDecl. For example:
/// ^{ statement-body } or ^(int arg1, float arg2){ statement-body }
-///
class BlockDecl : public Decl, public DeclContext {
public:
/// A class which contains all the information about a particular
@@ -3600,29 +3728,27 @@ private:
bool CapturesCXXThis : 1;
bool BlockMissingReturnType : 1;
bool IsConversionFromLambda : 1;
+
/// ParamInfo - new[]'d array of pointers to ParmVarDecls for the formal
/// parameters of this function. This is null if a prototype or if there are
/// no formals.
- ParmVarDecl **ParamInfo;
- unsigned NumParams;
+ ParmVarDecl **ParamInfo = nullptr;
+ unsigned NumParams = 0;
- Stmt *Body;
- TypeSourceInfo *SignatureAsWritten;
+ Stmt *Body = nullptr;
+ TypeSourceInfo *SignatureAsWritten = nullptr;
- const Capture *Captures;
- unsigned NumCaptures;
+ const Capture *Captures = nullptr;
+ unsigned NumCaptures = 0;
- unsigned ManglingNumber;
- Decl *ManglingContextDecl;
+ unsigned ManglingNumber = 0;
+ Decl *ManglingContextDecl = nullptr;
protected:
BlockDecl(DeclContext *DC, SourceLocation CaretLoc)
- : Decl(Block, DC, CaretLoc), DeclContext(Block),
- IsVariadic(false), CapturesCXXThis(false),
- BlockMissingReturnType(true), IsConversionFromLambda(false),
- ParamInfo(nullptr), NumParams(0), Body(nullptr),
- SignatureAsWritten(nullptr), Captures(nullptr), NumCaptures(0),
- ManglingNumber(0), ManglingContextDecl(nullptr) {}
+ : Decl(Block, DC, CaretLoc), DeclContext(Block), IsVariadic(false),
+ CapturesCXXThis(false), BlockMissingReturnType(true),
+ IsConversionFromLambda(false) {}
public:
static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L);
@@ -3649,8 +3775,9 @@ public:
}
// Iterator access to formal parameters.
- typedef MutableArrayRef<ParmVarDecl *>::iterator param_iterator;
- typedef ArrayRef<ParmVarDecl *>::const_iterator param_const_iterator;
+ using param_iterator = MutableArrayRef<ParmVarDecl *>::iterator;
+ using param_const_iterator = ArrayRef<ParmVarDecl *>::const_iterator;
+
bool param_empty() const { return parameters().empty(); }
param_iterator param_begin() { return parameters().begin(); }
param_iterator param_end() { return parameters().end(); }
@@ -3659,6 +3786,7 @@ public:
size_t param_size() const { return parameters().size(); }
unsigned getNumParams() const { return NumParams; }
+
const ParmVarDecl *getParamDecl(unsigned i) const {
assert(i < getNumParams() && "Illegal param #");
return ParamInfo[i];
@@ -3667,6 +3795,7 @@ public:
assert(i < getNumParams() && "Illegal param #");
return ParamInfo[i];
}
+
void setParams(ArrayRef<ParmVarDecl *> NewParamInfo);
/// hasCaptures - True if this block (or its nested blocks) captures
@@ -3677,7 +3806,7 @@ public:
/// Does not include an entry for 'this'.
unsigned getNumCaptures() const { return NumCaptures; }
- typedef ArrayRef<Capture>::const_iterator capture_const_iterator;
+ using capture_const_iterator = ArrayRef<Capture>::const_iterator;
ArrayRef<Capture> captures() const { return {Captures, NumCaptures}; }
@@ -3699,6 +3828,7 @@ public:
unsigned getBlockManglingNumber() const {
return ManglingNumber;
}
+
Decl *getBlockManglingContextDecl() const {
return ManglingContextDecl;
}
@@ -3735,8 +3865,10 @@ protected:
private:
/// \brief The number of parameters to the outlined function.
unsigned NumParams;
+
/// \brief The position of context parameter in list of parameters.
unsigned ContextParam;
+
/// \brief The body of the outlined function.
llvm::PointerIntPair<Stmt *, 1, bool> BodyAndNothrow;
@@ -3751,6 +3883,10 @@ private:
}
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+ friend TrailingObjects;
+
static CapturedDecl *Create(ASTContext &C, DeclContext *DC,
unsigned NumParams);
static CapturedDecl *CreateDeserialized(ASTContext &C, unsigned ID,
@@ -3793,8 +3929,8 @@ public:
}
unsigned getContextParamPosition() const { return ContextParam; }
- typedef ImplicitParamDecl *const *param_iterator;
- typedef llvm::iterator_range<param_iterator> param_range;
+ using param_iterator = ImplicitParamDecl *const *;
+ using param_range = llvm::iterator_range<param_iterator>;
/// \brief Retrieve an iterator pointing to the first parameter decl.
param_iterator param_begin() const { return getParams(); }
@@ -3810,10 +3946,6 @@ public:
static CapturedDecl *castFromDeclContext(const DeclContext *DC) {
return static_cast<CapturedDecl *>(const_cast<DeclContext *>(DC));
}
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
- friend TrailingObjects;
};
/// \brief Describes a module import declaration, which makes the contents
@@ -3828,6 +3960,11 @@ public:
/// \#include/\#import directives.
class ImportDecl final : public Decl,
llvm::TrailingObjects<ImportDecl, SourceLocation> {
+ friend class ASTContext;
+ friend class ASTDeclReader;
+ friend class ASTReader;
+ friend TrailingObjects;
+
/// \brief The imported module, along with a bit that indicates whether
/// we have source-location information for each identifier in the module
/// name.
@@ -3838,20 +3975,15 @@ class ImportDecl final : public Decl,
/// \brief The next import in the list of imports local to the translation
/// unit being parsed (not loaded from an AST file).
- ImportDecl *NextLocalImport;
+ ImportDecl *NextLocalImport = nullptr;
- friend class ASTReader;
- friend class ASTDeclReader;
- friend class ASTContext;
- friend TrailingObjects;
-
ImportDecl(DeclContext *DC, SourceLocation StartLoc, Module *Imported,
ArrayRef<SourceLocation> IdentifierLocs);
ImportDecl(DeclContext *DC, SourceLocation StartLoc, Module *Imported,
SourceLocation EndLoc);
- ImportDecl(EmptyShell Empty) : Decl(Import, Empty), NextLocalImport() { }
+ ImportDecl(EmptyShell Empty) : Decl(Import, Empty) {}
public:
/// \brief Create a new module import declaration.
@@ -3893,15 +4025,16 @@ public:
/// \endcode
class ExportDecl final : public Decl, public DeclContext {
virtual void anchor();
+
private:
+ friend class ASTDeclReader;
+
/// \brief The source location for the right brace (if valid).
SourceLocation RBraceLoc;
ExportDecl(DeclContext *DC, SourceLocation ExportLoc)
- : Decl(Export, DC, ExportLoc), DeclContext(Export),
- RBraceLoc(SourceLocation()) { }
-
- friend class ASTDeclReader;
+ : Decl(Export, DC, ExportLoc), DeclContext(Export),
+ RBraceLoc(SourceLocation()) {}
public:
static ExportDecl *Create(ASTContext &C, DeclContext *DC,
@@ -3936,9 +4069,9 @@ public:
/// \brief Represents an empty-declaration.
class EmptyDecl : public Decl {
+ EmptyDecl(DeclContext *DC, SourceLocation L) : Decl(Empty, DC, L) {}
+
virtual void anchor();
- EmptyDecl(DeclContext *DC, SourceLocation L)
- : Decl(Empty, DC, L) { }
public:
static EmptyDecl *Create(ASTContext &C, DeclContext *DC,
@@ -4015,6 +4148,6 @@ inline bool IsEnumDeclScoped(EnumDecl *ED) {
return ED->isScoped();
}
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_AST_DECL_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h b/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h
index 041f0fd484d45..f93c9f0b9aaa1 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h
@@ -1,4 +1,4 @@
-//===-- DeclBase.h - Base Classes for representing declarations -*- C++ -*-===//
+//===- DeclBase.h - Base Classes for representing declarations --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,33 +16,40 @@
#include "clang/AST/AttrIterator.h"
#include "clang/AST/DeclarationName.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/VersionTuple.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/PrettyStackTrace.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <iterator>
+#include <string>
+#include <type_traits>
+#include <utility>
namespace clang {
+
+class ASTContext;
class ASTMutationListener;
-class BlockDecl;
-class CXXRecordDecl;
-class CompoundStmt;
+class Attr;
class DeclContext;
-class DeclarationName;
-class DependentDiagnostic;
-class EnumDecl;
-class ExportDecl;
class ExternalSourceSymbolAttr;
class FunctionDecl;
class FunctionType;
+class IdentifierInfo;
enum Linkage : unsigned char;
-class LinkageComputer;
class LinkageSpecDecl;
class Module;
class NamedDecl;
-class NamespaceDecl;
class ObjCCategoryDecl;
class ObjCCategoryImplDecl;
class ObjCContainerDecl;
@@ -53,23 +60,21 @@ class ObjCMethodDecl;
class ObjCProtocolDecl;
struct PrintingPolicy;
class RecordDecl;
+class SourceManager;
class Stmt;
class StoredDeclsMap;
class TemplateDecl;
class TranslationUnitDecl;
class UsingDirectiveDecl;
-}
-
-namespace clang {
- /// \brief Captures the result of checking the availability of a
- /// declaration.
- enum AvailabilityResult {
- AR_Available = 0,
- AR_NotYetIntroduced,
- AR_Deprecated,
- AR_Unavailable
- };
+/// \brief Captures the result of checking the availability of a
+/// declaration.
+enum AvailabilityResult {
+ AR_Available = 0,
+ AR_NotYetIntroduced,
+ AR_Deprecated,
+ AR_Unavailable
+};
/// Decl - This represents one declaration (or definition), e.g. a variable,
/// typedef, function, struct, etc.
@@ -94,7 +99,7 @@ public:
/// \brief A placeholder type used to construct an empty shell of a
/// decl-derived type that will be filled in later (e.g., by some
/// deserialization method).
- struct EmptyShell { };
+ struct EmptyShell {};
/// IdentifierNamespace - The different namespaces in which
/// declarations may appear. According to C99 6.2.3, there are
@@ -208,15 +213,18 @@ public:
enum class ModuleOwnershipKind : unsigned {
/// This declaration is not owned by a module.
Unowned,
+
/// This declaration has an owning module, but is globally visible
/// (typically because its owning module is visible and we know that
/// modules cannot later become hidden in this compilation).
/// After serialization and deserialization, this will be converted
/// to VisibleWhenImported.
Visible,
+
/// This declaration has an owning module, and is visible when that
/// module is imported.
VisibleWhenImported,
+
/// This declaration has an owning module, but is only visible to
/// lookups that occur within that module.
ModulePrivate
@@ -238,7 +246,6 @@ private:
DeclContext *LexicalDC;
};
-
/// DeclCtx - Holds either a DeclContext* or a MultipleDC*.
/// For declarations that don't contain C++ scope specifiers, it contains
/// the DeclContext where the Decl was declared.
@@ -254,12 +261,14 @@ private:
/// // LexicalDC == global namespace
llvm::PointerUnion<DeclContext*, MultipleDC*> DeclCtx;
- inline bool isInSemaDC() const { return DeclCtx.is<DeclContext*>(); }
- inline bool isOutOfSemaDC() const { return DeclCtx.is<MultipleDC*>(); }
- inline MultipleDC *getMultipleDC() const {
+ bool isInSemaDC() const { return DeclCtx.is<DeclContext*>(); }
+ bool isOutOfSemaDC() const { return DeclCtx.is<MultipleDC*>(); }
+
+ MultipleDC *getMultipleDC() const {
return DeclCtx.get<MultipleDC*>();
}
- inline DeclContext *getSemanticDC() const {
+
+ DeclContext *getSemanticDC() const {
return DeclCtx.get<DeclContext*>();
}
@@ -298,10 +307,16 @@ private:
static bool StatisticsEnabled;
protected:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+ friend class ASTReader;
+ friend class CXXClassMemberWrapper;
+ friend class LinkageComputer;
+ template<typename decl_type> friend class Redeclarable;
+
/// Access - Used by C++ decls for the access specifier.
// NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum
unsigned Access : 2;
- friend class CXXClassMemberWrapper;
/// \brief Whether this declaration was loaded from an AST file.
unsigned FromASTFile : 1;
@@ -313,13 +328,6 @@ protected:
/// Otherwise, it is the linkage + 1.
mutable unsigned CacheValidAndLinkage : 3;
- friend class ASTDeclWriter;
- friend class ASTDeclReader;
- friend class ASTReader;
- friend class LinkageComputer;
-
- template<typename decl_type> friend class Redeclarable;
-
/// \brief Allocate memory for a deserialized declaration.
///
/// This routine must be used to allocate memory for any declaration that is
@@ -357,7 +365,7 @@ private:
protected:
Decl(Kind DK, DeclContext *DC, SourceLocation L)
: NextInContextAndBits(nullptr, getModuleOwnershipKindForChildOf(DC)),
- DeclCtx(DC), Loc(L), DeclKind(DK), InvalidDecl(0), HasAttrs(false),
+ DeclCtx(DC), Loc(L), DeclKind(DK), InvalidDecl(false), HasAttrs(false),
Implicit(false), Used(false), Referenced(false),
TopLevelDeclInObjCContainer(false), Access(AS_none), FromASTFile(0),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
@@ -366,9 +374,9 @@ protected:
}
Decl(Kind DK, EmptyShell Empty)
- : NextInContextAndBits(), DeclKind(DK), InvalidDecl(0), HasAttrs(false),
- Implicit(false), Used(false), Referenced(false),
- TopLevelDeclInObjCContainer(false), Access(AS_none), FromASTFile(0),
+ : DeclKind(DK), InvalidDecl(false), HasAttrs(false), Implicit(false),
+ Used(false), Referenced(false), TopLevelDeclInObjCContainer(false),
+ Access(AS_none), FromASTFile(0),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
CacheValidAndLinkage(0) {
if (StatisticsEnabled) add(DK);
@@ -392,14 +400,15 @@ protected:
}
public:
-
/// \brief Source range that this declaration covers.
virtual SourceRange getSourceRange() const LLVM_READONLY {
return SourceRange(getLocation(), getLocation());
}
+
SourceLocation getLocStart() const LLVM_READONLY {
return getSourceRange().getBegin();
}
+
SourceLocation getLocEnd() const LLVM_READONLY {
return getSourceRange().getEnd();
}
@@ -460,12 +469,15 @@ public:
}
bool hasAttrs() const { return HasAttrs; }
+
void setAttrs(const AttrVec& Attrs) {
return setAttrsImpl(Attrs, getASTContext());
}
+
AttrVec &getAttrs() {
return const_cast<AttrVec&>(const_cast<const Decl*>(this)->getAttrs());
}
+
const AttrVec &getAttrs() const;
void dropAttrs();
@@ -476,8 +488,8 @@ public:
setAttrs(AttrVec(1, A));
}
- typedef AttrVec::const_iterator attr_iterator;
- typedef llvm::iterator_range<attr_iterator> attr_range;
+ using attr_iterator = AttrVec::const_iterator;
+ using attr_range = llvm::iterator_range<attr_iterator>;
attr_range attrs() const {
return attr_range(attr_begin(), attr_end());
@@ -510,6 +522,7 @@ public:
specific_attr_iterator<T> specific_attr_begin() const {
return specific_attr_iterator<T>(attr_begin());
}
+
template <typename T>
specific_attr_iterator<T> specific_attr_end() const {
return specific_attr_iterator<T>(attr_end());
@@ -518,6 +531,7 @@ public:
template<typename T> T *getAttr() const {
return hasAttrs() ? getSpecificAttr<T>(getAttrs()) : nullptr;
}
+
template<typename T> bool hasAttr() const {
return hasAttrs() && hasSpecificAttr<T>(getAttrs());
}
@@ -616,7 +630,6 @@ protected:
}
public:
-
/// \brief Determine the availability of the given declaration.
///
/// This routine will determine the most restrictive availability of
@@ -698,6 +711,7 @@ public:
private:
Module *getOwningModuleSlow() const;
+
protected:
bool hasLocalOwningModuleStorage() const;
@@ -733,11 +747,18 @@ public:
return getModuleOwnershipKind() != ModuleOwnershipKind::Unowned;
}
- /// Get the module that owns this declaration.
+ /// Get the module that owns this declaration (for visibility purposes).
Module *getOwningModule() const {
return isFromASTFile() ? getImportedOwningModule() : getLocalOwningModule();
}
+ /// Get the module that owns this declaration for linkage purposes.
+ /// There only ever is such a module under the C++ Modules TS.
+ ///
+ /// \param IgnoreLinkage Ignore the linkage of the entity; assume that
+ /// all declarations in a global module fragment are unowned.
+ Module *getOwningModuleForLinkage(bool IgnoreLinkage = false) const;
+
/// \brief Determine whether this declaration might be hidden from name
/// lookup. Note that the declaration might be visible even if this returns
/// \c false, if the owning module is visible within the query context.
@@ -770,14 +791,17 @@ public:
unsigned getIdentifierNamespace() const {
return IdentifierNamespace;
}
+
bool isInIdentifierNamespace(unsigned NS) const {
return getIdentifierNamespace() & NS;
}
+
static unsigned getIdentifierNamespaceForKind(Kind DK);
bool hasTagIdentifierNamespace() const {
return isTagIdentifierNamespace(getIdentifierNamespace());
}
+
static bool isTagIdentifierNamespace(unsigned NS) {
// TagDecls have Tag and Type set and may also have TagFriend.
return (NS & ~IDNS_TagFriend) == (IDNS_Tag | IDNS_Type);
@@ -865,18 +889,18 @@ public:
/// \brief Iterates through all the redeclarations of the same decl.
class redecl_iterator {
/// Current - The current declaration.
- Decl *Current;
+ Decl *Current = nullptr;
Decl *Starter;
public:
- typedef Decl *value_type;
- typedef const value_type &reference;
- typedef const value_type *pointer;
- typedef std::forward_iterator_tag iterator_category;
- typedef std::ptrdiff_t difference_type;
+ using value_type = Decl *;
+ using reference = const value_type &;
+ using pointer = const value_type *;
+ using iterator_category = std::forward_iterator_tag;
+ using difference_type = std::ptrdiff_t;
- redecl_iterator() : Current(nullptr) { }
- explicit redecl_iterator(Decl *C) : Current(C), Starter(C) { }
+ redecl_iterator() = default;
+ explicit redecl_iterator(Decl *C) : Current(C), Starter(C) {}
reference operator*() const { return Current; }
value_type operator->() const { return Current; }
@@ -899,12 +923,13 @@ public:
friend bool operator==(redecl_iterator x, redecl_iterator y) {
return x.Current == y.Current;
}
+
friend bool operator!=(redecl_iterator x, redecl_iterator y) {
return x.Current != y.Current;
}
};
- typedef llvm::iterator_range<redecl_iterator> redecl_range;
+ using redecl_range = llvm::iterator_range<redecl_iterator>;
/// \brief Returns an iterator range for all the redeclarations of the same
/// decl. It will iterate at least once (when this decl is the only one).
@@ -915,6 +940,7 @@ public:
redecl_iterator redecls_begin() const {
return redecl_iterator(const_cast<Decl *>(this));
}
+
redecl_iterator redecls_end() const { return redecl_iterator(); }
/// \brief Retrieve the previous declaration that declares the same entity
@@ -1002,13 +1028,15 @@ public:
/// declaration, but in the semantic context of the enclosing namespace
/// scope.
void setLocalExternDecl() {
- assert((IdentifierNamespace == IDNS_Ordinary ||
- IdentifierNamespace == IDNS_OrdinaryFriend) &&
- "namespace is not ordinary");
-
Decl *Prev = getPreviousDecl();
IdentifierNamespace &= ~IDNS_Ordinary;
+ // It's OK for the declaration to still have the "invisible friend" flag or
+ // the "conflicts with tag declarations in this scope" flag for the outer
+ // scope.
+ assert((IdentifierNamespace & ~(IDNS_OrdinaryFriend | IDNS_Tag)) == 0 &&
+ "namespace is not ordinary");
+
IdentifierNamespace |= IDNS_LocalExtern;
if (Prev && Prev->getIdentifierNamespace() & IDNS_Ordinary)
IdentifierNamespace |= IDNS_Ordinary;
@@ -1094,10 +1122,13 @@ public:
static void printGroup(Decl** Begin, unsigned NumDecls,
raw_ostream &Out, const PrintingPolicy &Policy,
unsigned Indentation = 0);
+
// Debuggers don't usually respect default arguments.
void dump() const;
+
// Same as dump(), but forces color printing.
void dumpColor() const;
+
void dump(raw_ostream &Out, bool Deserialize = false) const;
/// \brief Looks through the Decl's underlying type to extract a FunctionType
@@ -1132,10 +1163,11 @@ class PrettyStackTraceDecl : public llvm::PrettyStackTraceEntry {
SourceLocation Loc;
SourceManager &SM;
const char *Message;
+
public:
PrettyStackTraceDecl(const Decl *theDecl, SourceLocation L,
SourceManager &sm, const char *Msg)
- : TheDecl(theDecl), Loc(L), SM(sm), Message(Msg) {}
+ : TheDecl(theDecl), Loc(L), SM(sm), Message(Msg) {}
void print(raw_ostream &OS) const override;
};
@@ -1144,30 +1176,35 @@ public:
/// single result (with no stable storage) or a collection of results (with
/// stable storage provided by the lookup table).
class DeclContextLookupResult {
- typedef ArrayRef<NamedDecl *> ResultTy;
+ using ResultTy = ArrayRef<NamedDecl *>;
+
ResultTy Result;
+
// If there is only one lookup result, it would be invalidated by
// reallocations of the name table, so store it separately.
- NamedDecl *Single;
+ NamedDecl *Single = nullptr;
static NamedDecl *const SingleElementDummyList;
public:
- DeclContextLookupResult() : Result(), Single() {}
+ DeclContextLookupResult() = default;
DeclContextLookupResult(ArrayRef<NamedDecl *> Result)
- : Result(Result), Single() {}
+ : Result(Result) {}
DeclContextLookupResult(NamedDecl *Single)
: Result(SingleElementDummyList), Single(Single) {}
class iterator;
- typedef llvm::iterator_adaptor_base<iterator, ResultTy::iterator,
- std::random_access_iterator_tag,
- NamedDecl *const> IteratorBase;
+
+ using IteratorBase =
+ llvm::iterator_adaptor_base<iterator, ResultTy::iterator,
+ std::random_access_iterator_tag,
+ NamedDecl *const>;
+
class iterator : public IteratorBase {
value_type SingleElement;
public:
- iterator() : IteratorBase(), SingleElement() {}
+ iterator() = default;
explicit iterator(pointer Pos, value_type Single = nullptr)
: IteratorBase(Pos), SingleElement(Single) {}
@@ -1175,9 +1212,10 @@ public:
return SingleElement ? SingleElement : IteratorBase::operator*();
}
};
- typedef iterator const_iterator;
- typedef iterator::pointer pointer;
- typedef iterator::reference reference;
+
+ using const_iterator = iterator;
+ using pointer = iterator::pointer;
+ using reference = iterator::reference;
iterator begin() const { return iterator(Result.begin(), Single); }
iterator end() const { return iterator(Result.end(), Single); }
@@ -1211,7 +1249,6 @@ public:
/// ExportDecl
/// BlockDecl
/// OMPDeclareReductionDecl
-///
class DeclContext {
/// DeclKind - This indicates which class this is.
unsigned DeclKind : 8;
@@ -1251,22 +1288,22 @@ class DeclContext {
/// contains an entry for a DeclarationName (and we haven't lazily
/// omitted anything), then it contains all relevant entries for that
/// name (modulo the hasExternalDecls() flag).
- mutable StoredDeclsMap *LookupPtr;
+ mutable StoredDeclsMap *LookupPtr = nullptr;
protected:
+ friend class ASTDeclReader;
+ friend class ASTWriter;
+ friend class ExternalASTSource;
+
/// FirstDecl - The first declaration stored within this declaration
/// context.
- mutable Decl *FirstDecl;
+ mutable Decl *FirstDecl = nullptr;
/// LastDecl - The last declaration stored within this declaration
/// context. FIXME: We could probably cache this value somewhere
/// outside of the DeclContext, to reduce the size of DeclContext by
/// another pointer.
- mutable Decl *LastDecl;
-
- friend class ExternalASTSource;
- friend class ASTDeclReader;
- friend class ASTWriter;
+ mutable Decl *LastDecl = nullptr;
/// \brief Build up a chain of declarations.
///
@@ -1279,8 +1316,7 @@ protected:
ExternalVisibleStorage(false),
NeedToReconcileExternalVisibleStorage(false),
HasLazyLocalLexicalLookups(false), HasLazyExternalLexicalLookups(false),
- UseQualifiedLookup(false),
- LookupPtr(nullptr), FirstDecl(nullptr), LastDecl(nullptr) {}
+ UseQualifiedLookup(false) {}
public:
~DeclContext();
@@ -1288,6 +1324,7 @@ public:
Decl::Kind getDeclKind() const {
return static_cast<Decl::Kind>(DeclKind);
}
+
const char *getDeclKindName() const;
/// getParent - Returns the containing DeclContext.
@@ -1495,19 +1532,20 @@ public:
/// within this context.
class decl_iterator {
/// Current - The current declaration.
- Decl *Current;
+ Decl *Current = nullptr;
public:
- typedef Decl *value_type;
- typedef const value_type &reference;
- typedef const value_type *pointer;
- typedef std::forward_iterator_tag iterator_category;
- typedef std::ptrdiff_t difference_type;
+ using value_type = Decl *;
+ using reference = const value_type &;
+ using pointer = const value_type *;
+ using iterator_category = std::forward_iterator_tag;
+ using difference_type = std::ptrdiff_t;
- decl_iterator() : Current(nullptr) { }
- explicit decl_iterator(Decl *C) : Current(C) { }
+ decl_iterator() = default;
+ explicit decl_iterator(Decl *C) : Current(C) {}
reference operator*() const { return Current; }
+
// This doesn't meet the iterator requirements, but it's convenient
value_type operator->() const { return Current; }
@@ -1525,12 +1563,13 @@ public:
friend bool operator==(decl_iterator x, decl_iterator y) {
return x.Current == y.Current;
}
+
friend bool operator!=(decl_iterator x, decl_iterator y) {
return x.Current != y.Current;
}
};
- typedef llvm::iterator_range<decl_iterator> decl_range;
+ using decl_range = llvm::iterator_range<decl_iterator>;
/// decls_begin/decls_end - Iterate over the declarations stored in
/// this context.
@@ -1569,16 +1608,16 @@ public:
}
public:
- typedef SpecificDecl *value_type;
- // TODO: Add reference and pointer typedefs (with some appropriate proxy
- // type) if we ever have a need for them.
- typedef void reference;
- typedef void pointer;
- typedef std::iterator_traits<DeclContext::decl_iterator>::difference_type
- difference_type;
- typedef std::forward_iterator_tag iterator_category;
+ using value_type = SpecificDecl *;
+ // TODO: Add reference and pointer types (with some appropriate proxy type)
+ // if we ever have a need for them.
+ using reference = void;
+ using pointer = void;
+ using difference_type =
+ std::iterator_traits<DeclContext::decl_iterator>::difference_type;
+ using iterator_category = std::forward_iterator_tag;
- specific_decl_iterator() : Current() { }
+ specific_decl_iterator() = default;
/// specific_decl_iterator - Construct a new iterator over a
/// subset of the declarations the range [C,
@@ -1593,6 +1632,7 @@ public:
}
value_type operator*() const { return cast<SpecificDecl>(*Current); }
+
// This doesn't meet the iterator requirements, but it's convenient
value_type operator->() const { return **this; }
@@ -1646,16 +1686,16 @@ public:
}
public:
- typedef SpecificDecl *value_type;
- // TODO: Add reference and pointer typedefs (with some appropriate proxy
- // type) if we ever have a need for them.
- typedef void reference;
- typedef void pointer;
- typedef std::iterator_traits<DeclContext::decl_iterator>::difference_type
- difference_type;
- typedef std::forward_iterator_tag iterator_category;
+ using value_type = SpecificDecl *;
+ // TODO: Add reference and pointer types (with some appropriate proxy type)
+ // if we ever have a need for them.
+ using reference = void;
+ using pointer = void;
+ using difference_type =
+ std::iterator_traits<DeclContext::decl_iterator>::difference_type;
+ using iterator_category = std::forward_iterator_tag;
- filtered_decl_iterator() : Current() { }
+ filtered_decl_iterator() = default;
/// filtered_decl_iterator - Construct a new iterator over a
/// subset of the declarations the range [C,
@@ -1733,8 +1773,8 @@ public:
/// @brief Checks whether a declaration is in this context.
bool containsDecl(Decl *D) const;
- typedef DeclContextLookupResult lookup_result;
- typedef lookup_result::iterator lookup_iterator;
+ using lookup_result = DeclContextLookupResult;
+ using lookup_iterator = lookup_result::iterator;
/// lookup - Find the declarations (if any) with the given Name in
/// this context. Returns a range of iterators that contains all of
@@ -1780,7 +1820,7 @@ public:
/// of looking up every possible name.
class all_lookups_iterator;
- typedef llvm::iterator_range<all_lookups_iterator> lookups_range;
+ using lookups_range = llvm::iterator_range<all_lookups_iterator>;
lookups_range lookups() const;
lookups_range noload_lookups() const;
@@ -1796,21 +1836,26 @@ public:
all_lookups_iterator noload_lookups_end() const;
struct udir_iterator;
- typedef llvm::iterator_adaptor_base<udir_iterator, lookup_iterator,
- std::random_access_iterator_tag,
- UsingDirectiveDecl *> udir_iterator_base;
+
+ using udir_iterator_base =
+ llvm::iterator_adaptor_base<udir_iterator, lookup_iterator,
+ std::random_access_iterator_tag,
+ UsingDirectiveDecl *>;
+
struct udir_iterator : udir_iterator_base {
udir_iterator(lookup_iterator I) : udir_iterator_base(I) {}
+
UsingDirectiveDecl *operator*() const;
};
- typedef llvm::iterator_range<udir_iterator> udir_range;
+ using udir_range = llvm::iterator_range<udir_iterator>;
udir_range using_directives() const;
// These are all defined in DependentDiagnostic.h.
class ddiag_iterator;
- typedef llvm::iterator_range<DeclContext::ddiag_iterator> ddiag_range;
+
+ using ddiag_range = llvm::iterator_range<DeclContext::ddiag_iterator>;
inline ddiag_range ddiags() const;
@@ -1883,6 +1928,8 @@ public:
bool Deserialize = false) const;
private:
+ friend class DependentDiagnostic;
+
void reconcileExternalVisibleStorage() const;
bool LoadLexicalDeclsFromExternalStorage() const;
@@ -1894,7 +1941,6 @@ private:
/// use of addDeclInternal().
void makeDeclVisibleInContextInternal(NamedDecl *D);
- friend class DependentDiagnostic;
StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const;
void buildLookupImpl(DeclContext *DCtx, bool Internal);
@@ -1933,8 +1979,7 @@ struct cast_convert_decl_context<ToTy, true> {
}
};
-
-} // end clang.
+} // namespace clang
namespace llvm {
@@ -1954,12 +1999,14 @@ struct cast_convert_val<ToTy,
return *::clang::cast_convert_decl_context<ToTy>::doit(&Val);
}
};
+
template<class ToTy>
struct cast_convert_val<ToTy, ::clang::DeclContext, ::clang::DeclContext> {
static ToTy &doit(::clang::DeclContext &Val) {
return *::clang::cast_convert_decl_context<ToTy>::doit(&Val);
}
};
+
template<class ToTy>
struct cast_convert_val<ToTy,
const ::clang::DeclContext*, const ::clang::DeclContext*> {
@@ -1967,6 +2014,7 @@ struct cast_convert_val<ToTy,
return ::clang::cast_convert_decl_context<ToTy>::doit(Val);
}
};
+
template<class ToTy>
struct cast_convert_val<ToTy, ::clang::DeclContext*, ::clang::DeclContext*> {
static ToTy *doit(::clang::DeclContext *Val) {
@@ -2003,6 +2051,6 @@ struct cast_convert_val< const ::clang::DeclContext, FromTy*, FromTy*> {
}
};
-} // end namespace llvm
+} // namespace llvm
-#endif
+#endif // LLVM_CLANG_AST_DECLBASE_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h b/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h
index 2f735c5506c46..88dc9a6559172 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h
@@ -1,4 +1,4 @@
-//===-- DeclCXX.h - Classes for representing C++ declarations -*- C++ -*-=====//
+//===- DeclCXX.h - Classes for representing C++ declarations --*- C++ -*-=====//
//
// The LLVM Compiler Infrastructure
//
@@ -6,11 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
/// \brief Defines the C++ Decl subclasses, other than those for templates
/// (found in DeclTemplate.h) and friends (in DeclFriend.h).
-///
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECLCXX_H
@@ -20,29 +20,56 @@
#include "clang/AST/ASTUnresolvedSet.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/LambdaCapture.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/Redeclarable.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/AST/UnresolvedSet.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/Lambda.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/OperatorKinds.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
+#include "llvm/Support/TrailingObjects.h"
+#include <cassert>
+#include <cstddef>
+#include <iterator>
+#include <memory>
+#include <vector>
namespace clang {
class ClassTemplateDecl;
-class ClassTemplateSpecializationDecl;
class ConstructorUsingShadowDecl;
class CXXBasePath;
class CXXBasePaths;
class CXXConstructorDecl;
-class CXXConversionDecl;
class CXXDestructorDecl;
-class CXXMethodDecl;
-class CXXRecordDecl;
-class CXXMemberLookupCriteria;
class CXXFinalOverriderMap;
class CXXIndirectPrimaryBaseSet;
+class CXXMethodDecl;
+class DiagnosticBuilder;
class FriendDecl;
-class LambdaExpr;
+class FunctionTemplateDecl;
+class IdentifierInfo;
+class MemberSpecializationInfo;
+class TemplateDecl;
+class TemplateParameterList;
class UsingDecl;
/// \brief Represents any kind of function declaration, whether it is a
@@ -50,10 +77,10 @@ class UsingDecl;
class AnyFunctionDecl {
NamedDecl *Function;
- AnyFunctionDecl(NamedDecl *ND) : Function(ND) { }
+ AnyFunctionDecl(NamedDecl *ND) : Function(ND) {}
public:
- AnyFunctionDecl(FunctionDecl *FD) : Function(FD) { }
+ AnyFunctionDecl(FunctionDecl *FD) : Function(FD) {}
AnyFunctionDecl(FunctionTemplateDecl *FTD);
/// \brief Implicily converts any function or function template into a
@@ -68,17 +95,18 @@ public:
}
};
-} // end namespace clang
+} // namespace clang
namespace llvm {
+
// Provide PointerLikeTypeTraits for non-cvr pointers.
template<>
- class PointerLikeTypeTraits< ::clang::AnyFunctionDecl> {
- public:
- static inline void *getAsVoidPointer(::clang::AnyFunctionDecl F) {
+ struct PointerLikeTypeTraits< ::clang::AnyFunctionDecl> {
+ static void *getAsVoidPointer(::clang::AnyFunctionDecl F) {
return F.get();
}
- static inline ::clang::AnyFunctionDecl getFromVoidPointer(void *P) {
+
+ static ::clang::AnyFunctionDecl getFromVoidPointer(void *P) {
return ::clang::AnyFunctionDecl::getFromNamedDecl(
static_cast< ::clang::NamedDecl*>(P));
}
@@ -86,7 +114,7 @@ namespace llvm {
enum { NumLowBitsAvailable = 2 };
};
-} // end namespace llvm
+} // namespace llvm
namespace clang {
@@ -101,7 +129,6 @@ namespace clang {
/// Also note that this class has nothing to do with so-called
/// "access declarations" (C++98 11.3 [class.access.dcl]).
class AccessSpecDecl : public Decl {
- virtual void anchor();
/// \brief The location of the ':'.
SourceLocation ColonLoc;
@@ -110,16 +137,21 @@ class AccessSpecDecl : public Decl {
: Decl(AccessSpec, DC, ASLoc), ColonLoc(ColonLoc) {
setAccess(AS);
}
- AccessSpecDecl(EmptyShell Empty)
- : Decl(AccessSpec, Empty) { }
+
+ AccessSpecDecl(EmptyShell Empty) : Decl(AccessSpec, Empty) {}
+
+ virtual void anchor();
+
public:
/// \brief The location of the access specifier.
SourceLocation getAccessSpecifierLoc() const { return getLocation(); }
+
/// \brief Sets the location of the access specifier.
void setAccessSpecifierLoc(SourceLocation ASLoc) { setLocation(ASLoc); }
/// \brief The location of the colon following the access specifier.
SourceLocation getColonLoc() const { return ColonLoc; }
+
/// \brief Sets the location of the colon.
void setColonLoc(SourceLocation CLoc) { ColonLoc = CLoc; }
@@ -132,6 +164,7 @@ public:
SourceLocation ColonLoc) {
return new (C, DC) AccessSpecDecl(AS, DC, ASLoc, ColonLoc);
}
+
static AccessSpecDecl *CreateDeserialized(ASTContext &C, unsigned ID);
// Implement isa/cast/dyncast/etc.
@@ -191,12 +224,11 @@ class CXXBaseSpecifier {
TypeSourceInfo *BaseTypeInfo;
public:
- CXXBaseSpecifier() { }
-
+ CXXBaseSpecifier() = default;
CXXBaseSpecifier(SourceRange R, bool V, bool BC, AccessSpecifier A,
TypeSourceInfo *TInfo, SourceLocation EllipsisLoc)
: Range(R), EllipsisLoc(EllipsisLoc), Virtual(V), BaseOfClass(BC),
- Access(A), InheritConstructors(false), BaseTypeInfo(TInfo) { }
+ Access(A), InheritConstructors(false), BaseTypeInfo(TInfo) {}
/// \brief Retrieves the source range that contains the entire base specifier.
SourceRange getSourceRange() const LLVM_READONLY { return Range; }
@@ -265,7 +297,16 @@ public:
/// \brief Represents a C++ struct/union/class.
class CXXRecordDecl : public RecordDecl {
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+ friend class ASTNodeImporter;
+ friend class ASTReader;
+ friend class ASTRecordWriter;
+ friend class ASTWriter;
+ friend class DeclContext;
+ friend class LambdaExpr;
+ friend void FunctionDecl::setPure(bool);
friend void TagDecl::startDefinition();
/// Values used in DefinitionData fields to represent special members.
@@ -280,8 +321,6 @@ class CXXRecordDecl : public RecordDecl {
};
struct DefinitionData {
- DefinitionData(CXXRecordDecl *D);
-
/// \brief True if this class has any user-declared constructors.
unsigned UserDeclaredConstructor : 1;
@@ -475,13 +514,13 @@ class CXXRecordDecl : public RecordDecl {
unsigned HasODRHash : 1;
/// \brief A hash of parts of the class to help in ODR checking.
- unsigned ODRHash;
+ unsigned ODRHash = 0;
/// \brief The number of base class specifiers in Bases.
- unsigned NumBases;
+ unsigned NumBases = 0;
/// \brief The number of virtual base class specifiers in VBases.
- unsigned NumVBases;
+ unsigned NumVBases = 0;
/// \brief Base classes of this class.
///
@@ -513,6 +552,8 @@ class CXXRecordDecl : public RecordDecl {
/// This is actually currently stored in reverse order.
LazyDeclPtr FirstFriend;
+ DefinitionData(CXXRecordDecl *D);
+
/// \brief Retrieve the set of direct base classes.
CXXBaseSpecifier *getBases() const {
if (!Bases.isOffset())
@@ -530,6 +571,7 @@ class CXXRecordDecl : public RecordDecl {
ArrayRef<CXXBaseSpecifier> bases() const {
return llvm::makeArrayRef(getBases(), NumBases);
}
+
ArrayRef<CXXBaseSpecifier> vbases() const {
return llvm::makeArrayRef(getVBases(), NumVBases);
}
@@ -543,22 +585,7 @@ class CXXRecordDecl : public RecordDecl {
/// \brief Describes a C++ closure type (generated by a lambda expression).
struct LambdaDefinitionData : public DefinitionData {
- typedef LambdaCapture Capture;
-
- LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info,
- bool Dependent, bool IsGeneric,
- LambdaCaptureDefault CaptureDefault)
- : DefinitionData(D), Dependent(Dependent), IsGenericLambda(IsGeneric),
- CaptureDefault(CaptureDefault), NumCaptures(0), NumExplicitCaptures(0),
- ManglingNumber(0), ContextDecl(nullptr), Captures(nullptr),
- MethodTyInfo(Info) {
- IsLambda = true;
-
- // C++1z [expr.prim.lambda]p4:
- // This class type is not an aggregate type.
- Aggregate = false;
- PlainOldData = false;
- }
+ using Capture = LambdaCapture;
/// \brief Whether this lambda is known to be dependent, even if its
/// context isn't dependent.
@@ -584,7 +611,7 @@ class CXXRecordDecl : public RecordDecl {
/// \brief The number used to indicate this lambda expression for name
/// mangling in the Itanium C++ ABI.
- unsigned ManglingNumber;
+ unsigned ManglingNumber = 0;
/// \brief The declaration that provides context for this lambda, if the
/// actual DeclContext does not suffice. This is used for lambdas that
@@ -594,11 +621,24 @@ class CXXRecordDecl : public RecordDecl {
/// \brief The list of captures, both explicit and implicit, for this
/// lambda.
- Capture *Captures;
+ Capture *Captures = nullptr;
/// \brief The type of the call method.
TypeSourceInfo *MethodTyInfo;
-
+
+ LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info,
+ bool Dependent, bool IsGeneric,
+ LambdaCaptureDefault CaptureDefault)
+ : DefinitionData(D), Dependent(Dependent), IsGenericLambda(IsGeneric),
+ CaptureDefault(CaptureDefault), NumCaptures(0), NumExplicitCaptures(0),
+ MethodTyInfo(Info) {
+ IsLambda = true;
+
+ // C++1z [expr.prim.lambda]p4:
+ // This class type is not an aggregate type.
+ Aggregate = false;
+ PlainOldData = false;
+ }
};
struct DefinitionData *dataPtr() const {
@@ -630,11 +670,8 @@ class CXXRecordDecl : public RecordDecl {
/// classes of class template specializations, this will be the
/// MemberSpecializationInfo referring to the member class that was
/// instantiated or specialized.
- llvm::PointerUnion<ClassTemplateDecl*, MemberSpecializationInfo*>
- TemplateOrInstantiation;
-
- friend class DeclContext;
- friend class LambdaExpr;
+ llvm::PointerUnion<ClassTemplateDecl *, MemberSpecializationInfo *>
+ TemplateOrInstantiation;
/// \brief Called from setBases and addedMember to notify the class that a
/// direct or virtual base class or a member of class type has been added.
@@ -648,9 +685,6 @@ class CXXRecordDecl : public RecordDecl {
void addedMember(Decl *D);
void markedVirtualFunctionPure();
- friend void FunctionDecl::setPure(bool);
-
- friend class ASTNodeImporter;
/// \brief Get the head of our list of friend declarations, possibly
/// deserializing the friends from an external AST source.
@@ -663,14 +697,15 @@ protected:
public:
/// \brief Iterator that traverses the base classes of a class.
- typedef CXXBaseSpecifier* base_class_iterator;
+ using base_class_iterator = CXXBaseSpecifier *;
/// \brief Iterator that traverses the base classes of a class.
- typedef const CXXBaseSpecifier* base_class_const_iterator;
+ using base_class_const_iterator = const CXXBaseSpecifier *;
CXXRecordDecl *getCanonicalDecl() override {
return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl());
}
+
const CXXRecordDecl *getCanonicalDecl() const {
return const_cast<CXXRecordDecl*>(this)->getCanonicalDecl();
}
@@ -679,6 +714,7 @@ public:
return cast_or_null<CXXRecordDecl>(
static_cast<RecordDecl *>(this)->getPreviousDecl());
}
+
const CXXRecordDecl *getPreviousDecl() const {
return const_cast<CXXRecordDecl*>(this)->getPreviousDecl();
}
@@ -730,9 +766,9 @@ public:
/// \brief Retrieves the number of base classes of this class.
unsigned getNumBases() const { return data().NumBases; }
- typedef llvm::iterator_range<base_class_iterator> base_class_range;
- typedef llvm::iterator_range<base_class_const_iterator>
- base_class_const_range;
+ using base_class_range = llvm::iterator_range<base_class_iterator>;
+ using base_class_const_range =
+ llvm::iterator_range<base_class_const_iterator>;
base_class_range bases() {
return base_class_range(bases_begin(), bases_end());
@@ -772,9 +808,9 @@ public:
/// Iterator access to method members. The method iterator visits
/// all method members of the class, including non-instance methods,
/// special methods, etc.
- typedef specific_decl_iterator<CXXMethodDecl> method_iterator;
- typedef llvm::iterator_range<specific_decl_iterator<CXXMethodDecl>>
- method_range;
+ using method_iterator = specific_decl_iterator<CXXMethodDecl>;
+ using method_range =
+ llvm::iterator_range<specific_decl_iterator<CXXMethodDecl>>;
method_range methods() const {
return method_range(method_begin(), method_end());
@@ -785,21 +821,23 @@ public:
method_iterator method_begin() const {
return method_iterator(decls_begin());
}
+
/// \brief Method past-the-end iterator.
method_iterator method_end() const {
return method_iterator(decls_end());
}
/// Iterator access to constructor members.
- typedef specific_decl_iterator<CXXConstructorDecl> ctor_iterator;
- typedef llvm::iterator_range<specific_decl_iterator<CXXConstructorDecl>>
- ctor_range;
+ using ctor_iterator = specific_decl_iterator<CXXConstructorDecl>;
+ using ctor_range =
+ llvm::iterator_range<specific_decl_iterator<CXXConstructorDecl>>;
ctor_range ctors() const { return ctor_range(ctor_begin(), ctor_end()); }
ctor_iterator ctor_begin() const {
return ctor_iterator(decls_begin());
}
+
ctor_iterator ctor_end() const {
return ctor_iterator(decls_end());
}
@@ -807,7 +845,7 @@ public:
/// An iterator over friend declarations. All of these are defined
/// in DeclFriend.h.
class friend_iterator;
- typedef llvm::iterator_range<friend_iterator> friend_range;
+ using friend_range = llvm::iterator_range<friend_iterator>;
friend_range friends() const;
friend_iterator friend_begin() const;
@@ -839,7 +877,10 @@ public:
/// \brief \c true if a defaulted destructor for this class would be deleted.
bool defaultedDestructorIsDeleted() const {
- return !data().DefaultedDestructorIsDeleted;
+ assert((!needsOverloadResolutionForDestructor() ||
+ (data().DeclaredSpecialMembers & SMF_Destructor)) &&
+ "this property has not yet been computed by Sema");
+ return data().DefaultedDestructorIsDeleted;
}
/// \brief \c true if we know for sure that this class has a single,
@@ -986,6 +1027,15 @@ public:
data().DefaultedMoveConstructorIsDeleted = true;
}
+ /// \brief Set that we attempted to declare an implicit destructor,
+ /// but overload resolution failed so we deleted it.
+ void setImplicitDestructorIsDeleted() {
+ assert((data().DefaultedDestructorIsDeleted ||
+ needsOverloadResolutionForDestructor()) &&
+ "destructor should not be deleted");
+ data().DefaultedDestructorIsDeleted = true;
+ }
+
/// \brief Determine whether this class should get an implicit move
/// constructor or if any existing special member function inhibits this.
bool needsImplicitMoveConstructor() const {
@@ -1144,24 +1194,28 @@ public:
void getCaptureFields(llvm::DenseMap<const VarDecl *, FieldDecl *> &Captures,
FieldDecl *&ThisCapture) const;
- typedef const LambdaCapture *capture_const_iterator;
- typedef llvm::iterator_range<capture_const_iterator> capture_const_range;
+ using capture_const_iterator = const LambdaCapture *;
+ using capture_const_range = llvm::iterator_range<capture_const_iterator>;
capture_const_range captures() const {
return capture_const_range(captures_begin(), captures_end());
}
+
capture_const_iterator captures_begin() const {
return isLambda() ? getLambdaData().Captures : nullptr;
}
+
capture_const_iterator captures_end() const {
return isLambda() ? captures_begin() + getLambdaData().NumCaptures
: nullptr;
}
- typedef UnresolvedSetIterator conversion_iterator;
+ using conversion_iterator = UnresolvedSetIterator;
+
conversion_iterator conversion_begin() const {
return data().Conversions.get(getASTContext()).begin();
}
+
conversion_iterator conversion_end() const {
return data().Conversions.get(getASTContext()).end();
}
@@ -1433,10 +1487,10 @@ public:
/// We resolve DR1361 by ignoring the second bullet. We resolve DR1452 by
/// treating types with trivial default constructors as literal types.
///
- /// Only in C++1z and beyond, are lambdas literal types.
+ /// Only in C++17 and beyond, are lambdas literal types.
bool isLiteral() const {
return hasTrivialDestructor() &&
- (!isLambda() || getASTContext().getLangOpts().CPlusPlus1z) &&
+ (!isLambda() || getASTContext().getLangOpts().CPlusPlus17) &&
!hasNonLiteralTypeFieldsOrBases() &&
(isAggregate() || isLambda() ||
hasConstexprNonCopyMoveConstructor() ||
@@ -1585,8 +1639,8 @@ public:
/// \param BaseDefinition the definition of the base class
///
/// \returns true if this base matched the search criteria
- typedef llvm::function_ref<bool(const CXXRecordDecl *BaseDefinition)>
- ForallBasesCallback;
+ using ForallBasesCallback =
+ llvm::function_ref<bool(const CXXRecordDecl *BaseDefinition)>;
/// \brief Determines if the given callback holds for all the direct
/// or indirect base classes of this type.
@@ -1614,8 +1668,9 @@ public:
/// base named by the \p Specifier.
///
/// \returns true if this base matched the search criteria, false otherwise.
- typedef llvm::function_ref<bool(const CXXBaseSpecifier *Specifier,
- CXXBasePath &Path)> BaseMatchesCallback;
+ using BaseMatchesCallback =
+ llvm::function_ref<bool(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path)>;
/// \brief Look for entities within the base classes of this C++ class,
/// transitively searching all base class subobjects.
@@ -1794,6 +1849,7 @@ public:
/// \brief Returns the inheritance model used for this record.
MSInheritanceAttr::Spelling getMSInheritanceModel() const;
+
/// \brief Calculate what the inheritance model would be for this class.
MSInheritanceAttr::Spelling calculateInheritanceModel() const;
@@ -1832,16 +1888,14 @@ public:
return getLambdaData().MethodTyInfo;
}
+ // \brief Determine whether this type is an Interface Like type for
+ // __interface inheritence purposes.
+ bool isInterfaceLike() const;
+
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) {
return K >= firstCXXRecord && K <= lastCXXRecord;
}
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
- friend class ASTRecordWriter;
- friend class ASTReader;
- friend class ASTWriter;
};
/// \brief Represents a C++ deduction guide declaration.
@@ -1856,6 +1910,7 @@ public:
/// the constructors of \c A.
class CXXDeductionGuideDecl : public FunctionDecl {
void anchor() override;
+
private:
CXXDeductionGuideDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
bool IsExplicit, const DeclarationNameInfo &NameInfo,
@@ -1869,6 +1924,9 @@ private:
}
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+
static CXXDeductionGuideDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, bool IsExplicit,
const DeclarationNameInfo &NameInfo,
@@ -1888,12 +1946,15 @@ public:
return getDeclName().getCXXDeductionGuideTemplate();
}
+ void setIsCopyDeductionCandidate() {
+ IsCopyDeductionCandidate = true;
+ }
+
+ bool isCopyDeductionCandidate() const { return IsCopyDeductionCandidate; }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == CXXDeductionGuide; }
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
};
/// \brief Represents a static or instance method of a struct/union/class.
@@ -1902,6 +1963,7 @@ public:
/// non-static) member functions, whether virtual or not.
class CXXMethodDecl : public FunctionDecl {
void anchor() override;
+
protected:
CXXMethodDecl(Kind DK, ASTContext &C, CXXRecordDecl *RD,
SourceLocation StartLoc, const DeclarationNameInfo &NameInfo,
@@ -1953,7 +2015,7 @@ public:
if (CD->isVirtualAsWritten() || CD->isPure())
return true;
- return (CD->begin_overridden_methods() != CD->end_overridden_methods());
+ return CD->size_overridden_methods() != 0;
}
/// If it's possible to devirtualize a call to this method, return the called
@@ -1999,18 +2061,23 @@ public:
/// True if this method is user-declared and was not
/// deleted or defaulted on its first declaration.
bool isUserProvided() const {
- return !(isDeleted() || getCanonicalDecl()->isDefaulted());
+ auto *DeclAsWritten = this;
+ if (auto *Pattern = getTemplateInstantiationPattern())
+ DeclAsWritten = cast<CXXMethodDecl>(Pattern);
+ return !(DeclAsWritten->isDeleted() ||
+ DeclAsWritten->getCanonicalDecl()->isDefaulted());
}
- ///
void addOverriddenMethod(const CXXMethodDecl *MD);
- typedef const CXXMethodDecl *const* method_iterator;
+ using method_iterator = const CXXMethodDecl *const *;
method_iterator begin_overridden_methods() const;
method_iterator end_overridden_methods() const;
unsigned size_overridden_methods() const;
- typedef ASTContext::overridden_method_range overridden_method_range;
+
+ using overridden_method_range= ASTContext::overridden_method_range;
+
overridden_method_range overridden_methods() const;
/// Returns the parent of this method declaration, which
@@ -2240,6 +2307,7 @@ public:
return Initializee.get<FieldDecl*>();
return nullptr;
}
+
FieldDecl *getAnyMember() const {
if (isMemberInitializer())
return Initializee.get<FieldDecl*>();
@@ -2301,11 +2369,11 @@ public:
/// Description of a constructor that was inherited from a base class.
class InheritedConstructor {
- ConstructorUsingShadowDecl *Shadow;
- CXXConstructorDecl *BaseCtor;
+ ConstructorUsingShadowDecl *Shadow = nullptr;
+ CXXConstructorDecl *BaseCtor = nullptr;
public:
- InheritedConstructor() : Shadow(), BaseCtor() {}
+ InheritedConstructor() = default;
InheritedConstructor(ConstructorUsingShadowDecl *Shadow,
CXXConstructorDecl *BaseCtor)
: Shadow(Shadow), BaseCtor(BaseCtor) {}
@@ -2329,8 +2397,6 @@ public:
class CXXConstructorDecl final
: public CXXMethodDecl,
private llvm::TrailingObjects<CXXConstructorDecl, InheritedConstructor> {
- void anchor() override;
-
/// \name Support for base and member initializers.
/// \{
/// \brief The arguments used to initialize the base or member.
@@ -2350,15 +2416,20 @@ class CXXConstructorDecl final
InheritedConstructor Inherited)
: CXXMethodDecl(CXXConstructor, C, RD, StartLoc, NameInfo, T, TInfo,
SC_None, isInline, isConstexpr, SourceLocation()),
- CtorInitializers(nullptr), NumCtorInitializers(0),
- IsInheritingConstructor((bool)Inherited) {
+ NumCtorInitializers(0), IsInheritingConstructor((bool)Inherited) {
setImplicit(isImplicitlyDeclared);
if (Inherited)
*getTrailingObjects<InheritedConstructor>() = Inherited;
IsExplicitSpecified = isExplicitSpecified;
}
+ void anchor() override;
+
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+ friend TrailingObjects;
+
static CXXConstructorDecl *CreateDeserialized(ASTContext &C, unsigned ID,
bool InheritsConstructor);
static CXXConstructorDecl *
@@ -2369,13 +2440,13 @@ public:
InheritedConstructor Inherited = InheritedConstructor());
/// \brief Iterates through the member/base initializer list.
- typedef CXXCtorInitializer **init_iterator;
+ using init_iterator = CXXCtorInitializer **;
/// \brief Iterates through the member/base initializer list.
- typedef CXXCtorInitializer *const *init_const_iterator;
+ using init_const_iterator = CXXCtorInitializer *const *;
- typedef llvm::iterator_range<init_iterator> init_range;
- typedef llvm::iterator_range<init_const_iterator> init_const_range;
+ using init_range = llvm::iterator_range<init_iterator>;
+ using init_const_range = llvm::iterator_range<init_const_iterator>;
init_range inits() { return init_range(init_begin(), init_end()); }
init_const_range inits() const {
@@ -2387,6 +2458,7 @@ public:
const auto *ConstThis = this;
return const_cast<init_iterator>(ConstThis->init_begin());
}
+
/// \brief Retrieve an iterator to the first initializer.
init_const_iterator init_begin() const;
@@ -2394,14 +2466,15 @@ public:
init_iterator init_end() {
return init_begin() + NumCtorInitializers;
}
+
/// \brief Retrieve an iterator past the last initializer.
init_const_iterator init_end() const {
return init_begin() + NumCtorInitializers;
}
- typedef std::reverse_iterator<init_iterator> init_reverse_iterator;
- typedef std::reverse_iterator<init_const_iterator>
- init_const_reverse_iterator;
+ using init_reverse_iterator = std::reverse_iterator<init_iterator>;
+ using init_const_reverse_iterator =
+ std::reverse_iterator<init_const_iterator>;
init_reverse_iterator init_rbegin() {
return init_reverse_iterator(init_end());
@@ -2532,10 +2605,6 @@ public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == CXXConstructor; }
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
- friend TrailingObjects;
};
/// \brief Represents a C++ destructor within a class.
@@ -2549,20 +2618,26 @@ public:
/// };
/// \endcode
class CXXDestructorDecl : public CXXMethodDecl {
- void anchor() override;
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
- FunctionDecl *OperatorDelete;
+ // FIXME: Don't allocate storage for these except in the first declaration
+ // of a virtual destructor.
+ FunctionDecl *OperatorDelete = nullptr;
+ Expr *OperatorDeleteThisArg = nullptr;
CXXDestructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isInline, bool isImplicitlyDeclared)
: CXXMethodDecl(CXXDestructor, C, RD, StartLoc, NameInfo, T, TInfo,
- SC_None, isInline, /*isConstexpr=*/false, SourceLocation()),
- OperatorDelete(nullptr) {
+ SC_None, isInline, /*isConstexpr=*/false, SourceLocation())
+ {
setImplicit(isImplicitlyDeclared);
}
+ void anchor() override;
+
public:
static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation StartLoc,
@@ -2572,11 +2647,16 @@ public:
bool isImplicitlyDeclared);
static CXXDestructorDecl *CreateDeserialized(ASTContext & C, unsigned ID);
- void setOperatorDelete(FunctionDecl *OD);
+ void setOperatorDelete(FunctionDecl *OD, Expr *ThisArg);
+
const FunctionDecl *getOperatorDelete() const {
return getCanonicalDecl()->OperatorDelete;
}
+ Expr *getOperatorDeleteThisArg() const {
+ return getCanonicalDecl()->OperatorDeleteThisArg;
+ }
+
CXXDestructorDecl *getCanonicalDecl() override {
return cast<CXXDestructorDecl>(FunctionDecl::getCanonicalDecl());
}
@@ -2587,9 +2667,6 @@ public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == CXXDestructor; }
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
};
/// \brief Represents a C++ conversion function within a class.
@@ -2603,8 +2680,6 @@ public:
/// };
/// \endcode
class CXXConversionDecl : public CXXMethodDecl {
- void anchor() override;
-
CXXConversionDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
const DeclarationNameInfo &NameInfo, QualType T,
TypeSourceInfo *TInfo, bool isInline,
@@ -2615,7 +2690,12 @@ class CXXConversionDecl : public CXXMethodDecl {
IsExplicitSpecified = isExplicitSpecified;
}
+ void anchor() override;
+
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+
static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation StartLoc,
const DeclarationNameInfo &NameInfo,
@@ -2652,9 +2732,6 @@ public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == CXXConversion; }
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
};
/// \brief Represents a linkage specification.
@@ -2665,6 +2742,7 @@ public:
/// \endcode
class LinkageSpecDecl : public Decl, public DeclContext {
virtual void anchor();
+
public:
/// \brief Represents the language in a linkage specification.
///
@@ -2676,25 +2754,29 @@ public:
lang_c = /* DW_LANG_C */ 0x0002,
lang_cxx = /* DW_LANG_C_plus_plus */ 0x0004
};
+
private:
/// \brief The language for this linkage specification.
unsigned Language : 3;
+
/// \brief True if this linkage spec has braces.
///
/// This is needed so that hasBraces() returns the correct result while the
/// linkage spec body is being parsed. Once RBraceLoc has been set this is
/// not used, so it doesn't need to be serialized.
unsigned HasBraces : 1;
+
/// \brief The source location for the extern keyword.
SourceLocation ExternLoc;
+
/// \brief The source location for the right brace (if valid).
SourceLocation RBraceLoc;
LinkageSpecDecl(DeclContext *DC, SourceLocation ExternLoc,
SourceLocation LangLoc, LanguageIDs lang, bool HasBraces)
- : Decl(LinkageSpec, DC, LangLoc), DeclContext(LinkageSpec),
- Language(lang), HasBraces(HasBraces), ExternLoc(ExternLoc),
- RBraceLoc(SourceLocation()) { }
+ : Decl(LinkageSpec, DC, LangLoc), DeclContext(LinkageSpec),
+ Language(lang), HasBraces(HasBraces), ExternLoc(ExternLoc),
+ RBraceLoc(SourceLocation()) {}
public:
static LinkageSpecDecl *Create(ASTContext &C, DeclContext *DC,
@@ -2705,6 +2787,7 @@ public:
/// \brief Return the language specified by this linkage specification.
LanguageIDs getLanguage() const { return LanguageIDs(Language); }
+
/// \brief Set the language specified by this linkage specification.
void setLanguage(LanguageIDs L) { Language = L; }
@@ -2737,9 +2820,11 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == LinkageSpec; }
+
static DeclContext *castToDeclContext(const LinkageSpecDecl *D) {
return static_cast<DeclContext *>(const_cast<LinkageSpecDecl*>(D));
}
+
static LinkageSpecDecl *castFromDeclContext(const DeclContext *DC) {
return static_cast<LinkageSpecDecl *>(const_cast<DeclContext*>(DC));
}
@@ -2756,7 +2841,6 @@ public:
/// artificial names for all using-directives in order to store
/// them in DeclContext effectively.
class UsingDirectiveDecl : public NamedDecl {
- void anchor() override;
/// \brief The location of the \c using keyword.
SourceLocation UsingLoc;
@@ -2773,6 +2857,16 @@ class UsingDirectiveDecl : public NamedDecl {
/// namespace.
DeclContext *CommonAncestor;
+ UsingDirectiveDecl(DeclContext *DC, SourceLocation UsingLoc,
+ SourceLocation NamespcLoc,
+ NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation IdentLoc,
+ NamedDecl *Nominated,
+ DeclContext *CommonAncestor)
+ : NamedDecl(UsingDirective, DC, IdentLoc, getName()), UsingLoc(UsingLoc),
+ NamespaceLoc(NamespcLoc), QualifierLoc(QualifierLoc),
+ NominatedNamespace(Nominated), CommonAncestor(CommonAncestor) {}
+
/// \brief Returns special DeclarationName used by using-directives.
///
/// This is only used by DeclContext for storing UsingDirectiveDecls in
@@ -2781,17 +2875,14 @@ class UsingDirectiveDecl : public NamedDecl {
return DeclarationName::getUsingDirectiveName();
}
- UsingDirectiveDecl(DeclContext *DC, SourceLocation UsingLoc,
- SourceLocation NamespcLoc,
- NestedNameSpecifierLoc QualifierLoc,
- SourceLocation IdentLoc,
- NamedDecl *Nominated,
- DeclContext *CommonAncestor)
- : NamedDecl(UsingDirective, DC, IdentLoc, getName()), UsingLoc(UsingLoc),
- NamespaceLoc(NamespcLoc), QualifierLoc(QualifierLoc),
- NominatedNamespace(Nominated), CommonAncestor(CommonAncestor) { }
+ void anchor() override;
public:
+ friend class ASTDeclReader;
+
+ // Friend for getUsingDirectiveName.
+ friend class DeclContext;
+
/// \brief Retrieve the nested-name-specifier that qualifies the
/// name of the namespace, with source-location information.
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
@@ -2844,11 +2935,6 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == UsingDirective; }
-
- // Friend for getUsingDirectiveName.
- friend class DeclContext;
-
- friend class ASTDeclReader;
};
/// \brief Represents a C++ namespace alias.
@@ -2860,7 +2946,7 @@ public:
/// \endcode
class NamespaceAliasDecl : public NamedDecl,
public Redeclarable<NamespaceAliasDecl> {
- void anchor() override;
+ friend class ASTDeclReader;
/// \brief The location of the \c namespace keyword.
SourceLocation NamespaceLoc;
@@ -2885,13 +2971,14 @@ class NamespaceAliasDecl : public NamedDecl,
NamespaceLoc(NamespaceLoc), IdentLoc(IdentLoc),
QualifierLoc(QualifierLoc), Namespace(Namespace) {}
- typedef Redeclarable<NamespaceAliasDecl> redeclarable_base;
+ void anchor() override;
+
+ using redeclarable_base = Redeclarable<NamespaceAliasDecl>;
+
NamespaceAliasDecl *getNextRedeclarationImpl() override;
NamespaceAliasDecl *getPreviousDeclImpl() override;
NamespaceAliasDecl *getMostRecentDeclImpl() override;
- friend class ASTDeclReader;
-
public:
static NamespaceAliasDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation NamespaceLoc,
@@ -2903,8 +2990,9 @@ public:
static NamespaceAliasDecl *CreateDeserialized(ASTContext &C, unsigned ID);
- typedef redeclarable_base::redecl_range redecl_range;
- typedef redeclarable_base::redecl_iterator redecl_iterator;
+ using redecl_range = redeclarable_base::redecl_range;
+ using redecl_iterator = redeclarable_base::redecl_iterator;
+
using redeclarable_base::redecls_begin;
using redeclarable_base::redecls_end;
using redeclarable_base::redecls;
@@ -2976,23 +3064,27 @@ public:
/// }
/// \endcode
class UsingShadowDecl : public NamedDecl, public Redeclarable<UsingShadowDecl> {
- void anchor() override;
+ friend class UsingDecl;
/// The referenced declaration.
- NamedDecl *Underlying;
+ NamedDecl *Underlying = nullptr;
/// \brief The using declaration which introduced this decl or the next using
/// shadow declaration contained in the aforementioned using declaration.
- NamedDecl *UsingOrNextShadow;
- friend class UsingDecl;
+ NamedDecl *UsingOrNextShadow = nullptr;
+
+ void anchor() override;
+
+ using redeclarable_base = Redeclarable<UsingShadowDecl>;
- typedef Redeclarable<UsingShadowDecl> redeclarable_base;
UsingShadowDecl *getNextRedeclarationImpl() override {
return getNextRedeclaration();
}
+
UsingShadowDecl *getPreviousDeclImpl() override {
return getPreviousDecl();
}
+
UsingShadowDecl *getMostRecentDeclImpl() override {
return getMostRecentDecl();
}
@@ -3003,6 +3095,9 @@ protected:
UsingShadowDecl(Kind K, ASTContext &C, EmptyShell);
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+
static UsingShadowDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation Loc, UsingDecl *Using,
NamedDecl *Target) {
@@ -3011,8 +3106,9 @@ public:
static UsingShadowDecl *CreateDeserialized(ASTContext &C, unsigned ID);
- typedef redeclarable_base::redecl_range redecl_range;
- typedef redeclarable_base::redecl_iterator redecl_iterator;
+ using redecl_range = redeclarable_base::redecl_range;
+ using redecl_iterator = redeclarable_base::redecl_iterator;
+
using redeclarable_base::redecls_begin;
using redeclarable_base::redecls_end;
using redeclarable_base::redecls;
@@ -3052,9 +3148,6 @@ public:
static bool classofKind(Kind K) {
return K == Decl::UsingShadow || K == Decl::ConstructorUsingShadow;
}
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
};
/// \brief Represents a shadow constructor declaration introduced into a
@@ -3068,18 +3161,16 @@ public:
/// };
/// \endcode
class ConstructorUsingShadowDecl final : public UsingShadowDecl {
- void anchor() override;
-
/// \brief If this constructor using declaration inherted the constructor
/// from an indirect base class, this is the ConstructorUsingShadowDecl
/// in the named direct base class from which the declaration was inherited.
- ConstructorUsingShadowDecl *NominatedBaseClassShadowDecl;
+ ConstructorUsingShadowDecl *NominatedBaseClassShadowDecl = nullptr;
/// \brief If this constructor using declaration inherted the constructor
/// from an indirect base class, this is the ConstructorUsingShadowDecl
/// that will be used to construct the unique direct or virtual base class
/// that receives the constructor arguments.
- ConstructorUsingShadowDecl *ConstructedBaseClassShadowDecl;
+ ConstructorUsingShadowDecl *ConstructedBaseClassShadowDecl = nullptr;
/// \brief \c true if the constructor ultimately named by this using shadow
/// declaration is within a virtual base class subobject of the class that
@@ -3105,12 +3196,16 @@ class ConstructorUsingShadowDecl final : public UsingShadowDecl {
IsVirtual = true;
}
}
+
ConstructorUsingShadowDecl(ASTContext &C, EmptyShell Empty)
- : UsingShadowDecl(ConstructorUsingShadow, C, Empty),
- NominatedBaseClassShadowDecl(), ConstructedBaseClassShadowDecl(),
- IsVirtual(false) {}
+ : UsingShadowDecl(ConstructorUsingShadow, C, Empty), IsVirtual(false) {}
+
+ void anchor() override;
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+
static ConstructorUsingShadowDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation Loc,
UsingDecl *Using, NamedDecl *Target,
@@ -3169,9 +3264,6 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ConstructorUsingShadow; }
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
};
/// \brief Represents a C++ using-declaration.
@@ -3181,8 +3273,6 @@ public:
/// using someNameSpace::someIdentifier;
/// \endcode
class UsingDecl : public NamedDecl, public Mergeable<UsingDecl> {
- void anchor() override;
-
/// \brief The source location of the 'using' keyword itself.
SourceLocation UsingLocation;
@@ -3208,7 +3298,12 @@ class UsingDecl : public NamedDecl, public Mergeable<UsingDecl> {
DNLoc(NameInfo.getInfo()), FirstUsingShadow(nullptr, HasTypenameKeyword) {
}
+ void anchor() override;
+
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+
/// \brief Return the source location of the 'using' keyword.
SourceLocation getUsingLoc() const { return UsingLocation; }
@@ -3241,17 +3336,17 @@ public:
/// this using declaration.
class shadow_iterator {
/// \brief The current using shadow declaration.
- UsingShadowDecl *Current;
+ UsingShadowDecl *Current = nullptr;
public:
- typedef UsingShadowDecl* value_type;
- typedef UsingShadowDecl* reference;
- typedef UsingShadowDecl* pointer;
- typedef std::forward_iterator_tag iterator_category;
- typedef std::ptrdiff_t difference_type;
+ using value_type = UsingShadowDecl *;
+ using reference = UsingShadowDecl *;
+ using pointer = UsingShadowDecl *;
+ using iterator_category = std::forward_iterator_tag;
+ using difference_type = std::ptrdiff_t;
- shadow_iterator() : Current(nullptr) { }
- explicit shadow_iterator(UsingShadowDecl *C) : Current(C) { }
+ shadow_iterator() = default;
+ explicit shadow_iterator(UsingShadowDecl *C) : Current(C) {}
reference operator*() const { return Current; }
pointer operator->() const { return Current; }
@@ -3275,14 +3370,16 @@ public:
}
};
- typedef llvm::iterator_range<shadow_iterator> shadow_range;
+ using shadow_range = llvm::iterator_range<shadow_iterator>;
shadow_range shadows() const {
return shadow_range(shadow_begin(), shadow_end());
}
+
shadow_iterator shadow_begin() const {
return shadow_iterator(FirstUsingShadow.getPointer());
}
+
shadow_iterator shadow_end() const { return shadow_iterator(); }
/// \brief Return the number of shadowed declarations associated with this
@@ -3310,9 +3407,6 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Using; }
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
};
/// Represents a pack of using declarations that a single
@@ -3331,8 +3425,6 @@ public:
class UsingPackDecl final
: public NamedDecl, public Mergeable<UsingPackDecl>,
private llvm::TrailingObjects<UsingPackDecl, NamedDecl *> {
- void anchor() override;
-
/// The UnresolvedUsingValueDecl or UnresolvedUsingTypenameDecl from
/// which this waas instantiated.
NamedDecl *InstantiatedFrom;
@@ -3352,7 +3444,13 @@ class UsingPackDecl final
getTrailingObjects<NamedDecl *>());
}
+ void anchor() override;
+
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+ friend TrailingObjects;
+
/// Get the using declaration from which this was instantiated. This will
/// always be an UnresolvedUsingValueDecl or an UnresolvedUsingTypenameDecl
/// that is a pack expansion.
@@ -3380,10 +3478,6 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == UsingPack; }
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
- friend TrailingObjects;
};
/// \brief Represents a dependent using declaration which was not marked with
@@ -3399,8 +3493,6 @@ public:
/// \endcode
class UnresolvedUsingValueDecl : public ValueDecl,
public Mergeable<UnresolvedUsingValueDecl> {
- void anchor() override;
-
/// \brief The source location of the 'using' keyword
SourceLocation UsingLocation;
@@ -3419,13 +3511,17 @@ class UnresolvedUsingValueDecl : public ValueDecl,
NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo,
SourceLocation EllipsisLoc)
- : ValueDecl(UnresolvedUsingValue, DC,
- NameInfo.getLoc(), NameInfo.getName(), Ty),
- UsingLocation(UsingLoc), EllipsisLoc(EllipsisLoc),
- QualifierLoc(QualifierLoc), DNLoc(NameInfo.getInfo())
- { }
+ : ValueDecl(UnresolvedUsingValue, DC,
+ NameInfo.getLoc(), NameInfo.getName(), Ty),
+ UsingLocation(UsingLoc), EllipsisLoc(EllipsisLoc),
+ QualifierLoc(QualifierLoc), DNLoc(NameInfo.getInfo()) {}
+
+ void anchor() override;
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+
/// \brief Returns the source location of the 'using' keyword.
SourceLocation getUsingLoc() const { return UsingLocation; }
@@ -3478,9 +3574,6 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == UnresolvedUsingValue; }
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
};
/// \brief Represents a dependent using declaration which was marked with
@@ -3497,7 +3590,7 @@ public:
class UnresolvedUsingTypenameDecl
: public TypeDecl,
public Mergeable<UnresolvedUsingTypenameDecl> {
- void anchor() override;
+ friend class ASTDeclReader;
/// \brief The source location of the 'typename' keyword
SourceLocation TypenameLocation;
@@ -3517,9 +3610,9 @@ class UnresolvedUsingTypenameDecl
: TypeDecl(UnresolvedUsingTypename, DC, TargetNameLoc, TargetName,
UsingLoc),
TypenameLocation(TypenameLoc), EllipsisLoc(EllipsisLoc),
- QualifierLoc(QualifierLoc) { }
+ QualifierLoc(QualifierLoc) {}
- friend class ASTDeclReader;
+ void anchor() override;
public:
/// \brief Returns the source location of the 'using' keyword.
@@ -3574,7 +3667,6 @@ public:
/// \brief Represents a C++11 static_assert declaration.
class StaticAssertDecl : public Decl {
- virtual void anchor();
llvm::PointerIntPair<Expr *, 1, bool> AssertExprAndFailed;
StringLiteral *Message;
SourceLocation RParenLoc;
@@ -3582,11 +3674,15 @@ class StaticAssertDecl : public Decl {
StaticAssertDecl(DeclContext *DC, SourceLocation StaticAssertLoc,
Expr *AssertExpr, StringLiteral *Message,
SourceLocation RParenLoc, bool Failed)
- : Decl(StaticAssert, DC, StaticAssertLoc),
- AssertExprAndFailed(AssertExpr, Failed), Message(Message),
- RParenLoc(RParenLoc) { }
+ : Decl(StaticAssert, DC, StaticAssertLoc),
+ AssertExprAndFailed(AssertExpr, Failed), Message(Message),
+ RParenLoc(RParenLoc) {}
+
+ virtual void anchor();
public:
+ friend class ASTDeclReader;
+
static StaticAssertDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation StaticAssertLoc,
Expr *AssertExpr, StringLiteral *Message,
@@ -3609,8 +3705,6 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == StaticAssert; }
-
- friend class ASTDeclReader;
};
/// A binding in a decomposition declaration. For instance, given:
@@ -3622,18 +3716,20 @@ public:
/// x[0], x[1], and x[2] respectively, where x is the implicit
/// DecompositionDecl of type 'int (&)[3]'.
class BindingDecl : public ValueDecl {
- void anchor() override;
-
/// The binding represented by this declaration. References to this
/// declaration are effectively equivalent to this expression (except
/// that it is only evaluated once at the point of declaration of the
/// binding).
- Expr *Binding;
+ Expr *Binding = nullptr;
BindingDecl(DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id)
- : ValueDecl(Decl::Binding, DC, IdLoc, Id, QualType()), Binding(nullptr) {}
+ : ValueDecl(Decl::Binding, DC, IdLoc, Id, QualType()) {}
+
+ void anchor() override;
public:
+ friend class ASTDeclReader;
+
static BindingDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation IdLoc, IdentifierInfo *Id);
static BindingDecl *CreateDeserialized(ASTContext &C, unsigned ID);
@@ -3657,8 +3753,6 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Decl::Binding; }
-
- friend class ASTDeclReader;
};
/// A decomposition declaration. For instance, given:
@@ -3672,8 +3766,6 @@ public:
class DecompositionDecl final
: public VarDecl,
private llvm::TrailingObjects<DecompositionDecl, BindingDecl *> {
- void anchor() override;
-
/// The number of BindingDecl*s following this object.
unsigned NumBindings;
@@ -3688,7 +3780,12 @@ class DecompositionDecl final
getTrailingObjects<BindingDecl *>());
}
+ void anchor() override;
+
public:
+ friend class ASTDeclReader;
+ friend TrailingObjects;
+
static DecompositionDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc,
SourceLocation LSquareLoc,
@@ -3706,9 +3803,6 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Decomposition; }
-
- friend TrailingObjects;
- friend class ASTDeclReader;
};
/// An instance of this class represents the declaration of a property
@@ -3748,6 +3842,8 @@ class MSPropertyDecl : public DeclaratorDecl {
GetterId(Getter), SetterId(Setter) {}
public:
+ friend class ASTDeclReader;
+
static MSPropertyDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, DeclarationName N, QualType T,
TypeSourceInfo *TInfo, SourceLocation StartL,
@@ -3760,8 +3856,6 @@ public:
IdentifierInfo* getGetterId() const { return GetterId; }
bool hasSetter() const { return SetterId != nullptr; }
IdentifierInfo* getSetterId() const { return SetterId; }
-
- friend class ASTDeclReader;
};
/// Insertion operator for diagnostics. This allows sending an AccessSpecifier
@@ -3772,6 +3866,6 @@ const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
const PartialDiagnostic &operator<<(const PartialDiagnostic &DB,
AccessSpecifier AS);
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_AST_DECLCXX_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclContextInternals.h b/contrib/llvm/tools/clang/include/clang/AST/DeclContextInternals.h
index eb86526e8eca0..6545f70f70b55 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclContextInternals.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclContextInternals.h
@@ -1,4 +1,4 @@
-//===-- DeclContextInternals.h - DeclContext Representation -----*- C++ -*-===//
+//===- DeclContextInternals.h - DeclContext Representation ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,10 +11,12 @@
// of DeclContext.
//
//===----------------------------------------------------------------------===//
+
#ifndef LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
#define LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclarationName.h"
#include "llvm/ADT/DenseMap.h"
@@ -22,6 +24,7 @@
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallVector.h"
#include <algorithm>
+#include <cassert>
namespace clang {
@@ -30,21 +33,20 @@ class DependentDiagnostic;
/// \brief An array of decls optimized for the common case of only containing
/// one entry.
struct StoredDeclsList {
-
/// \brief When in vector form, this is what the Data pointer points to.
- typedef SmallVector<NamedDecl *, 4> DeclsTy;
+ using DeclsTy = SmallVector<NamedDecl *, 4>;
/// \brief A collection of declarations, with a flag to indicate if we have
/// further external declarations.
- typedef llvm::PointerIntPair<DeclsTy *, 1, bool> DeclsAndHasExternalTy;
+ using DeclsAndHasExternalTy = llvm::PointerIntPair<DeclsTy *, 1, bool>;
/// \brief The stored data, which will be either a pointer to a NamedDecl,
/// or a pointer to a vector with a flag to indicate if there are further
/// external declarations.
- llvm::PointerUnion<NamedDecl*, DeclsAndHasExternalTy> Data;
+ llvm::PointerUnion<NamedDecl *, DeclsAndHasExternalTy> Data;
public:
- StoredDeclsList() {}
+ StoredDeclsList() = default;
StoredDeclsList(StoredDeclsList &&RHS) : Data(RHS.Data) {
RHS.Data = (NamedDecl *)nullptr;
@@ -186,7 +188,6 @@ public:
/// AddSubsequentDecl - This is called on the second and later decl when it is
/// not a redeclaration to merge it into the appropriate place in our list.
- ///
void AddSubsequentDecl(NamedDecl *D) {
assert(!isNull() && "don't AddSubsequentDecl when we have no decls");
@@ -237,28 +238,28 @@ public:
};
class StoredDeclsMap
- : public llvm::SmallDenseMap<DeclarationName, StoredDeclsList, 4> {
-
+ : public llvm::SmallDenseMap<DeclarationName, StoredDeclsList, 4> {
public:
static void DestroyAll(StoredDeclsMap *Map, bool Dependent);
private:
friend class ASTContext; // walks the chain deleting these
friend class DeclContext;
+
llvm::PointerIntPair<StoredDeclsMap*, 1> Previous;
};
class DependentStoredDeclsMap : public StoredDeclsMap {
public:
- DependentStoredDeclsMap() : FirstDiagnostic(nullptr) {}
+ DependentStoredDeclsMap() = default;
private:
- friend class DependentDiagnostic;
friend class DeclContext; // iterates over diagnostics
+ friend class DependentDiagnostic;
- DependentDiagnostic *FirstDiagnostic;
+ DependentDiagnostic *FirstDiagnostic = nullptr;
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h b/contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h
index 172c46a44ac1d..5d1c6b86fe118 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h
@@ -1,4 +1,4 @@
-//===-- DeclFriend.h - Classes for C++ friend declarations -*- C++ -*------===//
+//===- DeclFriend.h - Classes for C++ friend declarations -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,16 +15,30 @@
#ifndef LLVM_CLANG_AST_DECLFRIEND_H
#define LLVM_CLANG_AST_DECLFRIEND_H
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/TypeLoc.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/TrailingObjects.h"
+#include <cassert>
+#include <iterator>
namespace clang {
+class ASTContext;
+
/// FriendDecl - Represents the declaration of a friend entity,
/// which can be a function, a type, or a templated function or type.
-// For example:
+/// For example:
///
/// @code
/// template <typename T> class A {
@@ -41,10 +55,14 @@ class FriendDecl final
: public Decl,
private llvm::TrailingObjects<FriendDecl, TemplateParameterList *> {
virtual void anchor();
+
public:
- typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion;
+ using FriendUnion = llvm::PointerUnion<NamedDecl *, TypeSourceInfo *>;
private:
+ friend class CXXRecordDecl;
+ friend class CXXRecordDecl::friend_iterator;
+
// The declaration that's a friend of this class.
FriendUnion Friend;
@@ -64,35 +82,33 @@ private:
// template <class T> friend class A<T>::B;
unsigned NumTPLists : 31;
- friend class CXXRecordDecl::friend_iterator;
- friend class CXXRecordDecl;
-
FriendDecl(DeclContext *DC, SourceLocation L, FriendUnion Friend,
SourceLocation FriendL,
- ArrayRef<TemplateParameterList*> FriendTypeTPLists)
- : Decl(Decl::Friend, DC, L),
- Friend(Friend),
- NextFriend(),
- FriendLoc(FriendL),
- UnsupportedFriend(false),
- NumTPLists(FriendTypeTPLists.size()) {
+ ArrayRef<TemplateParameterList *> FriendTypeTPLists)
+ : Decl(Decl::Friend, DC, L), Friend(Friend), FriendLoc(FriendL),
+ UnsupportedFriend(false), NumTPLists(FriendTypeTPLists.size()) {
for (unsigned i = 0; i < NumTPLists; ++i)
getTrailingObjects<TemplateParameterList *>()[i] = FriendTypeTPLists[i];
}
FriendDecl(EmptyShell Empty, unsigned NumFriendTypeTPLists)
- : Decl(Decl::Friend, Empty), NextFriend(),
- UnsupportedFriend(false),
- NumTPLists(NumFriendTypeTPLists) { }
+ : Decl(Decl::Friend, Empty), UnsupportedFriend(false),
+ NumTPLists(NumFriendTypeTPLists) {}
FriendDecl *getNextFriend() {
if (!NextFriend.isOffset())
return cast_or_null<FriendDecl>(NextFriend.get(nullptr));
return getNextFriendSlowCase();
}
+
FriendDecl *getNextFriendSlowCase();
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+ friend class ASTNodeImporter;
+ friend TrailingObjects;
+
static FriendDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, FriendUnion Friend_,
SourceLocation FriendL,
@@ -108,9 +124,11 @@ public:
TypeSourceInfo *getFriendType() const {
return Friend.dyn_cast<TypeSourceInfo*>();
}
+
unsigned getFriendTypeNumTemplateParameterLists() const {
return NumTPLists;
}
+
TemplateParameterList *getFriendTypeTemplateParameterList(unsigned N) const {
assert(N < NumTPLists);
return getTrailingObjects<TemplateParameterList *>()[N];
@@ -119,7 +137,7 @@ public:
/// If this friend declaration doesn't name a type, return the inner
/// declaration.
NamedDecl *getFriendDecl() const {
- return Friend.dyn_cast<NamedDecl*>();
+ return Friend.dyn_cast<NamedDecl *>();
}
/// Retrieves the location of the 'friend' keyword.
@@ -164,27 +182,24 @@ public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Decl::Friend; }
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
- friend class ASTNodeImporter;
- friend TrailingObjects;
};
/// An iterator over the friend declarations of a class.
class CXXRecordDecl::friend_iterator {
+ friend class CXXRecordDecl;
+
FriendDecl *Ptr;
- friend class CXXRecordDecl;
explicit friend_iterator(FriendDecl *Ptr) : Ptr(Ptr) {}
+
public:
- friend_iterator() {}
+ friend_iterator() = default;
- typedef FriendDecl *value_type;
- typedef FriendDecl *reference;
- typedef FriendDecl *pointer;
- typedef int difference_type;
- typedef std::forward_iterator_tag iterator_category;
+ using value_type = FriendDecl *;
+ using reference = FriendDecl *;
+ using pointer = FriendDecl *;
+ using difference_type = int;
+ using iterator_category = std::forward_iterator_tag;
reference operator*() const { return Ptr; }
@@ -240,6 +255,6 @@ inline void CXXRecordDecl::pushFriendDecl(FriendDecl *FD) {
data().FirstFriend = FD;
}
-}
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_AST_DECLFRIEND_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h b/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h
index 6353b26f7bf57..6d5aaadf529cc 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h
@@ -1,4 +1,4 @@
-//===--- DeclGroup.h - Classes for representing groups of Decls -*- C++ -*-===//
+//===- DeclGroup.h - Classes for representing groups of Decls ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,26 +14,26 @@
#ifndef LLVM_CLANG_AST_DECLGROUP_H
#define LLVM_CLANG_AST_DECLGROUP_H
-#include "llvm/Support/DataTypes.h"
#include "llvm/Support/TrailingObjects.h"
#include <cassert>
+#include <cstdint>
namespace clang {
class ASTContext;
class Decl;
-class DeclGroup;
-class DeclGroupIterator;
class DeclGroup final : private llvm::TrailingObjects<DeclGroup, Decl *> {
// FIXME: Include a TypeSpecifier object.
- unsigned NumDecls;
+ unsigned NumDecls = 0;
private:
- DeclGroup() : NumDecls(0) {}
+ DeclGroup() = default;
DeclGroup(unsigned numdecls, Decl** decls);
public:
+ friend TrailingObjects;
+
static DeclGroup *Create(ASTContext &C, Decl **Decls, unsigned NumDecls);
unsigned size() const { return NumDecls; }
@@ -47,23 +47,21 @@ public:
assert (i < NumDecls && "Out-of-bounds access.");
return getTrailingObjects<Decl *>()[i];
}
-
- friend TrailingObjects;
};
class DeclGroupRef {
// Note this is not a PointerIntPair because we need the address of the
// non-group case to be valid as a Decl** for iteration.
enum Kind { SingleDeclKind=0x0, DeclGroupKind=0x1, Mask=0x1 };
- Decl* D;
+
+ Decl* D = nullptr;
Kind getKind() const {
return (Kind) (reinterpret_cast<uintptr_t>(D) & Mask);
}
public:
- DeclGroupRef() : D(nullptr) {}
-
+ DeclGroupRef() = default;
explicit DeclGroupRef(Decl* d) : D(d) {}
explicit DeclGroupRef(DeclGroup* dg)
: D((Decl*) (reinterpret_cast<uintptr_t>(dg) | DeclGroupKind)) {}
@@ -76,8 +74,8 @@ public:
return DeclGroupRef(DeclGroup::Create(C, Decls, NumDecls));
}
- typedef Decl** iterator;
- typedef Decl* const * const_iterator;
+ using iterator = Decl **;
+ using const_iterator = Decl * const *;
bool isNull() const { return D == nullptr; }
bool isSingleDecl() const { return getKind() == SingleDeclKind; }
@@ -133,22 +131,26 @@ public:
}
};
-} // end clang namespace
+} // namespace clang
namespace llvm {
+
// DeclGroupRef is "like a pointer", implement PointerLikeTypeTraits.
template <typename T>
- class PointerLikeTypeTraits;
+ struct PointerLikeTypeTraits;
template <>
- class PointerLikeTypeTraits<clang::DeclGroupRef> {
- public:
+ struct PointerLikeTypeTraits<clang::DeclGroupRef> {
static inline void *getAsVoidPointer(clang::DeclGroupRef P) {
return P.getAsOpaquePtr();
}
+
static inline clang::DeclGroupRef getFromVoidPointer(void *P) {
return clang::DeclGroupRef::getFromOpaquePtr(P);
}
+
enum { NumLowBitsAvailable = 0 };
};
-}
-#endif
+
+} // namespace llvm
+
+#endif // LLVM_CLANG_AST_DECLGROUP_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclLookups.h b/contrib/llvm/tools/clang/include/clang/AST/DeclLookups.h
index eba2266724fd3..2fff055825632 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclLookups.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclLookups.h
@@ -1,4 +1,4 @@
-//===-- DeclLookups.h - Low-level interface to all names in a DC-*- C++ -*-===//
+//===- DeclLookups.h - Low-level interface to all names in a DC -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -18,6 +18,9 @@
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclContextInternals.h"
#include "clang/AST/DeclarationName.h"
+#include "clang/AST/ExternalASTSource.h"
+#include <cstddef>
+#include <iterator>
namespace clang {
@@ -25,14 +28,15 @@ namespace clang {
/// of looking up every possible name.
class DeclContext::all_lookups_iterator {
StoredDeclsMap::iterator It, End;
+
public:
- typedef lookup_result value_type;
- typedef lookup_result reference;
- typedef lookup_result pointer;
- typedef std::forward_iterator_tag iterator_category;
- typedef std::ptrdiff_t difference_type;
+ using value_type = lookup_result;
+ using reference = lookup_result;
+ using pointer = lookup_result;
+ using iterator_category = std::forward_iterator_tag;
+ using difference_type = std::ptrdiff_t;
- all_lookups_iterator() {}
+ all_lookups_iterator() = default;
all_lookups_iterator(StoredDeclsMap::iterator It,
StoredDeclsMap::iterator End)
: It(It), End(End) {}
@@ -63,6 +67,7 @@ public:
friend bool operator==(all_lookups_iterator x, all_lookups_iterator y) {
return x.It == y.It;
}
+
friend bool operator!=(all_lookups_iterator x, all_lookups_iterator y) {
return x.It != y.It;
}
@@ -110,6 +115,6 @@ DeclContext::all_lookups_iterator DeclContext::noload_lookups_end() const {
return noload_lookups().end();
}
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_AST_DECLLOOKUPS_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h b/contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h
index 1cd6e004f751f..cef7d935370a2 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h
@@ -1,4 +1,4 @@
-//===--- DeclObjC.h - Classes for representing declarations -----*- C++ -*-===//
+//===- DeclObjC.h - Classes for representing declarations -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,33 +15,59 @@
#define LLVM_CLANG_AST_DECLOBJC_H
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/ExternalASTSource.h"
+#include "clang/AST/Redeclarable.h"
#include "clang/AST/SelectorLocationsKind.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/TrailingObjects.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <iterator>
+#include <string>
+#include <utility>
namespace clang {
+
+class ASTContext;
+class CompoundStmt;
+class CXXCtorInitializer;
class Expr;
-class Stmt;
-class FunctionDecl;
-class RecordDecl;
-class ObjCIvarDecl;
-class ObjCMethodDecl;
-class ObjCProtocolDecl;
class ObjCCategoryDecl;
+class ObjCCategoryImplDecl;
+class ObjCImplementationDecl;
+class ObjCInterfaceDecl;
+class ObjCIvarDecl;
class ObjCPropertyDecl;
class ObjCPropertyImplDecl;
-class CXXCtorInitializer;
+class ObjCProtocolDecl;
+class Stmt;
class ObjCListBase {
- ObjCListBase(const ObjCListBase &) = delete;
- void operator=(const ObjCListBase &) = delete;
protected:
/// List is an array of pointers to objects that are not owned by this object.
- void **List;
- unsigned NumElts;
+ void **List = nullptr;
+ unsigned NumElts = 0;
public:
- ObjCListBase() : List(nullptr), NumElts(0) {}
+ ObjCListBase() = default;
+ ObjCListBase(const ObjCListBase &) = delete;
+ ObjCListBase &operator=(const ObjCListBase &) = delete;
+
unsigned size() const { return NumElts; }
bool empty() const { return NumElts == 0; }
@@ -49,7 +75,6 @@ protected:
void set(void *const* InList, unsigned Elts, ASTContext &Ctx);
};
-
/// ObjCList - This is a simple template class used to hold various lists of
/// decls etc, which is heavily used by the ObjC front-end. This only use case
/// this supports is setting the list all at once and then reading elements out
@@ -61,7 +86,8 @@ public:
ObjCListBase::set(reinterpret_cast<void*const*>(InList), Elts, Ctx);
}
- typedef T* const * iterator;
+ using iterator = T* const *;
+
iterator begin() const { return (iterator)List; }
iterator end() const { return (iterator)List+NumElts; }
@@ -74,14 +100,15 @@ public:
/// \brief A list of Objective-C protocols, along with the source
/// locations at which they were referenced.
class ObjCProtocolList : public ObjCList<ObjCProtocolDecl> {
- SourceLocation *Locations;
+ SourceLocation *Locations = nullptr;
using ObjCList<ObjCProtocolDecl>::set;
public:
- ObjCProtocolList() : ObjCList<ObjCProtocolDecl>(), Locations(nullptr) { }
+ ObjCProtocolList() = default;
+
+ using loc_iterator = const SourceLocation *;
- typedef const SourceLocation *loc_iterator;
loc_iterator loc_begin() const { return Locations; }
loc_iterator loc_end() const { return Locations + size(); }
@@ -89,7 +116,6 @@ public:
const SourceLocation *Locs, ASTContext &Ctx);
};
-
/// ObjCMethodDecl - Represents an instance or class method declaration.
/// ObjC methods can be declared within 4 contexts: class interfaces,
/// categories, protocols, and class implementations. While C++ member
@@ -113,6 +139,7 @@ public:
class ObjCMethodDecl : public NamedDecl, public DeclContext {
public:
enum ImplementationControl { None, Required, Optional };
+
private:
// The conventional meaning of this method; an ObjCMethodFamily.
// This is not serialized; instead, it is computed on demand and
@@ -170,8 +197,8 @@ private:
/// \brief Array of ParmVarDecls for the formal parameters of this method
/// and optionally followed by selector locations.
- void *ParamsAndSelLocs;
- unsigned NumParams;
+ void *ParamsAndSelLocs = nullptr;
+ unsigned NumParams = 0;
/// List of attributes for this method declaration.
SourceLocation DeclEndLoc; // the location of the ';' or '{'.
@@ -181,14 +208,35 @@ private:
/// SelfDecl - Decl for the implicit self parameter. This is lazily
/// constructed by createImplicitParams.
- ImplicitParamDecl *SelfDecl;
+ ImplicitParamDecl *SelfDecl = nullptr;
+
/// CmdDecl - Decl for the implicit _cmd parameter. This is lazily
/// constructed by createImplicitParams.
- ImplicitParamDecl *CmdDecl;
+ ImplicitParamDecl *CmdDecl = nullptr;
+
+ ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc,
+ Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo,
+ DeclContext *contextDecl, bool isInstance = true,
+ bool isVariadic = false, bool isPropertyAccessor = false,
+ bool isImplicitlyDeclared = false, bool isDefined = false,
+ ImplementationControl impControl = None,
+ bool HasRelatedResultType = false)
+ : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo),
+ DeclContext(ObjCMethod), Family(InvalidObjCMethodFamily),
+ IsInstance(isInstance), IsVariadic(isVariadic),
+ IsPropertyAccessor(isPropertyAccessor), IsDefined(isDefined),
+ IsRedeclaration(0), HasRedeclaration(0), DeclImplementation(impControl),
+ objcDeclQualifier(OBJC_TQ_None),
+ RelatedResultType(HasRelatedResultType),
+ SelLocsKind(SelLoc_StandardNoSpace), IsOverriding(0), HasSkippedBody(0),
+ MethodDeclType(T), ReturnTInfo(ReturnTInfo), DeclEndLoc(endLoc) {
+ setImplicit(isImplicitlyDeclared);
+ }
SelectorLocationsKind getSelLocsKind() const {
return (SelectorLocationsKind)SelLocsKind;
}
+
bool hasStandardSelLocs() const {
return getSelLocsKind() != SelLoc_NonStandard;
}
@@ -223,33 +271,15 @@ private:
ArrayRef<ParmVarDecl*> Params,
ArrayRef<SourceLocation> SelLocs);
- ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc,
- Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo,
- DeclContext *contextDecl, bool isInstance = true,
- bool isVariadic = false, bool isPropertyAccessor = false,
- bool isImplicitlyDeclared = false, bool isDefined = false,
- ImplementationControl impControl = None,
- bool HasRelatedResultType = false)
- : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo),
- DeclContext(ObjCMethod), Family(InvalidObjCMethodFamily),
- IsInstance(isInstance), IsVariadic(isVariadic),
- IsPropertyAccessor(isPropertyAccessor), IsDefined(isDefined),
- IsRedeclaration(0), HasRedeclaration(0), DeclImplementation(impControl),
- objcDeclQualifier(OBJC_TQ_None),
- RelatedResultType(HasRelatedResultType),
- SelLocsKind(SelLoc_StandardNoSpace), IsOverriding(0), HasSkippedBody(0),
- MethodDeclType(T), ReturnTInfo(ReturnTInfo), ParamsAndSelLocs(nullptr),
- NumParams(0), DeclEndLoc(endLoc), Body(), SelfDecl(nullptr),
- CmdDecl(nullptr) {
- setImplicit(isImplicitlyDeclared);
- }
-
/// \brief A definition will return its interface declaration.
/// An interface declaration will return its definition.
/// Otherwise it will return itself.
ObjCMethodDecl *getNextRedeclarationImpl() override;
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+
static ObjCMethodDecl *
Create(ASTContext &C, SourceLocation beginLoc, SourceLocation endLoc,
Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo,
@@ -299,6 +329,7 @@ public:
return getLocStart();
return getSelectorLoc(0);
}
+
SourceLocation getSelectorLoc(unsigned Index) const {
assert(Index < getNumSelectorLocs() && "Index out of range!");
if (hasStandardSelLocs())
@@ -346,17 +377,20 @@ public:
// Iterator access to formal parameters.
unsigned param_size() const { return NumParams; }
- typedef const ParmVarDecl *const *param_const_iterator;
- typedef ParmVarDecl *const *param_iterator;
- typedef llvm::iterator_range<param_iterator> param_range;
- typedef llvm::iterator_range<param_const_iterator> param_const_range;
+
+ using param_const_iterator = const ParmVarDecl *const *;
+ using param_iterator = ParmVarDecl *const *;
+ using param_range = llvm::iterator_range<param_iterator>;
+ using param_const_range = llvm::iterator_range<param_const_iterator>;
param_const_iterator param_begin() const {
return param_const_iterator(getParams());
}
+
param_const_iterator param_end() const {
return param_const_iterator(getParams() + NumParams);
}
+
param_iterator param_begin() { return param_iterator(getParams()); }
param_iterator param_end() { return param_iterator(getParams() + NumParams); }
@@ -384,12 +418,14 @@ public:
struct GetTypeFn {
QualType operator()(const ParmVarDecl *PD) const { return PD->getType(); }
};
- typedef llvm::mapped_iterator<param_const_iterator, GetTypeFn>
- param_type_iterator;
+
+ using param_type_iterator =
+ llvm::mapped_iterator<param_const_iterator, GetTypeFn>;
param_type_iterator param_type_begin() const {
return llvm::map_iterator(param_begin(), GetTypeFn());
}
+
param_type_iterator param_type_end() const {
return llvm::map_iterator(param_end(), GetTypeFn());
}
@@ -462,9 +498,11 @@ public:
void setDeclImplementation(ImplementationControl ic) {
DeclImplementation = ic;
}
+
ImplementationControl getImplementationControl() const {
return ImplementationControl(DeclImplementation);
}
+
bool isOptional() const {
return getImplementationControl() == Optional;
}
@@ -499,24 +537,25 @@ public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ObjCMethod; }
+
static DeclContext *castToDeclContext(const ObjCMethodDecl *D) {
return static_cast<DeclContext *>(const_cast<ObjCMethodDecl*>(D));
}
+
static ObjCMethodDecl *castFromDeclContext(const DeclContext *DC) {
return static_cast<ObjCMethodDecl *>(const_cast<DeclContext*>(DC));
}
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
};
/// Describes the variance of a given generic parameter.
enum class ObjCTypeParamVariance : uint8_t {
/// The parameter is invariant: must match exactly.
Invariant,
+
/// The parameter is covariant, e.g., X<T> is a subtype of X<U> when
/// the type parameter is covariant and T is a subtype of U.
Covariant,
+
/// The parameter is contravariant, e.g., X<T> is a subtype of X<U>
/// when the type parameter is covariant and U is a subtype of T.
Contravariant,
@@ -535,8 +574,6 @@ enum class ObjCTypeParamVariance : uint8_t {
///
/// Objective-C type parameters are typedef-names in the grammar,
class ObjCTypeParamDecl : public TypedefNameDecl {
- void anchor() override;
-
/// Index of this type parameter in the type parameter list.
unsigned Index : 14;
@@ -555,12 +592,17 @@ class ObjCTypeParamDecl : public TypedefNameDecl {
unsigned index,
SourceLocation nameLoc, IdentifierInfo *name,
SourceLocation colonLoc, TypeSourceInfo *boundInfo)
- : TypedefNameDecl(ObjCTypeParam, ctx, dc, nameLoc, nameLoc, name,
- boundInfo),
- Index(index), Variance(static_cast<unsigned>(variance)),
- VarianceLoc(varianceLoc), ColonLoc(colonLoc) { }
+ : TypedefNameDecl(ObjCTypeParam, ctx, dc, nameLoc, nameLoc, name,
+ boundInfo),
+ Index(index), Variance(static_cast<unsigned>(variance)),
+ VarianceLoc(varianceLoc), ColonLoc(colonLoc) {}
+
+ void anchor() override;
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+
static ObjCTypeParamDecl *Create(ASTContext &ctx, DeclContext *dc,
ObjCTypeParamVariance variance,
SourceLocation varianceLoc,
@@ -600,9 +642,6 @@ public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ObjCTypeParam; }
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
};
/// Stores a list of Objective-C type parameters for a parameterized class
@@ -636,6 +675,8 @@ class ObjCTypeParamList final
SourceLocation rAngleLoc);
public:
+ friend TrailingObjects;
+
/// Create a new Objective-C type parameter list.
static ObjCTypeParamList *create(ASTContext &ctx,
SourceLocation lAngleLoc,
@@ -643,7 +684,7 @@ public:
SourceLocation rAngleLoc);
/// Iterate through the type parameters in the list.
- typedef ObjCTypeParamDecl **iterator;
+ using iterator = ObjCTypeParamDecl **;
iterator begin() { return getTrailingObjects<ObjCTypeParamDecl *>(); }
@@ -653,7 +694,7 @@ public:
unsigned size() const { return NumParams; }
// Iterate through the type parameters in the list.
- typedef ObjCTypeParamDecl * const *const_iterator;
+ using const_iterator = ObjCTypeParamDecl * const *;
const_iterator begin() const {
return getTrailingObjects<ObjCTypeParamDecl *>();
@@ -676,9 +717,11 @@ public:
SourceLocation getLAngleLoc() const {
return SourceLocation::getFromRawEncoding(Brackets.Begin);
}
+
SourceLocation getRAngleLoc() const {
return SourceLocation::getFromRawEncoding(Brackets.End);
}
+
SourceRange getSourceRange() const {
return SourceRange(getLAngleLoc(), getRAngleLoc());
}
@@ -686,7 +729,6 @@ public:
/// Gather the default set of type arguments to be substituted for
/// these type parameters when dealing with an unspecialized type.
void gatherDefaultTypeArgs(SmallVectorImpl<QualType> &typeArgs) const;
- friend TrailingObjects;
};
enum class ObjCPropertyQueryKind : uint8_t {
@@ -703,6 +745,7 @@ enum class ObjCPropertyQueryKind : uint8_t {
/// \endcode
class ObjCPropertyDecl : public NamedDecl {
void anchor() override;
+
public:
enum PropertyAttributeKind {
OBJC_PR_noattr = 0x00,
@@ -733,24 +776,42 @@ public:
enum SetterKind { Assign, Retain, Copy, Weak };
enum PropertyControl { None, Required, Optional };
+
private:
- SourceLocation AtLoc; // location of \@property
- SourceLocation LParenLoc; // location of '(' starting attribute list or null.
+ // location of \@property
+ SourceLocation AtLoc;
+
+ // location of '(' starting attribute list or null.
+ SourceLocation LParenLoc;
+
QualType DeclType;
TypeSourceInfo *DeclTypeSourceInfo;
unsigned PropertyAttributes : NumPropertyAttrsBits;
unsigned PropertyAttributesAsWritten : NumPropertyAttrsBits;
+
// \@required/\@optional
unsigned PropertyImplementation : 2;
- Selector GetterName; // getter name of NULL if no getter
- Selector SetterName; // setter name of NULL if no setter
- SourceLocation GetterNameLoc; // location of the getter attribute's value
- SourceLocation SetterNameLoc; // location of the setter attribute's value
+ // getter name of NULL if no getter
+ Selector GetterName;
+
+ // setter name of NULL if no setter
+ Selector SetterName;
+
+ // location of the getter attribute's value
+ SourceLocation GetterNameLoc;
+
+ // location of the setter attribute's value
+ SourceLocation SetterNameLoc;
+
+ // Declaration of getter instance method
+ ObjCMethodDecl *GetterMethodDecl = nullptr;
+
+ // Declaration of setter instance method
+ ObjCMethodDecl *SetterMethodDecl = nullptr;
- ObjCMethodDecl *GetterMethodDecl; // Declaration of getter instance method
- ObjCMethodDecl *SetterMethodDecl; // Declaration of setter instance method
- ObjCIvarDecl *PropertyIvarDecl; // Synthesize ivar for this property
+ // Synthesize ivar for this property
+ ObjCIvarDecl *PropertyIvarDecl = nullptr;
ObjCPropertyDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
SourceLocation AtLocation, SourceLocation LParenLocation,
@@ -760,11 +821,8 @@ private:
LParenLoc(LParenLocation), DeclType(T), DeclTypeSourceInfo(TSI),
PropertyAttributes(OBJC_PR_noattr),
PropertyAttributesAsWritten(OBJC_PR_noattr),
- PropertyImplementation(propControl),
- GetterName(Selector()),
- SetterName(Selector()),
- GetterMethodDecl(nullptr), SetterMethodDecl(nullptr),
- PropertyIvarDecl(nullptr) {}
+ PropertyImplementation(propControl), GetterName(Selector()),
+ SetterName(Selector()) {}
public:
static ObjCPropertyDecl *Create(ASTContext &C, DeclContext *DC,
@@ -799,9 +857,11 @@ public:
PropertyAttributeKind getPropertyAttributes() const {
return PropertyAttributeKind(PropertyAttributes);
}
+
void setPropertyAttributes(PropertyAttributeKind PRVal) {
PropertyAttributes |= PRVal;
}
+
void overwritePropertyAttributes(unsigned PRVal) {
PropertyAttributes = PRVal;
}
@@ -834,10 +894,12 @@ public:
bool isInstanceProperty() const { return !isClassProperty(); }
bool isClassProperty() const { return PropertyAttributes & OBJC_PR_class; }
+
ObjCPropertyQueryKind getQueryKind() const {
return isClassProperty() ? ObjCPropertyQueryKind::OBJC_PR_query_class :
ObjCPropertyQueryKind::OBJC_PR_query_instance;
}
+
static ObjCPropertyQueryKind getQueryKind(bool isClassProperty) {
return isClassProperty ? ObjCPropertyQueryKind::OBJC_PR_query_class :
ObjCPropertyQueryKind::OBJC_PR_query_instance;
@@ -860,6 +922,7 @@ public:
Selector getGetterName() const { return GetterName; }
SourceLocation getGetterNameLoc() const { return GetterNameLoc; }
+
void setGetterName(Selector Sel, SourceLocation Loc = SourceLocation()) {
GetterName = Sel;
GetterNameLoc = Loc;
@@ -867,6 +930,7 @@ public:
Selector getSetterName() const { return SetterName; }
SourceLocation getSetterNameLoc() const { return SetterNameLoc; }
+
void setSetterName(Selector Sel, SourceLocation Loc = SourceLocation()) {
SetterName = Sel;
SetterNameLoc = Loc;
@@ -882,9 +946,11 @@ public:
void setPropertyImplementation(PropertyControl pc) {
PropertyImplementation = pc;
}
+
PropertyControl getPropertyImplementation() const {
return PropertyControl(PropertyImplementation);
}
+
bool isOptional() const {
return getPropertyImplementation() == PropertyControl::Optional;
}
@@ -892,6 +958,7 @@ public:
void setPropertyIvarDecl(ObjCIvarDecl *Ivar) {
PropertyIvarDecl = Ivar;
}
+
ObjCIvarDecl *getPropertyIvarDecl() const {
return PropertyIvarDecl;
}
@@ -917,104 +984,116 @@ public:
/// ObjCProtocolDecl, and ObjCImplDecl.
///
class ObjCContainerDecl : public NamedDecl, public DeclContext {
- void anchor() override;
-
SourceLocation AtStart;
// These two locations in the range mark the end of the method container.
// The first points to the '@' token, and the second to the 'end' token.
SourceRange AtEnd;
-public:
+ void anchor() override;
+
+public:
ObjCContainerDecl(Kind DK, DeclContext *DC,
IdentifierInfo *Id, SourceLocation nameLoc,
SourceLocation atStartLoc)
- : NamedDecl(DK, DC, nameLoc, Id), DeclContext(DK), AtStart(atStartLoc) {}
+ : NamedDecl(DK, DC, nameLoc, Id), DeclContext(DK), AtStart(atStartLoc) {}
// Iterator access to instance/class properties.
- typedef specific_decl_iterator<ObjCPropertyDecl> prop_iterator;
- typedef llvm::iterator_range<specific_decl_iterator<ObjCPropertyDecl>>
- prop_range;
+ using prop_iterator = specific_decl_iterator<ObjCPropertyDecl>;
+ using prop_range =
+ llvm::iterator_range<specific_decl_iterator<ObjCPropertyDecl>>;
prop_range properties() const { return prop_range(prop_begin(), prop_end()); }
+
prop_iterator prop_begin() const {
return prop_iterator(decls_begin());
}
+
prop_iterator prop_end() const {
return prop_iterator(decls_end());
}
- typedef filtered_decl_iterator<ObjCPropertyDecl,
- &ObjCPropertyDecl::isInstanceProperty>
- instprop_iterator;
- typedef llvm::iterator_range<instprop_iterator> instprop_range;
+ using instprop_iterator =
+ filtered_decl_iterator<ObjCPropertyDecl,
+ &ObjCPropertyDecl::isInstanceProperty>;
+ using instprop_range = llvm::iterator_range<instprop_iterator>;
instprop_range instance_properties() const {
return instprop_range(instprop_begin(), instprop_end());
}
+
instprop_iterator instprop_begin() const {
return instprop_iterator(decls_begin());
}
+
instprop_iterator instprop_end() const {
return instprop_iterator(decls_end());
}
- typedef filtered_decl_iterator<ObjCPropertyDecl,
- &ObjCPropertyDecl::isClassProperty>
- classprop_iterator;
- typedef llvm::iterator_range<classprop_iterator> classprop_range;
+ using classprop_iterator =
+ filtered_decl_iterator<ObjCPropertyDecl,
+ &ObjCPropertyDecl::isClassProperty>;
+ using classprop_range = llvm::iterator_range<classprop_iterator>;
classprop_range class_properties() const {
return classprop_range(classprop_begin(), classprop_end());
}
+
classprop_iterator classprop_begin() const {
return classprop_iterator(decls_begin());
}
+
classprop_iterator classprop_end() const {
return classprop_iterator(decls_end());
}
// Iterator access to instance/class methods.
- typedef specific_decl_iterator<ObjCMethodDecl> method_iterator;
- typedef llvm::iterator_range<specific_decl_iterator<ObjCMethodDecl>>
- method_range;
+ using method_iterator = specific_decl_iterator<ObjCMethodDecl>;
+ using method_range =
+ llvm::iterator_range<specific_decl_iterator<ObjCMethodDecl>>;
method_range methods() const {
return method_range(meth_begin(), meth_end());
}
+
method_iterator meth_begin() const {
return method_iterator(decls_begin());
}
+
method_iterator meth_end() const {
return method_iterator(decls_end());
}
- typedef filtered_decl_iterator<ObjCMethodDecl,
- &ObjCMethodDecl::isInstanceMethod>
- instmeth_iterator;
- typedef llvm::iterator_range<instmeth_iterator> instmeth_range;
+ using instmeth_iterator =
+ filtered_decl_iterator<ObjCMethodDecl,
+ &ObjCMethodDecl::isInstanceMethod>;
+ using instmeth_range = llvm::iterator_range<instmeth_iterator>;
instmeth_range instance_methods() const {
return instmeth_range(instmeth_begin(), instmeth_end());
}
+
instmeth_iterator instmeth_begin() const {
return instmeth_iterator(decls_begin());
}
+
instmeth_iterator instmeth_end() const {
return instmeth_iterator(decls_end());
}
- typedef filtered_decl_iterator<ObjCMethodDecl,
- &ObjCMethodDecl::isClassMethod>
- classmeth_iterator;
- typedef llvm::iterator_range<classmeth_iterator> classmeth_range;
+ using classmeth_iterator =
+ filtered_decl_iterator<ObjCMethodDecl,
+ &ObjCMethodDecl::isClassMethod>;
+ using classmeth_range = llvm::iterator_range<classmeth_iterator>;
classmeth_range class_methods() const {
return classmeth_range(classmeth_begin(), classmeth_end());
}
+
classmeth_iterator classmeth_begin() const {
return classmeth_iterator(decls_begin());
}
+
classmeth_iterator classmeth_end() const {
return classmeth_iterator(decls_end());
}
@@ -1022,13 +1101,16 @@ public:
// Get the local instance/class method declared in this interface.
ObjCMethodDecl *getMethod(Selector Sel, bool isInstance,
bool AllowHidden = false) const;
+
ObjCMethodDecl *getInstanceMethod(Selector Sel,
bool AllowHidden = false) const {
return getMethod(Sel, true/*isInstance*/, AllowHidden);
}
+
ObjCMethodDecl *getClassMethod(Selector Sel, bool AllowHidden = false) const {
return getMethod(Sel, false/*isInstance*/, AllowHidden);
}
+
bool HasUserDeclaredSetterMethod(const ObjCPropertyDecl *P) const;
ObjCIvarDecl *getIvarDecl(IdentifierInfo *Id) const;
@@ -1036,13 +1118,11 @@ public:
FindPropertyDeclaration(const IdentifierInfo *PropertyId,
ObjCPropertyQueryKind QueryKind) const;
- typedef llvm::DenseMap<std::pair<IdentifierInfo*,
- unsigned/*isClassProperty*/>,
- ObjCPropertyDecl*> PropertyMap;
-
- typedef llvm::SmallDenseSet<const ObjCProtocolDecl *, 8> ProtocolPropertySet;
-
- typedef llvm::SmallVector<ObjCPropertyDecl*, 8> PropertyDeclOrder;
+ using PropertyMap =
+ llvm::DenseMap<std::pair<IdentifierInfo *, unsigned/*isClassProperty*/>,
+ ObjCPropertyDecl *>;
+ using ProtocolPropertySet = llvm::SmallDenseSet<const ObjCProtocolDecl *, 8>;
+ using PropertyDeclOrder = llvm::SmallVector<ObjCPropertyDecl *, 8>;
/// This routine collects list of properties to be implemented in the class.
/// This includes, class's and its conforming protocols' properties.
@@ -1057,6 +1137,7 @@ public:
SourceRange getAtEndRange() const {
return AtEnd;
}
+
void setAtEndRange(SourceRange atEnd) {
AtEnd = atEnd;
}
@@ -1067,6 +1148,7 @@ public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+
static bool classofKind(Kind K) {
return K >= firstObjCContainer &&
K <= lastObjCContainer;
@@ -1075,6 +1157,7 @@ public:
static DeclContext *castToDeclContext(const ObjCContainerDecl *D) {
return static_cast<DeclContext *>(const_cast<ObjCContainerDecl*>(D));
}
+
static ObjCContainerDecl *castFromDeclContext(const DeclContext *DC) {
return static_cast<ObjCContainerDecl *>(const_cast<DeclContext*>(DC));
}
@@ -1107,20 +1190,19 @@ public:
///
class ObjCInterfaceDecl : public ObjCContainerDecl
, public Redeclarable<ObjCInterfaceDecl> {
- void anchor() override;
+ friend class ASTContext;
/// TypeForDecl - This indicates the Type object that represents this
/// TypeDecl. It is a cache maintained by ASTContext::getObjCInterfaceType
- mutable const Type *TypeForDecl;
- friend class ASTContext;
+ mutable const Type *TypeForDecl = nullptr;
struct DefinitionData {
/// \brief The definition of this class, for quick access from any
/// declaration.
- ObjCInterfaceDecl *Definition;
+ ObjCInterfaceDecl *Definition = nullptr;
/// When non-null, this is always an ObjCObjectType.
- TypeSourceInfo *SuperClassTInfo;
+ TypeSourceInfo *SuperClassTInfo = nullptr;
/// Protocols referenced in the \@interface declaration
ObjCProtocolList ReferencedProtocols;
@@ -1133,11 +1215,11 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
/// Categories are stored as a linked list in the AST, since the categories
/// and class extensions come long after the initial interface declaration,
/// and we avoid dynamically-resized arrays in the AST wherever possible.
- ObjCCategoryDecl *CategoryList;
+ ObjCCategoryDecl *CategoryList = nullptr;
/// IvarList - List of all ivars defined by this class; including class
/// extensions and implementation. This list is built lazily.
- ObjCIvarDecl *IvarList;
+ ObjCIvarDecl *IvarList = nullptr;
/// \brief Indicates that the contents of this Objective-C class will be
/// completed by the external AST source when required.
@@ -1155,11 +1237,14 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
/// We didn't calculate whether the designated initializers should be
/// inherited or not.
IDI_Unknown = 0,
+
/// Designated initializers are inherited for the super class.
IDI_Inherited = 1,
+
/// The class does not inherit designated initializers.
IDI_NotInherited = 2
};
+
/// One of the \c InheritedDesignatedInitializersState enumeratos.
mutable unsigned InheritedDesignatedInitializers : 2;
@@ -1168,22 +1253,14 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
/// identifier,
SourceLocation EndLoc;
- DefinitionData() : Definition(), SuperClassTInfo(), CategoryList(), IvarList(),
- ExternallyCompleted(),
- IvarListMissingImplementation(true),
- HasDesignatedInitializers(),
- InheritedDesignatedInitializers(IDI_Unknown) { }
+ DefinitionData()
+ : ExternallyCompleted(false), IvarListMissingImplementation(true),
+ HasDesignatedInitializers(false),
+ InheritedDesignatedInitializers(IDI_Unknown) {}
};
- ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC, SourceLocation AtLoc,
- IdentifierInfo *Id, ObjCTypeParamList *typeParamList,
- SourceLocation CLoc, ObjCInterfaceDecl *PrevDecl,
- bool IsInternal);
-
- void LoadExternalDefinition() const;
-
/// The type parameters associated with this class, if any.
- ObjCTypeParamList *TypeParamList;
+ ObjCTypeParamList *TypeParamList = nullptr;
/// \brief Contains a pointer to the data associated with this class,
/// which will be NULL if this class has not yet been defined.
@@ -1192,6 +1269,15 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
/// declarations. It will be set unless modules are enabled.
llvm::PointerIntPair<DefinitionData *, 1, bool> Data;
+ ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC, SourceLocation AtLoc,
+ IdentifierInfo *Id, ObjCTypeParamList *typeParamList,
+ SourceLocation CLoc, ObjCInterfaceDecl *PrevDecl,
+ bool IsInternal);
+
+ void anchor() override;
+
+ void LoadExternalDefinition() const;
+
DefinitionData &data() const {
assert(Data.getPointer() && "Declaration has no definition!");
return *Data.getPointer();
@@ -1200,13 +1286,16 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
/// \brief Allocate the definition data for this class.
void allocateDefinitionData();
- typedef Redeclarable<ObjCInterfaceDecl> redeclarable_base;
+ using redeclarable_base = Redeclarable<ObjCInterfaceDecl>;
+
ObjCInterfaceDecl *getNextRedeclarationImpl() override {
return getNextRedeclaration();
}
+
ObjCInterfaceDecl *getPreviousDeclImpl() override {
return getPreviousDecl();
}
+
ObjCInterfaceDecl *getMostRecentDeclImpl() override {
return getMostRecentDecl();
}
@@ -1284,17 +1373,19 @@ public:
// Get the local instance/class method declared in a category.
ObjCMethodDecl *getCategoryInstanceMethod(Selector Sel) const;
ObjCMethodDecl *getCategoryClassMethod(Selector Sel) const;
+
ObjCMethodDecl *getCategoryMethod(Selector Sel, bool isInstance) const {
return isInstance ? getCategoryInstanceMethod(Sel)
: getCategoryClassMethod(Sel);
}
- typedef ObjCProtocolList::iterator protocol_iterator;
- typedef llvm::iterator_range<protocol_iterator> protocol_range;
+ using protocol_iterator = ObjCProtocolList::iterator;
+ using protocol_range = llvm::iterator_range<protocol_iterator>;
protocol_range protocols() const {
return protocol_range(protocol_begin(), protocol_end());
}
+
protocol_iterator protocol_begin() const {
// FIXME: Should make sure no callers ever do this.
if (!hasDefinition())
@@ -1305,6 +1396,7 @@ public:
return data().ReferencedProtocols.begin();
}
+
protocol_iterator protocol_end() const {
// FIXME: Should make sure no callers ever do this.
if (!hasDefinition())
@@ -1316,12 +1408,13 @@ public:
return data().ReferencedProtocols.end();
}
- typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
- typedef llvm::iterator_range<protocol_loc_iterator> protocol_loc_range;
+ using protocol_loc_iterator = ObjCProtocolList::loc_iterator;
+ using protocol_loc_range = llvm::iterator_range<protocol_loc_iterator>;
protocol_loc_range protocol_locs() const {
return protocol_loc_range(protocol_loc_begin(), protocol_loc_end());
}
+
protocol_loc_iterator protocol_loc_begin() const {
// FIXME: Should make sure no callers ever do this.
if (!hasDefinition())
@@ -1344,13 +1437,14 @@ public:
return data().ReferencedProtocols.loc_end();
}
- typedef ObjCList<ObjCProtocolDecl>::iterator all_protocol_iterator;
- typedef llvm::iterator_range<all_protocol_iterator> all_protocol_range;
+ using all_protocol_iterator = ObjCList<ObjCProtocolDecl>::iterator;
+ using all_protocol_range = llvm::iterator_range<all_protocol_iterator>;
all_protocol_range all_referenced_protocols() const {
return all_protocol_range(all_referenced_protocol_begin(),
all_referenced_protocol_end());
}
+
all_protocol_iterator all_referenced_protocol_begin() const {
// FIXME: Should make sure no callers ever do this.
if (!hasDefinition())
@@ -1363,6 +1457,7 @@ public:
? protocol_begin()
: data().AllReferencedProtocols.begin();
}
+
all_protocol_iterator all_referenced_protocol_end() const {
// FIXME: Should make sure no callers ever do this.
if (!hasDefinition())
@@ -1376,10 +1471,11 @@ public:
: data().AllReferencedProtocols.end();
}
- typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
- typedef llvm::iterator_range<specific_decl_iterator<ObjCIvarDecl>> ivar_range;
+ using ivar_iterator = specific_decl_iterator<ObjCIvarDecl>;
+ using ivar_range = llvm::iterator_range<specific_decl_iterator<ObjCIvarDecl>>;
ivar_range ivars() const { return ivar_range(ivar_begin(), ivar_end()); }
+
ivar_iterator ivar_begin() const {
if (const ObjCInterfaceDecl *Def = getDefinition())
return ivar_iterator(Def->decls_begin());
@@ -1387,6 +1483,7 @@ public:
// FIXME: Should make sure no callers ever do this.
return ivar_iterator();
}
+
ivar_iterator ivar_end() const {
if (const ObjCInterfaceDecl *Def = getDefinition())
return ivar_iterator(Def->decls_end());
@@ -1518,21 +1615,20 @@ public:
/// and extension iterators.
template<bool (*Filter)(ObjCCategoryDecl *)>
class filtered_category_iterator {
- ObjCCategoryDecl *Current;
+ ObjCCategoryDecl *Current = nullptr;
void findAcceptableCategory();
public:
- typedef ObjCCategoryDecl * value_type;
- typedef value_type reference;
- typedef value_type pointer;
- typedef std::ptrdiff_t difference_type;
- typedef std::input_iterator_tag iterator_category;
+ using value_type = ObjCCategoryDecl *;
+ using reference = value_type;
+ using pointer = value_type;
+ using difference_type = std::ptrdiff_t;
+ using iterator_category = std::input_iterator_tag;
- filtered_category_iterator() : Current(nullptr) { }
+ filtered_category_iterator() = default;
explicit filtered_category_iterator(ObjCCategoryDecl *Current)
- : Current(Current)
- {
+ : Current(Current) {
findAcceptableCategory();
}
@@ -1567,11 +1663,11 @@ private:
public:
/// \brief Iterator that walks over the list of categories and extensions
/// that are visible, i.e., not hidden in a non-imported submodule.
- typedef filtered_category_iterator<isVisibleCategory>
- visible_categories_iterator;
+ using visible_categories_iterator =
+ filtered_category_iterator<isVisibleCategory>;
- typedef llvm::iterator_range<visible_categories_iterator>
- visible_categories_range;
+ using visible_categories_range =
+ llvm::iterator_range<visible_categories_iterator>;
visible_categories_range visible_categories() const {
return visible_categories_range(visible_categories_begin(),
@@ -1603,9 +1699,9 @@ private:
public:
/// \brief Iterator that walks over all of the known categories and
/// extensions, including those that are hidden.
- typedef filtered_category_iterator<isKnownCategory> known_categories_iterator;
- typedef llvm::iterator_range<known_categories_iterator>
- known_categories_range;
+ using known_categories_iterator = filtered_category_iterator<isKnownCategory>;
+ using known_categories_range =
+ llvm::iterator_range<known_categories_iterator>;
known_categories_range known_categories() const {
return known_categories_range(known_categories_begin(),
@@ -1637,11 +1733,11 @@ private:
public:
/// \brief Iterator that walks over all of the visible extensions, skipping
/// any that are known but hidden.
- typedef filtered_category_iterator<isVisibleExtension>
- visible_extensions_iterator;
+ using visible_extensions_iterator =
+ filtered_category_iterator<isVisibleExtension>;
- typedef llvm::iterator_range<visible_extensions_iterator>
- visible_extensions_range;
+ using visible_extensions_range =
+ llvm::iterator_range<visible_extensions_iterator>;
visible_extensions_range visible_extensions() const {
return visible_extensions_range(visible_extensions_begin(),
@@ -1671,11 +1767,15 @@ private:
static bool isKnownExtension(ObjCCategoryDecl *Cat);
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+ friend class ASTReader;
+
/// \brief Iterator that walks over all of the known extensions.
- typedef filtered_category_iterator<isKnownExtension>
- known_extensions_iterator;
- typedef llvm::iterator_range<known_extensions_iterator>
- known_extensions_range;
+ using known_extensions_iterator =
+ filtered_category_iterator<isKnownExtension>;
+ using known_extensions_range =
+ llvm::iterator_range<known_extensions_iterator>;
known_extensions_range known_extensions() const {
return known_extensions_range(known_extensions_begin(),
@@ -1771,6 +1871,7 @@ public:
ObjCMethodDecl *lookupClassMethod(Selector Sel) const {
return lookupMethod(Sel, false/*isInstance*/);
}
+
ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName);
/// \brief Lookup a method in the classes implementation hierarchy.
@@ -1819,8 +1920,9 @@ public:
bool lookupCategory,
bool RHSIsQualifiedID = false);
- typedef redeclarable_base::redecl_range redecl_range;
- typedef redeclarable_base::redecl_iterator redecl_iterator;
+ using redecl_range = redeclarable_base::redecl_range;
+ using redecl_iterator = redeclarable_base::redecl_iterator;
+
using redeclarable_base::redecls_begin;
using redeclarable_base::redecls_end;
using redeclarable_base::redecls;
@@ -1839,10 +1941,6 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ObjCInterface; }
- friend class ASTReader;
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
-
private:
const ObjCInterfaceDecl *findInterfaceWithDesignatedInitializers() const;
bool inheritsDesignatedInitializers() const;
@@ -1876,9 +1974,9 @@ private:
SourceLocation IdLoc, IdentifierInfo *Id,
QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW,
bool synthesized)
- : FieldDecl(ObjCIvar, DC, StartLoc, IdLoc, Id, T, TInfo, BW,
- /*Mutable=*/false, /*HasInit=*/ICIS_NoInit),
- NextIvar(nullptr), DeclAccess(ac), Synthesized(synthesized) {}
+ : FieldDecl(ObjCIvar, DC, StartLoc, IdLoc, Id, T, TInfo, BW,
+ /*Mutable=*/false, /*HasInit=*/ICIS_NoInit),
+ DeclAccess(ac), Synthesized(synthesized) {}
public:
static ObjCIvarDecl *Create(ASTContext &C, ObjCContainerDecl *DC,
@@ -1918,26 +2016,27 @@ public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ObjCIvar; }
+
private:
/// NextIvar - Next Ivar in the list of ivars declared in class; class's
/// extensions and class's implementation
- ObjCIvarDecl *NextIvar;
+ ObjCIvarDecl *NextIvar = nullptr;
// NOTE: VC++ treats enums as signed, avoid using the AccessControl enum
unsigned DeclAccess : 3;
unsigned Synthesized : 1;
};
-
/// \brief Represents a field declaration created by an \@defs(...).
class ObjCAtDefsFieldDecl : public FieldDecl {
- void anchor() override;
ObjCAtDefsFieldDecl(DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
QualType T, Expr *BW)
- : FieldDecl(ObjCAtDefsField, DC, StartLoc, IdLoc, Id, T,
- /*TInfo=*/nullptr, // FIXME: Do ObjCAtDefs have declarators ?
- BW, /*Mutable=*/false, /*HasInit=*/ICIS_NoInit) {}
+ : FieldDecl(ObjCAtDefsField, DC, StartLoc, IdLoc, Id, T,
+ /*TInfo=*/nullptr, // FIXME: Do ObjCAtDefs have declarators ?
+ BW, /*Mutable=*/false, /*HasInit=*/ICIS_NoInit) {}
+
+ void anchor() override;
public:
static ObjCAtDefsFieldDecl *Create(ASTContext &C, DeclContext *DC,
@@ -1981,11 +2080,8 @@ public:
/// protocols are referenced using angle brackets as follows:
///
/// id \<NSDraggingInfo> anyObjectThatImplementsNSDraggingInfo;
-///
class ObjCProtocolDecl : public ObjCContainerDecl,
public Redeclarable<ObjCProtocolDecl> {
- void anchor() override;
-
struct DefinitionData {
// \brief The declaration that defines this protocol.
ObjCProtocolDecl *Definition;
@@ -2001,29 +2097,38 @@ class ObjCProtocolDecl : public ObjCContainerDecl,
/// declarations. It will be set unless modules are enabled.
llvm::PointerIntPair<DefinitionData *, 1, bool> Data;
+ ObjCProtocolDecl(ASTContext &C, DeclContext *DC, IdentifierInfo *Id,
+ SourceLocation nameLoc, SourceLocation atStartLoc,
+ ObjCProtocolDecl *PrevDecl);
+
+ void anchor() override;
+
DefinitionData &data() const {
assert(Data.getPointer() && "Objective-C protocol has no definition!");
return *Data.getPointer();
}
- ObjCProtocolDecl(ASTContext &C, DeclContext *DC, IdentifierInfo *Id,
- SourceLocation nameLoc, SourceLocation atStartLoc,
- ObjCProtocolDecl *PrevDecl);
-
void allocateDefinitionData();
- typedef Redeclarable<ObjCProtocolDecl> redeclarable_base;
+ using redeclarable_base = Redeclarable<ObjCProtocolDecl>;
+
ObjCProtocolDecl *getNextRedeclarationImpl() override {
return getNextRedeclaration();
}
+
ObjCProtocolDecl *getPreviousDeclImpl() override {
return getPreviousDecl();
}
+
ObjCProtocolDecl *getMostRecentDeclImpl() override {
return getMostRecentDecl();
}
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+ friend class ASTReader;
+
static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC,
IdentifierInfo *Id,
SourceLocation nameLoc,
@@ -2036,42 +2141,49 @@ public:
assert(hasDefinition() && "No definition available!");
return data().ReferencedProtocols;
}
- typedef ObjCProtocolList::iterator protocol_iterator;
- typedef llvm::iterator_range<protocol_iterator> protocol_range;
+
+ using protocol_iterator = ObjCProtocolList::iterator;
+ using protocol_range = llvm::iterator_range<protocol_iterator>;
protocol_range protocols() const {
return protocol_range(protocol_begin(), protocol_end());
}
+
protocol_iterator protocol_begin() const {
if (!hasDefinition())
return protocol_iterator();
return data().ReferencedProtocols.begin();
}
+
protocol_iterator protocol_end() const {
if (!hasDefinition())
return protocol_iterator();
return data().ReferencedProtocols.end();
}
- typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
- typedef llvm::iterator_range<protocol_loc_iterator> protocol_loc_range;
+
+ using protocol_loc_iterator = ObjCProtocolList::loc_iterator;
+ using protocol_loc_range = llvm::iterator_range<protocol_loc_iterator>;
protocol_loc_range protocol_locs() const {
return protocol_loc_range(protocol_loc_begin(), protocol_loc_end());
}
+
protocol_loc_iterator protocol_loc_begin() const {
if (!hasDefinition())
return protocol_loc_iterator();
return data().ReferencedProtocols.loc_begin();
}
+
protocol_loc_iterator protocol_loc_end() const {
if (!hasDefinition())
return protocol_loc_iterator();
return data().ReferencedProtocols.loc_end();
}
+
unsigned protocol_size() const {
if (!hasDefinition())
return 0;
@@ -2092,9 +2204,11 @@ public:
// Lookup a method. First, we search locally. If a method isn't
// found, we search referenced protocols and class categories.
ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance) const;
+
ObjCMethodDecl *lookupInstanceMethod(Selector Sel) const {
return lookupMethod(Sel, true/*isInstance*/);
}
+
ObjCMethodDecl *lookupClassMethod(Selector Sel) const {
return lookupMethod(Sel, false/*isInstance*/);
}
@@ -2141,8 +2255,9 @@ public:
return SourceRange(getAtStartLoc(), getLocation());
}
- typedef redeclarable_base::redecl_range redecl_range;
- typedef redeclarable_base::redecl_iterator redecl_iterator;
+ using redecl_range = redeclarable_base::redecl_range;
+ using redecl_iterator = redeclarable_base::redecl_iterator;
+
using redeclarable_base::redecls_begin;
using redeclarable_base::redecls_end;
using redeclarable_base::redecls;
@@ -2163,10 +2278,6 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ObjCProtocol; }
-
- friend class ASTReader;
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
};
/// ObjCCategoryDecl - Represents a category declaration. A category allows
@@ -2185,22 +2296,19 @@ public:
/// Categories were originally inspired by dynamic languages such as Common
/// Lisp and Smalltalk. More traditional class-based languages (C++, Java)
/// don't support this level of dynamism, which is both powerful and dangerous.
-///
class ObjCCategoryDecl : public ObjCContainerDecl {
- void anchor() override;
-
/// Interface belonging to this category
ObjCInterfaceDecl *ClassInterface;
/// The type parameters associated with this category, if any.
- ObjCTypeParamList *TypeParamList;
+ ObjCTypeParamList *TypeParamList = nullptr;
/// referenced protocols in this category.
ObjCProtocolList ReferencedProtocols;
/// Next category belonging to this class.
/// FIXME: this should not be a singly-linked list. Move storage elsewhere.
- ObjCCategoryDecl *NextClassCategory;
+ ObjCCategoryDecl *NextClassCategory = nullptr;
/// \brief The location of the category name in this declaration.
SourceLocation CategoryNameLoc;
@@ -2213,10 +2321,14 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc,
IdentifierInfo *Id, ObjCInterfaceDecl *IDecl,
ObjCTypeParamList *typeParamList,
- SourceLocation IvarLBraceLoc=SourceLocation(),
- SourceLocation IvarRBraceLoc=SourceLocation());
+ SourceLocation IvarLBraceLoc = SourceLocation(),
+ SourceLocation IvarRBraceLoc = SourceLocation());
+
+ void anchor() override;
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
static ObjCCategoryDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation AtLoc,
@@ -2257,26 +2369,31 @@ public:
return ReferencedProtocols;
}
- typedef ObjCProtocolList::iterator protocol_iterator;
- typedef llvm::iterator_range<protocol_iterator> protocol_range;
+ using protocol_iterator = ObjCProtocolList::iterator;
+ using protocol_range = llvm::iterator_range<protocol_iterator>;
protocol_range protocols() const {
return protocol_range(protocol_begin(), protocol_end());
}
+
protocol_iterator protocol_begin() const {
return ReferencedProtocols.begin();
}
+
protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
unsigned protocol_size() const { return ReferencedProtocols.size(); }
- typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
- typedef llvm::iterator_range<protocol_loc_iterator> protocol_loc_range;
+
+ using protocol_loc_iterator = ObjCProtocolList::loc_iterator;
+ using protocol_loc_range = llvm::iterator_range<protocol_loc_iterator>;
protocol_loc_range protocol_locs() const {
return protocol_loc_range(protocol_loc_begin(), protocol_loc_end());
}
+
protocol_loc_iterator protocol_loc_begin() const {
return ReferencedProtocols.loc_begin();
}
+
protocol_loc_iterator protocol_loc_end() const {
return ReferencedProtocols.loc_end();
}
@@ -2291,19 +2408,23 @@ public:
bool IsClassExtension() const { return getIdentifier() == nullptr; }
- typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
- typedef llvm::iterator_range<specific_decl_iterator<ObjCIvarDecl>> ivar_range;
+ using ivar_iterator = specific_decl_iterator<ObjCIvarDecl>;
+ using ivar_range = llvm::iterator_range<specific_decl_iterator<ObjCIvarDecl>>;
ivar_range ivars() const { return ivar_range(ivar_begin(), ivar_end()); }
+
ivar_iterator ivar_begin() const {
return ivar_iterator(decls_begin());
}
+
ivar_iterator ivar_end() const {
return ivar_iterator(decls_end());
}
+
unsigned ivar_size() const {
return std::distance(ivar_begin(), ivar_end());
}
+
bool ivar_empty() const {
return ivar_begin() == ivar_end();
}
@@ -2318,24 +2439,21 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ObjCCategory; }
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
};
class ObjCImplDecl : public ObjCContainerDecl {
- void anchor() override;
-
/// Class interface for this class/category implementation
ObjCInterfaceDecl *ClassInterface;
+ void anchor() override;
+
protected:
ObjCImplDecl(Kind DK, DeclContext *DC,
ObjCInterfaceDecl *classInterface,
IdentifierInfo *Id,
SourceLocation nameLoc, SourceLocation atStartLoc)
- : ObjCContainerDecl(DK, DC, Id, nameLoc, atStartLoc),
- ClassInterface(classInterface) {}
+ : ObjCContainerDecl(DK, DC, Id, nameLoc, atStartLoc),
+ ClassInterface(classInterface) {}
public:
const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
@@ -2347,6 +2465,7 @@ public:
method->setLexicalDeclContext(this);
addDecl(method);
}
+
void addClassMethod(ObjCMethodDecl *method) {
// FIXME: Context should be set correctly before we get here.
method->setLexicalDeclContext(this);
@@ -2360,21 +2479,24 @@ public:
ObjCPropertyImplDecl *FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const;
// Iterator access to properties.
- typedef specific_decl_iterator<ObjCPropertyImplDecl> propimpl_iterator;
- typedef llvm::iterator_range<specific_decl_iterator<ObjCPropertyImplDecl>>
- propimpl_range;
+ using propimpl_iterator = specific_decl_iterator<ObjCPropertyImplDecl>;
+ using propimpl_range =
+ llvm::iterator_range<specific_decl_iterator<ObjCPropertyImplDecl>>;
propimpl_range property_impls() const {
return propimpl_range(propimpl_begin(), propimpl_end());
}
+
propimpl_iterator propimpl_begin() const {
return propimpl_iterator(decls_begin());
}
+
propimpl_iterator propimpl_end() const {
return propimpl_iterator(decls_end());
}
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+
static bool classofKind(Kind K) {
return K >= firstObjCImpl && K <= lastObjCImpl;
}
@@ -2394,8 +2516,6 @@ public:
///
/// ObjCCategoryImplDecl
class ObjCCategoryImplDecl : public ObjCImplDecl {
- void anchor() override;
-
// Category name location
SourceLocation CategoryNameLoc;
@@ -2403,10 +2523,16 @@ class ObjCCategoryImplDecl : public ObjCImplDecl {
ObjCInterfaceDecl *classInterface,
SourceLocation nameLoc, SourceLocation atStartLoc,
SourceLocation CategoryNameLoc)
- : ObjCImplDecl(ObjCCategoryImpl, DC, classInterface, Id,
- nameLoc, atStartLoc),
- CategoryNameLoc(CategoryNameLoc) {}
+ : ObjCImplDecl(ObjCCategoryImpl, DC, classInterface, Id,
+ nameLoc, atStartLoc),
+ CategoryNameLoc(CategoryNameLoc) {}
+
+ void anchor() override;
+
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+
static ObjCCategoryImplDecl *Create(ASTContext &C, DeclContext *DC,
IdentifierInfo *Id,
ObjCInterfaceDecl *classInterface,
@@ -2421,9 +2547,6 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ObjCCategoryImpl;}
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
};
raw_ostream &operator<<(raw_ostream &OS, const ObjCCategoryImplDecl &CID);
@@ -2446,7 +2569,6 @@ raw_ostream &operator<<(raw_ostream &OS, const ObjCCategoryImplDecl &CID);
/// we allow instance variables to be specified in the implementation. When
/// specified, they need to be \em identical to the interface.
class ObjCImplementationDecl : public ObjCImplDecl {
- void anchor() override;
/// Implementation Class's super class.
ObjCInterfaceDecl *SuperClass;
SourceLocation SuperLoc;
@@ -2458,7 +2580,7 @@ class ObjCImplementationDecl : public ObjCImplDecl {
/// Support for ivar initialization.
/// \brief The arguments used to initialize the ivars
LazyCXXCtorInitializersPtr IvarInitializers;
- unsigned NumIvarInitializers;
+ unsigned NumIvarInitializers = 0;
/// Do the ivars of this class require initialization other than
/// zero-initialization?
@@ -2474,15 +2596,20 @@ class ObjCImplementationDecl : public ObjCImplDecl {
SourceLocation superLoc = SourceLocation(),
SourceLocation IvarLBraceLoc=SourceLocation(),
SourceLocation IvarRBraceLoc=SourceLocation())
- : ObjCImplDecl(ObjCImplementation, DC, classInterface,
- classInterface ? classInterface->getIdentifier()
- : nullptr,
- nameLoc, atStartLoc),
- SuperClass(superDecl), SuperLoc(superLoc), IvarLBraceLoc(IvarLBraceLoc),
- IvarRBraceLoc(IvarRBraceLoc),
- IvarInitializers(nullptr), NumIvarInitializers(0),
- HasNonZeroConstructors(false), HasDestructors(false) {}
+ : ObjCImplDecl(ObjCImplementation, DC, classInterface,
+ classInterface ? classInterface->getIdentifier()
+ : nullptr,
+ nameLoc, atStartLoc),
+ SuperClass(superDecl), SuperLoc(superLoc),
+ IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc),
+ HasNonZeroConstructors(false), HasDestructors(false) {}
+
+ void anchor() override;
+
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+
static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC,
ObjCInterfaceDecl *classInterface,
ObjCInterfaceDecl *superDecl,
@@ -2495,15 +2622,16 @@ public:
static ObjCImplementationDecl *CreateDeserialized(ASTContext &C, unsigned ID);
/// init_iterator - Iterates through the ivar initializer list.
- typedef CXXCtorInitializer **init_iterator;
+ using init_iterator = CXXCtorInitializer **;
/// init_const_iterator - Iterates through the ivar initializer list.
- typedef CXXCtorInitializer * const * init_const_iterator;
+ using init_const_iterator = CXXCtorInitializer * const *;
- typedef llvm::iterator_range<init_iterator> init_range;
- typedef llvm::iterator_range<init_const_iterator> init_const_range;
+ using init_range = llvm::iterator_range<init_iterator>;
+ using init_const_range = llvm::iterator_range<init_const_iterator>;
init_range inits() { return init_range(init_begin(), init_end()); }
+
init_const_range inits() const {
return init_const_range(init_begin(), init_end());
}
@@ -2513,6 +2641,7 @@ public:
const auto *ConstThis = this;
return const_cast<init_iterator>(ConstThis->init_begin());
}
+
/// begin() - Retrieve an iterator to the first initializer.
init_const_iterator init_begin() const;
@@ -2520,10 +2649,12 @@ public:
init_iterator init_end() {
return init_begin() + NumIvarInitializers;
}
+
/// end() - Retrieve an iterator past the last initializer.
init_const_iterator init_end() const {
return init_begin() + NumIvarInitializers;
}
+
/// getNumArgs - Number of ivars which must be initialized.
unsigned getNumIvarInitializers() const {
return NumIvarInitializers;
@@ -2585,28 +2716,29 @@ public:
void setIvarRBraceLoc(SourceLocation Loc) { IvarRBraceLoc = Loc; }
SourceLocation getIvarRBraceLoc() const { return IvarRBraceLoc; }
- typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
- typedef llvm::iterator_range<specific_decl_iterator<ObjCIvarDecl>> ivar_range;
+ using ivar_iterator = specific_decl_iterator<ObjCIvarDecl>;
+ using ivar_range = llvm::iterator_range<specific_decl_iterator<ObjCIvarDecl>>;
ivar_range ivars() const { return ivar_range(ivar_begin(), ivar_end()); }
+
ivar_iterator ivar_begin() const {
return ivar_iterator(decls_begin());
}
+
ivar_iterator ivar_end() const {
return ivar_iterator(decls_end());
}
+
unsigned ivar_size() const {
return std::distance(ivar_begin(), ivar_end());
}
+
bool ivar_empty() const {
return ivar_begin() == ivar_end();
}
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ObjCImplementation; }
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
};
raw_ostream &operator<<(raw_ostream &OS, const ObjCImplementationDecl &ID);
@@ -2614,13 +2746,15 @@ raw_ostream &operator<<(raw_ostream &OS, const ObjCImplementationDecl &ID);
/// ObjCCompatibleAliasDecl - Represents alias of a class. This alias is
/// declared as \@compatibility_alias alias class.
class ObjCCompatibleAliasDecl : public NamedDecl {
- void anchor() override;
/// Class that this is an alias of.
ObjCInterfaceDecl *AliasedClass;
ObjCCompatibleAliasDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
ObjCInterfaceDecl* aliasedClass)
- : NamedDecl(ObjCCompatibleAlias, DC, L, Id), AliasedClass(aliasedClass) {}
+ : NamedDecl(ObjCCompatibleAlias, DC, L, Id), AliasedClass(aliasedClass) {}
+
+ void anchor() override;
+
public:
static ObjCCompatibleAliasDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
@@ -2635,7 +2769,6 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ObjCCompatibleAlias; }
-
};
/// ObjCPropertyImplDecl - Represents implementation declaration of a property
@@ -2648,6 +2781,7 @@ public:
Synthesize,
Dynamic
};
+
private:
SourceLocation AtLoc; // location of \@synthesize or \@dynamic
@@ -2667,24 +2801,25 @@ private:
/// Null for \@dynamic. Non-null if property must be copy-constructed in
/// getter.
- Expr *GetterCXXConstructor;
+ Expr *GetterCXXConstructor = nullptr;
/// Null for \@dynamic. Non-null if property has assignment operator to call
/// in Setter synthesis.
- Expr *SetterCXXAssignment;
+ Expr *SetterCXXAssignment = nullptr;
ObjCPropertyImplDecl(DeclContext *DC, SourceLocation atLoc, SourceLocation L,
ObjCPropertyDecl *property,
Kind PK,
ObjCIvarDecl *ivarDecl,
SourceLocation ivarLoc)
- : Decl(ObjCPropertyImpl, DC, L), AtLoc(atLoc),
- IvarLoc(ivarLoc), PropertyDecl(property), PropertyIvarDecl(ivarDecl),
- GetterCXXConstructor(nullptr), SetterCXXAssignment(nullptr) {
- assert (PK == Dynamic || PropertyIvarDecl);
+ : Decl(ObjCPropertyImpl, DC, L), AtLoc(atLoc),
+ IvarLoc(ivarLoc), PropertyDecl(property), PropertyIvarDecl(ivarDecl) {
+ assert(PK == Dynamic || PropertyIvarDecl);
}
public:
+ friend class ASTDeclReader;
+
static ObjCPropertyImplDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation atLoc, SourceLocation L,
ObjCPropertyDecl *property,
@@ -2733,6 +2868,7 @@ public:
Expr *getGetterCXXConstructor() const {
return GetterCXXConstructor;
}
+
void setGetterCXXConstructor(Expr *getterCXXConstructor) {
GetterCXXConstructor = getterCXXConstructor;
}
@@ -2740,14 +2876,13 @@ public:
Expr *getSetterCXXAssignment() const {
return SetterCXXAssignment;
}
+
void setSetterCXXAssignment(Expr *setterCXXAssignment) {
SetterCXXAssignment = setterCXXAssignment;
}
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Decl::Kind K) { return K == ObjCPropertyImpl; }
-
- friend class ASTDeclReader;
};
template<bool (*Filter)(ObjCCategoryDecl *)>
@@ -2778,5 +2913,6 @@ inline bool ObjCInterfaceDecl::isKnownExtension(ObjCCategoryDecl *Cat) {
return Cat->IsClassExtension();
}
-} // end namespace clang
-#endif
+} // namespace clang
+
+#endif // LLVM_CLANG_AST_DECLOBJC_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclOpenMP.h b/contrib/llvm/tools/clang/include/clang/AST/DeclOpenMP.h
index 30ca79e9d0054..2a329c3732cb6 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclOpenMP.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclOpenMP.h
@@ -100,12 +100,22 @@ public:
///
/// Here 'omp_out += omp_in' is a combiner and 'omp_priv = 0' is an initializer.
class OMPDeclareReductionDecl final : public ValueDecl, public DeclContext {
+public:
+ enum InitKind {
+ CallInit, // Initialized by function call.
+ DirectInit, // omp_priv(<expr>)
+ CopyInit // omp_priv = <expr>
+ };
+
private:
friend class ASTDeclReader;
/// \brief Combiner for declare reduction construct.
Expr *Combiner;
/// \brief Initializer for declare reduction construct.
Expr *Initializer;
+ /// Kind of initializer - function call or omp_priv<init_expr> initializtion.
+ InitKind InitializerKind = CallInit;
+
/// \brief Reference to the previous declare reduction construct in the same
/// scope with the same name. Required for proper templates instantiation if
/// the declare reduction construct is declared inside compound statement.
@@ -117,7 +127,8 @@ private:
DeclarationName Name, QualType Ty,
OMPDeclareReductionDecl *PrevDeclInScope)
: ValueDecl(DK, DC, L, Name, Ty), DeclContext(DK), Combiner(nullptr),
- Initializer(nullptr), PrevDeclInScope(PrevDeclInScope) {}
+ Initializer(nullptr), InitializerKind(CallInit),
+ PrevDeclInScope(PrevDeclInScope) {}
void setPrevDeclInScope(OMPDeclareReductionDecl *Prev) {
PrevDeclInScope = Prev;
@@ -142,8 +153,13 @@ public:
/// construct.
Expr *getInitializer() { return Initializer; }
const Expr *getInitializer() const { return Initializer; }
+ /// Get initializer kind.
+ InitKind getInitializerKind() const { return InitializerKind; }
/// \brief Set initializer expression for the declare reduction construct.
- void setInitializer(Expr *E) { Initializer = E; }
+ void setInitializer(Expr *E, InitKind IK) {
+ Initializer = E;
+ InitializerKind = IK;
+ }
/// \brief Get reference to previous declare reduction construct in the same
/// scope with the same name.
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h b/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h
index 2879452f24046..7842d70971747 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h
@@ -1,4 +1,4 @@
-//===-- DeclTemplate.h - Classes for representing C++ templates -*- C++ -*-===//
+//===- DeclTemplate.h - Classes for representing C++ templates --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,42 +6,60 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
/// \brief Defines the C++ template declaration subclasses.
-///
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECLTEMPLATE_H
#define LLVM_CLANG_AST_DECLTEMPLATE_H
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclarationName.h"
#include "clang/AST/Redeclarable.h"
#include "clang/AST/TemplateBase.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/TrailingObjects.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <iterator>
#include <utility>
namespace clang {
enum BuiltinTemplateKind : int;
-class TemplateParameterList;
-class TemplateDecl;
-class RedeclarableTemplateDecl;
-class FunctionTemplateDecl;
class ClassTemplateDecl;
class ClassTemplatePartialSpecializationDecl;
-class TemplateTypeParmDecl;
+class Expr;
+class FunctionTemplateDecl;
+class IdentifierInfo;
class NonTypeTemplateParmDecl;
+class TemplateDecl;
class TemplateTemplateParmDecl;
-class TypeAliasTemplateDecl;
+class TemplateTypeParmDecl;
+class UnresolvedSetImpl;
class VarTemplateDecl;
class VarTemplatePartialSpecializationDecl;
/// \brief Stores a template parameter of any kind.
-typedef llvm::PointerUnion3<TemplateTypeParmDecl*, NonTypeTemplateParmDecl*,
- TemplateTemplateParmDecl*> TemplateParameter;
+using TemplateParameter =
+ llvm::PointerUnion3<TemplateTypeParmDecl *, NonTypeTemplateParmDecl *,
+ TemplateTemplateParmDecl *>;
NamedDecl *getAsNamedDecl(TemplateParameter P);
@@ -50,7 +68,6 @@ NamedDecl *getAsNamedDecl(TemplateParameter P);
class TemplateParameterList final
: private llvm::TrailingObjects<TemplateParameterList, NamedDecl *,
Expr *> {
-
/// The location of the 'template' keyword.
SourceLocation TemplateLoc;
@@ -69,6 +86,10 @@ class TemplateParameterList final
unsigned HasRequiresClause : 1;
protected:
+ TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc,
+ ArrayRef<NamedDecl *> Params, SourceLocation RAngleLoc,
+ Expr *RequiresClause);
+
size_t numTrailingObjects(OverloadToken<NamedDecl *>) const {
return NumParams;
}
@@ -77,11 +98,11 @@ protected:
return HasRequiresClause;
}
- TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc,
- ArrayRef<NamedDecl *> Params, SourceLocation RAngleLoc,
- Expr *RequiresClause);
-
public:
+ template <size_t N, bool HasRequiresClause>
+ friend class FixedSizeTemplateParameterListStorage;
+ friend TrailingObjects;
+
static TemplateParameterList *Create(const ASTContext &C,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
@@ -90,10 +111,10 @@ public:
Expr *RequiresClause);
/// \brief Iterates through the template parameters in this list.
- typedef NamedDecl** iterator;
+ using iterator = NamedDecl **;
/// \brief Iterates through the template parameters in this list.
- typedef NamedDecl* const* const_iterator;
+ using const_iterator = NamedDecl * const *;
iterator begin() { return getTrailingObjects<NamedDecl *>(); }
const_iterator begin() const { return getTrailingObjects<NamedDecl *>(); }
@@ -113,7 +134,6 @@ public:
assert(Idx < size() && "Template parameter index out-of-range");
return begin()[Idx];
}
-
const NamedDecl* getParam(unsigned Idx) const {
assert(Idx < size() && "Template parameter index out-of-range");
return begin()[Idx];
@@ -157,11 +177,6 @@ public:
return SourceRange(TemplateLoc, RAngleLoc);
}
- friend TrailingObjects;
-
- template <size_t N, bool HasRequiresClause>
- friend class FixedSizeTemplateParameterListStorage;
-
public:
// FIXME: workaround for MSVC 2013; remove when no longer needed
using FixedSizeStorageOwner = TrailingObjects::FixedSizeStorageOwner;
@@ -201,14 +216,16 @@ class TemplateArgumentList final
/// argument list.
unsigned NumArguments;
- TemplateArgumentList(const TemplateArgumentList &Other) = delete;
- void operator=(const TemplateArgumentList &Other) = delete;
-
// Constructs an instance with an internal Argument list, containing
// a copy of the Args array. (Called by CreateCopy)
TemplateArgumentList(ArrayRef<TemplateArgument> Args);
public:
+ friend TrailingObjects;
+
+ TemplateArgumentList(const TemplateArgumentList &) = delete;
+ TemplateArgumentList &operator=(const TemplateArgumentList &) = delete;
+
/// \brief Type used to indicate that the template argument list itself is a
/// stack object. It does not own its template arguments.
enum OnStackType { OnStack };
@@ -254,8 +271,6 @@ public:
/// \brief Retrieve a pointer to the template argument list.
const TemplateArgument *data() const { return Arguments; }
-
- friend TrailingObjects;
};
void *allocateDefaultArgStorageChain(const ASTContext &C);
@@ -297,9 +312,11 @@ public:
/// Determine whether there is a default argument for this parameter.
bool isSet() const { return !ValueOrInherited.isNull(); }
+
/// Determine whether the default argument for this parameter was inherited
/// from a previous declaration of the same entity.
bool isInherited() const { return ValueOrInherited.template is<ParmDecl*>(); }
+
/// Get the default argument's value. This does not consider whether the
/// default argument is visible.
ArgType get() const {
@@ -310,6 +327,7 @@ public:
return C->Value;
return Storage->ValueOrInherited.template get<ArgType>();
}
+
/// Get the parameter from which we inherit the default argument, if any.
/// This is the parameter on which the default argument was actually written.
const ParmDecl *getInheritedFrom() const {
@@ -319,11 +337,13 @@ public:
return C->PrevDeclWithDefaultArg;
return nullptr;
}
+
/// Set the default argument.
void set(ArgType Arg) {
assert(!isSet() && "default argument already set");
ValueOrInherited = Arg;
}
+
/// Set that the default argument was inherited from another parameter.
void setInherited(const ASTContext &C, ParmDecl *InheritedFrom) {
assert(!isInherited() && "default argument already inherited");
@@ -334,6 +354,7 @@ public:
ValueOrInherited = new (allocateDefaultArgStorageChain(C))
Chain{InheritedFrom, ValueOrInherited.template get<ArgType>()};
}
+
/// Remove the default argument, even if it was inherited.
void clear() {
ValueOrInherited = ArgType();
@@ -350,7 +371,7 @@ class ConstrainedTemplateDeclInfo {
friend TemplateDecl;
public:
- ConstrainedTemplateDeclInfo() : TemplateParams(), AssociatedConstraints() {}
+ ConstrainedTemplateDeclInfo() = default;
TemplateParameterList *getTemplateParameters() const {
return TemplateParams;
@@ -365,8 +386,8 @@ protected:
void setAssociatedConstraints(Expr *AC) { AssociatedConstraints = AC; }
- TemplateParameterList *TemplateParams;
- Expr *AssociatedConstraints;
+ TemplateParameterList *TemplateParams = nullptr;
+ Expr *AssociatedConstraints = nullptr;
};
@@ -377,13 +398,14 @@ protected:
/// reference to the templated scoped declaration: the underlying AST node.
class TemplateDecl : public NamedDecl {
void anchor() override;
+
protected:
// Construct a template decl with the given name and parameters.
// Used when there is no templated element (e.g., for tt-params).
TemplateDecl(ConstrainedTemplateDeclInfo *CTDI, Kind DK, DeclContext *DC,
SourceLocation L, DeclarationName Name,
TemplateParameterList *Params)
- : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr, false),
+ : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr),
TemplateParams(CTDI) {
this->setTemplateParameters(Params);
}
@@ -396,7 +418,7 @@ protected:
TemplateDecl(ConstrainedTemplateDeclInfo *CTDI, Kind DK, DeclContext *DC,
SourceLocation L, DeclarationName Name,
TemplateParameterList *Params, NamedDecl *Decl)
- : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl, false),
+ : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl),
TemplateParams(CTDI) {
this->setTemplateParameters(Params);
}
@@ -428,31 +450,22 @@ public:
}
/// Get the underlying, templated declaration.
- NamedDecl *getTemplatedDecl() const { return TemplatedDecl.getPointer(); }
+ NamedDecl *getTemplatedDecl() const { return TemplatedDecl; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+
static bool classofKind(Kind K) {
return K >= firstTemplate && K <= lastTemplate;
}
SourceRange getSourceRange() const override LLVM_READONLY {
return SourceRange(getTemplateParameters()->getTemplateLoc(),
- TemplatedDecl.getPointer()->getSourceRange().getEnd());
+ TemplatedDecl->getSourceRange().getEnd());
}
- /// Whether this is a (C++ Concepts TS) function or variable concept.
- bool isConcept() const { return TemplatedDecl.getInt(); }
- void setConcept() { TemplatedDecl.setInt(true); }
-
protected:
- /// \brief The named declaration from which this template was instantiated.
- /// (or null).
- ///
- /// The boolean value will be true to indicate that this template
- /// (function or variable) is a concept.
- llvm::PointerIntPair<NamedDecl *, 1, bool> TemplatedDecl;
-
+ NamedDecl *TemplatedDecl;
/// \brief The template parameter list and optional requires-clause
/// associated with this declaration; alternatively, a
/// \c ConstrainedTemplateDeclInfo if the associated constraints of the
@@ -481,9 +494,9 @@ public:
/// \brief Initialize the underlying templated declaration and
/// template parameters.
void init(NamedDecl *templatedDecl, TemplateParameterList* templateParams) {
- assert(!TemplatedDecl.getPointer() && "TemplatedDecl already set!");
+ assert(!TemplatedDecl && "TemplatedDecl already set!");
assert(!TemplateParams && "TemplateParams already set!");
- TemplatedDecl.setPointer(templatedDecl);
+ TemplatedDecl = templatedDecl;
TemplateParams = templateParams;
}
};
@@ -498,11 +511,10 @@ class FunctionTemplateSpecializationInfo : public llvm::FoldingSetNode {
const TemplateArgumentList *TemplateArgs,
const ASTTemplateArgumentListInfo *TemplateArgsAsWritten,
SourceLocation POI)
- : Function(FD),
- Template(Template, TSK - 1),
- TemplateArguments(TemplateArgs),
- TemplateArgumentsAsWritten(TemplateArgsAsWritten),
- PointOfInstantiation(POI) { }
+ : Function(FD), Template(Template, TSK - 1),
+ TemplateArguments(TemplateArgs),
+ TemplateArgumentsAsWritten(TemplateArgsAsWritten),
+ PointOfInstantiation(POI) {}
public:
static FunctionTemplateSpecializationInfo *
@@ -604,7 +616,7 @@ public:
explicit
MemberSpecializationInfo(NamedDecl *IF, TemplateSpecializationKind TSK,
SourceLocation POI = SourceLocation())
- : MemberAndTSK(IF, TSK - 1), PointOfInstantiation(POI) {
+ : MemberAndTSK(IF, TSK - 1), PointOfInstantiation(POI) {
assert(TSK != TSK_Undeclared &&
"Cannot encode undeclared template specializations for members");
}
@@ -681,6 +693,8 @@ class DependentFunctionTemplateSpecializationInfo final
const TemplateArgumentListInfo &TemplateArgs);
public:
+ friend TrailingObjects;
+
static DependentFunctionTemplateSpecializationInfo *
Create(ASTContext &Context, const UnresolvedSetImpl &Templates,
const TemplateArgumentListInfo &TemplateArgs);
@@ -716,32 +730,34 @@ public:
SourceLocation getRAngleLoc() const {
return AngleLocs.getEnd();
}
-
- friend TrailingObjects;
};
/// Declaration of a redeclarable template.
class RedeclarableTemplateDecl : public TemplateDecl,
public Redeclarable<RedeclarableTemplateDecl>
{
- typedef Redeclarable<RedeclarableTemplateDecl> redeclarable_base;
+ using redeclarable_base = Redeclarable<RedeclarableTemplateDecl>;
+
RedeclarableTemplateDecl *getNextRedeclarationImpl() override {
return getNextRedeclaration();
}
+
RedeclarableTemplateDecl *getPreviousDeclImpl() override {
return getPreviousDecl();
}
+
RedeclarableTemplateDecl *getMostRecentDeclImpl() override {
return getMostRecentDecl();
}
protected:
template <typename EntryType> struct SpecEntryTraits {
- typedef EntryType DeclType;
+ using DeclType = EntryType;
static DeclType *getDecl(EntryType *D) {
return D;
}
+
static ArrayRef<TemplateArgument> getTemplateArgs(EntryType *D) {
return D->getTemplateArgs().asArray();
}
@@ -756,7 +772,7 @@ protected:
typename std::iterator_traits<typename llvm::FoldingSetVector<
EntryType>::iterator>::iterator_category,
DeclType *, ptrdiff_t, DeclType *, DeclType *> {
- SpecIterator() {}
+ SpecIterator() = default;
explicit SpecIterator(
typename llvm::FoldingSetVector<EntryType>::iterator SetIter)
: SpecIterator::iterator_adaptor_base(std::move(SetIter)) {}
@@ -764,6 +780,7 @@ protected:
DeclType *operator*() const {
return SETraits::getDecl(&*this->I)->getMostRecentDecl();
}
+
DeclType *operator->() const { return **this; }
};
@@ -773,6 +790,8 @@ protected:
return SpecIterator<EntryType>(isEnd ? Specs.end() : Specs.begin());
}
+ void loadLazySpecializationsImpl() const;
+
template <class EntryType> typename SpecEntryTraits<EntryType>::DeclType*
findSpecializationImpl(llvm::FoldingSetVector<EntryType> &Specs,
ArrayRef<TemplateArgument> Args, void *&InsertPos);
@@ -782,7 +801,7 @@ protected:
EntryType *Entry, void *InsertPos);
struct CommonBase {
- CommonBase() : InstantiatedFromMember(nullptr, false) { }
+ CommonBase() : InstantiatedFromMember(nullptr, false) {}
/// \brief The template from which this was most
/// directly instantiated (or null).
@@ -791,11 +810,18 @@ protected:
/// was explicitly specialized.
llvm::PointerIntPair<RedeclarableTemplateDecl*, 1, bool>
InstantiatedFromMember;
+
+ /// \brief If non-null, points to an array of specializations (including
+ /// partial specializations) known only by their external declaration IDs.
+ ///
+ /// The first value in the array is the number of specializations/partial
+ /// specializations that follow.
+ uint32_t *LazySpecializations = nullptr;
};
/// \brief Pointer to the common data shared by all declarations of this
/// template.
- mutable CommonBase *Common;
+ mutable CommonBase *Common = nullptr;
/// \brief Retrieves the "common" pointer shared by all (re-)declarations of
/// the same template. Calling this routine may implicitly allocate memory
@@ -809,8 +835,8 @@ protected:
ASTContext &C, DeclContext *DC, SourceLocation L,
DeclarationName Name, TemplateParameterList *Params,
NamedDecl *Decl)
- : TemplateDecl(CTDI, DK, DC, L, Name, Params, Decl), redeclarable_base(C),
- Common() {}
+ : TemplateDecl(CTDI, DK, DC, L, Name, Params, Decl), redeclarable_base(C)
+ {}
RedeclarableTemplateDecl(Kind DK, ASTContext &C, DeclContext *DC,
SourceLocation L, DeclarationName Name,
@@ -818,6 +844,9 @@ protected:
: RedeclarableTemplateDecl(nullptr, DK, C, DC, L, Name, Params, Decl) {}
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+ friend class ASTReader;
template <class decl_type> friend class RedeclarableTemplate;
/// \brief Retrieves the canonical declaration of this template.
@@ -858,7 +887,7 @@ public:
}
/// \brief Retrieve the member template from which this template was
- /// instantiated, or NULL if this template was not instantiated from a
+ /// instantiated, or nullptr if this template was not instantiated from a
/// member template.
///
/// A template is instantiated from a member template when the member
@@ -902,8 +931,9 @@ public:
getCommonPtr()->InstantiatedFromMember.setPointer(TD);
}
- typedef redeclarable_base::redecl_range redecl_range;
- typedef redeclarable_base::redecl_iterator redecl_iterator;
+ using redecl_range = redeclarable_base::redecl_range;
+ using redecl_iterator = redeclarable_base::redecl_iterator;
+
using redeclarable_base::redecls_begin;
using redeclarable_base::redecls_end;
using redeclarable_base::redecls;
@@ -913,22 +943,20 @@ public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+
static bool classofKind(Kind K) {
return K >= firstRedeclarableTemplate && K <= lastRedeclarableTemplate;
}
-
- friend class ASTReader;
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
};
template <> struct RedeclarableTemplateDecl::
SpecEntryTraits<FunctionTemplateSpecializationInfo> {
- typedef FunctionDecl DeclType;
+ using DeclType = FunctionDecl;
static DeclType *getDecl(FunctionTemplateSpecializationInfo *I) {
return I->Function;
}
+
static ArrayRef<TemplateArgument>
getTemplateArgs(FunctionTemplateSpecializationInfo *I) {
return I->TemplateArguments->asArray();
@@ -938,11 +966,11 @@ SpecEntryTraits<FunctionTemplateSpecializationInfo> {
/// Declaration of a template function.
class FunctionTemplateDecl : public RedeclarableTemplateDecl {
protected:
+ friend class FunctionDecl;
+
/// \brief Data that is common to all of the declarations of a given
/// function template.
struct Common : CommonBase {
- Common() : InjectedArgs(), LazySpecializations() { }
-
/// \brief The function template specializations for this function
/// template, including explicit specializations and instantiations.
llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> Specializations;
@@ -954,14 +982,9 @@ protected:
/// many template arguments as template parameaters) for the function
/// template, and is allocated lazily, since most function templates do not
/// require the use of this information.
- TemplateArgument *InjectedArgs;
+ TemplateArgument *InjectedArgs = nullptr;
- /// \brief If non-null, points to an array of specializations known only
- /// by their external declaration IDs.
- ///
- /// The first value in the array is the number of of specializations
- /// that follow.
- uint32_t *LazySpecializations;
+ Common() = default;
};
FunctionTemplateDecl(ASTContext &C, DeclContext *DC, SourceLocation L,
@@ -976,8 +999,6 @@ protected:
return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
}
- friend class FunctionDecl;
-
/// \brief Retrieve the set of function template specializations of this
/// function template.
llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> &
@@ -991,12 +1012,15 @@ protected:
void *InsertPos);
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+
/// \brief Load any lazily-loaded specializations from the external source.
void LoadLazySpecializations() const;
/// Get the underlying function declaration of the template.
FunctionDecl *getTemplatedDecl() const {
- return static_cast<FunctionDecl *>(TemplatedDecl.getPointer());
+ return static_cast<FunctionDecl *>(TemplatedDecl);
}
/// Returns whether this template declaration defines the primary
@@ -1020,14 +1044,11 @@ public:
}
/// \brief Retrieve the previous declaration of this function template, or
- /// NULL if no such declaration exists.
+ /// nullptr if no such declaration exists.
FunctionTemplateDecl *getPreviousDecl() {
return cast_or_null<FunctionTemplateDecl>(
static_cast<RedeclarableTemplateDecl *>(this)->getPreviousDecl());
}
-
- /// \brief Retrieve the previous declaration of this function template, or
- /// NULL if no such declaration exists.
const FunctionTemplateDecl *getPreviousDecl() const {
return cast_or_null<FunctionTemplateDecl>(
static_cast<const RedeclarableTemplateDecl *>(this)->getPreviousDecl());
@@ -1047,12 +1068,13 @@ public:
RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
}
- typedef SpecIterator<FunctionTemplateSpecializationInfo> spec_iterator;
- typedef llvm::iterator_range<spec_iterator> spec_range;
+ using spec_iterator = SpecIterator<FunctionTemplateSpecializationInfo>;
+ using spec_range = llvm::iterator_range<spec_iterator>;
spec_range specializations() const {
return spec_range(spec_begin(), spec_end());
}
+
spec_iterator spec_begin() const {
return makeSpecIterator(getSpecializations(), false);
}
@@ -1083,9 +1105,6 @@ public:
// Implement isa/cast/dyncast support
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == FunctionTemplate; }
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
};
//===----------------------------------------------------------------------===//
@@ -1102,19 +1121,17 @@ public:
/// This class is inheritedly privately by different kinds of template
/// parameters and is not part of the Decl hierarchy. Just a facility.
class TemplateParmPosition {
- TemplateParmPosition() = delete;
-
protected:
- TemplateParmPosition(unsigned D, unsigned P)
- : Depth(D), Position(P)
- { }
-
// FIXME: These probably don't need to be ints. int:5 for depth, int:8 for
// position? Maybe?
unsigned Depth;
unsigned Position;
+ TemplateParmPosition(unsigned D, unsigned P) : Depth(D), Position(P) {}
+
public:
+ TemplateParmPosition() = delete;
+
/// Get the nesting depth of the template parameter.
unsigned getDepth() const { return Depth; }
void setDepth(unsigned D) { Depth = D; }
@@ -1134,6 +1151,9 @@ public:
/// template<typename T> class vector;
/// \endcode
class TemplateTypeParmDecl : public TypeDecl {
+ /// Sema creates these on the stack during auto type deduction.
+ friend class Sema;
+
/// \brief Whether this template type parameter was declaration with
/// the 'typename' keyword.
///
@@ -1141,18 +1161,14 @@ class TemplateTypeParmDecl : public TypeDecl {
bool Typename : 1;
/// \brief The default template argument, if any.
- typedef DefaultArgStorage<TemplateTypeParmDecl, TypeSourceInfo *>
- DefArgStorage;
+ using DefArgStorage =
+ DefaultArgStorage<TemplateTypeParmDecl, TypeSourceInfo *>;
DefArgStorage DefaultArgument;
TemplateTypeParmDecl(DeclContext *DC, SourceLocation KeyLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
bool Typename)
- : TypeDecl(TemplateTypeParm, DC, IdLoc, Id, KeyLoc), Typename(Typename),
- DefaultArgument() { }
-
- /// Sema creates these on the stack during auto type deduction.
- friend class Sema;
+ : TypeDecl(TemplateTypeParm, DC, IdLoc, Id, KeyLoc), Typename(Typename) {}
public:
static TemplateTypeParmDecl *Create(const ASTContext &C, DeclContext *DC,
@@ -1199,6 +1215,7 @@ public:
void setDefaultArgument(TypeSourceInfo *DefArg) {
DefaultArgument.set(DefArg);
}
+
/// \brief Set that this default argument was inherited from another
/// parameter.
void setInheritedDefaultArgument(const ASTContext &C,
@@ -1241,9 +1258,12 @@ class NonTypeTemplateParmDecl final
protected TemplateParmPosition,
private llvm::TrailingObjects<NonTypeTemplateParmDecl,
std::pair<QualType, TypeSourceInfo *>> {
+ friend class ASTDeclReader;
+ friend TrailingObjects;
+
/// \brief The default template argument, if any, and whether or not
/// it was inherited.
- typedef DefaultArgStorage<NonTypeTemplateParmDecl, Expr*> DefArgStorage;
+ using DefArgStorage = DefaultArgStorage<NonTypeTemplateParmDecl, Expr *>;
DefArgStorage DefaultArgument;
// FIXME: Collapse this into TemplateParamPosition; or, just move depth/index
@@ -1255,10 +1275,10 @@ class NonTypeTemplateParmDecl final
/// \brief Whether this non-type template parameter is an "expanded"
/// parameter pack, meaning that its type is a pack expansion and we
/// already know the set of types that expansion expands to.
- bool ExpandedParameterPack;
+ bool ExpandedParameterPack = false;
/// \brief The number of types in an expanded parameter pack.
- unsigned NumExpandedTypes;
+ unsigned NumExpandedTypes = 0;
size_t numTrailingObjects(
OverloadToken<std::pair<QualType, TypeSourceInfo *>>) const {
@@ -1269,10 +1289,8 @@ class NonTypeTemplateParmDecl final
SourceLocation IdLoc, unsigned D, unsigned P,
IdentifierInfo *Id, QualType T,
bool ParameterPack, TypeSourceInfo *TInfo)
- : DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc),
- TemplateParmPosition(D, P), ParameterPack(ParameterPack),
- ExpandedParameterPack(false), NumExpandedTypes(0)
- { }
+ : DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc),
+ TemplateParmPosition(D, P), ParameterPack(ParameterPack) {}
NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, unsigned D, unsigned P,
@@ -1281,9 +1299,6 @@ class NonTypeTemplateParmDecl final
ArrayRef<QualType> ExpandedTypes,
ArrayRef<TypeSourceInfo *> ExpandedTInfos);
- friend class ASTDeclReader;
- friend TrailingObjects;
-
public:
static NonTypeTemplateParmDecl *
Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
@@ -1428,11 +1443,9 @@ class TemplateTemplateParmDecl final
protected TemplateParmPosition,
private llvm::TrailingObjects<TemplateTemplateParmDecl,
TemplateParameterList *> {
- void anchor() override;
-
/// \brief The default template argument, if any.
- typedef DefaultArgStorage<TemplateTemplateParmDecl, TemplateArgumentLoc *>
- DefArgStorage;
+ using DefArgStorage =
+ DefaultArgStorage<TemplateTemplateParmDecl, TemplateArgumentLoc *>;
DefArgStorage DefaultArgument;
/// \brief Whether this parameter is a parameter pack.
@@ -1441,25 +1454,29 @@ class TemplateTemplateParmDecl final
/// \brief Whether this template template parameter is an "expanded"
/// parameter pack, meaning that it is a pack expansion and we
/// already know the set of template parameters that expansion expands to.
- bool ExpandedParameterPack;
+ bool ExpandedParameterPack = false;
/// \brief The number of parameters in an expanded parameter pack.
- unsigned NumExpandedParams;
+ unsigned NumExpandedParams = 0;
TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L,
unsigned D, unsigned P, bool ParameterPack,
IdentifierInfo *Id, TemplateParameterList *Params)
- : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
- TemplateParmPosition(D, P), ParameterPack(ParameterPack),
- ExpandedParameterPack(false), NumExpandedParams(0)
- { }
+ : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
+ TemplateParmPosition(D, P), ParameterPack(ParameterPack) {}
TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L,
unsigned D, unsigned P,
IdentifierInfo *Id, TemplateParameterList *Params,
ArrayRef<TemplateParameterList *> Expansions);
+ void anchor() override;
+
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+ friend TrailingObjects;
+
static TemplateTemplateParmDecl *Create(const ASTContext &C, DeclContext *DC,
SourceLocation L, unsigned D,
unsigned P, bool ParameterPack,
@@ -1579,22 +1596,18 @@ public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == TemplateTemplateParm; }
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
- friend TrailingObjects;
};
/// \brief Represents the builtin template declaration which is used to
/// implement __make_integer_seq and other builtin templates. It serves
/// no real purpose beyond existing as a place to hold template parameters.
class BuiltinTemplateDecl : public TemplateDecl {
- void anchor() override;
+ BuiltinTemplateKind BTK;
BuiltinTemplateDecl(const ASTContext &C, DeclContext *DC,
DeclarationName Name, BuiltinTemplateKind BTK);
- BuiltinTemplateKind BTK;
+ void anchor() override;
public:
// Implement isa/cast/dyncast support
@@ -1629,7 +1642,6 @@ public:
/// \endcode
class ClassTemplateSpecializationDecl
: public CXXRecordDecl, public llvm::FoldingSetNode {
-
/// \brief Structure that stores information about a class template
/// specialization that was instantiated from a class template partial
/// specialization.
@@ -1650,19 +1662,20 @@ class ClassTemplateSpecializationDecl
/// \brief Further info for explicit template specialization/instantiation.
struct ExplicitSpecializationInfo {
/// \brief The type-as-written.
- TypeSourceInfo *TypeAsWritten;
+ TypeSourceInfo *TypeAsWritten = nullptr;
+
/// \brief The location of the extern keyword.
SourceLocation ExternLoc;
+
/// \brief The location of the template keyword.
SourceLocation TemplateKeywordLoc;
- ExplicitSpecializationInfo()
- : TypeAsWritten(nullptr), ExternLoc(), TemplateKeywordLoc() {}
+ ExplicitSpecializationInfo() = default;
};
/// \brief Further info for explicit template specialization/instantiation.
/// Does not apply to implicit specializations.
- ExplicitSpecializationInfo *ExplicitInfo;
+ ExplicitSpecializationInfo *ExplicitInfo = nullptr;
/// \brief The template arguments used to describe this specialization.
const TemplateArgumentList *TemplateArgs;
@@ -1685,6 +1698,9 @@ protected:
explicit ClassTemplateSpecializationDecl(ASTContext &C, Kind DK);
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+
static ClassTemplateSpecializationDecl *
Create(ASTContext &Context, TagKind TK, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
@@ -1828,6 +1844,7 @@ public:
ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
ExplicitInfo->TypeAsWritten = T;
}
+
/// \brief Gets the type of this specialization as it was written by
/// the user, if it was so written.
TypeSourceInfo *getTypeAsWritten() const {
@@ -1838,6 +1855,7 @@ public:
SourceLocation getExternLoc() const {
return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation();
}
+
/// \brief Sets the location of the extern keyword.
void setExternLoc(SourceLocation Loc) {
if (!ExplicitInfo)
@@ -1851,6 +1869,7 @@ public:
ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
ExplicitInfo->TemplateKeywordLoc = Loc;
}
+
/// \brief Gets the location of the template keyword, if present.
SourceLocation getTemplateKeywordLoc() const {
return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation();
@@ -1871,25 +1890,21 @@ public:
}
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+
static bool classofKind(Kind K) {
return K >= firstClassTemplateSpecialization &&
K <= lastClassTemplateSpecialization;
}
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
};
class ClassTemplatePartialSpecializationDecl
: public ClassTemplateSpecializationDecl {
- void anchor() override;
-
/// \brief The list of template parameters
- TemplateParameterList* TemplateParams;
+ TemplateParameterList* TemplateParams = nullptr;
/// \brief The source info for the template arguments as written.
/// FIXME: redundant with TypeAsWritten?
- const ASTTemplateArgumentListInfo *ArgsAsWritten;
+ const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr;
/// \brief The class template partial specialization from which this
/// class template partial specialization was instantiated.
@@ -1911,10 +1926,14 @@ class ClassTemplatePartialSpecializationDecl
ClassTemplatePartialSpecializationDecl(ASTContext &C)
: ClassTemplateSpecializationDecl(C, ClassTemplatePartialSpecialization),
- TemplateParams(nullptr), ArgsAsWritten(nullptr),
InstantiatedFromMember(nullptr, false) {}
+ void anchor() override;
+
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+
static ClassTemplatePartialSpecializationDecl *
Create(ASTContext &Context, TagKind TK, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
@@ -2024,12 +2043,10 @@ public:
// FIXME: Add Profile support!
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+
static bool classofKind(Kind K) {
return K == ClassTemplatePartialSpecialization;
}
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
};
/// Declaration of a class template.
@@ -2038,8 +2055,6 @@ protected:
/// \brief Data that is common to all of the declarations of a given
/// class template.
struct Common : CommonBase {
- Common() : LazySpecializations() { }
-
/// \brief The class template specializations for this class
/// template, including explicit specializations and instantiations.
llvm::FoldingSetVector<ClassTemplateSpecializationDecl> Specializations;
@@ -2052,12 +2067,7 @@ protected:
/// \brief The injected-class-name type for this class template.
QualType InjectedClassNameType;
- /// \brief If non-null, points to an array of specializations (including
- /// partial specializations) known only by their external declaration IDs.
- ///
- /// The first value in the array is the number of of specializations/
- /// partial specializations that follow.
- uint32_t *LazySpecializations;
+ Common() = default;
};
/// \brief Retrieve the set of specializations of this class template.
@@ -2087,12 +2097,15 @@ protected:
}
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+
/// \brief Load any lazily-loaded specializations from the external source.
void LoadLazySpecializations() const;
/// \brief Get the underlying class declarations of the template.
CXXRecordDecl *getTemplatedDecl() const {
- return static_cast<CXXRecordDecl *>(TemplatedDecl.getPointer());
+ return static_cast<CXXRecordDecl *>(TemplatedDecl);
}
/// \brief Returns whether this template declaration defines the primary
@@ -2132,14 +2145,11 @@ public:
}
/// \brief Retrieve the previous declaration of this class template, or
- /// NULL if no such declaration exists.
+ /// nullptr if no such declaration exists.
ClassTemplateDecl *getPreviousDecl() {
return cast_or_null<ClassTemplateDecl>(
static_cast<RedeclarableTemplateDecl *>(this)->getPreviousDecl());
}
-
- /// \brief Retrieve the previous declaration of this class template, or
- /// NULL if no such declaration exists.
const ClassTemplateDecl *getPreviousDecl() const {
return cast_or_null<ClassTemplateDecl>(
static_cast<const RedeclarableTemplateDecl *>(
@@ -2180,7 +2190,7 @@ public:
/// template.
///
/// \returns the class template partial specialization that exactly matches
- /// the type \p T, or NULL if no such partial specialization exists.
+ /// the type \p T, or nullptr if no such partial specialization exists.
ClassTemplatePartialSpecializationDecl *findPartialSpecialization(QualType T);
/// \brief Find a class template partial specialization which was instantiated
@@ -2189,8 +2199,8 @@ public:
/// \param D a member class template partial specialization.
///
/// \returns the class template partial specialization which was instantiated
- /// from the given member partial specialization, or NULL if no such partial
- /// specialization exists.
+ /// from the given member partial specialization, or nullptr if no such
+ /// partial specialization exists.
ClassTemplatePartialSpecializationDecl *
findPartialSpecInstantiatedFromMember(
ClassTemplatePartialSpecializationDecl *D);
@@ -2211,8 +2221,8 @@ public:
/// \endcode
QualType getInjectedClassNameSpecialization();
- typedef SpecIterator<ClassTemplateSpecializationDecl> spec_iterator;
- typedef llvm::iterator_range<spec_iterator> spec_range;
+ using spec_iterator = SpecIterator<ClassTemplateSpecializationDecl>;
+ using spec_range = llvm::iterator_range<spec_iterator>;
spec_range specializations() const {
return spec_range(spec_begin(), spec_end());
@@ -2229,9 +2239,6 @@ public:
// Implement isa/cast/dyncast support
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ClassTemplate; }
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
};
/// \brief Declaration of a friend template.
@@ -2249,15 +2256,16 @@ public:
/// will yield a FriendDecl, not a FriendTemplateDecl.
class FriendTemplateDecl : public Decl {
virtual void anchor();
+
public:
- typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion;
+ using FriendUnion = llvm::PointerUnion<NamedDecl *,TypeSourceInfo *>;
private:
// The number of template parameters; always non-zero.
- unsigned NumParams;
+ unsigned NumParams = 0;
// The parameter list.
- TemplateParameterList **Params;
+ TemplateParameterList **Params = nullptr;
// The declaration that's a friend of this class.
FriendUnion Friend;
@@ -2271,13 +2279,11 @@ private:
: Decl(Decl::FriendTemplate, DC, Loc), NumParams(Params.size()),
Params(Params.data()), Friend(Friend), FriendLoc(FriendLoc) {}
- FriendTemplateDecl(EmptyShell Empty)
- : Decl(Decl::FriendTemplate, Empty),
- NumParams(0),
- Params(nullptr)
- {}
+ FriendTemplateDecl(EmptyShell Empty) : Decl(Decl::FriendTemplate, Empty) {}
public:
+ friend class ASTDeclReader;
+
static FriendTemplateDecl *
Create(ASTContext &Context, DeclContext *DC, SourceLocation Loc,
MutableArrayRef<TemplateParameterList *> Params, FriendUnion Friend,
@@ -2316,8 +2322,6 @@ public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Decl::FriendTemplate; }
-
- friend class ASTDeclReader;
};
/// \brief Declaration of an alias template.
@@ -2328,7 +2332,7 @@ public:
/// \endcode
class TypeAliasTemplateDecl : public RedeclarableTemplateDecl {
protected:
- typedef CommonBase Common;
+ using Common = CommonBase;
TypeAliasTemplateDecl(ASTContext &C, DeclContext *DC, SourceLocation L,
DeclarationName Name, TemplateParameterList *Params,
@@ -2343,9 +2347,12 @@ protected:
}
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+
/// Get the underlying function declaration of the template.
TypeAliasDecl *getTemplatedDecl() const {
- return static_cast<TypeAliasDecl *>(TemplatedDecl.getPointer());
+ return static_cast<TypeAliasDecl *>(TemplatedDecl);
}
@@ -2359,14 +2366,11 @@ public:
}
/// \brief Retrieve the previous declaration of this function template, or
- /// NULL if no such declaration exists.
+ /// nullptr if no such declaration exists.
TypeAliasTemplateDecl *getPreviousDecl() {
return cast_or_null<TypeAliasTemplateDecl>(
static_cast<RedeclarableTemplateDecl *>(this)->getPreviousDecl());
}
-
- /// \brief Retrieve the previous declaration of this function template, or
- /// NULL if no such declaration exists.
const TypeAliasTemplateDecl *getPreviousDecl() const {
return cast_or_null<TypeAliasTemplateDecl>(
static_cast<const RedeclarableTemplateDecl *>(
@@ -2378,7 +2382,6 @@ public:
RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
}
-
/// \brief Create a function template node.
static TypeAliasTemplateDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
@@ -2392,9 +2395,6 @@ public:
// Implement isa/cast/dyncast support
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == TypeAliasTemplate; }
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
};
/// \brief Declaration of a function specialization at template class scope.
@@ -2414,7 +2414,9 @@ public:
/// CXXMethodDecl. Then during an instantiation of class A, it will be
/// transformed into an actual function specialization.
class ClassScopeFunctionSpecializationDecl : public Decl {
- virtual void anchor();
+ CXXMethodDecl *Specialization;
+ bool HasExplicitTemplateArgs;
+ TemplateArgumentListInfo TemplateArgs;
ClassScopeFunctionSpecializationDecl(DeclContext *DC, SourceLocation Loc,
CXXMethodDecl *FD, bool Args,
@@ -2424,13 +2426,14 @@ class ClassScopeFunctionSpecializationDecl : public Decl {
TemplateArgs(std::move(TemplArgs)) {}
ClassScopeFunctionSpecializationDecl(EmptyShell Empty)
- : Decl(Decl::ClassScopeFunctionSpecialization, Empty) {}
+ : Decl(Decl::ClassScopeFunctionSpecialization, Empty) {}
- CXXMethodDecl *Specialization;
- bool HasExplicitTemplateArgs;
- TemplateArgumentListInfo TemplateArgs;
+ virtual void anchor();
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+
CXXMethodDecl *getSpecialization() const { return Specialization; }
bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; }
const TemplateArgumentListInfo& templateArgs() const { return TemplateArgs; }
@@ -2450,17 +2453,15 @@ public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+
static bool classofKind(Kind K) {
return K == Decl::ClassScopeFunctionSpecialization;
}
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
};
/// Implementation of inline functions that require the template declarations
inline AnyFunctionDecl::AnyFunctionDecl(FunctionTemplateDecl *FTD)
- : Function(FTD) { }
+ : Function(FTD) {}
/// \brief Represents a variable template specialization, which refers to
/// a variable template with a given set of template arguments.
@@ -2498,19 +2499,20 @@ class VarTemplateSpecializationDecl : public VarDecl,
/// \brief Further info for explicit template specialization/instantiation.
struct ExplicitSpecializationInfo {
/// \brief The type-as-written.
- TypeSourceInfo *TypeAsWritten;
+ TypeSourceInfo *TypeAsWritten = nullptr;
+
/// \brief The location of the extern keyword.
SourceLocation ExternLoc;
+
/// \brief The location of the template keyword.
SourceLocation TemplateKeywordLoc;
- ExplicitSpecializationInfo()
- : TypeAsWritten(nullptr), ExternLoc(), TemplateKeywordLoc() {}
+ ExplicitSpecializationInfo() = default;
};
/// \brief Further info for explicit template specialization/instantiation.
/// Does not apply to implicit specializations.
- ExplicitSpecializationInfo *ExplicitInfo;
+ ExplicitSpecializationInfo *ExplicitInfo = nullptr;
/// \brief The template arguments used to describe this specialization.
const TemplateArgumentList *TemplateArgs;
@@ -2523,6 +2525,12 @@ class VarTemplateSpecializationDecl : public VarDecl,
/// Really a value of type TemplateSpecializationKind.
unsigned SpecializationKind : 3;
+ /// \brief Whether this declaration is a complete definition of the
+ /// variable template specialization. We can't otherwise tell apart
+ /// an instantiated declaration from an instantiated definition with
+ /// no initializer.
+ unsigned IsCompleteDefinition : 1;
+
protected:
VarTemplateSpecializationDecl(Kind DK, ASTContext &Context, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
@@ -2534,6 +2542,10 @@ protected:
explicit VarTemplateSpecializationDecl(Kind DK, ASTContext &Context);
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+ friend class VarDecl;
+
static VarTemplateSpecializationDecl *
Create(ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T,
@@ -2596,6 +2608,8 @@ public:
PointOfInstantiation = Loc;
}
+ void setCompleteDefinition() { IsCompleteDefinition = true; }
+
/// \brief If this variable template specialization is an instantiation of
/// a template (rather than an explicit specialization), return the
/// variable template or variable template partial specialization from which
@@ -2668,6 +2682,7 @@ public:
ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
ExplicitInfo->TypeAsWritten = T;
}
+
/// \brief Gets the type of this specialization as it was written by
/// the user, if it was so written.
TypeSourceInfo *getTypeAsWritten() const {
@@ -2678,6 +2693,7 @@ public:
SourceLocation getExternLoc() const {
return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation();
}
+
/// \brief Sets the location of the extern keyword.
void setExternLoc(SourceLocation Loc) {
if (!ExplicitInfo)
@@ -2691,6 +2707,7 @@ public:
ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
ExplicitInfo->TemplateKeywordLoc = Loc;
}
+
/// \brief Gets the location of the template keyword, if present.
SourceLocation getTemplateKeywordLoc() const {
return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation();
@@ -2709,25 +2726,21 @@ public:
}
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+
static bool classofKind(Kind K) {
return K >= firstVarTemplateSpecialization &&
K <= lastVarTemplateSpecialization;
}
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
};
class VarTemplatePartialSpecializationDecl
: public VarTemplateSpecializationDecl {
- void anchor() override;
-
/// \brief The list of template parameters
- TemplateParameterList *TemplateParams;
+ TemplateParameterList *TemplateParams = nullptr;
/// \brief The source info for the template arguments as written.
/// FIXME: redundant with TypeAsWritten?
- const ASTTemplateArgumentListInfo *ArgsAsWritten;
+ const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr;
/// \brief The variable template partial specialization from which this
/// variable template partial specialization was instantiated.
@@ -2745,11 +2758,16 @@ class VarTemplatePartialSpecializationDecl
const ASTTemplateArgumentListInfo *ArgInfos);
VarTemplatePartialSpecializationDecl(ASTContext &Context)
- : VarTemplateSpecializationDecl(VarTemplatePartialSpecialization, Context),
- TemplateParams(nullptr), ArgsAsWritten(nullptr),
- InstantiatedFromMember(nullptr, false) {}
+ : VarTemplateSpecializationDecl(VarTemplatePartialSpecialization,
+ Context),
+ InstantiatedFromMember(nullptr, false) {}
+
+ void anchor() override;
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+
static VarTemplatePartialSpecializationDecl *
Create(ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, TemplateParameterList *Params,
@@ -2841,12 +2859,10 @@ public:
}
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+
static bool classofKind(Kind K) {
return K == VarTemplatePartialSpecialization;
}
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
};
/// Declaration of a variable template.
@@ -2855,8 +2871,6 @@ protected:
/// \brief Data that is common to all of the declarations of a given
/// variable template.
struct Common : CommonBase {
- Common() : LazySpecializations() {}
-
/// \brief The variable template specializations for this variable
/// template, including explicit specializations and instantiations.
llvm::FoldingSetVector<VarTemplateSpecializationDecl> Specializations;
@@ -2866,12 +2880,7 @@ protected:
llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl>
PartialSpecializations;
- /// \brief If non-null, points to an array of specializations (including
- /// partial specializations) known ownly by their external declaration IDs.
- ///
- /// The first value in the array is the number of of specializations/
- /// partial specializations that follow.
- uint32_t *LazySpecializations;
+ Common() = default;
};
/// \brief Retrieve the set of specializations of this variable template.
@@ -2895,12 +2904,15 @@ protected:
}
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+
/// \brief Load any lazily-loaded specializations from the external source.
void LoadLazySpecializations() const;
/// \brief Get the underlying variable declarations of the template.
VarDecl *getTemplatedDecl() const {
- return static_cast<VarDecl *>(TemplatedDecl.getPointer());
+ return static_cast<VarDecl *>(TemplatedDecl);
}
/// \brief Returns whether this template declaration defines the primary
@@ -2937,14 +2949,11 @@ public:
}
/// \brief Retrieve the previous declaration of this variable template, or
- /// NULL if no such declaration exists.
+ /// nullptr if no such declaration exists.
VarTemplateDecl *getPreviousDecl() {
return cast_or_null<VarTemplateDecl>(
static_cast<RedeclarableTemplateDecl *>(this)->getPreviousDecl());
}
-
- /// \brief Retrieve the previous declaration of this variable template, or
- /// NULL if no such declaration exists.
const VarTemplateDecl *getPreviousDecl() const {
return cast_or_null<VarTemplateDecl>(
static_cast<const RedeclarableTemplateDecl *>(
@@ -2986,13 +2995,13 @@ public:
///
/// \returns the variable template partial specialization which was
/// instantiated
- /// from the given member partial specialization, or NULL if no such partial
- /// specialization exists.
+ /// from the given member partial specialization, or nullptr if no such
+ /// partial specialization exists.
VarTemplatePartialSpecializationDecl *findPartialSpecInstantiatedFromMember(
VarTemplatePartialSpecializationDecl *D);
- typedef SpecIterator<VarTemplateSpecializationDecl> spec_iterator;
- typedef llvm::iterator_range<spec_iterator> spec_range;
+ using spec_iterator = SpecIterator<VarTemplateSpecializationDecl>;
+ using spec_range = llvm::iterator_range<spec_iterator>;
spec_range specializations() const {
return spec_range(spec_begin(), spec_end());
@@ -3009,9 +3018,6 @@ public:
// Implement isa/cast/dyncast support
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == VarTemplate; }
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
};
inline NamedDecl *getAsNamedDecl(TemplateParameter P) {
@@ -3032,6 +3038,6 @@ inline TemplateDecl *getAsTypeTemplateDecl(Decl *D) {
: nullptr;
}
-} /* end of namespace clang */
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_AST_DECLTEMPLATE_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/DeclVisitor.h
index 4eaae35778b93..3ff274bd6a7a1 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclVisitor.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclVisitor.h
@@ -1,4 +1,4 @@
-//===--- DeclVisitor.h - Visitor for Decl subclasses ------------*- C++ -*-===//
+//===- DeclVisitor.h - Visitor for Decl subclasses --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,27 +10,30 @@
// This file defines the DeclVisitor interface.
//
//===----------------------------------------------------------------------===//
+
#ifndef LLVM_CLANG_AST_DECLVISITOR_H
#define LLVM_CLANG_AST_DECLVISITOR_H
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclOpenMP.h"
#include "clang/AST/DeclTemplate.h"
+#include "llvm/Support/ErrorHandling.h"
namespace clang {
+
namespace declvisitor {
-template <typename T> struct make_ptr { typedef T *type; };
-template <typename T> struct make_const_ptr { typedef const T *type; };
+template <typename T> struct make_ptr { using type = T *; };
+template <typename T> struct make_const_ptr { using type = const T *; };
/// \brief A simple visitor class that helps create declaration visitors.
template<template <typename> class Ptr, typename ImplClass, typename RetTy=void>
class Base {
public:
-
#define PTR(CLASS) typename Ptr<CLASS>::type
#define DISPATCH(NAME, CLASS) \
return static_cast<ImplClass*>(this)->Visit##NAME(static_cast<PTR(CLASS)>(D))
@@ -57,23 +60,23 @@ public:
#undef DISPATCH
};
-} // end namespace declvisitor
+} // namespace declvisitor
/// \brief A simple visitor class that helps create declaration visitors.
///
/// This class does not preserve constness of Decl pointers (see also
/// ConstDeclVisitor).
-template<typename ImplClass, typename RetTy=void>
+template<typename ImplClass, typename RetTy = void>
class DeclVisitor
: public declvisitor::Base<declvisitor::make_ptr, ImplClass, RetTy> {};
/// \brief A simple visitor class that helps create declaration visitors.
///
/// This class preserves constness of Decl pointers (see also DeclVisitor).
-template<typename ImplClass, typename RetTy=void>
+template<typename ImplClass, typename RetTy = void>
class ConstDeclVisitor
: public declvisitor::Base<declvisitor::make_const_ptr, ImplClass, RetTy> {};
-} // end namespace clang
+} // namespace clang
#endif // LLVM_CLANG_AST_DECLVISITOR_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h b/contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h
index 5e773c9683847..467b02c52b0c9 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h
@@ -1,4 +1,4 @@
-//===-- DeclarationName.h - Representation of declaration names -*- C++ -*-===//
+//===- DeclarationName.h - Representation of declaration names --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,36 +10,42 @@
// This file declares the DeclarationName and DeclarationNameTable classes.
//
//===----------------------------------------------------------------------===//
+
#ifndef LLVM_CLANG_AST_DECLARATIONNAME_H
#define LLVM_CLANG_AST_DECLARATIONNAME_H
+#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/Support/Compiler.h"
-
-namespace llvm {
- template <typename T> struct DenseMapInfo;
-}
+#include "llvm/Support/type_traits.h"
+#include <cassert>
+#include <cstdint>
+#include <cstring>
+#include <string>
namespace clang {
- class ASTContext;
- class CXXDeductionGuideNameExtra;
- class CXXLiteralOperatorIdName;
- class CXXOperatorIdName;
- class CXXSpecialName;
- class DeclarationNameExtra;
- class IdentifierInfo;
- class MultiKeywordSelector;
- enum OverloadedOperatorKind : int;
- struct PrintingPolicy;
- class QualType;
- class TemplateDecl;
- class Type;
- class TypeSourceInfo;
- class UsingDirectiveDecl;
- template <typename> class CanQual;
- typedef CanQual<Type> CanQualType;
+class ASTContext;
+template <typename> class CanQual;
+class CXXDeductionGuideNameExtra;
+class CXXLiteralOperatorIdName;
+class CXXOperatorIdName;
+class CXXSpecialName;
+class DeclarationNameExtra;
+class IdentifierInfo;
+class MultiKeywordSelector;
+enum OverloadedOperatorKind : int;
+struct PrintingPolicy;
+class QualType;
+class TemplateDecl;
+class Type;
+class TypeSourceInfo;
+class UsingDirectiveDecl;
+
+using CanQualType = CanQual<Type>;
/// DeclarationName - The name of a declaration. In the common case,
/// this just stores an IdentifierInfo pointer to a normal
@@ -63,9 +69,13 @@ public:
CXXLiteralOperatorName,
CXXUsingDirective
};
+
static const unsigned NumNameKinds = CXXUsingDirective + 1;
private:
+ friend class DeclarationNameTable;
+ friend class NamedDecl;
+
/// StoredNameKind - The kind of name that is actually stored in the
/// upper bits of the Ptr field. This is only used internally.
///
@@ -99,7 +109,18 @@ private:
/// DeclarationNameExtra structure, whose first value will tell us
/// whether this is an Objective-C selector, C++ operator-id name,
/// or special C++ name.
- uintptr_t Ptr;
+ uintptr_t Ptr = 0;
+
+ // Construct a declaration name from the name of a C++ constructor,
+ // destructor, or conversion function.
+ DeclarationName(DeclarationNameExtra *Name)
+ : Ptr(reinterpret_cast<uintptr_t>(Name)) {
+ assert((Ptr & PtrMask) == 0 && "Improperly aligned DeclarationNameExtra");
+ Ptr |= StoredDeclarationNameExtra;
+ }
+
+ /// Construct a declaration name from a raw pointer.
+ DeclarationName(uintptr_t Ptr) : Ptr(Ptr) {}
/// getStoredNameKind - Return the kind of object that is stored in
/// Ptr.
@@ -146,36 +167,22 @@ private:
return nullptr;
}
- // Construct a declaration name from the name of a C++ constructor,
- // destructor, or conversion function.
- DeclarationName(DeclarationNameExtra *Name)
- : Ptr(reinterpret_cast<uintptr_t>(Name)) {
- assert((Ptr & PtrMask) == 0 && "Improperly aligned DeclarationNameExtra");
- Ptr |= StoredDeclarationNameExtra;
- }
-
- /// Construct a declaration name from a raw pointer.
- DeclarationName(uintptr_t Ptr) : Ptr(Ptr) { }
-
- friend class DeclarationNameTable;
- friend class NamedDecl;
-
/// getFETokenInfoAsVoidSlow - Retrieves the front end-specified pointer
/// for this name as a void pointer if it's not an identifier.
void *getFETokenInfoAsVoidSlow() const;
public:
/// DeclarationName - Used to create an empty selector.
- DeclarationName() : Ptr(0) { }
+ DeclarationName() = default;
// Construct a declaration name from an IdentifierInfo *.
DeclarationName(const IdentifierInfo *II)
- : Ptr(reinterpret_cast<uintptr_t>(II)) {
+ : Ptr(reinterpret_cast<uintptr_t>(II)) {
assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
}
// Construct a declaration name from an Objective-C selector.
- DeclarationName(Selector Sel) : Ptr(Sel.InfoPtr) { }
+ DeclarationName(Selector Sel) : Ptr(Sel.InfoPtr) {}
/// getUsingDirectiveName - Return name for all using-directives.
static DeclarationName getUsingDirectiveName();
@@ -344,16 +351,24 @@ inline bool operator>=(DeclarationName LHS, DeclarationName RHS) {
/// getCXXConstructorName).
class DeclarationNameTable {
const ASTContext &Ctx;
- void *CXXSpecialNamesImpl; // Actually a FoldingSet<CXXSpecialName> *
- CXXOperatorIdName *CXXOperatorNames; // Operator names
- void *CXXLiteralOperatorNames; // Actually a CXXOperatorIdName*
- void *CXXDeductionGuideNames; // FoldingSet<CXXDeductionGuideNameExtra> *
- DeclarationNameTable(const DeclarationNameTable&) = delete;
- void operator=(const DeclarationNameTable&) = delete;
+ // Actually a FoldingSet<CXXSpecialName> *
+ void *CXXSpecialNamesImpl;
+
+ // Operator names
+ CXXOperatorIdName *CXXOperatorNames;
+
+ // Actually a CXXOperatorIdName*
+ void *CXXLiteralOperatorNames;
+
+ // FoldingSet<CXXDeductionGuideNameExtra> *
+ void *CXXDeductionGuideNames;
public:
DeclarationNameTable(const ASTContext &C);
+ DeclarationNameTable(const DeclarationNameTable &) = delete;
+ DeclarationNameTable &operator=(const DeclarationNameTable &) = delete;
+
~DeclarationNameTable();
/// getIdentifier - Create a declaration name that is a simple
@@ -428,10 +443,10 @@ struct DeclarationNameLoc {
};
DeclarationNameLoc(DeclarationName Name);
+
// FIXME: this should go away once all DNLocs are properly initialized.
DeclarationNameLoc() { memset((void*) this, 0, sizeof(*this)); }
-}; // struct DeclarationNameLoc
-
+};
/// DeclarationNameInfo - A collector data type for bundling together
/// a DeclarationName and the correspnding source/type location info.
@@ -439,29 +454,33 @@ struct DeclarationNameInfo {
private:
/// Name - The declaration name, also encoding name kind.
DeclarationName Name;
+
/// Loc - The main source location for the declaration name.
SourceLocation NameLoc;
+
/// Info - Further source/type location info for special kinds of names.
DeclarationNameLoc LocInfo;
public:
// FIXME: remove it.
- DeclarationNameInfo() {}
+ DeclarationNameInfo() = default;
DeclarationNameInfo(DeclarationName Name, SourceLocation NameLoc)
- : Name(Name), NameLoc(NameLoc), LocInfo(Name) {}
+ : Name(Name), NameLoc(NameLoc), LocInfo(Name) {}
DeclarationNameInfo(DeclarationName Name, SourceLocation NameLoc,
DeclarationNameLoc LocInfo)
- : Name(Name), NameLoc(NameLoc), LocInfo(LocInfo) {}
+ : Name(Name), NameLoc(NameLoc), LocInfo(LocInfo) {}
/// getName - Returns the embedded declaration name.
DeclarationName getName() const { return Name; }
+
/// setName - Sets the embedded declaration name.
void setName(DeclarationName N) { Name = N; }
/// getLoc - Returns the main location of the declaration name.
SourceLocation getLoc() const { return NameLoc; }
+
/// setLoc - Sets the main location of the declaration name.
void setLoc(SourceLocation L) { NameLoc = L; }
@@ -477,6 +496,7 @@ public:
Name.getNameKind() == DeclarationName::CXXConversionFunctionName);
return LocInfo.NamedType.TInfo;
}
+
/// setNamedTypeInfo - Sets the source type info associated to
/// the name. Assumes it is a constructor, destructor or conversion.
void setNamedTypeInfo(TypeSourceInfo *TInfo) {
@@ -495,6 +515,7 @@ public:
SourceLocation::getFromRawEncoding(LocInfo.CXXOperatorName.EndOpNameLoc)
);
}
+
/// setCXXOperatorNameRange - Sets the range of the operator name
/// (without the operator keyword). Assumes it is a C++ operator.
void setCXXOperatorNameRange(SourceRange R) {
@@ -511,6 +532,7 @@ public:
return SourceLocation::
getFromRawEncoding(LocInfo.CXXLiteralOperatorName.OpNameLoc);
}
+
/// setCXXLiteralOperatorNameLoc - Sets the location of the literal
/// operator name (not the operator keyword).
/// Assumes it is a literal operator.
@@ -534,15 +556,19 @@ public:
/// getBeginLoc - Retrieve the location of the first token.
SourceLocation getBeginLoc() const { return NameLoc; }
+
/// getEndLoc - Retrieve the location of the last token.
SourceLocation getEndLoc() const;
+
/// getSourceRange - The range of the declaration name.
SourceRange getSourceRange() const LLVM_READONLY {
return SourceRange(getLocStart(), getLocEnd());
}
+
SourceLocation getLocStart() const LLVM_READONLY {
return getBeginLoc();
}
+
SourceLocation getLocEnd() const LLVM_READONLY {
SourceLocation EndLoc = getEndLoc();
return EndLoc.isValid() ? EndLoc : getLocStart();
@@ -573,9 +599,10 @@ inline raw_ostream &operator<<(raw_ostream &OS,
return OS;
}
-} // end namespace clang
+} // namespace clang
namespace llvm {
+
/// Define DenseMapInfo so that DeclarationNames can be used as keys
/// in DenseMap and DenseSets.
template<>
@@ -601,6 +628,6 @@ struct DenseMapInfo<clang::DeclarationName> {
template <>
struct isPodLike<clang::DeclarationName> { static const bool value = true; };
-} // end namespace llvm
+} // namespace llvm
-#endif
+#endif // LLVM_CLANG_AST_DECLARATIONNAME_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DependentDiagnostic.h b/contrib/llvm/tools/clang/include/clang/AST/DependentDiagnostic.h
index 8e038c83c9890..a514326c6cb10 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DependentDiagnostic.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DependentDiagnostic.h
@@ -1,4 +1,4 @@
-//===-- DependentDiagnostic.h - Dependently-generated diagnostics -*- C++ -*-=//
+//==- DependentDiagnostic.h - Dependently-generated diagnostics --*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
@@ -23,6 +23,9 @@
#include "clang/AST/Type.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
+#include <cassert>
+#include <iterator>
namespace clang {
@@ -94,6 +97,9 @@ public:
}
private:
+ friend class DeclContext::ddiag_iterator;
+ friend class DependentStoredDeclsMap;
+
DependentDiagnostic(const PartialDiagnostic &PDiag,
PartialDiagnostic::Storage *Storage)
: Diag(PDiag, Storage) {}
@@ -102,8 +108,6 @@ private:
DeclContext *Parent,
const PartialDiagnostic &PDiag);
- friend class DependentStoredDeclsMap;
- friend class DeclContext::ddiag_iterator;
DependentDiagnostic *NextDiagnostic;
PartialDiagnostic Diag;
@@ -118,19 +122,17 @@ private:
} AccessData;
};
-///
-
/// An iterator over the dependent diagnostics in a dependent context.
class DeclContext::ddiag_iterator {
public:
- ddiag_iterator() : Ptr(nullptr) {}
+ ddiag_iterator() = default;
explicit ddiag_iterator(DependentDiagnostic *Ptr) : Ptr(Ptr) {}
- typedef DependentDiagnostic *value_type;
- typedef DependentDiagnostic *reference;
- typedef DependentDiagnostic *pointer;
- typedef int difference_type;
- typedef std::forward_iterator_tag iterator_category;
+ using value_type = DependentDiagnostic *;
+ using reference = DependentDiagnostic *;
+ using pointer = DependentDiagnostic *;
+ using difference_type = int;
+ using iterator_category = std::forward_iterator_tag;
reference operator*() const { return Ptr; }
@@ -168,7 +170,7 @@ public:
}
private:
- DependentDiagnostic *Ptr;
+ DependentDiagnostic *Ptr = nullptr;
};
inline DeclContext::ddiag_range DeclContext::ddiags() const {
@@ -184,6 +186,6 @@ inline DeclContext::ddiag_range DeclContext::ddiags() const {
return ddiag_range(ddiag_iterator(Map->FirstDiagnostic), ddiag_iterator());
}
-}
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_AST_DEPENDENTDIAGNOSTIC_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Expr.h b/contrib/llvm/tools/clang/include/clang/AST/Expr.h
index 0cdbd2a97ee4f..f2770940372fd 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/Expr.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/Expr.h
@@ -24,6 +24,7 @@
#include "clang/AST/Type.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SyncScope.h"
#include "clang/Basic/TypeTraits.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APSInt.h"
@@ -274,6 +275,7 @@ public:
MLV_LValueCast, // Specialized form of MLV_InvalidExpression.
MLV_IncompleteType,
MLV_ConstQualified,
+ MLV_ConstQualifiedField,
MLV_ConstAddrSpace,
MLV_ArrayType,
MLV_NoSetterProperty,
@@ -323,6 +325,7 @@ public:
CM_LValueCast, // Same as CM_RValue, but indicates GCC cast-as-lvalue ext
CM_NoSetterProperty,// Implicit assignment to ObjC property without setter
CM_ConstQualified,
+ CM_ConstQualifiedField,
CM_ConstAddrSpace,
CM_ArrayType,
CM_IncompleteType
@@ -2345,6 +2348,12 @@ public:
SourceLocation getLocStart() const LLVM_READONLY;
SourceLocation getLocEnd() const LLVM_READONLY;
+ bool isCallToStdMove() const {
+ const FunctionDecl* FD = getDirectCallee();
+ return getNumArgs() == 1 && FD && FD->isInStdNamespace() &&
+ FD->getIdentifier() && FD->getIdentifier()->isStr("move");
+ }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() >= firstCallExprConstant &&
T->getStmtClass() <= lastCallExprConstant;
@@ -2733,7 +2742,6 @@ protected:
ty->containsUnexpandedParameterPack()) ||
(op && op->containsUnexpandedParameterPack()))),
Op(op) {
- assert(kind != CK_Invalid && "creating cast with invalid cast kind");
CastExprBits.Kind = kind;
setBasePathSize(BasePathSize);
assert(CastConsistency());
@@ -2771,6 +2779,16 @@ public:
path_const_iterator path_begin() const { return path_buffer(); }
path_const_iterator path_end() const { return path_buffer() + path_size(); }
+ const FieldDecl *getTargetUnionField() const {
+ assert(getCastKind() == CK_ToUnion);
+ return getTargetFieldForToUnionCast(getType(), getSubExpr()->getType());
+ }
+
+ static const FieldDecl *getTargetFieldForToUnionCast(QualType unionType,
+ QualType opType);
+ static const FieldDecl *getTargetFieldForToUnionCast(const RecordDecl *RD,
+ QualType opType);
+
static bool classof(const Stmt *T) {
return T->getStmtClass() >= firstCastExprConstant &&
T->getStmtClass() <= lastCastExprConstant;
@@ -3054,7 +3072,7 @@ public:
static bool isEqualityOp(Opcode Opc) { return Opc == BO_EQ || Opc == BO_NE; }
bool isEqualityOp() const { return isEqualityOp(getOpcode()); }
- static bool isComparisonOp(Opcode Opc) { return Opc >= BO_LT && Opc<=BO_NE; }
+ static bool isComparisonOp(Opcode Opc) { return Opc >= BO_Cmp && Opc<=BO_NE; }
bool isComparisonOp() const { return isComparisonOp(getOpcode()); }
static Opcode negateComparisonOp(Opcode Opc) {
@@ -3113,6 +3131,12 @@ public:
return isShiftAssignOp(getOpcode());
}
+ // Return true if a binary operator using the specified opcode and operands
+ // would match the 'p = (i8*)nullptr + n' idiom for casting a pointer-sized
+ // integer to a pointer.
+ static bool isNullPointerArithmeticExtension(ASTContext &Ctx, Opcode Opc,
+ Expr *LHS, Expr *RHS);
+
static bool classof(const Stmt *S) {
return S->getStmtClass() >= firstBinaryOperatorConstant &&
S->getStmtClass() <= lastBinaryOperatorConstant;
@@ -3986,6 +4010,10 @@ public:
/// initializer)?
bool isTransparent() const;
+ /// Is this the zero initializer {0} in a language which considers it
+ /// idiomatic?
+ bool isIdiomaticZeroInitializer(const LangOptions &LangOpts) const;
+
SourceLocation getLBraceLoc() const { return LBraceLoc; }
void setLBraceLoc(SourceLocation Loc) { LBraceLoc = Loc; }
SourceLocation getRBraceLoc() const { return RBraceLoc; }
@@ -3995,6 +4023,9 @@ public:
InitListExpr *getSemanticForm() const {
return isSemanticForm() ? nullptr : AltForm.getPointer();
}
+ bool isSyntacticForm() const {
+ return !AltForm.getInt() || !AltForm.getPointer();
+ }
InitListExpr *getSyntacticForm() const {
return isSemanticForm() ? AltForm.getPointer() : nullptr;
}
@@ -5064,9 +5095,11 @@ public:
/// AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*,
/// __atomic_load, __atomic_store, and __atomic_compare_exchange_*, for the
-/// similarly-named C++11 instructions, and __c11 variants for <stdatomic.h>.
-/// All of these instructions take one primary pointer and at least one memory
-/// order.
+/// similarly-named C++11 instructions, and __c11 variants for <stdatomic.h>,
+/// and corresponding __opencl_atomic_* for OpenCL 2.0.
+/// All of these instructions take one primary pointer, at least one memory
+/// order. The instructions for which getScopeModel returns non-null value
+/// take one synch scope.
class AtomicExpr : public Expr {
public:
enum AtomicOp {
@@ -5078,14 +5111,16 @@ public:
};
private:
+ /// \brief Location of sub-expressions.
+ /// The location of Scope sub-expression is NumSubExprs - 1, which is
+ /// not fixed, therefore is not defined in enum.
enum { PTR, ORDER, VAL1, ORDER_FAIL, VAL2, WEAK, END_EXPR };
- Stmt* SubExprs[END_EXPR];
+ Stmt *SubExprs[END_EXPR + 1];
unsigned NumSubExprs;
SourceLocation BuiltinLoc, RParenLoc;
AtomicOp Op;
friend class ASTStmtReader;
-
public:
AtomicExpr(SourceLocation BLoc, ArrayRef<Expr*> args, QualType t,
AtomicOp op, SourceLocation RP);
@@ -5103,8 +5138,12 @@ public:
Expr *getOrder() const {
return cast<Expr>(SubExprs[ORDER]);
}
+ Expr *getScope() const {
+ assert(getScopeModel() && "No scope");
+ return cast<Expr>(SubExprs[NumSubExprs - 1]);
+ }
Expr *getVal1() const {
- if (Op == AO__c11_atomic_init)
+ if (Op == AO__c11_atomic_init || Op == AO__opencl_atomic_init)
return cast<Expr>(SubExprs[ORDER]);
assert(NumSubExprs > VAL1);
return cast<Expr>(SubExprs[VAL1]);
@@ -5123,6 +5162,7 @@ public:
assert(NumSubExprs > WEAK);
return cast<Expr>(SubExprs[WEAK]);
}
+ QualType getValueType() const;
AtomicOp getOp() const { return Op; }
unsigned getNumSubExprs() const { return NumSubExprs; }
@@ -5139,10 +5179,17 @@ public:
bool isCmpXChg() const {
return getOp() == AO__c11_atomic_compare_exchange_strong ||
getOp() == AO__c11_atomic_compare_exchange_weak ||
+ getOp() == AO__opencl_atomic_compare_exchange_strong ||
+ getOp() == AO__opencl_atomic_compare_exchange_weak ||
getOp() == AO__atomic_compare_exchange ||
getOp() == AO__atomic_compare_exchange_n;
}
+ bool isOpenCL() const {
+ return getOp() >= AO__opencl_atomic_init &&
+ getOp() <= AO__opencl_atomic_fetch_max;
+ }
+
SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
@@ -5160,6 +5207,24 @@ public:
const_child_range children() const {
return const_child_range(SubExprs, SubExprs + NumSubExprs);
}
+
+ /// \brief Get atomic scope model for the atomic op code.
+ /// \return empty atomic scope model if the atomic op code does not have
+ /// scope operand.
+ static std::unique_ptr<AtomicScopeModel> getScopeModel(AtomicOp Op) {
+ auto Kind =
+ (Op >= AO__opencl_atomic_load && Op <= AO__opencl_atomic_fetch_max)
+ ? AtomicScopeModelKind::OpenCL
+ : AtomicScopeModelKind::None;
+ return AtomicScopeModel::create(Kind);
+ }
+
+ /// \brief Get atomic scope model.
+ /// \return empty atomic scope model if this atomic expression does not have
+ /// scope operand.
+ std::unique_ptr<AtomicScopeModel> getScopeModel() const {
+ return getScopeModel(getOp());
+ }
};
/// TypoExpr - Internal placeholder for expressions where typo correction
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h b/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h
index 79d2c58099c4c..58054dda31aa8 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h
@@ -1,4 +1,4 @@
-//===--- ExprCXX.h - Classes for representing expressions -------*- C++ -*-===//
+//===- ExprCXX.h - Classes for representing expressions ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,31 +6,57 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
/// \brief Defines the clang::Expr interface and subclasses for C++ expressions.
-///
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_EXPRCXX_H
#define LLVM_CLANG_AST_EXPRCXX_H
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
-#include "clang/AST/LambdaCapture.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/OperationKinds.h"
+#include "clang/AST/Stmt.h"
#include "clang/AST/TemplateBase.h"
+#include "clang/AST/Type.h"
#include "clang/AST/UnresolvedSet.h"
+#include "clang/Basic/ExceptionSpecificationType.h"
#include "clang/Basic/ExpressionTraits.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/Lambda.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/OperatorKinds.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TypeTraits.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/TrailingObjects.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
namespace clang {
-class CXXTemporary;
-class MSPropertyDecl;
-class TemplateArgumentListInfo;
-class UuidAttr;
+class ASTContext;
+class DeclAccessPair;
+class IdentifierInfo;
+class LambdaCapture;
+class NonTypeTemplateParmDecl;
+class TemplateParameterList;
//===--------------------------------------------------------------------===//
// C++ Expressions.
@@ -52,23 +78,28 @@ class UuidAttr;
class CXXOperatorCallExpr : public CallExpr {
/// \brief The overloaded operator.
OverloadedOperatorKind Operator;
+
SourceRange Range;
// Only meaningful for floating point types.
FPOptions FPFeatures;
SourceRange getSourceRangeImpl() const LLVM_READONLY;
+
public:
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
CXXOperatorCallExpr(ASTContext& C, OverloadedOperatorKind Op, Expr *fn,
ArrayRef<Expr*> args, QualType t, ExprValueKind VK,
SourceLocation operatorloc, FPOptions FPFeatures)
- : CallExpr(C, CXXOperatorCallExprClass, fn, args, t, VK, operatorloc),
- Operator(Op), FPFeatures(FPFeatures) {
+ : CallExpr(C, CXXOperatorCallExprClass, fn, args, t, VK, operatorloc),
+ Operator(Op), FPFeatures(FPFeatures) {
Range = getSourceRangeImpl();
}
- explicit CXXOperatorCallExpr(ASTContext& C, EmptyShell Empty) :
- CallExpr(C, CXXOperatorCallExprClass, Empty) { }
+ explicit CXXOperatorCallExpr(ASTContext& C, EmptyShell Empty)
+ : CallExpr(C, CXXOperatorCallExprClass, Empty) {}
/// \brief Returns the kind of overloaded operator that this
/// expression refers to.
@@ -120,9 +151,6 @@ public:
bool isFPContractableWithinStatement() const {
return FPFeatures.allowFPContractWithinStatement();
}
-
- friend class ASTStmtReader;
- friend class ASTStmtWriter;
};
/// Represents a call to a member function that
@@ -137,10 +165,10 @@ class CXXMemberCallExpr : public CallExpr {
public:
CXXMemberCallExpr(ASTContext &C, Expr *fn, ArrayRef<Expr*> args,
QualType t, ExprValueKind VK, SourceLocation RP)
- : CallExpr(C, CXXMemberCallExprClass, fn, args, t, VK, RP) {}
+ : CallExpr(C, CXXMemberCallExprClass, fn, args, t, VK, RP) {}
CXXMemberCallExpr(ASTContext &C, EmptyShell Empty)
- : CallExpr(C, CXXMemberCallExprClass, Empty) { }
+ : CallExpr(C, CXXMemberCallExprClass, Empty) {}
/// \brief Retrieves the implicit object argument for the member call.
///
@@ -183,7 +211,7 @@ public:
: CallExpr(C, CUDAKernelCallExprClass, fn, Config, args, t, VK, RP) {}
CUDAKernelCallExpr(ASTContext &C, EmptyShell Empty)
- : CallExpr(C, CUDAKernelCallExprClass, END_PREARG, Empty) { }
+ : CallExpr(C, CUDAKernelCallExprClass, END_PREARG, Empty) {}
const CallExpr *getConfig() const {
return cast_or_null<CallExpr>(getPreArg(CONFIG));
@@ -217,23 +245,28 @@ public:
/// reinterpret_cast, and CXXConstCastExpr for \c const_cast.
class CXXNamedCastExpr : public ExplicitCastExpr {
private:
- SourceLocation Loc; // the location of the casting op
- SourceLocation RParenLoc; // the location of the right parenthesis
- SourceRange AngleBrackets; // range for '<' '>'
+ // the location of the casting op
+ SourceLocation Loc;
+
+ // the location of the right parenthesis
+ SourceLocation RParenLoc;
+
+ // range for '<' '>'
+ SourceRange AngleBrackets;
protected:
+ friend class ASTStmtReader;
+
CXXNamedCastExpr(StmtClass SC, QualType ty, ExprValueKind VK,
CastKind kind, Expr *op, unsigned PathSize,
TypeSourceInfo *writtenTy, SourceLocation l,
SourceLocation RParenLoc,
SourceRange AngleBrackets)
- : ExplicitCastExpr(SC, ty, VK, kind, op, PathSize, writtenTy), Loc(l),
- RParenLoc(RParenLoc), AngleBrackets(AngleBrackets) {}
+ : ExplicitCastExpr(SC, ty, VK, kind, op, PathSize, writtenTy), Loc(l),
+ RParenLoc(RParenLoc), AngleBrackets(AngleBrackets) {}
explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize)
- : ExplicitCastExpr(SC, Shell, PathSize) { }
-
- friend class ASTStmtReader;
+ : ExplicitCastExpr(SC, Shell, PathSize) {}
public:
const char *getCastName() const;
@@ -273,13 +306,16 @@ class CXXStaticCastExpr final
unsigned pathSize, TypeSourceInfo *writtenTy,
SourceLocation l, SourceLocation RParenLoc,
SourceRange AngleBrackets)
- : CXXNamedCastExpr(CXXStaticCastExprClass, ty, vk, kind, op, pathSize,
- writtenTy, l, RParenLoc, AngleBrackets) {}
+ : CXXNamedCastExpr(CXXStaticCastExprClass, ty, vk, kind, op, pathSize,
+ writtenTy, l, RParenLoc, AngleBrackets) {}
explicit CXXStaticCastExpr(EmptyShell Empty, unsigned PathSize)
- : CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize) { }
+ : CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize) {}
public:
+ friend class CastExpr;
+ friend TrailingObjects;
+
static CXXStaticCastExpr *Create(const ASTContext &Context, QualType T,
ExprValueKind VK, CastKind K, Expr *Op,
const CXXCastPath *Path,
@@ -292,9 +328,6 @@ public:
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXStaticCastExprClass;
}
-
- friend TrailingObjects;
- friend class CastExpr;
};
/// \brief A C++ @c dynamic_cast expression (C++ [expr.dynamic.cast]).
@@ -309,13 +342,16 @@ class CXXDynamicCastExpr final
Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy,
SourceLocation l, SourceLocation RParenLoc,
SourceRange AngleBrackets)
- : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, VK, kind, op, pathSize,
- writtenTy, l, RParenLoc, AngleBrackets) {}
+ : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, VK, kind, op, pathSize,
+ writtenTy, l, RParenLoc, AngleBrackets) {}
explicit CXXDynamicCastExpr(EmptyShell Empty, unsigned pathSize)
- : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize) { }
+ : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize) {}
public:
+ friend class CastExpr;
+ friend TrailingObjects;
+
static CXXDynamicCastExpr *Create(const ASTContext &Context, QualType T,
ExprValueKind VK, CastKind Kind, Expr *Op,
const CXXCastPath *Path,
@@ -331,9 +367,6 @@ public:
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXDynamicCastExprClass;
}
-
- friend TrailingObjects;
- friend class CastExpr;
};
/// \brief A C++ @c reinterpret_cast expression (C++ [expr.reinterpret.cast]).
@@ -353,13 +386,16 @@ class CXXReinterpretCastExpr final
TypeSourceInfo *writtenTy, SourceLocation l,
SourceLocation RParenLoc,
SourceRange AngleBrackets)
- : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, vk, kind, op,
- pathSize, writtenTy, l, RParenLoc, AngleBrackets) {}
+ : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, vk, kind, op,
+ pathSize, writtenTy, l, RParenLoc, AngleBrackets) {}
CXXReinterpretCastExpr(EmptyShell Empty, unsigned pathSize)
- : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize) { }
+ : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize) {}
public:
+ friend class CastExpr;
+ friend TrailingObjects;
+
static CXXReinterpretCastExpr *Create(const ASTContext &Context, QualType T,
ExprValueKind VK, CastKind Kind,
Expr *Op, const CXXCastPath *Path,
@@ -372,9 +408,6 @@ public:
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXReinterpretCastExprClass;
}
-
- friend TrailingObjects;
- friend class CastExpr;
};
/// \brief A C++ \c const_cast expression (C++ [expr.const.cast]).
@@ -390,13 +423,16 @@ class CXXConstCastExpr final
CXXConstCastExpr(QualType ty, ExprValueKind VK, Expr *op,
TypeSourceInfo *writtenTy, SourceLocation l,
SourceLocation RParenLoc, SourceRange AngleBrackets)
- : CXXNamedCastExpr(CXXConstCastExprClass, ty, VK, CK_NoOp, op,
- 0, writtenTy, l, RParenLoc, AngleBrackets) {}
+ : CXXNamedCastExpr(CXXConstCastExprClass, ty, VK, CK_NoOp, op,
+ 0, writtenTy, l, RParenLoc, AngleBrackets) {}
explicit CXXConstCastExpr(EmptyShell Empty)
- : CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0) { }
+ : CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0) {}
public:
+ friend class CastExpr;
+ friend TrailingObjects;
+
static CXXConstCastExpr *Create(const ASTContext &Context, QualType T,
ExprValueKind VK, Expr *Op,
TypeSourceInfo *WrittenTy, SourceLocation L,
@@ -407,9 +443,6 @@ public:
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXConstCastExprClass;
}
-
- friend TrailingObjects;
- friend class CastExpr;
};
/// \brief A call to a literal operator (C++11 [over.literal])
@@ -426,22 +459,37 @@ class UserDefinedLiteral : public CallExpr {
SourceLocation UDSuffixLoc;
public:
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
UserDefinedLiteral(const ASTContext &C, Expr *Fn, ArrayRef<Expr*> Args,
QualType T, ExprValueKind VK, SourceLocation LitEndLoc,
SourceLocation SuffixLoc)
- : CallExpr(C, UserDefinedLiteralClass, Fn, Args, T, VK, LitEndLoc),
- UDSuffixLoc(SuffixLoc) {}
+ : CallExpr(C, UserDefinedLiteralClass, Fn, Args, T, VK, LitEndLoc),
+ UDSuffixLoc(SuffixLoc) {}
+
explicit UserDefinedLiteral(const ASTContext &C, EmptyShell Empty)
- : CallExpr(C, UserDefinedLiteralClass, Empty) {}
+ : CallExpr(C, UserDefinedLiteralClass, Empty) {}
/// The kind of literal operator which is invoked.
enum LiteralOperatorKind {
- LOK_Raw, ///< Raw form: operator "" X (const char *)
- LOK_Template, ///< Raw form: operator "" X<cs...> ()
- LOK_Integer, ///< operator "" X (unsigned long long)
- LOK_Floating, ///< operator "" X (long double)
- LOK_String, ///< operator "" X (const CharT *, size_t)
- LOK_Character ///< operator "" X (CharT)
+ /// Raw form: operator "" X (const char *)
+ LOK_Raw,
+
+ /// Raw form: operator "" X<cs...> ()
+ LOK_Template,
+
+ /// operator "" X (unsigned long long)
+ LOK_Integer,
+
+ /// operator "" X (long double)
+ LOK_Floating,
+
+ /// operator "" X (const CharT *, size_t)
+ LOK_String,
+
+ /// operator "" X (CharT)
+ LOK_Character
};
/// \brief Returns the kind of literal operator invocation
@@ -461,8 +509,8 @@ public:
return getRParenLoc();
return getArg(0)->getLocStart();
}
- SourceLocation getLocEnd() const { return getRParenLoc(); }
+ SourceLocation getLocEnd() const { return getRParenLoc(); }
/// \brief Returns the location of a ud-suffix in the expression.
///
@@ -476,24 +524,21 @@ public:
static bool classof(const Stmt *S) {
return S->getStmtClass() == UserDefinedLiteralClass;
}
-
- friend class ASTStmtReader;
- friend class ASTStmtWriter;
};
/// \brief A boolean literal, per ([C++ lex.bool] Boolean literals).
-///
class CXXBoolLiteralExpr : public Expr {
bool Value;
SourceLocation Loc;
+
public:
- CXXBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) :
- Expr(CXXBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
- false, false),
- Value(val), Loc(l) {}
+ CXXBoolLiteralExpr(bool val, QualType Ty, SourceLocation l)
+ : Expr(CXXBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
+ false, false),
+ Value(val), Loc(l) {}
explicit CXXBoolLiteralExpr(EmptyShell Empty)
- : Expr(CXXBoolLiteralExprClass, Empty) { }
+ : Expr(CXXBoolLiteralExprClass, Empty) {}
bool getValue() const { return Value; }
void setValue(bool V) { Value = V; }
@@ -519,14 +564,15 @@ public:
/// Introduced in C++11, the only literal of type \c nullptr_t is \c nullptr.
class CXXNullPtrLiteralExpr : public Expr {
SourceLocation Loc;
+
public:
- CXXNullPtrLiteralExpr(QualType Ty, SourceLocation l) :
- Expr(CXXNullPtrLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
- false, false),
- Loc(l) {}
+ CXXNullPtrLiteralExpr(QualType Ty, SourceLocation l)
+ : Expr(CXXNullPtrLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false,
+ false, false, false),
+ Loc(l) {}
explicit CXXNullPtrLiteralExpr(EmptyShell Empty)
- : Expr(CXXNullPtrLiteralExprClass, Empty) { }
+ : Expr(CXXNullPtrLiteralExprClass, Empty) {}
SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
@@ -546,18 +592,21 @@ public:
/// \brief Implicit construction of a std::initializer_list<T> object from an
/// array temporary within list-initialization (C++11 [dcl.init.list]p5).
class CXXStdInitializerListExpr : public Expr {
- Stmt *SubExpr;
+ Stmt *SubExpr = nullptr;
CXXStdInitializerListExpr(EmptyShell Empty)
- : Expr(CXXStdInitializerListExprClass, Empty), SubExpr(nullptr) {}
+ : Expr(CXXStdInitializerListExprClass, Empty) {}
public:
+ friend class ASTReader;
+ friend class ASTStmtReader;
+
CXXStdInitializerListExpr(QualType Ty, Expr *SubExpr)
- : Expr(CXXStdInitializerListExprClass, Ty, VK_RValue, OK_Ordinary,
- Ty->isDependentType(), SubExpr->isValueDependent(),
- SubExpr->isInstantiationDependent(),
- SubExpr->containsUnexpandedParameterPack()),
- SubExpr(SubExpr) {}
+ : Expr(CXXStdInitializerListExprClass, Ty, VK_RValue, OK_Ordinary,
+ Ty->isDependentType(), SubExpr->isValueDependent(),
+ SubExpr->isInstantiationDependent(),
+ SubExpr->containsUnexpandedParameterPack()),
+ SubExpr(SubExpr) {}
Expr *getSubExpr() { return static_cast<Expr*>(SubExpr); }
const Expr *getSubExpr() const { return static_cast<const Expr*>(SubExpr); }
@@ -565,9 +614,11 @@ public:
SourceLocation getLocStart() const LLVM_READONLY {
return SubExpr->getLocStart();
}
+
SourceLocation getLocEnd() const LLVM_READONLY {
return SubExpr->getLocEnd();
}
+
SourceRange getSourceRange() const LLVM_READONLY {
return SubExpr->getSourceRange();
}
@@ -577,9 +628,6 @@ public:
}
child_range children() { return child_range(&SubExpr, &SubExpr + 1); }
-
- friend class ASTReader;
- friend class ASTStmtReader;
};
/// A C++ \c typeid expression (C++ [expr.typeid]), which gets
@@ -594,27 +642,29 @@ private:
public:
CXXTypeidExpr(QualType Ty, TypeSourceInfo *Operand, SourceRange R)
- : Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary,
- // typeid is never type-dependent (C++ [temp.dep.expr]p4)
- false,
- // typeid is value-dependent if the type or expression are dependent
- Operand->getType()->isDependentType(),
- Operand->getType()->isInstantiationDependentType(),
- Operand->getType()->containsUnexpandedParameterPack()),
- Operand(Operand), Range(R) { }
+ : Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary,
+ // typeid is never type-dependent (C++ [temp.dep.expr]p4)
+ false,
+ // typeid is value-dependent if the type or expression are
+ // dependent
+ Operand->getType()->isDependentType(),
+ Operand->getType()->isInstantiationDependentType(),
+ Operand->getType()->containsUnexpandedParameterPack()),
+ Operand(Operand), Range(R) {}
CXXTypeidExpr(QualType Ty, Expr *Operand, SourceRange R)
- : Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary,
- // typeid is never type-dependent (C++ [temp.dep.expr]p4)
- false,
- // typeid is value-dependent if the type or expression are dependent
- Operand->isTypeDependent() || Operand->isValueDependent(),
- Operand->isInstantiationDependent(),
- Operand->containsUnexpandedParameterPack()),
- Operand(Operand), Range(R) { }
+ : Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary,
+ // typeid is never type-dependent (C++ [temp.dep.expr]p4)
+ false,
+ // typeid is value-dependent if the type or expression are
+ // dependent
+ Operand->isTypeDependent() || Operand->isValueDependent(),
+ Operand->isInstantiationDependent(),
+ Operand->containsUnexpandedParameterPack()),
+ Operand(Operand), Range(R) {}
CXXTypeidExpr(EmptyShell Empty, bool isExpr)
- : Expr(CXXTypeidExprClass, Empty) {
+ : Expr(CXXTypeidExprClass, Empty) {
if (isExpr)
Operand = (Expr*)nullptr;
else
@@ -683,26 +733,30 @@ class MSPropertyRefExpr : public Expr {
NestedNameSpecifierLoc QualifierLoc;
public:
+ friend class ASTStmtReader;
+
MSPropertyRefExpr(Expr *baseExpr, MSPropertyDecl *decl, bool isArrow,
QualType ty, ExprValueKind VK,
NestedNameSpecifierLoc qualifierLoc,
SourceLocation nameLoc)
- : Expr(MSPropertyRefExprClass, ty, VK, OK_Ordinary,
- /*type-dependent*/ false, baseExpr->isValueDependent(),
- baseExpr->isInstantiationDependent(),
- baseExpr->containsUnexpandedParameterPack()),
- BaseExpr(baseExpr), TheDecl(decl),
- MemberLoc(nameLoc), IsArrow(isArrow),
- QualifierLoc(qualifierLoc) {}
+ : Expr(MSPropertyRefExprClass, ty, VK, OK_Ordinary,
+ /*type-dependent*/ false, baseExpr->isValueDependent(),
+ baseExpr->isInstantiationDependent(),
+ baseExpr->containsUnexpandedParameterPack()),
+ BaseExpr(baseExpr), TheDecl(decl),
+ MemberLoc(nameLoc), IsArrow(isArrow),
+ QualifierLoc(qualifierLoc) {}
MSPropertyRefExpr(EmptyShell Empty) : Expr(MSPropertyRefExprClass, Empty) {}
SourceRange getSourceRange() const LLVM_READONLY {
return SourceRange(getLocStart(), getLocEnd());
}
+
bool isImplicitAccess() const {
return getBaseExpr() && getBaseExpr()->isImplicitCXXThis();
}
+
SourceLocation getLocStart() const {
if (!isImplicitAccess())
return BaseExpr->getLocStart();
@@ -711,11 +765,13 @@ public:
else
return MemberLoc;
}
+
SourceLocation getLocEnd() const { return getMemberLoc(); }
child_range children() {
return child_range((Stmt**)&BaseExpr, (Stmt**)&BaseExpr + 1);
}
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == MSPropertyRefExprClass;
}
@@ -725,8 +781,6 @@ public:
bool isArrow() const { return IsArrow; }
SourceLocation getMemberLoc() const { return MemberLoc; }
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
-
- friend class ASTStmtReader;
};
/// MS property subscript expression.
@@ -742,7 +796,9 @@ public:
/// This is a syntactic pseudo-object expression.
class MSPropertySubscriptExpr : public Expr {
friend class ASTStmtReader;
+
enum { BASE_EXPR, IDX_EXPR, NUM_SUBEXPRS = 2 };
+
Stmt *SubExprs[NUM_SUBEXPRS];
SourceLocation RBracketLoc;
@@ -773,6 +829,7 @@ public:
SourceLocation getLocStart() const LLVM_READONLY {
return getBase()->getLocStart();
}
+
SourceLocation getLocEnd() const LLVM_READONLY { return RBracketLoc; }
SourceLocation getRBracketLoc() const { return RBracketLoc; }
@@ -891,13 +948,13 @@ class CXXThisExpr : public Expr {
public:
CXXThisExpr(SourceLocation L, QualType Type, bool isImplicit)
- : Expr(CXXThisExprClass, Type, VK_RValue, OK_Ordinary,
- // 'this' is type-dependent if the class type of the enclosing
- // member function is dependent (C++ [temp.dep.expr]p2)
- Type->isDependentType(), Type->isDependentType(),
- Type->isInstantiationDependentType(),
- /*ContainsUnexpandedParameterPack=*/false),
- Loc(L), Implicit(isImplicit) { }
+ : Expr(CXXThisExprClass, Type, VK_RValue, OK_Ordinary,
+ // 'this' is type-dependent if the class type of the enclosing
+ // member function is dependent (C++ [temp.dep.expr]p2)
+ Type->isDependentType(), Type->isDependentType(),
+ Type->isInstantiationDependentType(),
+ /*ContainsUnexpandedParameterPack=*/false),
+ Loc(L), Implicit(isImplicit) {}
CXXThisExpr(EmptyShell Empty) : Expr(CXXThisExprClass, Empty) {}
@@ -926,23 +983,25 @@ public:
/// 'throw' assignment-expression. When assignment-expression isn't
/// present, Op will be null.
class CXXThrowExpr : public Expr {
+ friend class ASTStmtReader;
+
Stmt *Op;
SourceLocation ThrowLoc;
+
/// \brief Whether the thrown variable (if any) is in scope.
unsigned IsThrownVariableInScope : 1;
- friend class ASTStmtReader;
-
public:
// \p Ty is the void type which is used as the result type of the
// expression. The \p l is the location of the throw keyword. \p expr
// can by null, if the optional expression to throw isn't present.
CXXThrowExpr(Expr *expr, QualType Ty, SourceLocation l,
- bool IsThrownVariableInScope) :
- Expr(CXXThrowExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
- expr && expr->isInstantiationDependent(),
- expr && expr->containsUnexpandedParameterPack()),
- Op(expr), ThrowLoc(l), IsThrownVariableInScope(IsThrownVariableInScope) {}
+ bool IsThrownVariableInScope)
+ : Expr(CXXThrowExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
+ expr && expr->isInstantiationDependent(),
+ expr && expr->containsUnexpandedParameterPack()),
+ Op(expr), ThrowLoc(l),
+ IsThrownVariableInScope(IsThrownVariableInScope) {}
CXXThrowExpr(EmptyShell Empty) : Expr(CXXThrowExprClass, Empty) {}
const Expr *getSubExpr() const { return cast_or_null<Expr>(Op); }
@@ -958,6 +1017,7 @@ public:
bool isThrownVariableInScope() const { return IsThrownVariableInScope; }
SourceLocation getLocStart() const LLVM_READONLY { return ThrowLoc; }
+
SourceLocation getLocEnd() const LLVM_READONLY {
if (!getSubExpr())
return ThrowLoc;
@@ -987,15 +1047,19 @@ class CXXDefaultArgExpr final : public Expr {
SourceLocation Loc;
CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param)
- : Expr(SC,
- param->hasUnparsedDefaultArg()
- ? param->getType().getNonReferenceType()
- : param->getDefaultArg()->getType(),
- param->getDefaultArg()->getValueKind(),
- param->getDefaultArg()->getObjectKind(), false, false, false, false),
- Param(param), Loc(Loc) { }
+ : Expr(SC,
+ param->hasUnparsedDefaultArg()
+ ? param->getType().getNonReferenceType()
+ : param->getDefaultArg()->getType(),
+ param->getDefaultArg()->getValueKind(),
+ param->getDefaultArg()->getObjectKind(), false, false, false,
+ false),
+ Param(param), Loc(Loc) {}
public:
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
CXXDefaultArgExpr(EmptyShell Empty) : Expr(CXXDefaultArgExprClass, Empty) {}
// \p Param is the parameter whose default argument is used by this
@@ -1036,9 +1100,6 @@ public:
child_range children() {
return child_range(child_iterator(), child_iterator());
}
-
- friend class ASTStmtReader;
- friend class ASTStmtWriter;
};
/// \brief A use of a default initializer in a constructor or in aggregate
@@ -1062,6 +1123,9 @@ class CXXDefaultInitExpr : public Expr {
CXXDefaultInitExpr(EmptyShell Empty) : Expr(CXXDefaultInitExprClass, Empty) {}
public:
+ friend class ASTReader;
+ friend class ASTStmtReader;
+
/// \p Field is the non-static data member whose default initializer is used
/// by this expression.
static CXXDefaultInitExpr *Create(const ASTContext &C, SourceLocation Loc,
@@ -1094,9 +1158,6 @@ public:
child_range children() {
return child_range(child_iterator(), child_iterator());
}
-
- friend class ASTReader;
- friend class ASTStmtReader;
};
/// \brief Represents a C++ temporary.
@@ -1105,13 +1166,14 @@ class CXXTemporary {
const CXXDestructorDecl *Destructor;
explicit CXXTemporary(const CXXDestructorDecl *destructor)
- : Destructor(destructor) { }
+ : Destructor(destructor) {}
public:
static CXXTemporary *Create(const ASTContext &C,
const CXXDestructorDecl *Destructor);
const CXXDestructorDecl *getDestructor() const { return Destructor; }
+
void setDestructor(const CXXDestructorDecl *Dtor) {
Destructor = Dtor;
}
@@ -1132,21 +1194,20 @@ public:
/// }
/// \endcode
class CXXBindTemporaryExpr : public Expr {
- CXXTemporary *Temp;
-
- Stmt *SubExpr;
+ CXXTemporary *Temp = nullptr;
+ Stmt *SubExpr = nullptr;
CXXBindTemporaryExpr(CXXTemporary *temp, Expr* SubExpr)
- : Expr(CXXBindTemporaryExprClass, SubExpr->getType(),
- VK_RValue, OK_Ordinary, SubExpr->isTypeDependent(),
- SubExpr->isValueDependent(),
- SubExpr->isInstantiationDependent(),
- SubExpr->containsUnexpandedParameterPack()),
- Temp(temp), SubExpr(SubExpr) { }
+ : Expr(CXXBindTemporaryExprClass, SubExpr->getType(),
+ VK_RValue, OK_Ordinary, SubExpr->isTypeDependent(),
+ SubExpr->isValueDependent(),
+ SubExpr->isInstantiationDependent(),
+ SubExpr->containsUnexpandedParameterPack()),
+ Temp(temp), SubExpr(SubExpr) {}
public:
CXXBindTemporaryExpr(EmptyShell Empty)
- : Expr(CXXBindTemporaryExprClass, Empty), Temp(nullptr), SubExpr(nullptr) {}
+ : Expr(CXXBindTemporaryExprClass, Empty) {}
static CXXBindTemporaryExpr *Create(const ASTContext &C, CXXTemporary *Temp,
Expr* SubExpr);
@@ -1162,6 +1223,7 @@ public:
SourceLocation getLocStart() const LLVM_READONLY {
return SubExpr->getLocStart();
}
+
SourceLocation getLocEnd() const LLVM_READONLY { return SubExpr->getLocEnd();}
// Implement isa/cast/dyncast/etc.
@@ -1184,8 +1246,7 @@ public:
};
private:
- CXXConstructorDecl *Constructor;
-
+ CXXConstructorDecl *Constructor = nullptr;
SourceLocation Loc;
SourceRange ParenOrBraceRange;
unsigned NumArgs : 16;
@@ -1195,7 +1256,7 @@ private:
unsigned StdInitListInitialization : 1;
unsigned ZeroInitialization : 1;
unsigned ConstructKind : 2;
- Stmt **Args;
+ Stmt **Args = nullptr;
void setConstructor(CXXConstructorDecl *C) { Constructor = C; }
@@ -1214,15 +1275,16 @@ protected:
/// \brief Construct an empty C++ construction expression.
CXXConstructExpr(StmtClass SC, EmptyShell Empty)
- : Expr(SC, Empty), Constructor(nullptr), NumArgs(0), Elidable(false),
- HadMultipleCandidates(false), ListInitialization(false),
- ZeroInitialization(false), ConstructKind(0), Args(nullptr)
- { }
+ : Expr(SC, Empty), NumArgs(0), Elidable(false),
+ HadMultipleCandidates(false), ListInitialization(false),
+ ZeroInitialization(false), ConstructKind(0) {}
public:
+ friend class ASTStmtReader;
+
/// \brief Construct an empty C++ construction expression.
explicit CXXConstructExpr(EmptyShell Empty)
- : CXXConstructExpr(CXXConstructExprClass, Empty) {}
+ : CXXConstructExpr(CXXConstructExprClass, Empty) {}
static CXXConstructExpr *Create(const ASTContext &C, QualType T,
SourceLocation Loc,
@@ -1278,10 +1340,10 @@ public:
ConstructKind = CK;
}
- typedef ExprIterator arg_iterator;
- typedef ConstExprIterator const_arg_iterator;
- typedef llvm::iterator_range<arg_iterator> arg_range;
- typedef llvm::iterator_range<const_arg_iterator> arg_const_range;
+ using arg_iterator = ExprIterator;
+ using const_arg_iterator = ConstExprIterator;
+ using arg_range = llvm::iterator_range<arg_iterator>;
+ using arg_const_range = llvm::iterator_range<const_arg_iterator>;
arg_range arguments() { return arg_range(arg_begin(), arg_end()); }
arg_const_range arguments() const {
@@ -1329,8 +1391,6 @@ public:
child_range children() {
return child_range(&Args[0], &Args[0]+NumArgs);
}
-
- friend class ASTStmtReader;
};
/// \brief Represents a call to an inherited base class constructor from an
@@ -1339,7 +1399,7 @@ public:
/// base class constructor.
class CXXInheritedCtorInitExpr : public Expr {
private:
- CXXConstructorDecl *Constructor;
+ CXXConstructorDecl *Constructor = nullptr;
/// The location of the using declaration.
SourceLocation Loc;
@@ -1352,6 +1412,8 @@ private:
unsigned InheritedFromVirtualBase : 1;
public:
+ friend class ASTStmtReader;
+
/// \brief Construct a C++ inheriting construction expression.
CXXInheritedCtorInitExpr(SourceLocation Loc, QualType T,
CXXConstructorDecl *Ctor, bool ConstructsVirtualBase,
@@ -1366,7 +1428,7 @@ public:
/// \brief Construct an empty C++ inheriting construction expression.
explicit CXXInheritedCtorInitExpr(EmptyShell Empty)
- : Expr(CXXInheritedCtorInitExprClass, Empty), Constructor(nullptr),
+ : Expr(CXXInheritedCtorInitExprClass, Empty),
ConstructsVirtualBase(false), InheritedFromVirtualBase(false) {}
/// \brief Get the constructor that this expression will call.
@@ -1393,11 +1455,10 @@ public:
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXInheritedCtorInitExprClass;
}
+
child_range children() {
return child_range(child_iterator(), child_iterator());
}
-
- friend class ASTStmtReader;
};
/// \brief Represents an explicit C++ type conversion that uses "functional"
@@ -1417,14 +1478,17 @@ class CXXFunctionalCastExpr final
TypeSourceInfo *writtenTy,
CastKind kind, Expr *castExpr, unsigned pathSize,
SourceLocation lParenLoc, SourceLocation rParenLoc)
- : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, VK, kind,
- castExpr, pathSize, writtenTy),
- LParenLoc(lParenLoc), RParenLoc(rParenLoc) {}
+ : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, VK, kind,
+ castExpr, pathSize, writtenTy),
+ LParenLoc(lParenLoc), RParenLoc(rParenLoc) {}
explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize)
- : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize) { }
+ : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize) {}
public:
+ friend class CastExpr;
+ friend TrailingObjects;
+
static CXXFunctionalCastExpr *Create(const ASTContext &Context, QualType T,
ExprValueKind VK,
TypeSourceInfo *Written,
@@ -1446,9 +1510,6 @@ public:
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXFunctionalCastExprClass;
}
-
- friend TrailingObjects;
- friend class CastExpr;
};
/// @brief Represents a C++ functional cast expression that builds a
@@ -1467,9 +1528,11 @@ public:
/// };
/// \endcode
class CXXTemporaryObjectExpr : public CXXConstructExpr {
- TypeSourceInfo *Type;
+ TypeSourceInfo *Type = nullptr;
public:
+ friend class ASTStmtReader;
+
CXXTemporaryObjectExpr(const ASTContext &C,
CXXConstructorDecl *Cons,
QualType Type,
@@ -1481,7 +1544,7 @@ public:
bool StdInitListInitialization,
bool ZeroInitialization);
explicit CXXTemporaryObjectExpr(EmptyShell Empty)
- : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty), Type() { }
+ : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty) {}
TypeSourceInfo *getTypeSourceInfo() const { return Type; }
@@ -1491,8 +1554,6 @@ public:
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXTemporaryObjectExprClass;
}
-
- friend class ASTStmtReader;
};
/// \brief A C++ lambda expression, which produces a function object
@@ -1558,9 +1619,9 @@ class LambdaExpr final : public Expr,
/// \brief Construct an empty lambda expression.
LambdaExpr(EmptyShell Empty, unsigned NumCaptures)
- : Expr(LambdaExprClass, Empty),
- NumCaptures(NumCaptures), CaptureDefault(LCD_None), ExplicitParams(false),
- ExplicitResultType(false) {
+ : Expr(LambdaExprClass, Empty), NumCaptures(NumCaptures),
+ CaptureDefault(LCD_None), ExplicitParams(false),
+ ExplicitResultType(false) {
getStoredStmts()[NumCaptures] = nullptr;
}
@@ -1569,6 +1630,10 @@ class LambdaExpr final : public Expr,
Stmt *const *getStoredStmts() const { return getTrailingObjects<Stmt *>(); }
public:
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+ friend TrailingObjects;
+
/// \brief Construct a new lambda expression.
static LambdaExpr *
Create(const ASTContext &C, CXXRecordDecl *Class, SourceRange IntroducerRange,
@@ -1597,10 +1662,10 @@ public:
/// \brief An iterator that walks over the captures of the lambda,
/// both implicit and explicit.
- typedef const LambdaCapture *capture_iterator;
+ using capture_iterator = const LambdaCapture *;
/// \brief An iterator over a range of lambda captures.
- typedef llvm::iterator_range<capture_iterator> capture_range;
+ using capture_range = llvm::iterator_range<capture_iterator>;
/// \brief Retrieve this lambda's captures.
capture_range captures() const;
@@ -1639,11 +1704,11 @@ public:
/// \brief Iterator that walks over the capture initialization
/// arguments.
- typedef Expr **capture_init_iterator;
+ using capture_init_iterator = Expr **;
/// \brief Const iterator that walks over the capture initialization
/// arguments.
- typedef Expr *const *const_capture_init_iterator;
+ using const_capture_init_iterator = Expr *const *;
/// \brief Retrieve the initialization expressions for this lambda's captures.
llvm::iterator_range<capture_init_iterator> capture_inits() {
@@ -1723,26 +1788,23 @@ public:
SourceLocation getLocStart() const LLVM_READONLY {
return IntroducerRange.getBegin();
}
+
SourceLocation getLocEnd() const LLVM_READONLY { return ClosingBrace; }
child_range children() {
// Includes initialization exprs plus body stmt
return child_range(getStoredStmts(), getStoredStmts() + NumCaptures + 1);
}
-
- friend TrailingObjects;
- friend class ASTStmtReader;
- friend class ASTStmtWriter;
};
/// An expression "T()" which creates a value-initialized rvalue of type
/// T, which is a non-class type. See (C++98 [5.2.3p2]).
class CXXScalarValueInitExpr : public Expr {
+ friend class ASTStmtReader;
+
SourceLocation RParenLoc;
TypeSourceInfo *TypeInfo;
- friend class ASTStmtReader;
-
public:
/// \brief Create an explicitly-written scalar-value initialization
/// expression.
@@ -1754,7 +1816,7 @@ public:
RParenLoc(rParenLoc), TypeInfo(TypeInfo) {}
explicit CXXScalarValueInitExpr(EmptyShell Shell)
- : Expr(CXXScalarValueInitExprClass, Shell) { }
+ : Expr(CXXScalarValueInitExprClass, Shell) {}
TypeSourceInfo *getTypeSourceInfo() const {
return TypeInfo;
@@ -1778,11 +1840,16 @@ public:
/// \brief Represents a new-expression for memory allocation and constructor
/// calls, e.g: "new CXXNewExpr(foo)".
class CXXNewExpr : public Expr {
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
/// Contains an optional array size expression, an optional initialization
/// expression, and any number of optional placement arguments, in that order.
- Stmt **SubExprs;
+ Stmt **SubExprs = nullptr;
+
/// \brief Points to the allocation function used.
FunctionDecl *OperatorNew;
+
/// \brief Points to the deallocation function used in case of error. May be
/// null.
FunctionDecl *OperatorDelete;
@@ -1802,27 +1869,35 @@ class CXXNewExpr : public Expr {
/// Was the usage ::new, i.e. is the global new to be used?
unsigned GlobalNew : 1;
+
/// Do we allocate an array? If so, the first SubExpr is the size expression.
unsigned Array : 1;
+
/// Should the alignment be passed to the allocation function?
unsigned PassAlignment : 1;
+
/// If this is an array allocation, does the usual deallocation
/// function for the allocated type want to know the allocated size?
unsigned UsualArrayDeleteWantsSize : 1;
+
/// The number of placement new arguments.
unsigned NumPlacementArgs : 26;
+
/// What kind of initializer do we have? Could be none, parens, or braces.
/// In storage, we distinguish between "none, and no initializer expr", and
/// "none, but an implicit initializer expr".
unsigned StoredInitializationStyle : 2;
- friend class ASTStmtReader;
- friend class ASTStmtWriter;
public:
enum InitializationStyle {
- NoInit, ///< New-expression has no initializer as written.
- CallInit, ///< New-expression has a C++98 paren-delimited initializer.
- ListInit ///< New-expression has a C++11 list-initializer.
+ /// New-expression has no initializer as written.
+ NoInit,
+
+ /// New-expression has a C++98 paren-delimited initializer.
+ CallInit,
+
+ /// New-expression has a C++11 list-initializer.
+ ListInit
};
CXXNewExpr(const ASTContext &C, bool globalNew, FunctionDecl *operatorNew,
@@ -1833,7 +1908,7 @@ public:
QualType ty, TypeSourceInfo *AllocatedTypeInfo,
SourceRange Range, SourceRange directInitRange);
explicit CXXNewExpr(EmptyShell Shell)
- : Expr(CXXNewExprClass, Shell), SubExprs(nullptr) { }
+ : Expr(CXXNewExprClass, Shell) {}
void AllocateArgsArray(const ASTContext &C, bool isArray,
unsigned numPlaceArgs, bool hasInitializer);
@@ -1870,6 +1945,7 @@ public:
void setOperatorDelete(FunctionDecl *D) { OperatorDelete = D; }
bool isArray() const { return Array; }
+
Expr *getArraySize() {
return Array ? cast<Expr>(SubExprs[0]) : nullptr;
}
@@ -1878,6 +1954,7 @@ public:
}
unsigned getNumPlacementArgs() const { return NumPlacementArgs; }
+
Expr **getPlacementArgs() {
return reinterpret_cast<Expr **>(SubExprs + Array + hasInitializer());
}
@@ -1932,8 +2009,8 @@ public:
return UsualArrayDeleteWantsSize;
}
- typedef ExprIterator arg_iterator;
- typedef ConstExprIterator const_arg_iterator;
+ using arg_iterator = ExprIterator;
+ using const_arg_iterator = ConstExprIterator;
llvm::iterator_range<arg_iterator> placement_arguments() {
return llvm::make_range(placement_arg_begin(), placement_arg_end());
@@ -1956,7 +2033,8 @@ public:
return SubExprs + Array + hasInitializer() + getNumPlacementArgs();
}
- typedef Stmt **raw_arg_iterator;
+ using raw_arg_iterator = Stmt **;
+
raw_arg_iterator raw_arg_begin() { return SubExprs; }
raw_arg_iterator raw_arg_end() {
return SubExprs + Array + hasInitializer() + getNumPlacementArgs();
@@ -1974,6 +2052,7 @@ public:
SourceRange getSourceRange() const LLVM_READONLY {
return Range;
}
+
SourceLocation getLocStart() const LLVM_READONLY { return getStartLoc(); }
SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); }
@@ -1991,36 +2070,43 @@ public:
/// destructor calls, e.g. "delete[] pArray".
class CXXDeleteExpr : public Expr {
/// Points to the operator delete overload that is used. Could be a member.
- FunctionDecl *OperatorDelete;
+ FunctionDecl *OperatorDelete = nullptr;
+
/// The pointer expression to be deleted.
- Stmt *Argument;
+ Stmt *Argument = nullptr;
+
/// Location of the expression.
SourceLocation Loc;
+
/// Is this a forced global delete, i.e. "::delete"?
bool GlobalDelete : 1;
+
/// Is this the array form of delete, i.e. "delete[]"?
bool ArrayForm : 1;
+
/// ArrayFormAsWritten can be different from ArrayForm if 'delete' is applied
/// to pointer-to-array type (ArrayFormAsWritten will be false while ArrayForm
/// will be true).
bool ArrayFormAsWritten : 1;
+
/// Does the usual deallocation function for the element type require
/// a size_t argument?
bool UsualArrayDeleteWantsSize : 1;
+
public:
+ friend class ASTStmtReader;
+
CXXDeleteExpr(QualType ty, bool globalDelete, bool arrayForm,
bool arrayFormAsWritten, bool usualArrayDeleteWantsSize,
FunctionDecl *operatorDelete, Expr *arg, SourceLocation loc)
- : Expr(CXXDeleteExprClass, ty, VK_RValue, OK_Ordinary, false, false,
- arg->isInstantiationDependent(),
- arg->containsUnexpandedParameterPack()),
- OperatorDelete(operatorDelete), Argument(arg), Loc(loc),
- GlobalDelete(globalDelete),
- ArrayForm(arrayForm), ArrayFormAsWritten(arrayFormAsWritten),
- UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) { }
- explicit CXXDeleteExpr(EmptyShell Shell)
- : Expr(CXXDeleteExprClass, Shell), OperatorDelete(nullptr),
- Argument(nullptr) {}
+ : Expr(CXXDeleteExprClass, ty, VK_RValue, OK_Ordinary, false, false,
+ arg->isInstantiationDependent(),
+ arg->containsUnexpandedParameterPack()),
+ OperatorDelete(operatorDelete), Argument(arg), Loc(loc),
+ GlobalDelete(globalDelete),
+ ArrayForm(arrayForm), ArrayFormAsWritten(arrayFormAsWritten),
+ UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) {}
+ explicit CXXDeleteExpr(EmptyShell Shell) : Expr(CXXDeleteExprClass, Shell) {}
bool isGlobalDelete() const { return GlobalDelete; }
bool isArrayForm() const { return ArrayForm; }
@@ -2054,8 +2140,6 @@ public:
// Iterators
child_range children() { return child_range(&Argument, &Argument+1); }
-
- friend class ASTStmtReader;
};
/// \brief Stores the type being destroyed by a pseudo-destructor expression.
@@ -2068,10 +2152,10 @@ class PseudoDestructorTypeStorage {
SourceLocation Location;
public:
- PseudoDestructorTypeStorage() { }
+ PseudoDestructorTypeStorage() = default;
PseudoDestructorTypeStorage(IdentifierInfo *II, SourceLocation Loc)
- : Type(II), Location(Loc) { }
+ : Type(II), Location(Loc) {}
PseudoDestructorTypeStorage(TypeSourceInfo *Info);
@@ -2111,8 +2195,10 @@ public:
/// for scalar types. A pseudo-destructor expression has no run-time semantics
/// beyond evaluating the base expression.
class CXXPseudoDestructorExpr : public Expr {
+ friend class ASTStmtReader;
+
/// \brief The base expression (that is being destroyed).
- Stmt *Base;
+ Stmt *Base = nullptr;
/// \brief Whether the operator was an arrow ('->'); otherwise, it was a
/// period ('.').
@@ -2126,7 +2212,7 @@ class CXXPseudoDestructorExpr : public Expr {
/// \brief The type that precedes the '::' in a qualified pseudo-destructor
/// expression.
- TypeSourceInfo *ScopeType;
+ TypeSourceInfo *ScopeType = nullptr;
/// \brief The location of the '::' in a qualified pseudo-destructor
/// expression.
@@ -2139,8 +2225,6 @@ class CXXPseudoDestructorExpr : public Expr {
/// resolve the name.
PseudoDestructorTypeStorage DestroyedType;
- friend class ASTStmtReader;
-
public:
CXXPseudoDestructorExpr(const ASTContext &Context,
Expr *Base, bool isArrow, SourceLocation OperatorLoc,
@@ -2151,8 +2235,7 @@ public:
PseudoDestructorTypeStorage DestroyedType);
explicit CXXPseudoDestructorExpr(EmptyShell Shell)
- : Expr(CXXPseudoDestructorExprClass, Shell),
- Base(nullptr), IsArrow(false), QualifierLoc(), ScopeType(nullptr) { }
+ : Expr(CXXPseudoDestructorExprClass, Shell), IsArrow(false) {}
Expr *getBase() const { return cast<Expr>(Base); }
@@ -2270,13 +2353,17 @@ class TypeTraitExpr final
SourceLocation RParenLoc,
bool Value);
- TypeTraitExpr(EmptyShell Empty) : Expr(TypeTraitExprClass, Empty) { }
+ TypeTraitExpr(EmptyShell Empty) : Expr(TypeTraitExprClass, Empty) {}
size_t numTrailingObjects(OverloadToken<TypeSourceInfo *>) const {
return getNumArgs();
}
public:
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+ friend TrailingObjects;
+
/// \brief Create a new type trait expression.
static TypeTraitExpr *Create(const ASTContext &C, QualType T,
SourceLocation Loc, TypeTrait Kind,
@@ -2323,10 +2410,6 @@ public:
child_range children() {
return child_range(child_iterator(), child_iterator());
}
-
- friend TrailingObjects;
- friend class ASTStmtReader;
- friend class ASTStmtWriter;
};
/// \brief An Embarcadero array type trait, as used in the implementation of
@@ -2338,13 +2421,11 @@ public:
/// __array_extent(int, 1) == 20
/// \endcode
class ArrayTypeTraitExpr : public Expr {
- virtual void anchor();
-
/// \brief The trait. An ArrayTypeTrait enum in MSVC compat unsigned.
unsigned ATT : 2;
/// \brief The value of the type trait. Unspecified if dependent.
- uint64_t Value;
+ uint64_t Value = 0;
/// \brief The array dimension being queried, or -1 if not used.
Expr *Dimension;
@@ -2356,26 +2437,28 @@ class ArrayTypeTraitExpr : public Expr {
SourceLocation RParen;
/// \brief The type being queried.
- TypeSourceInfo *QueriedType;
+ TypeSourceInfo *QueriedType = nullptr;
+
+ virtual void anchor();
public:
+ friend class ASTStmtReader;
+
ArrayTypeTraitExpr(SourceLocation loc, ArrayTypeTrait att,
TypeSourceInfo *queried, uint64_t value,
Expr *dimension, SourceLocation rparen, QualType ty)
- : Expr(ArrayTypeTraitExprClass, ty, VK_RValue, OK_Ordinary,
- false, queried->getType()->isDependentType(),
- (queried->getType()->isInstantiationDependentType() ||
- (dimension && dimension->isInstantiationDependent())),
- queried->getType()->containsUnexpandedParameterPack()),
- ATT(att), Value(value), Dimension(dimension),
- Loc(loc), RParen(rparen), QueriedType(queried) { }
-
+ : Expr(ArrayTypeTraitExprClass, ty, VK_RValue, OK_Ordinary,
+ false, queried->getType()->isDependentType(),
+ (queried->getType()->isInstantiationDependentType() ||
+ (dimension && dimension->isInstantiationDependent())),
+ queried->getType()->containsUnexpandedParameterPack()),
+ ATT(att), Value(value), Dimension(dimension),
+ Loc(loc), RParen(rparen), QueriedType(queried) {}
explicit ArrayTypeTraitExpr(EmptyShell Empty)
- : Expr(ArrayTypeTraitExprClass, Empty), ATT(0), Value(false),
- QueriedType() { }
+ : Expr(ArrayTypeTraitExprClass, Empty), ATT(0) {}
- virtual ~ArrayTypeTraitExpr() { }
+ virtual ~ArrayTypeTraitExpr() = default;
SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
SourceLocation getLocEnd() const LLVM_READONLY { return RParen; }
@@ -2398,8 +2481,6 @@ public:
child_range children() {
return child_range(child_iterator(), child_iterator());
}
-
- friend class ASTStmtReader;
};
/// \brief An expression trait intrinsic.
@@ -2412,6 +2493,7 @@ public:
class ExpressionTraitExpr : public Expr {
/// \brief The trait. A ExpressionTrait enum in MSVC compatible unsigned.
unsigned ET : 31;
+
/// \brief The value of the type trait. Unspecified if dependent.
unsigned Value : 1;
@@ -2422,23 +2504,25 @@ class ExpressionTraitExpr : public Expr {
SourceLocation RParen;
/// \brief The expression being queried.
- Expr* QueriedExpression;
+ Expr* QueriedExpression = nullptr;
+
public:
+ friend class ASTStmtReader;
+
ExpressionTraitExpr(SourceLocation loc, ExpressionTrait et,
Expr *queried, bool value,
SourceLocation rparen, QualType resultType)
- : Expr(ExpressionTraitExprClass, resultType, VK_RValue, OK_Ordinary,
- false, // Not type-dependent
- // Value-dependent if the argument is type-dependent.
- queried->isTypeDependent(),
- queried->isInstantiationDependent(),
- queried->containsUnexpandedParameterPack()),
- ET(et), Value(value), Loc(loc), RParen(rparen),
- QueriedExpression(queried) { }
+ : Expr(ExpressionTraitExprClass, resultType, VK_RValue, OK_Ordinary,
+ false, // Not type-dependent
+ // Value-dependent if the argument is type-dependent.
+ queried->isTypeDependent(),
+ queried->isInstantiationDependent(),
+ queried->containsUnexpandedParameterPack()),
+ ET(et), Value(value), Loc(loc), RParen(rparen),
+ QueriedExpression(queried) {}
explicit ExpressionTraitExpr(EmptyShell Empty)
- : Expr(ExpressionTraitExprClass, Empty), ET(0), Value(false),
- QueriedExpression() { }
+ : Expr(ExpressionTraitExprClass, Empty), ET(0), Value(false) {}
SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
SourceLocation getLocEnd() const LLVM_READONLY { return RParen; }
@@ -2457,11 +2541,8 @@ public:
child_range children() {
return child_range(child_iterator(), child_iterator());
}
-
- friend class ASTStmtReader;
};
-
/// \brief A reference to an overloaded function set, either an
/// \c UnresolvedLookupExpr or an \c UnresolvedMemberExpr.
class OverloadExpr : public Expr {
@@ -2475,13 +2556,26 @@ class OverloadExpr : public Expr {
/// include UsingShadowDecls. Access is relative to the naming
/// class.
// FIXME: Allocate this data after the OverloadExpr subclass.
- DeclAccessPair *Results;
- unsigned NumResults;
+ DeclAccessPair *Results = nullptr;
+
+ unsigned NumResults = 0;
protected:
/// \brief Whether the name includes info for explicit template
/// keyword and arguments.
- bool HasTemplateKWAndArgsInfo;
+ bool HasTemplateKWAndArgsInfo = false;
+
+ OverloadExpr(StmtClass K, const ASTContext &C,
+ NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs,
+ UnresolvedSetIterator Begin, UnresolvedSetIterator End,
+ bool KnownDependent,
+ bool KnownInstantiationDependent,
+ bool KnownContainsUnexpandedParameterPack);
+
+ OverloadExpr(StmtClass K, EmptyShell Empty) : Expr(K, Empty) {}
/// \brief Return the optional template keyword and arguments info.
ASTTemplateKWAndArgsInfo *
@@ -2496,25 +2590,14 @@ protected:
/// Return the optional template arguments.
TemplateArgumentLoc *getTrailingTemplateArgumentLoc(); // defined far below
- OverloadExpr(StmtClass K, const ASTContext &C,
- NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc,
- const DeclarationNameInfo &NameInfo,
- const TemplateArgumentListInfo *TemplateArgs,
- UnresolvedSetIterator Begin, UnresolvedSetIterator End,
- bool KnownDependent,
- bool KnownInstantiationDependent,
- bool KnownContainsUnexpandedParameterPack);
-
- OverloadExpr(StmtClass K, EmptyShell Empty)
- : Expr(K, Empty), QualifierLoc(), Results(nullptr), NumResults(0),
- HasTemplateKWAndArgsInfo(false) { }
-
void initializeResults(const ASTContext &C,
UnresolvedSetIterator Begin,
UnresolvedSetIterator End);
public:
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
struct FindResult {
OverloadExpr *Expression;
bool IsAddressOfOperand;
@@ -2552,7 +2635,8 @@ public:
/// \brief Gets the naming class of this lookup, if any.
CXXRecordDecl *getNamingClass() const;
- typedef UnresolvedSetImpl::iterator decls_iterator;
+ using decls_iterator = UnresolvedSetImpl::iterator;
+
decls_iterator decls_begin() const { return UnresolvedSetIterator(Results); }
decls_iterator decls_end() const {
return UnresolvedSetIterator(Results + NumResults);
@@ -2636,9 +2720,6 @@ public:
return T->getStmtClass() == UnresolvedLookupExprClass ||
T->getStmtClass() == UnresolvedMemberExprClass;
}
-
- friend class ASTStmtReader;
- friend class ASTStmtWriter;
};
/// \brief A reference to a name which we were able to look up during
@@ -2656,25 +2737,25 @@ class UnresolvedLookupExpr final
: public OverloadExpr,
private llvm::TrailingObjects<
UnresolvedLookupExpr, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> {
+ friend class ASTStmtReader;
+ friend class OverloadExpr;
+ friend TrailingObjects;
+
/// True if these lookup results should be extended by
/// argument-dependent lookup if this is the operand of a function
/// call.
- bool RequiresADL;
+ bool RequiresADL = false;
/// True if these lookup results are overloaded. This is pretty
/// trivially rederivable if we urgently need to kill this field.
- bool Overloaded;
+ bool Overloaded = false;
/// The naming class (C++ [class.access.base]p5) of the lookup, if
/// any. This can generally be recalculated from the context chain,
/// but that can be fairly expensive for unqualified lookups. If we
/// want to improve memory use here, this could go in a union
/// against the qualified-lookup bits.
- CXXRecordDecl *NamingClass;
-
- size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
- return HasTemplateKWAndArgsInfo ? 1 : 0;
- }
+ CXXRecordDecl *NamingClass = nullptr;
UnresolvedLookupExpr(const ASTContext &C,
CXXRecordDecl *NamingClass,
@@ -2684,20 +2765,17 @@ class UnresolvedLookupExpr final
bool RequiresADL, bool Overloaded,
const TemplateArgumentListInfo *TemplateArgs,
UnresolvedSetIterator Begin, UnresolvedSetIterator End)
- : OverloadExpr(UnresolvedLookupExprClass, C, QualifierLoc, TemplateKWLoc,
- NameInfo, TemplateArgs, Begin, End, false, false, false),
- RequiresADL(RequiresADL),
- Overloaded(Overloaded), NamingClass(NamingClass)
- {}
+ : OverloadExpr(UnresolvedLookupExprClass, C, QualifierLoc, TemplateKWLoc,
+ NameInfo, TemplateArgs, Begin, End, false, false, false),
+ RequiresADL(RequiresADL),
+ Overloaded(Overloaded), NamingClass(NamingClass) {}
UnresolvedLookupExpr(EmptyShell Empty)
- : OverloadExpr(UnresolvedLookupExprClass, Empty),
- RequiresADL(false), Overloaded(false), NamingClass(nullptr)
- {}
+ : OverloadExpr(UnresolvedLookupExprClass, Empty) {}
- friend TrailingObjects;
- friend class OverloadExpr;
- friend class ASTStmtReader;
+ size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
+ return HasTemplateKWAndArgsInfo ? 1 : 0;
+ }
public:
static UnresolvedLookupExpr *Create(const ASTContext &C,
@@ -2743,6 +2821,7 @@ public:
return l.getBeginLoc();
return getNameInfo().getLocStart();
}
+
SourceLocation getLocEnd() const LLVM_READONLY {
if (hasExplicitTemplateArgs())
return getRAngleLoc();
@@ -2788,17 +2867,21 @@ class DependentScopeDeclRefExpr final
/// keyword and arguments.
bool HasTemplateKWAndArgsInfo;
- size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
- return HasTemplateKWAndArgsInfo ? 1 : 0;
- }
-
DependentScopeDeclRefExpr(QualType T,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *Args);
+ size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
+ return HasTemplateKWAndArgsInfo ? 1 : 0;
+ }
+
public:
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+ friend TrailingObjects;
+
static DependentScopeDeclRefExpr *Create(const ASTContext &C,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
@@ -2888,6 +2971,7 @@ public:
SourceLocation getLocStart() const LLVM_READONLY {
return QualifierLoc.getBeginLoc();
}
+
SourceLocation getLocEnd() const LLVM_READONLY {
if (hasExplicitTemplateArgs())
return getRAngleLoc();
@@ -2901,10 +2985,6 @@ public:
child_range children() {
return child_range(child_iterator(), child_iterator());
}
-
- friend TrailingObjects;
- friend class ASTStmtReader;
- friend class ASTStmtWriter;
};
/// Represents an expression -- generally a full-expression -- that
@@ -2925,18 +3005,18 @@ public:
/// It's useful to remember the set of blocks; we could also
/// remember the set of temporaries, but there's currently
/// no need.
- typedef BlockDecl *CleanupObject;
+ using CleanupObject = BlockDecl *;
private:
+ friend class ASTStmtReader;
+ friend TrailingObjects;
+
Stmt *SubExpr;
ExprWithCleanups(EmptyShell, unsigned NumObjects);
ExprWithCleanups(Expr *SubExpr, bool CleanupsHaveSideEffects,
ArrayRef<CleanupObject> Objects);
- friend TrailingObjects;
- friend class ASTStmtReader;
-
public:
static ExprWithCleanups *Create(const ASTContext &C, EmptyShell empty,
unsigned numObjects);
@@ -2959,6 +3039,7 @@ public:
Expr *getSubExpr() { return cast<Expr>(SubExpr); }
const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
+
bool cleanupsHaveSideEffects() const {
return ExprWithCleanupsBits.CleanupsHaveSideEffects;
}
@@ -2970,6 +3051,7 @@ public:
SourceLocation getLocStart() const LLVM_READONLY {
return SubExpr->getLocStart();
}
+
SourceLocation getLocEnd() const LLVM_READONLY { return SubExpr->getLocEnd();}
// Implement isa/cast/dyncast/etc.
@@ -3005,8 +3087,11 @@ public:
class CXXUnresolvedConstructExpr final
: public Expr,
private llvm::TrailingObjects<CXXUnresolvedConstructExpr, Expr *> {
+ friend class ASTStmtReader;
+ friend TrailingObjects;
+
/// \brief The type being constructed.
- TypeSourceInfo *Type;
+ TypeSourceInfo *Type = nullptr;
/// \brief The location of the left parentheses ('(').
SourceLocation LParenLoc;
@@ -3023,10 +3108,7 @@ class CXXUnresolvedConstructExpr final
SourceLocation RParenLoc);
CXXUnresolvedConstructExpr(EmptyShell Empty, unsigned NumArgs)
- : Expr(CXXUnresolvedConstructExprClass, Empty), Type(), NumArgs(NumArgs) { }
-
- friend TrailingObjects;
- friend class ASTStmtReader;
+ : Expr(CXXUnresolvedConstructExprClass, Empty), NumArgs(NumArgs) {}
public:
static CXXUnresolvedConstructExpr *Create(const ASTContext &C,
@@ -3056,14 +3138,21 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+ /// Determine whether this expression models list-initialization.
+ /// If so, there will be exactly one subexpression, which will be
+ /// an InitListExpr.
+ bool isListInitialization() const { return LParenLoc.isInvalid(); }
+
/// \brief Retrieve the number of arguments.
unsigned arg_size() const { return NumArgs; }
- typedef Expr** arg_iterator;
+ using arg_iterator = Expr **;
+
arg_iterator arg_begin() { return getTrailingObjects<Expr *>(); }
arg_iterator arg_end() { return arg_begin() + NumArgs; }
- typedef const Expr* const * const_arg_iterator;
+ using const_arg_iterator = const Expr* const *;
+
const_arg_iterator arg_begin() const { return getTrailingObjects<Expr *>(); }
const_arg_iterator arg_end() const {
return arg_begin() + NumArgs;
@@ -3085,6 +3174,7 @@ public:
}
SourceLocation getLocStart() const LLVM_READONLY;
+
SourceLocation getLocEnd() const LLVM_READONLY {
if (!RParenLoc.isValid() && NumArgs > 0)
return getArg(NumArgs - 1)->getLocEnd();
@@ -3165,6 +3255,10 @@ class CXXDependentScopeMemberExpr final
const TemplateArgumentListInfo *TemplateArgs);
public:
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+ friend TrailingObjects;
+
CXXDependentScopeMemberExpr(const ASTContext &C, Expr *Base,
QualType BaseType, bool IsArrow,
SourceLocation OperatorLoc,
@@ -3214,7 +3308,6 @@ public:
/// name, with source location information.
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
-
/// \brief Retrieve the first part of the nested-name-specifier that was
/// found in the scope of the member access expression when the member access
/// was initially parsed.
@@ -3326,10 +3419,6 @@ public:
return child_range(child_iterator(), child_iterator());
return child_range(&Base, &Base + 1);
}
-
- friend TrailingObjects;
- friend class ASTStmtReader;
- friend class ASTStmtWriter;
};
/// \brief Represents a C++ member access expression for which lookup
@@ -3351,6 +3440,10 @@ class UnresolvedMemberExpr final
: public OverloadExpr,
private llvm::TrailingObjects<
UnresolvedMemberExpr, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> {
+ friend class ASTStmtReader;
+ friend class OverloadExpr;
+ friend TrailingObjects;
+
/// \brief Whether this member expression used the '->' operator or
/// the '.' operator.
bool IsArrow : 1;
@@ -3363,7 +3456,7 @@ class UnresolvedMemberExpr final
/// e.g., the \c x in x.f.
///
/// This can be null if this is an 'unbased' member expression.
- Stmt *Base;
+ Stmt *Base = nullptr;
/// \brief The type of the base expression; never null.
QualType BaseType;
@@ -3371,10 +3464,6 @@ class UnresolvedMemberExpr final
/// \brief The location of the '->' or '.' operator.
SourceLocation OperatorLoc;
- size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
- return HasTemplateKWAndArgsInfo ? 1 : 0;
- }
-
UnresolvedMemberExpr(const ASTContext &C, bool HasUnresolvedUsing,
Expr *Base, QualType BaseType, bool IsArrow,
SourceLocation OperatorLoc,
@@ -3385,12 +3474,12 @@ class UnresolvedMemberExpr final
UnresolvedSetIterator Begin, UnresolvedSetIterator End);
UnresolvedMemberExpr(EmptyShell Empty)
- : OverloadExpr(UnresolvedMemberExprClass, Empty), IsArrow(false),
- HasUnresolvedUsing(false), Base(nullptr) { }
+ : OverloadExpr(UnresolvedMemberExprClass, Empty), IsArrow(false),
+ HasUnresolvedUsing(false) {}
- friend TrailingObjects;
- friend class OverloadExpr;
- friend class ASTStmtReader;
+ size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
+ return HasTemplateKWAndArgsInfo ? 1 : 0;
+ }
public:
static UnresolvedMemberExpr *
@@ -3463,6 +3552,7 @@ public:
return l.getBeginLoc();
return getMemberNameInfo().getLocStart();
}
+
SourceLocation getLocEnd() const LLVM_READONLY {
if (hasExplicitTemplateArgs())
return getRAngleLoc();
@@ -3508,26 +3598,23 @@ inline TemplateArgumentLoc *OverloadExpr::getTrailingTemplateArgumentLoc() {
/// The noexcept expression tests whether a given expression might throw. Its
/// result is a boolean constant.
class CXXNoexceptExpr : public Expr {
+ friend class ASTStmtReader;
+
bool Value : 1;
Stmt *Operand;
SourceRange Range;
- friend class ASTStmtReader;
-
public:
CXXNoexceptExpr(QualType Ty, Expr *Operand, CanThrowResult Val,
SourceLocation Keyword, SourceLocation RParen)
- : Expr(CXXNoexceptExprClass, Ty, VK_RValue, OK_Ordinary,
- /*TypeDependent*/false,
- /*ValueDependent*/Val == CT_Dependent,
- Val == CT_Dependent || Operand->isInstantiationDependent(),
- Operand->containsUnexpandedParameterPack()),
- Value(Val == CT_Cannot), Operand(Operand), Range(Keyword, RParen)
- { }
+ : Expr(CXXNoexceptExprClass, Ty, VK_RValue, OK_Ordinary,
+ /*TypeDependent*/false,
+ /*ValueDependent*/Val == CT_Dependent,
+ Val == CT_Dependent || Operand->isInstantiationDependent(),
+ Operand->containsUnexpandedParameterPack()),
+ Value(Val == CT_Cannot), Operand(Operand), Range(Keyword, RParen) {}
- CXXNoexceptExpr(EmptyShell Empty)
- : Expr(CXXNoexceptExprClass, Empty)
- { }
+ CXXNoexceptExpr(EmptyShell Empty) : Expr(CXXNoexceptExprClass, Empty) {}
Expr *getOperand() const { return static_cast<Expr*>(Operand); }
@@ -3563,6 +3650,9 @@ public:
/// template is instantiated, the pack expansion will instantiate to zero or
/// or more function arguments to the function object \c f.
class PackExpansionExpr : public Expr {
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
SourceLocation EllipsisLoc;
/// \brief The number of expansions that will be produced by this pack
@@ -3574,21 +3664,18 @@ class PackExpansionExpr : public Expr {
Stmt *Pattern;
- friend class ASTStmtReader;
- friend class ASTStmtWriter;
-
public:
PackExpansionExpr(QualType T, Expr *Pattern, SourceLocation EllipsisLoc,
Optional<unsigned> NumExpansions)
- : Expr(PackExpansionExprClass, T, Pattern->getValueKind(),
- Pattern->getObjectKind(), /*TypeDependent=*/true,
- /*ValueDependent=*/true, /*InstantiationDependent=*/true,
- /*ContainsUnexpandedParameterPack=*/false),
- EllipsisLoc(EllipsisLoc),
- NumExpansions(NumExpansions? *NumExpansions + 1 : 0),
- Pattern(Pattern) { }
+ : Expr(PackExpansionExprClass, T, Pattern->getValueKind(),
+ Pattern->getObjectKind(), /*TypeDependent=*/true,
+ /*ValueDependent=*/true, /*InstantiationDependent=*/true,
+ /*ContainsUnexpandedParameterPack=*/false),
+ EllipsisLoc(EllipsisLoc),
+ NumExpansions(NumExpansions ? *NumExpansions + 1 : 0),
+ Pattern(Pattern) {}
- PackExpansionExpr(EmptyShell Empty) : Expr(PackExpansionExprClass, Empty) { }
+ PackExpansionExpr(EmptyShell Empty) : Expr(PackExpansionExprClass, Empty) {}
/// \brief Retrieve the pattern of the pack expansion.
Expr *getPattern() { return reinterpret_cast<Expr *>(Pattern); }
@@ -3612,6 +3699,7 @@ public:
SourceLocation getLocStart() const LLVM_READONLY {
return Pattern->getLocStart();
}
+
SourceLocation getLocEnd() const LLVM_READONLY { return EllipsisLoc; }
static bool classof(const Stmt *T) {
@@ -3624,7 +3712,6 @@ public:
}
};
-
/// \brief Represents an expression that computes the length of a parameter
/// pack.
///
@@ -3637,6 +3724,10 @@ public:
class SizeOfPackExpr final
: public Expr,
private llvm::TrailingObjects<SizeOfPackExpr, TemplateArgument> {
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+ friend TrailingObjects;
+
/// \brief The location of the \c sizeof keyword.
SourceLocation OperatorLoc;
@@ -3659,11 +3750,7 @@ class SizeOfPackExpr final
unsigned Length;
/// \brief The parameter pack.
- NamedDecl *Pack;
-
- friend TrailingObjects;
- friend class ASTStmtReader;
- friend class ASTStmtWriter;
+ NamedDecl *Pack = nullptr;
/// \brief Create an expression that computes the length of
/// the given parameter pack.
@@ -3684,7 +3771,7 @@ class SizeOfPackExpr final
/// \brief Create an empty expression.
SizeOfPackExpr(EmptyShell Empty, unsigned NumPartialArgs)
- : Expr(SizeOfPackExprClass, Empty), Length(NumPartialArgs), Pack() {}
+ : Expr(SizeOfPackExprClass, Empty), Length(NumPartialArgs) {}
public:
static SizeOfPackExpr *Create(ASTContext &Context, SourceLocation OperatorLoc,
@@ -3749,6 +3836,9 @@ public:
/// \brief Represents a reference to a non-type template parameter
/// that has been substituted with a template argument.
class SubstNonTypeTemplateParmExpr : public Expr {
+ friend class ASTReader;
+ friend class ASTStmtReader;
+
/// \brief The replaced parameter.
NonTypeTemplateParmDecl *Param;
@@ -3758,10 +3848,8 @@ class SubstNonTypeTemplateParmExpr : public Expr {
/// \brief The location of the non-type template parameter reference.
SourceLocation NameLoc;
- friend class ASTReader;
- friend class ASTStmtReader;
explicit SubstNonTypeTemplateParmExpr(EmptyShell Empty)
- : Expr(SubstNonTypeTemplateParmExprClass, Empty) { }
+ : Expr(SubstNonTypeTemplateParmExprClass, Empty) {}
public:
SubstNonTypeTemplateParmExpr(QualType type,
@@ -3769,11 +3857,11 @@ public:
SourceLocation loc,
NonTypeTemplateParmDecl *param,
Expr *replacement)
- : Expr(SubstNonTypeTemplateParmExprClass, type, valueKind, OK_Ordinary,
- replacement->isTypeDependent(), replacement->isValueDependent(),
- replacement->isInstantiationDependent(),
- replacement->containsUnexpandedParameterPack()),
- Param(param), Replacement(replacement), NameLoc(loc) {}
+ : Expr(SubstNonTypeTemplateParmExprClass, type, valueKind, OK_Ordinary,
+ replacement->isTypeDependent(), replacement->isValueDependent(),
+ replacement->isInstantiationDependent(),
+ replacement->containsUnexpandedParameterPack()),
+ Param(param), Replacement(replacement), NameLoc(loc) {}
SourceLocation getNameLoc() const { return NameLoc; }
SourceLocation getLocStart() const LLVM_READONLY { return NameLoc; }
@@ -3804,6 +3892,9 @@ public:
/// arguments), this type will be replaced with the appropriate underlying
/// expression at the current pack substitution index.
class SubstNonTypeTemplateParmPackExpr : public Expr {
+ friend class ASTReader;
+ friend class ASTStmtReader;
+
/// \brief The non-type template parameter pack itself.
NonTypeTemplateParmDecl *Param;
@@ -3817,10 +3908,8 @@ class SubstNonTypeTemplateParmPackExpr : public Expr {
/// \brief The location of the non-type template parameter pack reference.
SourceLocation NameLoc;
- friend class ASTReader;
- friend class ASTStmtReader;
explicit SubstNonTypeTemplateParmPackExpr(EmptyShell Empty)
- : Expr(SubstNonTypeTemplateParmPackExprClass, Empty) { }
+ : Expr(SubstNonTypeTemplateParmPackExprClass, Empty) {}
public:
SubstNonTypeTemplateParmPackExpr(QualType T,
@@ -3868,6 +3957,10 @@ public:
class FunctionParmPackExpr final
: public Expr,
private llvm::TrailingObjects<FunctionParmPackExpr, ParmVarDecl *> {
+ friend class ASTReader;
+ friend class ASTStmtReader;
+ friend TrailingObjects;
+
/// \brief The function parameter pack which was referenced.
ParmVarDecl *ParamPack;
@@ -3881,10 +3974,6 @@ class FunctionParmPackExpr final
SourceLocation NameLoc, unsigned NumParams,
ParmVarDecl *const *Params);
- friend TrailingObjects;
- friend class ASTReader;
- friend class ASTStmtReader;
-
public:
static FunctionParmPackExpr *Create(const ASTContext &Context, QualType T,
ParmVarDecl *ParamPack,
@@ -3901,7 +3990,7 @@ public:
/// \brief Iterators over the parameters which the parameter pack expanded
/// into.
- typedef ParmVarDecl * const *iterator;
+ using iterator = ParmVarDecl * const *;
iterator begin() const { return getTrailingObjects<ParmVarDecl *>(); }
iterator end() const { return begin() + NumParameters; }
@@ -3945,6 +4034,9 @@ public:
/// declaration which is responsible for the lifetime extension.
class MaterializeTemporaryExpr : public Expr {
private:
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
struct ExtraState {
/// \brief The temporary-generating expression whose value will be
/// materialized.
@@ -3958,24 +4050,21 @@ private:
};
llvm::PointerUnion<Stmt *, ExtraState *> State;
- friend class ASTStmtReader;
- friend class ASTStmtWriter;
-
void initializeExtraState(const ValueDecl *ExtendedBy,
unsigned ManglingNumber);
public:
MaterializeTemporaryExpr(QualType T, Expr *Temporary,
bool BoundToLvalueReference)
- : Expr(MaterializeTemporaryExprClass, T,
- BoundToLvalueReference? VK_LValue : VK_XValue, OK_Ordinary,
- Temporary->isTypeDependent(), Temporary->isValueDependent(),
- Temporary->isInstantiationDependent(),
- Temporary->containsUnexpandedParameterPack()),
+ : Expr(MaterializeTemporaryExprClass, T,
+ BoundToLvalueReference? VK_LValue : VK_XValue, OK_Ordinary,
+ Temporary->isTypeDependent(), Temporary->isValueDependent(),
+ Temporary->isInstantiationDependent(),
+ Temporary->containsUnexpandedParameterPack()),
State(Temporary) {}
MaterializeTemporaryExpr(EmptyShell Empty)
- : Expr(MaterializeTemporaryExprClass, Empty) { }
+ : Expr(MaterializeTemporaryExprClass, Empty) {}
Stmt *getTemporary() const {
return State.is<Stmt *>() ? State.get<Stmt *>()
@@ -4026,6 +4115,7 @@ public:
SourceLocation getLocStart() const LLVM_READONLY {
return getTemporary()->getLocStart();
}
+
SourceLocation getLocEnd() const LLVM_READONLY {
return getTemporary()->getLocEnd();
}
@@ -4053,14 +4143,15 @@ public:
/// ( ... op expr )
/// ( expr op ... op expr )
class CXXFoldExpr : public Expr {
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
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,
@@ -4073,6 +4164,7 @@ public:
SubExprs[0] = LHS;
SubExprs[1] = RHS;
}
+
CXXFoldExpr(EmptyShell Empty) : Expr(CXXFoldExprClass, Empty) {}
Expr *getLHS() const { return static_cast<Expr*>(SubExprs[0]); }
@@ -4082,10 +4174,13 @@ public:
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(); }
@@ -4095,6 +4190,7 @@ public:
SourceLocation getLocStart() const LLVM_READONLY {
return LParenLoc;
}
+
SourceLocation getLocEnd() const LLVM_READONLY {
return RParenLoc;
}
@@ -4121,13 +4217,15 @@ public:
/// expression is evaluated, and its result is the result of the overall
/// expression.
class CoroutineSuspendExpr : public Expr {
+ friend class ASTStmtReader;
+
SourceLocation KeywordLoc;
enum SubExpr { Common, Ready, Suspend, Resume, Count };
+
Stmt *SubExprs[SubExpr::Count];
OpaqueValueExpr *OpaqueValue = nullptr;
- friend class ASTStmtReader;
public:
CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, Expr *Common,
Expr *Ready, Expr *Suspend, Expr *Resume,
@@ -4142,6 +4240,7 @@ public:
SubExprs[SubExpr::Suspend] = Suspend;
SubExprs[SubExpr::Resume] = Resume;
}
+
CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, QualType Ty,
Expr *Common)
: Expr(SC, Ty, VK_RValue, OK_Ordinary, true, true, true,
@@ -4154,6 +4253,7 @@ public:
SubExprs[SubExpr::Suspend] = nullptr;
SubExprs[SubExpr::Resume] = nullptr;
}
+
CoroutineSuspendExpr(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty) {
SubExprs[SubExpr::Common] = nullptr;
SubExprs[SubExpr::Ready] = nullptr;
@@ -4162,18 +4262,22 @@ public:
}
SourceLocation getKeywordLoc() const { return KeywordLoc; }
+
Expr *getCommonExpr() const {
return static_cast<Expr*>(SubExprs[SubExpr::Common]);
}
+
/// \brief getOpaqueValue - Return the opaque value placeholder.
OpaqueValueExpr *getOpaqueValue() const { return OpaqueValue; }
Expr *getReadyExpr() const {
return static_cast<Expr*>(SubExprs[SubExpr::Ready]);
}
+
Expr *getSuspendExpr() const {
return static_cast<Expr*>(SubExprs[SubExpr::Suspend]);
}
+
Expr *getResumeExpr() const {
return static_cast<Expr*>(SubExprs[SubExpr::Resume]);
}
@@ -4181,6 +4285,7 @@ public:
SourceLocation getLocStart() const LLVM_READONLY {
return KeywordLoc;
}
+
SourceLocation getLocEnd() const LLVM_READONLY {
return getCommonExpr()->getLocEnd();
}
@@ -4198,6 +4303,7 @@ public:
/// \brief Represents a 'co_await' expression.
class CoawaitExpr : public CoroutineSuspendExpr {
friend class ASTStmtReader;
+
public:
CoawaitExpr(SourceLocation CoawaitLoc, Expr *Operand, Expr *Ready,
Expr *Suspend, Expr *Resume, OpaqueValueExpr *OpaqueValue,
@@ -4206,11 +4312,13 @@ public:
Suspend, Resume, OpaqueValue) {
CoawaitBits.IsImplicit = IsImplicit;
}
+
CoawaitExpr(SourceLocation CoawaitLoc, QualType Ty, Expr *Operand,
bool IsImplicit = false)
: CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Ty, Operand) {
CoawaitBits.IsImplicit = IsImplicit;
}
+
CoawaitExpr(EmptyShell Empty)
: CoroutineSuspendExpr(CoawaitExprClass, Empty) {}
@@ -4230,11 +4338,11 @@ public:
/// \brief Represents a 'co_await' expression while the type of the promise
/// is dependent.
class DependentCoawaitExpr : public Expr {
+ friend class ASTStmtReader;
+
SourceLocation KeywordLoc;
Stmt *SubExprs[2];
- friend class ASTStmtReader;
-
public:
DependentCoawaitExpr(SourceLocation KeywordLoc, QualType Ty, Expr *Op,
UnresolvedLookupExpr *OpCoawait)
@@ -4255,12 +4363,15 @@ public:
: Expr(DependentCoawaitExprClass, Empty) {}
Expr *getOperand() const { return cast<Expr>(SubExprs[0]); }
+
UnresolvedLookupExpr *getOperatorCoawaitLookup() const {
return cast<UnresolvedLookupExpr>(SubExprs[1]);
}
+
SourceLocation getKeywordLoc() const { return KeywordLoc; }
SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; }
+
SourceLocation getLocEnd() const LLVM_READONLY {
return getOperand()->getLocEnd();
}
@@ -4275,6 +4386,7 @@ public:
/// \brief Represents a 'co_yield' expression.
class CoyieldExpr : public CoroutineSuspendExpr {
friend class ASTStmtReader;
+
public:
CoyieldExpr(SourceLocation CoyieldLoc, Expr *Operand, Expr *Ready,
Expr *Suspend, Expr *Resume, OpaqueValueExpr *OpaqueValue)
@@ -4295,6 +4407,6 @@ public:
}
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_AST_EXPRCXX_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h b/contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h
index cd9381758618a..ab2df8a34819e 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h
@@ -1,4 +1,4 @@
-//===--- ExprObjC.h - Classes for representing ObjC expressions -*- C++ -*-===//
+//===- ExprObjC.h - Classes for representing ObjC expressions ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,28 +14,51 @@
#ifndef LLVM_CLANG_AST_EXPROBJC_H
#define LLVM_CLANG_AST_EXPROBJC_H
+#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/OperationKinds.h"
#include "clang/AST/SelectorLocationsKind.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/Type.h"
#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Basic/VersionTuple.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/TrailingObjects.h"
+#include "llvm/Support/type_traits.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
namespace clang {
- class IdentifierInfo;
- class ASTContext;
+
+class ASTContext;
+class CXXBaseSpecifier;
/// ObjCStringLiteral, used for Objective-C string literals
/// i.e. @"foo".
class ObjCStringLiteral : public Expr {
Stmt *String;
SourceLocation AtLoc;
+
public:
ObjCStringLiteral(StringLiteral *SL, QualType T, SourceLocation L)
- : Expr(ObjCStringLiteralClass, T, VK_RValue, OK_Ordinary, false, false,
- false, false),
- String(SL), AtLoc(L) {}
+ : Expr(ObjCStringLiteralClass, T, VK_RValue, OK_Ordinary, false, false,
+ false, false),
+ String(SL), AtLoc(L) {}
explicit ObjCStringLiteral(EmptyShell Empty)
- : Expr(ObjCStringLiteralClass, Empty) {}
+ : Expr(ObjCStringLiteralClass, Empty) {}
StringLiteral *getString() { return cast<StringLiteral>(String); }
const StringLiteral *getString() const { return cast<StringLiteral>(String); }
@@ -47,26 +70,26 @@ public:
SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; }
SourceLocation getLocEnd() const LLVM_READONLY { return String->getLocEnd(); }
+ // Iterators
+ child_range children() { return child_range(&String, &String+1); }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCStringLiteralClass;
}
-
- // Iterators
- child_range children() { return child_range(&String, &String+1); }
};
/// ObjCBoolLiteralExpr - Objective-C Boolean Literal.
-///
class ObjCBoolLiteralExpr : public Expr {
bool Value;
SourceLocation Loc;
+
public:
- ObjCBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) :
- Expr(ObjCBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
- false, false), Value(val), Loc(l) {}
-
+ ObjCBoolLiteralExpr(bool val, QualType Ty, SourceLocation l)
+ : Expr(ObjCBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
+ false, false),
+ Value(val), Loc(l) {}
explicit ObjCBoolLiteralExpr(EmptyShell Empty)
- : Expr(ObjCBoolLiteralExprClass, Empty) { }
+ : Expr(ObjCBoolLiteralExprClass, Empty) {}
bool getValue() const { return Value; }
void setValue(bool V) { Value = V; }
@@ -77,14 +100,14 @@ public:
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == ObjCBoolLiteralExprClass;
- }
-
// Iterators
child_range children() {
return child_range(child_iterator(), child_iterator());
}
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCBoolLiteralExprClass;
+ }
};
/// ObjCBoxedExpr - used for generalized expression boxing.
@@ -95,15 +118,19 @@ class ObjCBoxedExpr : public Expr {
Stmt *SubExpr;
ObjCMethodDecl *BoxingMethod;
SourceRange Range;
+
public:
+ friend class ASTStmtReader;
+
ObjCBoxedExpr(Expr *E, QualType T, ObjCMethodDecl *method,
SourceRange R)
- : Expr(ObjCBoxedExprClass, T, VK_RValue, OK_Ordinary,
- E->isTypeDependent(), E->isValueDependent(),
- E->isInstantiationDependent(), E->containsUnexpandedParameterPack()),
- SubExpr(E), BoxingMethod(method), Range(R) {}
+ : Expr(ObjCBoxedExprClass, T, VK_RValue, OK_Ordinary,
+ E->isTypeDependent(), E->isValueDependent(),
+ E->isInstantiationDependent(),
+ E->containsUnexpandedParameterPack()),
+ SubExpr(E), BoxingMethod(method), Range(R) {}
explicit ObjCBoxedExpr(EmptyShell Empty)
- : Expr(ObjCBoxedExprClass, Empty) {}
+ : Expr(ObjCBoxedExprClass, Empty) {}
Expr *getSubExpr() { return cast<Expr>(SubExpr); }
const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
@@ -116,27 +143,27 @@ public:
SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
+
SourceRange getSourceRange() const LLVM_READONLY {
return Range;
}
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == ObjCBoxedExprClass;
- }
-
// Iterators
child_range children() { return child_range(&SubExpr, &SubExpr+1); }
- typedef ConstExprIterator const_arg_iterator;
+ using const_arg_iterator = ConstExprIterator;
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;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCBoxedExprClass;
+ }
};
/// ObjCArrayLiteral - used for objective-c array containers; as in:
@@ -153,9 +180,12 @@ class ObjCArrayLiteral final
SourceRange SR);
explicit ObjCArrayLiteral(EmptyShell Empty, unsigned NumElements)
- : Expr(ObjCArrayLiteralClass, Empty), NumElements(NumElements) {}
+ : Expr(ObjCArrayLiteralClass, Empty), NumElements(NumElements) {}
public:
+ friend class ASTStmtReader;
+ friend TrailingObjects;
+
static ObjCArrayLiteral *Create(const ASTContext &C,
ArrayRef<Expr *> Elements,
QualType T, ObjCMethodDecl * Method,
@@ -168,10 +198,6 @@ public:
SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
SourceRange getSourceRange() const LLVM_READONLY { return Range; }
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == ObjCArrayLiteralClass;
- }
-
/// \brief Retrieve elements of array of literals.
Expr **getElements() { return getTrailingObjects<Expr *>(); }
@@ -183,7 +209,7 @@ public:
/// getNumElements - Return number of elements of objective-c array literal.
unsigned getNumElements() const { return NumElements; }
- /// getExpr - Return the Expr at the specified index.
+ /// getElement - Return the Element at the specified index.
Expr *getElement(unsigned Index) {
assert((Index < NumElements) && "Arg access out of range!");
return cast<Expr>(getElements()[Index]);
@@ -203,8 +229,9 @@ public:
reinterpret_cast<Stmt **>(getElements()) + NumElements);
}
- friend TrailingObjects;
- friend class ASTStmtReader;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCArrayLiteralClass;
+ }
};
/// \brief An element in an Objective-C dictionary literal.
@@ -226,13 +253,17 @@ struct ObjCDictionaryElement {
/// \brief Determines whether this dictionary element is a pack expansion.
bool isPackExpansion() const { return EllipsisLoc.isValid(); }
};
-} // end namespace clang
+
+} // namespace clang
namespace llvm {
+
template <> struct isPodLike<clang::ObjCDictionaryElement> : std::true_type {};
-}
+
+} // namespace llvm
namespace clang {
+
/// \brief Internal struct for storing Key/value pair.
struct ObjCDictionaryLiteral_KeyValuePair {
Expr *Key;
@@ -274,12 +305,8 @@ class ObjCDictionaryLiteral final
SourceRange Range;
ObjCMethodDecl *DictWithObjectsMethod;
- typedef ObjCDictionaryLiteral_KeyValuePair KeyValuePair;
- typedef ObjCDictionaryLiteral_ExpansionData ExpansionData;
-
- size_t numTrailingObjects(OverloadToken<KeyValuePair>) const {
- return NumElements;
- }
+ using KeyValuePair = ObjCDictionaryLiteral_KeyValuePair;
+ using ExpansionData = ObjCDictionaryLiteral_ExpansionData;
ObjCDictionaryLiteral(ArrayRef<ObjCDictionaryElement> VK,
bool HasPackExpansions,
@@ -288,10 +315,18 @@ class ObjCDictionaryLiteral final
explicit ObjCDictionaryLiteral(EmptyShell Empty, unsigned NumElements,
bool HasPackExpansions)
- : Expr(ObjCDictionaryLiteralClass, Empty), NumElements(NumElements),
- HasPackExpansions(HasPackExpansions) {}
+ : Expr(ObjCDictionaryLiteralClass, Empty), NumElements(NumElements),
+ HasPackExpansions(HasPackExpansions) {}
+
+ size_t numTrailingObjects(OverloadToken<KeyValuePair>) const {
+ return NumElements;
+ }
public:
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+ friend TrailingObjects;
+
static ObjCDictionaryLiteral *Create(const ASTContext &C,
ArrayRef<ObjCDictionaryElement> VK,
bool HasPackExpansions,
@@ -320,17 +355,14 @@ public:
return Result;
}
- ObjCMethodDecl *getDictWithObjectsMethod() const
- { return DictWithObjectsMethod; }
+ ObjCMethodDecl *getDictWithObjectsMethod() const {
+ return DictWithObjectsMethod;
+ }
SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
SourceRange getSourceRange() const LLVM_READONLY { return Range; }
-
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == ObjCDictionaryLiteralClass;
- }
-
+
// Iterators
child_range children() {
// Note: we're taking advantage of the layout of the KeyValuePair struct
@@ -342,12 +374,11 @@ public:
reinterpret_cast<Stmt **>(getTrailingObjects<KeyValuePair>()) +
NumElements * 2);
}
-
- friend class ASTStmtReader;
- friend class ASTStmtWriter;
- friend TrailingObjects;
-};
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCDictionaryLiteralClass;
+ }
+};
/// ObjCEncodeExpr, used for \@encode in Objective-C. \@encode has the same
/// type and behavior as StringLiteral except that the string initializer is
@@ -355,19 +386,19 @@ public:
class ObjCEncodeExpr : public Expr {
TypeSourceInfo *EncodedType;
SourceLocation AtLoc, RParenLoc;
+
public:
ObjCEncodeExpr(QualType T, TypeSourceInfo *EncodedType,
SourceLocation at, SourceLocation rp)
- : Expr(ObjCEncodeExprClass, T, VK_LValue, OK_Ordinary,
- EncodedType->getType()->isDependentType(),
- EncodedType->getType()->isDependentType(),
- EncodedType->getType()->isInstantiationDependentType(),
- EncodedType->getType()->containsUnexpandedParameterPack()),
- EncodedType(EncodedType), AtLoc(at), RParenLoc(rp) {}
+ : Expr(ObjCEncodeExprClass, T, VK_LValue, OK_Ordinary,
+ EncodedType->getType()->isDependentType(),
+ EncodedType->getType()->isDependentType(),
+ EncodedType->getType()->isInstantiationDependentType(),
+ EncodedType->getType()->containsUnexpandedParameterPack()),
+ EncodedType(EncodedType), AtLoc(at), RParenLoc(rp) {}
explicit ObjCEncodeExpr(EmptyShell Empty) : Expr(ObjCEncodeExprClass, Empty){}
-
SourceLocation getAtLoc() const { return AtLoc; }
void setAtLoc(SourceLocation L) { AtLoc = L; }
SourceLocation getRParenLoc() const { return RParenLoc; }
@@ -376,6 +407,7 @@ public:
QualType getEncodedType() const { return EncodedType->getType(); }
TypeSourceInfo *getEncodedTypeSourceInfo() const { return EncodedType; }
+
void setEncodedTypeSourceInfo(TypeSourceInfo *EncType) {
EncodedType = EncType;
}
@@ -383,28 +415,29 @@ public:
SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; }
SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == ObjCEncodeExprClass;
- }
-
// Iterators
child_range children() {
return child_range(child_iterator(), child_iterator());
}
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCEncodeExprClass;
+ }
};
/// ObjCSelectorExpr used for \@selector in Objective-C.
class ObjCSelectorExpr : public Expr {
Selector SelName;
SourceLocation AtLoc, RParenLoc;
+
public:
ObjCSelectorExpr(QualType T, Selector selInfo,
SourceLocation at, SourceLocation rp)
- : Expr(ObjCSelectorExprClass, T, VK_RValue, OK_Ordinary, false, false,
- false, false),
- SelName(selInfo), AtLoc(at), RParenLoc(rp){}
+ : Expr(ObjCSelectorExprClass, T, VK_RValue, OK_Ordinary, false, false,
+ false, false),
+ SelName(selInfo), AtLoc(at), RParenLoc(rp) {}
explicit ObjCSelectorExpr(EmptyShell Empty)
- : Expr(ObjCSelectorExprClass, Empty) {}
+ : Expr(ObjCSelectorExprClass, Empty) {}
Selector getSelector() const { return SelName; }
void setSelector(Selector S) { SelName = S; }
@@ -420,14 +453,14 @@ public:
/// getNumArgs - Return the number of actual arguments to this call.
unsigned getNumArgs() const { return SelName.getNumArgs(); }
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == ObjCSelectorExprClass;
- }
-
// Iterators
child_range children() {
return child_range(child_iterator(), child_iterator());
}
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCSelectorExprClass;
+ }
};
/// ObjCProtocolExpr used for protocol expression in Objective-C.
@@ -441,14 +474,18 @@ public:
class ObjCProtocolExpr : public Expr {
ObjCProtocolDecl *TheProtocol;
SourceLocation AtLoc, ProtoLoc, RParenLoc;
+
public:
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol,
SourceLocation at, SourceLocation protoLoc, SourceLocation rp)
- : Expr(ObjCProtocolExprClass, T, VK_RValue, OK_Ordinary, false, false,
- false, false),
- TheProtocol(protocol), AtLoc(at), ProtoLoc(protoLoc), RParenLoc(rp) {}
+ : Expr(ObjCProtocolExprClass, T, VK_RValue, OK_Ordinary, false, false,
+ false, false),
+ TheProtocol(protocol), AtLoc(at), ProtoLoc(protoLoc), RParenLoc(rp) {}
explicit ObjCProtocolExpr(EmptyShell Empty)
- : Expr(ObjCProtocolExprClass, Empty) {}
+ : Expr(ObjCProtocolExprClass, Empty) {}
ObjCProtocolDecl *getProtocol() const { return TheProtocol; }
void setProtocol(ObjCProtocolDecl *P) { TheProtocol = P; }
@@ -462,17 +499,14 @@ public:
SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; }
SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == ObjCProtocolExprClass;
- }
-
// Iterators
child_range children() {
return child_range(child_iterator(), child_iterator());
}
- friend class ASTStmtReader;
- friend class ASTStmtWriter;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCProtocolExprClass;
+ }
};
/// ObjCIvarRefExpr - A reference to an ObjC instance variable.
@@ -480,27 +514,31 @@ class ObjCIvarRefExpr : public Expr {
ObjCIvarDecl *D;
Stmt *Base;
SourceLocation Loc;
+
/// OpLoc - This is the location of '.' or '->'
SourceLocation OpLoc;
-
- bool IsArrow:1; // True if this is "X->F", false if this is "X.F".
- bool IsFreeIvar:1; // True if ivar reference has no base (self assumed).
+
+ // True if this is "X->F", false if this is "X.F".
+ bool IsArrow : 1;
+
+ // True if ivar reference has no base (self assumed).
+ bool IsFreeIvar : 1;
public:
ObjCIvarRefExpr(ObjCIvarDecl *d, QualType t,
SourceLocation l, SourceLocation oploc,
Expr *base,
- bool arrow = false, bool freeIvar = false) :
- Expr(ObjCIvarRefExprClass, t, VK_LValue,
- d->isBitField() ? OK_BitField : OK_Ordinary,
- /*TypeDependent=*/false, base->isValueDependent(),
- base->isInstantiationDependent(),
- base->containsUnexpandedParameterPack()),
- D(d), Base(base), Loc(l), OpLoc(oploc),
- IsArrow(arrow), IsFreeIvar(freeIvar) {}
+ bool arrow = false, bool freeIvar = false)
+ : Expr(ObjCIvarRefExprClass, t, VK_LValue,
+ d->isBitField() ? OK_BitField : OK_Ordinary,
+ /*TypeDependent=*/false, base->isValueDependent(),
+ base->isInstantiationDependent(),
+ base->containsUnexpandedParameterPack()),
+ D(d), Base(base), Loc(l), OpLoc(oploc), IsArrow(arrow),
+ IsFreeIvar(freeIvar) {}
explicit ObjCIvarRefExpr(EmptyShell Empty)
- : Expr(ObjCIvarRefExprClass, Empty) {}
+ : Expr(ObjCIvarRefExprClass, Empty) {}
ObjCIvarDecl *getDecl() { return D; }
const ObjCIvarDecl *getDecl() const { return D; }
@@ -526,12 +564,12 @@ public:
SourceLocation getOpLoc() const { return OpLoc; }
void setOpLoc(SourceLocation L) { OpLoc = L; }
+ // Iterators
+ child_range children() { return child_range(&Base, &Base+1); }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCIvarRefExprClass;
}
-
- // Iterators
- child_range children() { return child_range(&Base, &Base+1); }
};
/// ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC
@@ -542,7 +580,7 @@ private:
/// pointer is an (optional) ObjCMethodDecl and Setter may be set.
/// if the bool is false, this is an explicit property reference;
/// the pointer is an ObjCPropertyDecl and Setter is always null.
- llvm::PointerIntPair<NamedDecl*, 1, bool> PropertyOrGetter;
+ llvm::PointerIntPair<NamedDecl *, 1, bool> PropertyOrGetter;
/// \brief Indicates whether the property reference will result in a message
/// to the getter, the setter, or both.
@@ -567,40 +605,39 @@ private:
/// the location of the 'super' keyword. When it's an interface,
/// this is that interface.
SourceLocation ReceiverLoc;
- llvm::PointerUnion3<Stmt*, const Type*, ObjCInterfaceDecl*> Receiver;
+ llvm::PointerUnion3<Stmt *, const Type *, ObjCInterfaceDecl *> Receiver;
public:
ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
ExprValueKind VK, ExprObjectKind OK,
SourceLocation l, Expr *base)
- : Expr(ObjCPropertyRefExprClass, t, VK, OK,
- /*TypeDependent=*/false, base->isValueDependent(),
- base->isInstantiationDependent(),
- base->containsUnexpandedParameterPack()),
- PropertyOrGetter(PD, false), SetterAndMethodRefFlags(),
- IdLoc(l), ReceiverLoc(), Receiver(base) {
+ : Expr(ObjCPropertyRefExprClass, t, VK, OK,
+ /*TypeDependent=*/false, base->isValueDependent(),
+ base->isInstantiationDependent(),
+ base->containsUnexpandedParameterPack()),
+ PropertyOrGetter(PD, false), IdLoc(l), Receiver(base) {
assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject));
}
ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
ExprValueKind VK, ExprObjectKind OK,
SourceLocation l, SourceLocation sl, QualType st)
- : Expr(ObjCPropertyRefExprClass, t, VK, OK,
- /*TypeDependent=*/false, false, st->isInstantiationDependentType(),
- st->containsUnexpandedParameterPack()),
- PropertyOrGetter(PD, false), SetterAndMethodRefFlags(),
- IdLoc(l), ReceiverLoc(sl), Receiver(st.getTypePtr()) {
+ : Expr(ObjCPropertyRefExprClass, t, VK, OK,
+ /*TypeDependent=*/false, false, st->isInstantiationDependentType(),
+ st->containsUnexpandedParameterPack()),
+ PropertyOrGetter(PD, false), IdLoc(l), ReceiverLoc(sl),
+ Receiver(st.getTypePtr()) {
assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject));
}
ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
QualType T, ExprValueKind VK, ExprObjectKind OK,
SourceLocation IdLoc, Expr *Base)
- : Expr(ObjCPropertyRefExprClass, T, VK, OK, false,
- Base->isValueDependent(), Base->isInstantiationDependent(),
- Base->containsUnexpandedParameterPack()),
- PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0),
- IdLoc(IdLoc), ReceiverLoc(), Receiver(Base) {
+ : Expr(ObjCPropertyRefExprClass, T, VK, OK, false,
+ Base->isValueDependent(), Base->isInstantiationDependent(),
+ Base->containsUnexpandedParameterPack()),
+ PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0),
+ IdLoc(IdLoc), Receiver(Base) {
assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject));
}
@@ -608,9 +645,9 @@ public:
QualType T, ExprValueKind VK, ExprObjectKind OK,
SourceLocation IdLoc,
SourceLocation SuperLoc, QualType SuperTy)
- : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false, false),
- PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0),
- IdLoc(IdLoc), ReceiverLoc(SuperLoc), Receiver(SuperTy.getTypePtr()) {
+ : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false, false),
+ PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0),
+ IdLoc(IdLoc), ReceiverLoc(SuperLoc), Receiver(SuperTy.getTypePtr()) {
assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject));
}
@@ -618,14 +655,14 @@ public:
QualType T, ExprValueKind VK, ExprObjectKind OK,
SourceLocation IdLoc,
SourceLocation ReceiverLoc, ObjCInterfaceDecl *Receiver)
- : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false, false),
- PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0),
- IdLoc(IdLoc), ReceiverLoc(ReceiverLoc), Receiver(Receiver) {
+ : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false, false),
+ PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0),
+ IdLoc(IdLoc), ReceiverLoc(ReceiverLoc), Receiver(Receiver) {
assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject));
}
explicit ObjCPropertyRefExpr(EmptyShell Empty)
- : Expr(ObjCPropertyRefExprClass, Empty) {}
+ : Expr(ObjCPropertyRefExprClass, Empty) {}
bool isImplicitProperty() const { return PropertyOrGetter.getInt(); }
bool isExplicitProperty() const { return !PropertyOrGetter.getInt(); }
@@ -689,6 +726,7 @@ public:
SourceLocation getLocation() const { return IdLoc; }
SourceLocation getReceiverLocation() const { return ReceiverLoc; }
+
QualType getSuperReceiverType() const {
return QualType(Receiver.get<const Type*>(), 0);
}
@@ -696,6 +734,7 @@ public:
ObjCInterfaceDecl *getClassReceiver() const {
return Receiver.get<ObjCInterfaceDecl*>();
}
+
bool isObjectReceiver() const { return Receiver.is<Stmt*>(); }
bool isSuperReceiver() const { return Receiver.is<const Type*>(); }
bool isClassReceiver() const { return Receiver.is<ObjCInterfaceDecl*>(); }
@@ -706,11 +745,8 @@ public:
SourceLocation getLocStart() const LLVM_READONLY {
return isObjectReceiver() ? getBase()->getLocStart() :getReceiverLocation();
}
- SourceLocation getLocEnd() const LLVM_READONLY { return IdLoc; }
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == ObjCPropertyRefExprClass;
- }
+ SourceLocation getLocEnd() const LLVM_READONLY { return IdLoc; }
// Iterators
child_range children() {
@@ -721,15 +757,21 @@ public:
return child_range(child_iterator(), child_iterator());
}
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCPropertyRefExprClass;
+ }
+
private:
friend class ASTStmtReader;
friend class ASTStmtWriter;
+
void setExplicitProperty(ObjCPropertyDecl *D, unsigned methRefFlags) {
PropertyOrGetter.setPointer(D);
PropertyOrGetter.setInt(false);
SetterAndMethodRefFlags.setPointer(nullptr);
SetterAndMethodRefFlags.setInt(methRefFlags);
}
+
void setImplicitProperty(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
unsigned methRefFlags) {
PropertyOrGetter.setPointer(Getter);
@@ -737,6 +779,7 @@ private:
SetterAndMethodRefFlags.setPointer(Setter);
SetterAndMethodRefFlags.setInt(methRefFlags);
}
+
void setBase(Expr *Base) { Receiver = Base; }
void setSuperReceiver(QualType T) { Receiver = T.getTypePtr(); }
void setClassReceiver(ObjCInterfaceDecl *D) { Receiver = D; }
@@ -756,10 +799,10 @@ private:
/// ObjCSubscriptRefExpr - used for array and dictionary subscripting.
/// array[4] = array[3]; dictionary[key] = dictionary[alt_key];
-///
class ObjCSubscriptRefExpr : public Expr {
// Location of ']' in an indexing expression.
SourceLocation RBracket;
+
// array/dictionary base expression.
// for arrays, this is a numeric expression. For dictionaries, this is
// an objective-c object pointer expression.
@@ -773,24 +816,24 @@ class ObjCSubscriptRefExpr : public Expr {
ObjCMethodDecl *SetAtIndexMethodDecl;
public:
-
ObjCSubscriptRefExpr(Expr *base, Expr *key, QualType T,
ExprValueKind VK, ExprObjectKind OK,
ObjCMethodDecl *getMethod,
ObjCMethodDecl *setMethod, SourceLocation RB)
- : Expr(ObjCSubscriptRefExprClass, T, VK, OK,
- base->isTypeDependent() || key->isTypeDependent(),
- base->isValueDependent() || key->isValueDependent(),
- base->isInstantiationDependent() || key->isInstantiationDependent(),
- (base->containsUnexpandedParameterPack() ||
- key->containsUnexpandedParameterPack())),
- RBracket(RB),
- GetAtIndexMethodDecl(getMethod),
- SetAtIndexMethodDecl(setMethod)
- {SubExprs[BASE] = base; SubExprs[KEY] = key;}
+ : Expr(ObjCSubscriptRefExprClass, T, VK, OK,
+ base->isTypeDependent() || key->isTypeDependent(),
+ base->isValueDependent() || key->isValueDependent(),
+ (base->isInstantiationDependent() ||
+ key->isInstantiationDependent()),
+ (base->containsUnexpandedParameterPack() ||
+ key->containsUnexpandedParameterPack())),
+ RBracket(RB), GetAtIndexMethodDecl(getMethod),
+ SetAtIndexMethodDecl(setMethod) {
+ SubExprs[BASE] = base; SubExprs[KEY] = key;
+ }
explicit ObjCSubscriptRefExpr(EmptyShell Empty)
- : Expr(ObjCSubscriptRefExprClass, Empty) {}
+ : Expr(ObjCSubscriptRefExprClass, Empty) {}
SourceLocation getRBracket() const { return RBracket; }
void setRBracket(SourceLocation RB) { RBracket = RB; }
@@ -798,11 +841,8 @@ public:
SourceLocation getLocStart() const LLVM_READONLY {
return SubExprs[BASE]->getLocStart();
}
- SourceLocation getLocEnd() const LLVM_READONLY { return RBracket; }
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == ObjCSubscriptRefExprClass;
- }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RBracket; }
Expr *getBaseExpr() const { return cast<Expr>(SubExprs[BASE]); }
void setBaseExpr(Stmt *S) { SubExprs[BASE] = S; }
@@ -825,10 +865,14 @@ public:
child_range children() {
return child_range(SubExprs, SubExprs+END_EXPR);
}
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCSubscriptRefExprClass;
+ }
+
private:
friend class ASTStmtReader;
};
-
/// \brief An expression that sends a message to the given Objective-C
/// object or class.
@@ -856,14 +900,13 @@ private:
/// The "void *" trailing objects are actually ONE void * (the
/// receiver pointer), and NumArgs Expr *. But due to the
/// implementation of children(), these must be together contiguously.
-
class ObjCMessageExpr final
: public Expr,
private llvm::TrailingObjects<ObjCMessageExpr, void *, SourceLocation> {
/// \brief Stores either the selector that this message is sending
/// to (when \c HasMethod is zero) or an \c ObjCMethodDecl pointer
/// referring to the method that we type-checked against.
- uintptr_t SelectorOrMethod;
+ uintptr_t SelectorOrMethod = 0;
enum { NumArgsBitWidth = 16 };
@@ -904,16 +947,9 @@ class ObjCMessageExpr final
/// brackets ('[' and ']', respectively).
SourceLocation LBracLoc, RBracLoc;
- size_t numTrailingObjects(OverloadToken<void *>) const { return NumArgs + 1; }
-
- void setNumArgs(unsigned Num) {
- assert((Num >> NumArgsBitWidth) == 0 && "Num of args is out of range!");
- NumArgs = Num;
- }
-
ObjCMessageExpr(EmptyShell Empty, unsigned NumArgs)
- : Expr(ObjCMessageExprClass, Empty), SelectorOrMethod(0), Kind(0),
- HasMethod(0), IsDelegateInitCall(0), IsImplicit(0), SelLocsKind(0) {
+ : Expr(ObjCMessageExprClass, Empty), Kind(0), HasMethod(false),
+ IsDelegateInitCall(false), IsImplicit(false), SelLocsKind(0) {
setNumArgs(NumArgs);
}
@@ -950,6 +986,13 @@ class ObjCMessageExpr final
SourceLocation RBracLoc,
bool isImplicit);
+ size_t numTrailingObjects(OverloadToken<void *>) const { return NumArgs + 1; }
+
+ void setNumArgs(unsigned Num) {
+ assert((Num >> NumArgsBitWidth) == 0 && "Num of args is out of range!");
+ NumArgs = Num;
+ }
+
void initArgsAndSelLocs(ArrayRef<Expr *> Args,
ArrayRef<SourceLocation> SelLocs,
SelectorLocationsKind SelLocsK);
@@ -965,6 +1008,7 @@ class ObjCMessageExpr final
SelectorLocationsKind getSelLocsKind() const {
return (SelectorLocationsKind)SelLocsKind;
}
+
bool hasStandardSelLocs() const {
return getSelLocsKind() != SelLoc_NonStandard;
}
@@ -997,14 +1041,21 @@ class ObjCMessageExpr final
unsigned NumStoredSelLocs);
public:
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+ friend TrailingObjects;
+
/// \brief The kind of receiver this message is sending to.
enum ReceiverKind {
/// \brief The receiver is a class.
Class = 0,
+
/// \brief The receiver is an object instance.
Instance,
+
/// \brief The receiver is a superclass.
SuperClass,
+
/// \brief The receiver is the instance of the superclass object.
SuperInstance
};
@@ -1029,7 +1080,7 @@ public:
/// \param Sel The selector used to determine which method gets called.
///
/// \param Method The Objective-C method against which this message
- /// send was type-checked. May be NULL.
+ /// send was type-checked. May be nullptr.
///
/// \param Args The message send arguments.
///
@@ -1065,7 +1116,7 @@ public:
/// \param Sel The selector used to determine which method gets called.
///
/// \param Method The Objective-C method against which this message
- /// send was type-checked. May be NULL.
+ /// send was type-checked. May be nullptr.
///
/// \param Args The message send arguments.
///
@@ -1099,7 +1150,7 @@ public:
/// \param Sel The selector used to determine which method gets called.
///
/// \param Method The Objective-C method against which this message
- /// send was type-checked. May be NULL.
+ /// send was type-checked. May be nullptr.
///
/// \param Args The message send arguments.
///
@@ -1175,11 +1226,11 @@ public:
if (TypeSourceInfo *TSInfo = getClassReceiverTypeInfo())
return TSInfo->getType();
- return QualType();
+ return {};
}
/// \brief Returns a type-source information of a class message
- /// send, or NULL if the message is not a class message.
+ /// send, or nullptr if the message is not a class message.
TypeSourceInfo *getClassReceiverTypeInfo() const {
if (getReceiverKind() == Class)
return reinterpret_cast<TypeSourceInfo *>(getReceiverPointer());
@@ -1220,7 +1271,7 @@ public:
/// whether the message is a class or an instance method, whether it
/// is a send to super or not, etc.
///
- /// \returns The Objective-C interface if known, otherwise NULL.
+ /// \returns The Objective-C interface if known, otherwise nullptr.
ObjCInterfaceDecl *getReceiverInterface() const;
/// \brief Retrieve the type referred to by 'super'.
@@ -1295,6 +1346,7 @@ public:
assert(Arg < NumArgs && "Arg access out of range!");
return getArgs()[Arg];
}
+
/// setArg - Set the specified argument.
void setArg(unsigned Arg, Expr *ArgExpr) {
assert(Arg < NumArgs && "Arg access out of range!");
@@ -1315,6 +1367,7 @@ public:
return getLocStart();
return getSelectorLoc(0);
}
+
SourceLocation getSelectorLoc(unsigned Index) const {
assert(Index < getNumSelectorLocs() && "Index out of range!");
if (hasStandardSelLocs())
@@ -1341,18 +1394,15 @@ public:
LBracLoc = R.getBegin();
RBracLoc = R.getEnd();
}
+
SourceLocation getLocStart() const LLVM_READONLY { return LBracLoc; }
SourceLocation getLocEnd() const LLVM_READONLY { return RBracLoc; }
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == ObjCMessageExprClass;
- }
-
// Iterators
child_range children();
- typedef ExprIterator arg_iterator;
- typedef ConstExprIterator const_arg_iterator;
+ using arg_iterator = ExprIterator;
+ using const_arg_iterator = ConstExprIterator;
llvm::iterator_range<arg_iterator> arguments() {
return llvm::make_range(arg_begin(), arg_end());
@@ -1363,19 +1413,22 @@ public:
}
arg_iterator arg_begin() { return reinterpret_cast<Stmt **>(getArgs()); }
+
arg_iterator arg_end() {
return reinterpret_cast<Stmt **>(getArgs() + NumArgs);
}
+
const_arg_iterator arg_begin() const {
return reinterpret_cast<Stmt const * const*>(getArgs());
}
+
const_arg_iterator arg_end() const {
return reinterpret_cast<Stmt const * const*>(getArgs() + NumArgs);
}
- friend TrailingObjects;
- friend class ASTStmtReader;
- friend class ASTStmtWriter;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCMessageExprClass;
+ }
};
/// ObjCIsaExpr - Represent X->isa and X.isa when X is an ObjC 'id' type.
@@ -1392,17 +1445,18 @@ class ObjCIsaExpr : public Expr {
/// IsArrow - True if this is "X->F", false if this is "X.F".
bool IsArrow;
+
public:
ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, SourceLocation oploc,
QualType ty)
- : Expr(ObjCIsaExprClass, ty, VK_LValue, OK_Ordinary,
- /*TypeDependent=*/false, base->isValueDependent(),
- base->isInstantiationDependent(),
- /*ContainsUnexpandedParameterPack=*/false),
- Base(base), IsaMemberLoc(l), OpLoc(oploc), IsArrow(isarrow) {}
+ : Expr(ObjCIsaExprClass, ty, VK_LValue, OK_Ordinary,
+ /*TypeDependent=*/false, base->isValueDependent(),
+ base->isInstantiationDependent(),
+ /*ContainsUnexpandedParameterPack=*/false),
+ Base(base), IsaMemberLoc(l), OpLoc(oploc), IsArrow(isarrow) {}
/// \brief Build an empty expression.
- explicit ObjCIsaExpr(EmptyShell Empty) : Expr(ObjCIsaExprClass, Empty) { }
+ explicit ObjCIsaExpr(EmptyShell Empty) : Expr(ObjCIsaExprClass, Empty) {}
void setBase(Expr *E) { Base = E; }
Expr *getBase() const { return cast<Expr>(Base); }
@@ -1430,15 +1484,14 @@ public:
SourceLocation getExprLoc() const LLVM_READONLY { return IsaMemberLoc; }
+ // Iterators
+ child_range children() { return child_range(&Base, &Base+1); }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCIsaExprClass;
}
-
- // Iterators
- child_range children() { return child_range(&Base, &Base+1); }
};
-
/// ObjCIndirectCopyRestoreExpr - Represents the passing of a function
/// argument by indirect copy-restore in ARC. This is used to support
/// passing indirect arguments with the wrong lifetime, e.g. when
@@ -1462,27 +1515,27 @@ public:
/// __autoreleasing; this qualifier is ignored when initializing
/// the value.
class ObjCIndirectCopyRestoreExpr : public Expr {
+ friend class ASTReader;
+ friend class ASTStmtReader;
+
Stmt *Operand;
// unsigned ObjCIndirectCopyRestoreBits.ShouldCopy : 1;
- friend class ASTReader;
- friend class ASTStmtReader;
+ explicit ObjCIndirectCopyRestoreExpr(EmptyShell Empty)
+ : Expr(ObjCIndirectCopyRestoreExprClass, Empty) {}
void setShouldCopy(bool shouldCopy) {
ObjCIndirectCopyRestoreExprBits.ShouldCopy = shouldCopy;
}
- explicit ObjCIndirectCopyRestoreExpr(EmptyShell Empty)
- : Expr(ObjCIndirectCopyRestoreExprClass, Empty) { }
-
public:
ObjCIndirectCopyRestoreExpr(Expr *operand, QualType type, bool shouldCopy)
- : Expr(ObjCIndirectCopyRestoreExprClass, type, VK_LValue, OK_Ordinary,
- operand->isTypeDependent(), operand->isValueDependent(),
- operand->isInstantiationDependent(),
- operand->containsUnexpandedParameterPack()),
- Operand(operand) {
+ : Expr(ObjCIndirectCopyRestoreExprClass, type, VK_LValue, OK_Ordinary,
+ operand->isTypeDependent(), operand->isValueDependent(),
+ operand->isInstantiationDependent(),
+ operand->containsUnexpandedParameterPack()),
+ Operand(operand) {
setShouldCopy(shouldCopy);
}
@@ -1519,26 +1572,26 @@ public:
class ObjCBridgedCastExpr final
: public ExplicitCastExpr,
private llvm::TrailingObjects<ObjCBridgedCastExpr, CXXBaseSpecifier *> {
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+ friend class CastExpr;
+ friend TrailingObjects;
+
SourceLocation LParenLoc;
SourceLocation BridgeKeywordLoc;
unsigned Kind : 2;
- friend TrailingObjects;
- friend class CastExpr;
- friend class ASTStmtReader;
- friend class ASTStmtWriter;
-
public:
ObjCBridgedCastExpr(SourceLocation LParenLoc, ObjCBridgeCastKind Kind,
CastKind CK, SourceLocation BridgeKeywordLoc,
TypeSourceInfo *TSInfo, Expr *Operand)
- : ExplicitCastExpr(ObjCBridgedCastExprClass, TSInfo->getType(), VK_RValue,
- CK, Operand, 0, TSInfo),
- LParenLoc(LParenLoc), BridgeKeywordLoc(BridgeKeywordLoc), Kind(Kind) { }
+ : ExplicitCastExpr(ObjCBridgedCastExprClass, TSInfo->getType(), VK_RValue,
+ CK, Operand, 0, TSInfo),
+ LParenLoc(LParenLoc), BridgeKeywordLoc(BridgeKeywordLoc), Kind(Kind) {}
/// \brief Construct an empty Objective-C bridged cast.
explicit ObjCBridgedCastExpr(EmptyShell Shell)
- : ExplicitCastExpr(ObjCBridgedCastExprClass, Shell, 0) { }
+ : ExplicitCastExpr(ObjCBridgedCastExprClass, Shell, 0) {}
SourceLocation getLParenLoc() const { return LParenLoc; }
@@ -1554,6 +1607,7 @@ public:
SourceLocation getBridgeKeywordLoc() const { return BridgeKeywordLoc; }
SourceLocation getLocStart() const LLVM_READONLY { return LParenLoc; }
+
SourceLocation getLocEnd() const LLVM_READONLY {
return getSubExpr()->getLocEnd();
}
@@ -1577,10 +1631,11 @@ public:
/// expressions.
///
class ObjCAvailabilityCheckExpr : public Expr {
+ friend class ASTStmtReader;
+
VersionTuple VersionToCheck;
SourceLocation AtLoc, RParen;
- friend class ASTStmtReader;
public:
ObjCAvailabilityCheckExpr(VersionTuple VersionToCheck, SourceLocation AtLoc,
SourceLocation RParen, QualType Ty)
@@ -1608,6 +1663,6 @@ public:
}
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_AST_EXPROBJC_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExternalASTMerger.h b/contrib/llvm/tools/clang/include/clang/AST/ExternalASTMerger.h
index 51d0c30ad23bf..81492aec6e13e 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ExternalASTMerger.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ExternalASTMerger.h
@@ -16,34 +16,159 @@
#include "clang/AST/ASTImporter.h"
#include "clang/AST/ExternalASTSource.h"
+#include "llvm/Support/raw_ostream.h"
namespace clang {
+/// ExternalASTSource implementation that merges information from several
+/// ASTContexts.
+///
+/// ExtermalASTMerger maintains a vector of ASTImporters that it uses to import
+/// (potentially incomplete) Decls and DeclContexts from the source ASTContexts
+/// in response to ExternalASTSource API calls.
+///
+/// When lookup occurs in the resulting imported DeclContexts, the original
+/// DeclContexts need to be queried. Roughly, there are three cases here:
+///
+/// - The DeclContext of origin can be found by simple name lookup. In this
+/// case, no additional state is required.
+///
+/// - The DeclContext of origin is different from what would be found by name
+/// lookup. In this case, Origins contains an entry overriding lookup and
+/// specifying the correct pair of DeclContext/ASTContext.
+///
+/// - The DeclContext of origin was determined by another ExterenalASTMerger.
+/// (This is possible when the source ASTContext for one of the Importers has
+/// its own ExternalASTMerger). The origin must be properly forwarded in this
+/// case.
+///
+/// ExternalASTMerger's job is to maintain the data structures necessary to
+/// allow this. The data structures themselves can be extracted (read-only) and
+/// copied for re-use.
class ExternalASTMerger : public ExternalASTSource {
public:
- struct ImporterPair {
- std::unique_ptr<ASTImporter> Forward;
- std::unique_ptr<ASTImporter> Reverse;
+ /// A single origin for a DeclContext. Unlike Decls, DeclContexts do
+ /// not allow their containing ASTContext to be determined in all cases.
+ struct DCOrigin {
+ DeclContext *DC;
+ ASTContext *AST;
};
+ typedef std::map<const DeclContext *, DCOrigin> OriginMap;
+ typedef std::vector<std::unique_ptr<ASTImporter>> ImporterVector;
private:
- std::vector<ImporterPair> Importers;
+ /// One importer exists for each source.
+ ImporterVector Importers;
+ /// Overrides in case name lookup would return nothing or would return
+ /// the wrong thing.
+ OriginMap Origins;
+ /// The installed log stream.
+ llvm::raw_ostream *LogStream;
public:
- struct ImporterEndpoint {
+ /// The target for an ExternalASTMerger.
+ ///
+ /// ASTImporters require both ASTContext and FileManager to be able to
+ /// import SourceLocations properly.
+ struct ImporterTarget {
ASTContext &AST;
FileManager &FM;
};
- ExternalASTMerger(const ImporterEndpoint &Target,
- llvm::ArrayRef<ImporterEndpoint> Sources);
+ /// A source for an ExternalASTMerger.
+ ///
+ /// ASTImporters require both ASTContext and FileManager to be able to
+ /// import SourceLocations properly. Additionally, when import occurs for
+ /// a DeclContext whose origin has been overridden, then this
+ /// ExternalASTMerger must be able to determine that.
+ struct ImporterSource {
+ ASTContext &AST;
+ FileManager &FM;
+ const OriginMap &OM;
+ };
+private:
+ /// The target for this ExtenralASTMerger.
+ ImporterTarget Target;
+
+public:
+ ExternalASTMerger(const ImporterTarget &Target,
+ llvm::ArrayRef<ImporterSource> Sources);
+
+ /// Add a set of ASTContexts as possible origins.
+ ///
+ /// Usually the set will be initialized in the constructor, but long-lived
+ /// ExternalASTMergers may neeed to import from new sources (for example,
+ /// newly-parsed source files).
+ ///
+ /// Ensures that Importers does not gain duplicate entries as a result.
+ void AddSources(llvm::ArrayRef<ImporterSource> Sources);
+
+ /// Remove a set of ASTContexts as possible origins.
+ ///
+ /// Sometimes an origin goes away (for example, if a source file gets
+ /// superseded by a newer version).
+ ///
+ /// The caller is responsible for ensuring that this doesn't leave
+ /// DeclContexts that can't be completed.
+ void RemoveSources(llvm::ArrayRef<ImporterSource> Sources);
+
+ /// Implementation of the ExternalASTSource API.
bool FindExternalVisibleDeclsByName(const DeclContext *DC,
DeclarationName Name) override;
+ /// Implementation of the ExternalASTSource API.
void
FindExternalLexicalDecls(const DeclContext *DC,
llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
SmallVectorImpl<Decl *> &Result) override;
+
+ /// Implementation of the ExternalASTSource API.
+ void CompleteType(TagDecl *Tag) override;
+
+ /// Implementation of the ExternalASTSource API.
+ void CompleteType(ObjCInterfaceDecl *Interface) override;
+
+ /// Returns true if DC can be found in any source AST context.
+ bool CanComplete(DeclContext *DC);
+
+ /// Records an origin in Origins only if name lookup would find
+ /// something different or nothing at all.
+ void MaybeRecordOrigin(const DeclContext *ToDC, DCOrigin Origin);
+
+ /// Regardless of any checks, override the Origin for a DeclContext.
+ void ForceRecordOrigin(const DeclContext *ToDC, DCOrigin Origin);
+
+ /// Get a read-only view of the Origins map, for use in constructing
+ /// an ImporterSource for another ExternalASTMerger.
+ const OriginMap &GetOrigins() { return Origins; }
+
+ /// Returns true if Importers contains an ASTImporter whose source is
+ /// OriginContext.
+ bool HasImporterForOrigin(ASTContext &OriginContext);
+
+ /// Returns a reference to the ASTRImporter from Importers whose origin
+ /// is OriginContext. This allows manual import of ASTs while preserving the
+ /// OriginMap correctly.
+ ASTImporter &ImporterForOrigin(ASTContext &OriginContext);
+
+ /// Sets the current log stream.
+ void SetLogStream(llvm::raw_string_ostream &Stream) { LogStream = &Stream; }
+private:
+ /// Records and origin in Origins.
+ void RecordOriginImpl(const DeclContext *ToDC, DCOrigin Origin,
+ ASTImporter &importer);
+
+ /// Performs an action for every DeclContext that is identified as
+ /// corresponding (either by forced origin or by name lookup) to DC.
+ template <typename CallbackType>
+ void ForEachMatchingDC(const DeclContext *DC, CallbackType Callback);
+
+public:
+ /// Log something if there is a logging callback installed.
+ llvm::raw_ostream &logs() { return *LogStream; }
+
+ /// True if the log stream is not llvm::nulls();
+ bool LoggingEnabled() { return LogStream != &llvm::nulls(); }
};
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h b/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h
index d8dd18ecb8d3b..be013c5d6b6a1 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h
@@ -1,4 +1,4 @@
-//===--- ExternalASTSource.h - Abstract External AST Interface --*- C++ -*-===//
+//===- ExternalASTSource.h - Abstract External AST Interface ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,24 +11,44 @@
// construction of AST nodes from some external source.
//
//===----------------------------------------------------------------------===//
+
#ifndef LLVM_CLANG_AST_EXTERNALASTSOURCE_H
#define LLVM_CLANG_AST_EXTERNALASTSOURCE_H
#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclBase.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/Module.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <iterator>
+#include <string>
+#include <utility>
namespace clang {
class ASTConsumer;
+class ASTContext;
class CXXBaseSpecifier;
class CXXCtorInitializer;
+class CXXRecordDecl;
class DeclarationName;
-class ExternalSemaSource; // layering violation required for downcasting
class FieldDecl;
-class Module;
+class IdentifierInfo;
class NamedDecl;
+class ObjCInterfaceDecl;
class RecordDecl;
class Selector;
class Stmt;
@@ -42,30 +62,31 @@ class TagDecl;
/// actual type and declaration nodes, and read parts of declaration
/// contexts.
class ExternalASTSource : public RefCountedBase<ExternalASTSource> {
+ friend class ExternalSemaSource;
+
/// Generation number for this external AST source. Must be increased
/// whenever we might have added new redeclarations for existing decls.
- uint32_t CurrentGeneration;
+ uint32_t CurrentGeneration = 0;
/// \brief Whether this AST source also provides information for
/// semantic analysis.
- bool SemaSource;
-
- friend class ExternalSemaSource;
+ bool SemaSource = false;
public:
- ExternalASTSource() : CurrentGeneration(0), SemaSource(false) { }
-
+ ExternalASTSource() = default;
virtual ~ExternalASTSource();
/// \brief RAII class for safely pairing a StartedDeserializing call
/// with FinishedDeserializing.
class Deserializing {
ExternalASTSource *Source;
+
public:
explicit Deserializing(ExternalASTSource *source) : Source(source) {
assert(Source);
Source->StartedDeserializing();
}
+
~Deserializing() {
Source->FinishedDeserializing();
}
@@ -122,7 +143,7 @@ public:
virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset);
/// \brief Update an out-of-date identifier.
- virtual void updateOutOfDateIdentifier(IdentifierInfo &II) { }
+ virtual void updateOutOfDateIdentifier(IdentifierInfo &II) {}
/// \brief Find all declarations with the given name in the given context,
/// and add them to the context by calling SetExternalVisibleDeclsForName
@@ -154,12 +175,13 @@ public:
const Module *ClangModule = nullptr;
public:
- ASTSourceDescriptor(){};
+ ASTSourceDescriptor() = default;
ASTSourceDescriptor(StringRef Name, StringRef Path, StringRef ASTFile,
ASTFileSignature Signature)
: PCHModuleName(std::move(Name)), Path(std::move(Path)),
- ASTFile(std::move(ASTFile)), Signature(Signature){};
+ ASTFile(std::move(ASTFile)), Signature(Signature) {}
ASTSourceDescriptor(const Module &M);
+
std::string getModuleName() const;
StringRef getPath() const { return Path; }
StringRef getASTFile() const { return ASTFile; }
@@ -246,7 +268,6 @@ public:
/// The default implementation of this method is a no-op.
virtual void PrintStats();
-
/// \brief Perform layout on the given record.
///
/// This routine allows the external AST source to provide an specific
@@ -289,7 +310,7 @@ public:
size_t mmap_bytes;
MemoryBufferSizes(size_t malloc_bytes, size_t mmap_bytes)
- : malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {}
+ : malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {}
};
/// Return the amount of memory used by memory buffers, breaking down
@@ -329,12 +350,12 @@ struct LazyOffsetPtr {
///
/// If the low bit is clear, a pointer to the AST node. If the low
/// bit is set, the upper 63 bits are the offset.
- mutable uint64_t Ptr;
+ mutable uint64_t Ptr = 0;
public:
- LazyOffsetPtr() : Ptr(0) { }
+ LazyOffsetPtr() = default;
+ explicit LazyOffsetPtr(T *Ptr) : Ptr(reinterpret_cast<uint64_t>(Ptr)) {}
- explicit LazyOffsetPtr(T *Ptr) : Ptr(reinterpret_cast<uint64_t>(Ptr)) { }
explicit LazyOffsetPtr(uint64_t Offset) : Ptr((Offset << 1) | 0x01) {
assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits");
if (Offset == 0)
@@ -392,15 +413,16 @@ struct LazyGenerationalUpdatePtr {
/// A cache of the value of this pointer, in the most recent generation in
/// which we queried it.
struct LazyData {
- LazyData(ExternalASTSource *Source, T Value)
- : ExternalSource(Source), LastGeneration(0), LastValue(Value) {}
ExternalASTSource *ExternalSource;
- uint32_t LastGeneration;
+ uint32_t LastGeneration = 0;
T LastValue;
+
+ LazyData(ExternalASTSource *Source, T Value)
+ : ExternalSource(Source), LastValue(Value) {}
};
// Our value is represented as simply T if there is no external AST source.
- typedef llvm::PointerUnion<T, LazyData*> ValueType;
+ using ValueType = llvm::PointerUnion<T, LazyData*>;
ValueType Value;
LazyGenerationalUpdatePtr(ValueType V) : Value(V) {}
@@ -459,25 +481,31 @@ public:
return LazyGenerationalUpdatePtr(ValueType::getFromOpaqueValue(Ptr));
}
};
-} // end namespace clang
+
+} // namespace clang
/// Specialize PointerLikeTypeTraits to allow LazyGenerationalUpdatePtr to be
/// placed into a PointerUnion.
namespace llvm {
+
template<typename Owner, typename T,
void (clang::ExternalASTSource::*Update)(Owner)>
struct PointerLikeTypeTraits<
clang::LazyGenerationalUpdatePtr<Owner, T, Update>> {
- typedef clang::LazyGenerationalUpdatePtr<Owner, T, Update> Ptr;
+ using Ptr = clang::LazyGenerationalUpdatePtr<Owner, T, Update>;
+
static void *getAsVoidPointer(Ptr P) { return P.getOpaqueValue(); }
static Ptr getFromVoidPointer(void *P) { return Ptr::getFromOpaqueValue(P); }
+
enum {
NumLowBitsAvailable = PointerLikeTypeTraits<T>::NumLowBitsAvailable - 1
};
};
-}
+
+} // namespace llvm
namespace clang {
+
/// \brief Represents a lazily-loaded vector of data.
///
/// The lazily-loaded vector of data contains data that is partially loaded
@@ -511,13 +539,14 @@ public:
class iterator
: public llvm::iterator_adaptor_base<
iterator, int, std::random_access_iterator_tag, T, int, T *, T &> {
+ friend class LazyVector;
+
LazyVector *Self;
iterator(LazyVector *Self, int Position)
: iterator::iterator_adaptor_base(Position), Self(Self) {}
bool isLoaded() const { return this->I < 0; }
- friend class LazyVector;
public:
iterator() : iterator(nullptr, 0) {}
@@ -562,23 +591,23 @@ public:
};
/// \brief A lazy pointer to a statement.
-typedef LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt>
- LazyDeclStmtPtr;
+using LazyDeclStmtPtr =
+ LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt>;
/// \brief A lazy pointer to a declaration.
-typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl>
- LazyDeclPtr;
+using LazyDeclPtr =
+ LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl>;
/// \brief A lazy pointer to a set of CXXCtorInitializers.
-typedef LazyOffsetPtr<CXXCtorInitializer *, uint64_t,
- &ExternalASTSource::GetExternalCXXCtorInitializers>
- LazyCXXCtorInitializersPtr;
+using LazyCXXCtorInitializersPtr =
+ LazyOffsetPtr<CXXCtorInitializer *, uint64_t,
+ &ExternalASTSource::GetExternalCXXCtorInitializers>;
/// \brief A lazy pointer to a set of CXXBaseSpecifiers.
-typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t,
- &ExternalASTSource::GetExternalCXXBaseSpecifiers>
- LazyCXXBaseSpecifiersPtr;
+using LazyCXXBaseSpecifiersPtr =
+ LazyOffsetPtr<CXXBaseSpecifier, uint64_t,
+ &ExternalASTSource::GetExternalCXXBaseSpecifiers>;
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_AST_EXTERNALASTSOURCE_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/GlobalDecl.h b/contrib/llvm/tools/clang/include/clang/AST/GlobalDecl.h
index adf63a3aea69c..3b3e4367d56c3 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/GlobalDecl.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/GlobalDecl.h
@@ -1,4 +1,4 @@
-//===--- GlobalDecl.h - Global declaration holder ---------------*- C++ -*-===//
+//===- GlobalDecl.h - Global declaration holder -----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -19,6 +19,12 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclOpenMP.h"
#include "clang/Basic/ABI.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/type_traits.h"
+#include <cassert>
namespace clang {
@@ -27,7 +33,7 @@ namespace clang {
/// a CXXDestructorDecl and the destructor type (Base, Complete) or
/// a VarDecl, a FunctionDecl or a BlockDecl.
class GlobalDecl {
- llvm::PointerIntPair<const Decl*, 2> Value;
+ llvm::PointerIntPair<const Decl *, 2> Value;
void Init(const Decl *D) {
assert(!isa<CXXConstructorDecl>(D) && "Use other ctor with ctor decls!");
@@ -37,19 +43,15 @@ class GlobalDecl {
}
public:
- GlobalDecl() {}
-
+ GlobalDecl() = default;
GlobalDecl(const VarDecl *D) { Init(D);}
GlobalDecl(const FunctionDecl *D) { Init(D); }
GlobalDecl(const BlockDecl *D) { Init(D); }
GlobalDecl(const CapturedDecl *D) { Init(D); }
GlobalDecl(const ObjCMethodDecl *D) { Init(D); }
GlobalDecl(const OMPDeclareReductionDecl *D) { Init(D); }
-
- GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type)
- : Value(D, Type) {}
- GlobalDecl(const CXXDestructorDecl *D, CXXDtorType Type)
- : Value(D, Type) {}
+ GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type) : Value(D, Type) {}
+ GlobalDecl(const CXXDestructorDecl *D, CXXDtorType Type) : Value(D, Type) {}
GlobalDecl getCanonicalDecl() const {
GlobalDecl CanonGD;
@@ -90,10 +92,9 @@ public:
}
};
-} // end namespace clang
+} // namespace clang
namespace llvm {
- template<class> struct DenseMapInfo;
template<> struct DenseMapInfo<clang::GlobalDecl> {
static inline clang::GlobalDecl getEmptyKey() {
@@ -113,7 +114,6 @@ namespace llvm {
clang::GlobalDecl RHS) {
return LHS == RHS;
}
-
};
// GlobalDecl isn't *technically* a POD type. However, its copy constructor,
@@ -122,6 +122,7 @@ namespace llvm {
struct isPodLike<clang::GlobalDecl> {
static const bool value = true;
};
-} // end namespace llvm
-#endif
+} // namespace llvm
+
+#endif // LLVM_CLANG_AST_GLOBALDECL_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/LexicallyOrderedRecursiveASTVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/LexicallyOrderedRecursiveASTVisitor.h
new file mode 100644
index 0000000000000..264f20f19ad5b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/LexicallyOrderedRecursiveASTVisitor.h
@@ -0,0 +1,164 @@
+//===--- LexicallyOrderedRecursiveASTVisitor.h - ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the LexicallyOrderedRecursiveASTVisitor interface, which
+// recursively traverses the entire AST in a lexical order.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_LEXICALLY_ORDERED_RECURSIVEASTVISITOR_H
+#define LLVM_CLANG_AST_LEXICALLY_ORDERED_RECURSIVEASTVISITOR_H
+
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/Support/SaveAndRestore.h"
+
+namespace clang {
+
+/// A RecursiveASTVisitor subclass that guarantees that AST traversal is
+/// performed in a lexical order (i.e. the order in which declarations are
+/// written in the source).
+///
+/// RecursiveASTVisitor doesn't guarantee lexical ordering because there are
+/// some declarations, like Objective-C @implementation declarations
+/// that might be represented in the AST differently to how they were written
+/// in the source.
+/// In particular, Objective-C @implementation declarations may contain
+/// non-Objective-C declarations, like functions:
+///
+/// @implementation MyClass
+///
+/// - (void) method { }
+/// void normalFunction() { }
+///
+/// @end
+///
+/// Clang's AST stores these declarations outside of the @implementation
+/// declaration, so the example above would be represented using the following
+/// AST:
+/// |-ObjCImplementationDecl ... MyClass
+/// | `-ObjCMethodDecl ... method
+/// | ...
+/// `-FunctionDecl ... normalFunction
+/// ...
+///
+/// This class ensures that these declarations are traversed before the
+/// corresponding TraverseDecl for the @implementation returns. This ensures
+/// that the lexical parent relationship between these declarations and the
+/// @implementation is preserved while traversing the AST. Note that the
+/// current implementation doesn't mix these declarations with the declarations
+/// contained in the @implementation, so the traversal of all of the
+/// declarations in the @implementation still doesn't follow the lexical order.
+template <typename Derived>
+class LexicallyOrderedRecursiveASTVisitor
+ : public RecursiveASTVisitor<Derived> {
+ using BaseType = RecursiveASTVisitor<Derived>;
+
+public:
+ LexicallyOrderedRecursiveASTVisitor(const SourceManager &SM) : SM(SM) {}
+
+ bool TraverseObjCImplementationDecl(ObjCImplementationDecl *D) {
+ // Objective-C @implementation declarations should not trigger early exit
+ // until the additional decls are traversed as their children are not
+ // lexically ordered.
+ bool Result = BaseType::TraverseObjCImplementationDecl(D);
+ return TraverseAdditionalLexicallyNestedDeclarations() ? Result : false;
+ }
+
+ bool TraverseObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
+ bool Result = BaseType::TraverseObjCCategoryImplDecl(D);
+ return TraverseAdditionalLexicallyNestedDeclarations() ? Result : false;
+ }
+
+ bool TraverseDeclContextHelper(DeclContext *DC) {
+ if (!DC)
+ return true;
+
+ for (auto I = DC->decls_begin(), E = DC->decls_end(); I != E;) {
+ Decl *Child = *I;
+ if (BaseType::canIgnoreChildDeclWhileTraversingDeclContext(Child)) {
+ ++I;
+ continue;
+ }
+ if (!isa<ObjCImplementationDecl>(Child) &&
+ !isa<ObjCCategoryImplDecl>(Child)) {
+ if (!BaseType::getDerived().TraverseDecl(Child))
+ return false;
+ ++I;
+ continue;
+ }
+ // Gather declarations that follow the Objective-C implementation
+ // declarations but are lexically contained in the implementation.
+ LexicallyNestedDeclarations.clear();
+ for (++I; I != E; ++I) {
+ Decl *Sibling = *I;
+ if (!SM.isBeforeInTranslationUnit(Sibling->getLocStart(),
+ Child->getLocEnd()))
+ break;
+ if (!BaseType::canIgnoreChildDeclWhileTraversingDeclContext(Sibling))
+ LexicallyNestedDeclarations.push_back(Sibling);
+ }
+ if (!BaseType::getDerived().TraverseDecl(Child))
+ return false;
+ }
+ return true;
+ }
+
+ Stmt::child_range getStmtChildren(Stmt *S) { return S->children(); }
+
+ SmallVector<Stmt *, 8> getStmtChildren(CXXOperatorCallExpr *CE) {
+ SmallVector<Stmt *, 8> Children(CE->children());
+ bool Swap;
+ // Switch the operator and the first operand for all infix and postfix
+ // operations.
+ switch (CE->getOperator()) {
+ case OO_Arrow:
+ case OO_Call:
+ case OO_Subscript:
+ Swap = true;
+ break;
+ case OO_PlusPlus:
+ case OO_MinusMinus:
+ // These are postfix unless there is exactly one argument.
+ Swap = Children.size() != 2;
+ break;
+ default:
+ Swap = CE->isInfixBinaryOp();
+ break;
+ }
+ if (Swap && Children.size() > 1)
+ std::swap(Children[0], Children[1]);
+ return Children;
+ }
+
+private:
+ bool TraverseAdditionalLexicallyNestedDeclarations() {
+ // FIXME: Ideally the gathered declarations and the declarations in the
+ // @implementation should be mixed and sorted to get a true lexical order,
+ // but right now we only care about getting the correct lexical parent, so
+ // we can traverse the gathered nested declarations after the declarations
+ // in the decl context.
+ assert(!BaseType::getDerived().shouldTraversePostOrder() &&
+ "post-order traversal is not supported for lexically ordered "
+ "recursive ast visitor");
+ for (Decl *D : LexicallyNestedDeclarations) {
+ if (!BaseType::getDerived().TraverseDecl(D))
+ return false;
+ }
+ return true;
+ }
+
+ const SourceManager &SM;
+ llvm::SmallVector<Decl *, 8> LexicallyNestedDeclarations;
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_AST_LEXICALLY_ORDERED_RECURSIVEASTVISITOR_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h b/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h
index b1ff9bdff5891..e2cb45c36de6b 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h
@@ -1,4 +1,4 @@
-//===--- NestedNameSpecifier.h - C++ nested name specifiers -----*- C++ -*-===//
+//===- NestedNameSpecifier.h - C++ nested name specifiers -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,38 +11,42 @@
// a C++ nested-name-specifier.
//
//===----------------------------------------------------------------------===//
+
#ifndef LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H
#define LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/Support/Compiler.h"
+#include <cstdint>
+#include <cstdlib>
+#include <utility>
namespace clang {
class ASTContext;
class CXXRecordDecl;
+class IdentifierInfo;
+class LangOptions;
class NamespaceAliasDecl;
class NamespaceDecl;
-class IdentifierInfo;
struct PrintingPolicy;
class Type;
class TypeLoc;
-class LangOptions;
/// \brief Represents a C++ nested name specifier, such as
/// "\::std::vector<int>::".
///
/// C++ nested name specifiers are the prefixes to qualified
-/// namespaces. For example, "foo::" in "foo::x" is a nested name
+/// names. For example, "foo::" in "foo::x" is a nested name
/// specifier. Nested name specifiers are made up of a sequence of
/// specifiers, each of which can be a namespace, type, identifier
/// (for dependent names), decltype specifier, or the global specifier ('::').
/// The last two specifiers can only appear at the start of a
/// nested-namespace-specifier.
class NestedNameSpecifier : public llvm::FoldingSetNode {
-
/// \brief Enumeration describing
enum StoredSpecifierKind {
StoredIdentifier = 0,
@@ -66,7 +70,7 @@ class NestedNameSpecifier : public llvm::FoldingSetNode {
/// specifier '::'. Otherwise, the pointer is one of
/// IdentifierInfo*, Namespace*, or Type*, depending on the kind of
/// specifier as encoded within the prefix.
- void* Specifier;
+ void* Specifier = nullptr;
public:
/// \brief The kind of specifier that completes this nested name
@@ -74,17 +78,23 @@ public:
enum SpecifierKind {
/// \brief An identifier, stored as an IdentifierInfo*.
Identifier,
+
/// \brief A namespace, stored as a NamespaceDecl*.
Namespace,
+
/// \brief A namespace alias, stored as a NamespaceAliasDecl*.
NamespaceAlias,
+
/// \brief A type, stored as a Type*.
TypeSpec,
+
/// \brief A type that was preceded by the 'template' keyword,
/// stored as a Type*.
TypeSpecWithTemplate,
+
/// \brief The global specifier '::'. There is no stored value.
Global,
+
/// \brief Microsoft's '__super' specifier, stored as a CXXRecordDecl* of
/// the class it appeared in.
Super
@@ -92,17 +102,11 @@ public:
private:
/// \brief Builds the global specifier.
- NestedNameSpecifier()
- : Prefix(nullptr, StoredIdentifier), Specifier(nullptr) {}
+ NestedNameSpecifier() : Prefix(nullptr, StoredIdentifier) {}
/// \brief Copy constructor used internally to clone nested name
/// specifiers.
- NestedNameSpecifier(const NestedNameSpecifier &Other)
- : llvm::FoldingSetNode(Other), Prefix(Other.Prefix),
- Specifier(Other.Specifier) {
- }
-
- void operator=(const NestedNameSpecifier &) = delete;
+ NestedNameSpecifier(const NestedNameSpecifier &Other) = default;
/// \brief Either find or insert the given nested name specifier
/// mockup in the given context.
@@ -110,6 +114,8 @@ private:
const NestedNameSpecifier &Mockup);
public:
+ NestedNameSpecifier &operator=(const NestedNameSpecifier &) = delete;
+
/// \brief Builds a specifier combining a prefix and an identifier.
///
/// The prefix must be dependent, since nested name specifiers
@@ -224,8 +230,8 @@ public:
/// \brief A C++ nested-name-specifier augmented with source location
/// information.
class NestedNameSpecifierLoc {
- NestedNameSpecifier *Qualifier;
- void *Data;
+ NestedNameSpecifier *Qualifier = nullptr;
+ void *Data = nullptr;
/// \brief Determines the data length for the last component in the
/// given nested-name-specifier.
@@ -237,12 +243,12 @@ class NestedNameSpecifierLoc {
public:
/// \brief Construct an empty nested-name-specifier.
- NestedNameSpecifierLoc() : Qualifier(nullptr), Data(nullptr) { }
+ NestedNameSpecifierLoc() = default;
/// \brief Construct a nested-name-specifier with source location information
/// from
NestedNameSpecifierLoc(NestedNameSpecifier *Qualifier, void *Data)
- : Qualifier(Qualifier), Data(Data) { }
+ : Qualifier(Qualifier), Data(Data) {}
/// \brief Evalutes true when this nested-name-specifier location is
/// non-empty.
@@ -339,7 +345,7 @@ public:
class NestedNameSpecifierLocBuilder {
/// \brief The current representation of the nested-name-specifier we're
/// building.
- NestedNameSpecifier *Representation;
+ NestedNameSpecifier *Representation = nullptr;
/// \brief Buffer used to store source-location information for the
/// nested-name-specifier.
@@ -347,21 +353,18 @@ class NestedNameSpecifierLocBuilder {
/// Note that we explicitly manage the buffer (rather than using a
/// SmallVector) because \c Declarator expects it to be possible to memcpy()
/// a \c CXXScopeSpec, and CXXScopeSpec uses a NestedNameSpecifierLocBuilder.
- char *Buffer;
+ char *Buffer = nullptr;
/// \brief The size of the buffer used to store source-location information
/// for the nested-name-specifier.
- unsigned BufferSize;
+ unsigned BufferSize = 0;
/// \brief The capacity of the buffer used to store source-location
/// information for the nested-name-specifier.
- unsigned BufferCapacity;
+ unsigned BufferCapacity = 0;
public:
- NestedNameSpecifierLocBuilder()
- : Representation(nullptr), Buffer(nullptr), BufferSize(0),
- BufferCapacity(0) {}
-
+ NestedNameSpecifierLocBuilder() = default;
NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other);
NestedNameSpecifierLocBuilder &
@@ -451,6 +454,7 @@ public:
/// \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.
///
@@ -511,6 +515,6 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
return DB;
}
-}
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/OpenMPClause.h b/contrib/llvm/tools/clang/include/clang/AST/OpenMPClause.h
index a1cae8e18f84e..1f732f67517a4 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/OpenMPClause.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/OpenMPClause.h
@@ -6,35 +6,55 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+//
/// \file
/// \brief This file defines OpenMP AST classes for clauses.
/// There are clauses for executable directives, clauses for declarative
/// directives and clauses which can be used in both kinds of directives.
-///
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_OPENMPCLAUSE_H
#define LLVM_CLANG_AST_OPENMPCLAUSE_H
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtIterator.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/OpenMPKinds.h"
#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/TrailingObjects.h"
+#include <cassert>
+#include <cstddef>
+#include <iterator>
+#include <utility>
namespace clang {
+class ASTContext;
+
//===----------------------------------------------------------------------===//
// AST classes for clauses.
//===----------------------------------------------------------------------===//
/// \brief This is a basic class for representing single OpenMP clause.
-///
class OMPClause {
/// \brief Starting location of the clause (the clause keyword).
SourceLocation StartLoc;
+
/// \brief Ending location of the clause.
SourceLocation EndLoc;
+
/// \brief Kind of the clause.
OpenMPClauseKind Kind;
@@ -45,11 +65,13 @@ protected:
public:
/// \brief Returns the starting location of the clause.
SourceLocation getLocStart() const { return StartLoc; }
+
/// \brief Returns the ending location of the clause.
SourceLocation getLocEnd() const { return EndLoc; }
/// \brief Sets the starting location of the clause.
void setLocStart(SourceLocation Loc) { StartLoc = Loc; }
+
/// \brief Sets the ending location of the clause.
void setLocEnd(SourceLocation Loc) { EndLoc = Loc; }
@@ -58,16 +80,17 @@ public:
bool isImplicit() const { return StartLoc.isInvalid(); }
- typedef StmtIterator child_iterator;
- typedef ConstStmtIterator const_child_iterator;
- typedef llvm::iterator_range<child_iterator> child_range;
- typedef llvm::iterator_range<const_child_iterator> const_child_range;
+ using child_iterator = StmtIterator;
+ using const_child_iterator = ConstStmtIterator;
+ using child_range = llvm::iterator_range<child_iterator>;
+ using const_child_range = llvm::iterator_range<const_child_iterator>;
child_range children();
const_child_range children() const {
auto Children = const_cast<OMPClause *>(this)->children();
return const_child_range(Children.begin(), Children.end());
}
+
static bool classof(const OMPClause *) { return true; }
};
@@ -75,29 +98,34 @@ public:
/// 'shedule', 'firstprivate' etc.
class OMPClauseWithPreInit {
friend class OMPClauseReader;
+
/// Pre-initialization statement for the clause.
- Stmt *PreInit;
+ Stmt *PreInit = nullptr;
+
/// Region that captures the associated stmt.
- OpenMPDirectiveKind CaptureRegion;
+ OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
protected:
+ OMPClauseWithPreInit(const OMPClause *This) {
+ assert(get(This) && "get is not tuned for pre-init.");
+ }
+
/// Set pre-initialization statement for the clause.
void setPreInitStmt(Stmt *S, OpenMPDirectiveKind ThisRegion = OMPD_unknown) {
PreInit = S;
CaptureRegion = ThisRegion;
}
- OMPClauseWithPreInit(const OMPClause *This)
- : PreInit(nullptr), CaptureRegion(OMPD_unknown) {
- assert(get(This) && "get is not tuned for pre-init.");
- }
public:
/// Get pre-initialization statement for the clause.
const Stmt *getPreInitStmt() const { return PreInit; }
+
/// Get pre-initialization statement for the clause.
Stmt *getPreInitStmt() { return PreInit; }
+
/// Get capture region for the stmt in the clause.
OpenMPDirectiveKind getCaptureRegion() { return CaptureRegion; }
+
static OMPClauseWithPreInit *get(OMPClause *C);
static const OMPClauseWithPreInit *get(const OMPClause *C);
};
@@ -106,21 +134,25 @@ public:
/// 'lastprivate', 'reduction' etc.
class OMPClauseWithPostUpdate : public OMPClauseWithPreInit {
friend class OMPClauseReader;
+
/// Post-update expression for the clause.
- Expr *PostUpdate;
+ Expr *PostUpdate = nullptr;
+
protected:
- /// Set pre-initialization statement for the clause.
- void setPostUpdateExpr(Expr *S) { PostUpdate = S; }
- OMPClauseWithPostUpdate(const OMPClause *This)
- : OMPClauseWithPreInit(This), PostUpdate(nullptr) {
+ OMPClauseWithPostUpdate(const OMPClause *This) : OMPClauseWithPreInit(This) {
assert(get(This) && "get is not tuned for post-update.");
}
+ /// Set pre-initialization statement for the clause.
+ void setPostUpdateExpr(Expr *S) { PostUpdate = S; }
+
public:
/// Get post-update expression for the clause.
const Expr *getPostUpdateExpr() const { return PostUpdate; }
+
/// Get post-update expression for the clause.
Expr *getPostUpdateExpr() { return PostUpdate; }
+
static OMPClauseWithPostUpdate *get(OMPClause *C);
static const OMPClauseWithPostUpdate *get(const OMPClause *C);
};
@@ -130,12 +162,25 @@ public:
/// '#pragma omp ...' directives.
template <class T> class OMPVarListClause : public OMPClause {
friend class OMPClauseReader;
+
/// \brief Location of '('.
SourceLocation LParenLoc;
+
/// \brief Number of variables in the list.
unsigned NumVars;
protected:
+ /// \brief Build a clause with \a N variables
+ ///
+ /// \param K Kind of the clause.
+ /// \param StartLoc Starting location of the clause (the clause keyword).
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param N Number of the variables in the clause.
+ OMPVarListClause(OpenMPClauseKind K, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc, unsigned N)
+ : OMPClause(K, StartLoc, EndLoc), LParenLoc(LParenLoc), NumVars(N) {}
+
/// \brief Fetches list of variables associated with this clause.
MutableArrayRef<Expr *> getVarRefs() {
return MutableArrayRef<Expr *>(
@@ -150,23 +195,11 @@ protected:
static_cast<T *>(this)->template getTrailingObjects<Expr *>());
}
- /// \brief Build a clause with \a N variables
- ///
- /// \param K Kind of the clause.
- /// \param StartLoc Starting location of the clause (the clause keyword).
- /// \param LParenLoc Location of '('.
- /// \param EndLoc Ending location of the clause.
- /// \param N Number of the variables in the clause.
- ///
- OMPVarListClause(OpenMPClauseKind K, SourceLocation StartLoc,
- SourceLocation LParenLoc, SourceLocation EndLoc, unsigned N)
- : OMPClause(K, StartLoc, EndLoc), LParenLoc(LParenLoc), NumVars(N) {}
-
public:
- typedef MutableArrayRef<Expr *>::iterator varlist_iterator;
- typedef ArrayRef<const Expr *>::iterator varlist_const_iterator;
- typedef llvm::iterator_range<varlist_iterator> varlist_range;
- typedef llvm::iterator_range<varlist_const_iterator> varlist_const_range;
+ using varlist_iterator = MutableArrayRef<Expr *>::iterator;
+ using varlist_const_iterator = ArrayRef<const Expr *>::iterator;
+ using varlist_range = llvm::iterator_range<varlist_iterator>;
+ using varlist_const_range = llvm::iterator_range<varlist_const_iterator>;
unsigned varlist_size() const { return NumVars; }
bool varlist_empty() const { return NumVars == 0; }
@@ -185,6 +218,7 @@ public:
/// \brief Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+
/// \brief Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
@@ -203,31 +237,34 @@ public:
/// \endcode
/// In this example directive '#pragma omp parallel' has simple 'if' clause with
/// condition 'a > 5' and directive name modifier 'parallel'.
-///
class OMPIfClause : public OMPClause, public OMPClauseWithPreInit {
friend class OMPClauseReader;
+
/// \brief Location of '('.
SourceLocation LParenLoc;
+
/// \brief Condition of the 'if' clause.
- Stmt *Condition;
+ Stmt *Condition = nullptr;
+
/// \brief Location of ':' (if any).
SourceLocation ColonLoc;
+
/// \brief Directive name modifier for the clause.
- OpenMPDirectiveKind NameModifier;
+ OpenMPDirectiveKind NameModifier = OMPD_unknown;
+
/// \brief Name modifier location.
SourceLocation NameModifierLoc;
/// \brief Set condition.
- ///
void setCondition(Expr *Cond) { Condition = Cond; }
+
/// \brief Set directive name modifier for the clause.
- ///
void setNameModifier(OpenMPDirectiveKind NM) { NameModifier = NM; }
+
/// \brief Set location of directive name modifier for the clause.
- ///
void setNameModifierLoc(SourceLocation Loc) { NameModifierLoc = Loc; }
+
/// \brief Set location of ':'.
- ///
void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
public:
@@ -243,7 +280,6 @@ public:
/// \param NameModifierLoc Location of directive name modifier.
/// \param ColonLoc [OpenMP 4.1] Location of ':'.
/// \param EndLoc Ending location of the clause.
- ///
OMPIfClause(OpenMPDirectiveKind NameModifier, Expr *Cond, Stmt *HelperCond,
OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation NameModifierLoc,
@@ -255,14 +291,13 @@ public:
}
/// \brief Build an empty clause.
- ///
OMPIfClause()
: OMPClause(OMPC_if, SourceLocation(), SourceLocation()),
- OMPClauseWithPreInit(this), LParenLoc(), Condition(nullptr), ColonLoc(),
- NameModifier(OMPD_unknown), NameModifierLoc() {}
+ OMPClauseWithPreInit(this) {}
/// \brief Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+
/// \brief Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
@@ -271,17 +306,18 @@ public:
/// \brief Returns condition.
Expr *getCondition() const { return cast_or_null<Expr>(Condition); }
+
/// \brief Return directive name modifier associated with the clause.
OpenMPDirectiveKind getNameModifier() const { return NameModifier; }
/// \brief Return the location of directive name modifier.
SourceLocation getNameModifierLoc() const { return NameModifierLoc; }
+ child_range children() { return child_range(&Condition, &Condition + 1); }
+
static bool classof(const OMPClause *T) {
return T->getClauseKind() == OMPC_if;
}
-
- child_range children() { return child_range(&Condition, &Condition + 1); }
};
/// \brief This represents 'final' clause in the '#pragma omp ...' directive.
@@ -291,16 +327,16 @@ public:
/// \endcode
/// In this example directive '#pragma omp task' has simple 'final'
/// clause with condition 'a > 5'.
-///
class OMPFinalClause : public OMPClause {
friend class OMPClauseReader;
+
/// \brief Location of '('.
SourceLocation LParenLoc;
+
/// \brief Condition of the 'if' clause.
- Stmt *Condition;
+ Stmt *Condition = nullptr;
/// \brief Set condition.
- ///
void setCondition(Expr *Cond) { Condition = Cond; }
public:
@@ -310,31 +346,29 @@ public:
/// \param LParenLoc Location of '('.
/// \param Cond Condition of the clause.
/// \param EndLoc Ending location of the clause.
- ///
OMPFinalClause(Expr *Cond, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc)
: OMPClause(OMPC_final, StartLoc, EndLoc), LParenLoc(LParenLoc),
Condition(Cond) {}
/// \brief Build an empty clause.
- ///
OMPFinalClause()
- : OMPClause(OMPC_final, SourceLocation(), SourceLocation()),
- LParenLoc(SourceLocation()), Condition(nullptr) {}
+ : OMPClause(OMPC_final, SourceLocation(), SourceLocation()) {}
/// \brief Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+
/// \brief Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
/// \brief Returns condition.
Expr *getCondition() const { return cast_or_null<Expr>(Condition); }
+ child_range children() { return child_range(&Condition, &Condition + 1); }
+
static bool classof(const OMPClause *T) {
return T->getClauseKind() == OMPC_final;
}
-
- child_range children() { return child_range(&Condition, &Condition + 1); }
};
/// \brief This represents 'num_threads' clause in the '#pragma omp ...'
@@ -345,16 +379,16 @@ public:
/// \endcode
/// In this example directive '#pragma omp parallel' has simple 'num_threads'
/// clause with number of threads '6'.
-///
class OMPNumThreadsClause : public OMPClause, public OMPClauseWithPreInit {
friend class OMPClauseReader;
+
/// \brief Location of '('.
SourceLocation LParenLoc;
+
/// \brief Condition of the 'num_threads' clause.
- Stmt *NumThreads;
+ Stmt *NumThreads = nullptr;
/// \brief Set condition.
- ///
void setNumThreads(Expr *NThreads) { NumThreads = NThreads; }
public:
@@ -367,7 +401,6 @@ public:
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
- ///
OMPNumThreadsClause(Expr *NumThreads, Stmt *HelperNumThreads,
OpenMPDirectiveKind CaptureRegion,
SourceLocation StartLoc, SourceLocation LParenLoc,
@@ -379,25 +412,24 @@ public:
}
/// \brief Build an empty clause.
- ///
OMPNumThreadsClause()
: OMPClause(OMPC_num_threads, SourceLocation(), SourceLocation()),
- OMPClauseWithPreInit(this), LParenLoc(SourceLocation()),
- NumThreads(nullptr) {}
+ OMPClauseWithPreInit(this) {}
/// \brief Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+
/// \brief Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
/// \brief Returns number of threads.
Expr *getNumThreads() const { return cast_or_null<Expr>(NumThreads); }
+ child_range children() { return child_range(&NumThreads, &NumThreads + 1); }
+
static bool classof(const OMPClause *T) {
return T->getClauseKind() == OMPC_num_threads;
}
-
- child_range children() { return child_range(&NumThreads, &NumThreads + 1); }
};
/// \brief This represents 'safelen' clause in the '#pragma omp ...'
@@ -412,13 +444,14 @@ public:
/// concurrently with SIMD instructions can have a greater distance
/// in the logical iteration space than its value. The parameter of
/// the safelen clause must be a constant positive integer expression.
-///
class OMPSafelenClause : public OMPClause {
friend class OMPClauseReader;
+
/// \brief Location of '('.
SourceLocation LParenLoc;
+
/// \brief Safe iteration space distance.
- Stmt *Safelen;
+ Stmt *Safelen = nullptr;
/// \brief Set safelen.
void setSafelen(Expr *Len) { Safelen = Len; }
@@ -429,31 +462,29 @@ public:
/// \param Len Expression associated with this clause.
/// \param StartLoc Starting location of the clause.
/// \param EndLoc Ending location of the clause.
- ///
OMPSafelenClause(Expr *Len, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc)
: OMPClause(OMPC_safelen, StartLoc, EndLoc), LParenLoc(LParenLoc),
Safelen(Len) {}
/// \brief Build an empty clause.
- ///
explicit OMPSafelenClause()
- : OMPClause(OMPC_safelen, SourceLocation(), SourceLocation()),
- LParenLoc(SourceLocation()), Safelen(nullptr) {}
+ : OMPClause(OMPC_safelen, SourceLocation(), SourceLocation()) {}
/// \brief Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+
/// \brief Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
/// \brief Return safe iteration space distance.
Expr *getSafelen() const { return cast_or_null<Expr>(Safelen); }
+ child_range children() { return child_range(&Safelen, &Safelen + 1); }
+
static bool classof(const OMPClause *T) {
return T->getClauseKind() == OMPC_safelen;
}
-
- child_range children() { return child_range(&Safelen, &Safelen + 1); }
};
/// \brief This represents 'simdlen' clause in the '#pragma omp ...'
@@ -467,13 +498,14 @@ public:
/// If the 'simdlen' clause is used then it specifies the preferred number of
/// iterations to be executed concurrently. The parameter of the 'simdlen'
/// clause must be a constant positive integer expression.
-///
class OMPSimdlenClause : public OMPClause {
friend class OMPClauseReader;
+
/// \brief Location of '('.
SourceLocation LParenLoc;
+
/// \brief Safe iteration space distance.
- Stmt *Simdlen;
+ Stmt *Simdlen = nullptr;
/// \brief Set simdlen.
void setSimdlen(Expr *Len) { Simdlen = Len; }
@@ -484,31 +516,29 @@ public:
/// \param Len Expression associated with this clause.
/// \param StartLoc Starting location of the clause.
/// \param EndLoc Ending location of the clause.
- ///
OMPSimdlenClause(Expr *Len, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc)
: OMPClause(OMPC_simdlen, StartLoc, EndLoc), LParenLoc(LParenLoc),
Simdlen(Len) {}
/// \brief Build an empty clause.
- ///
explicit OMPSimdlenClause()
- : OMPClause(OMPC_simdlen, SourceLocation(), SourceLocation()),
- LParenLoc(SourceLocation()), Simdlen(nullptr) {}
+ : OMPClause(OMPC_simdlen, SourceLocation(), SourceLocation()) {}
/// \brief Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+
/// \brief Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
/// \brief Return safe iteration space distance.
Expr *getSimdlen() const { return cast_or_null<Expr>(Simdlen); }
+ child_range children() { return child_range(&Simdlen, &Simdlen + 1); }
+
static bool classof(const OMPClause *T) {
return T->getClauseKind() == OMPC_simdlen;
}
-
- child_range children() { return child_range(&Simdlen, &Simdlen + 1); }
};
/// \brief This represents 'collapse' clause in the '#pragma omp ...'
@@ -522,13 +552,14 @@ public:
/// The parameter must be a constant positive integer expression, it specifies
/// the number of nested loops that should be collapsed into a single iteration
/// space.
-///
class OMPCollapseClause : public OMPClause {
friend class OMPClauseReader;
+
/// \brief Location of '('.
SourceLocation LParenLoc;
+
/// \brief Number of for-loops.
- Stmt *NumForLoops;
+ Stmt *NumForLoops = nullptr;
/// \brief Set the number of associated for-loops.
void setNumForLoops(Expr *Num) { NumForLoops = Num; }
@@ -540,31 +571,29 @@ public:
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
- ///
OMPCollapseClause(Expr *Num, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation EndLoc)
: OMPClause(OMPC_collapse, StartLoc, EndLoc), LParenLoc(LParenLoc),
NumForLoops(Num) {}
/// \brief Build an empty clause.
- ///
explicit OMPCollapseClause()
- : OMPClause(OMPC_collapse, SourceLocation(), SourceLocation()),
- LParenLoc(SourceLocation()), NumForLoops(nullptr) {}
+ : OMPClause(OMPC_collapse, SourceLocation(), SourceLocation()) {}
/// \brief Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+
/// \brief Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
/// \brief Return the number of associated for-loops.
Expr *getNumForLoops() const { return cast_or_null<Expr>(NumForLoops); }
+ child_range children() { return child_range(&NumForLoops, &NumForLoops + 1); }
+
static bool classof(const OMPClause *T) {
return T->getClauseKind() == OMPC_collapse;
}
-
- child_range children() { return child_range(&NumForLoops, &NumForLoops + 1); }
};
/// \brief This represents 'default' clause in the '#pragma omp ...' directive.
@@ -574,26 +603,26 @@ public:
/// \endcode
/// In this example directive '#pragma omp parallel' has simple 'default'
/// clause with kind 'shared'.
-///
class OMPDefaultClause : public OMPClause {
friend class OMPClauseReader;
+
/// \brief Location of '('.
SourceLocation LParenLoc;
+
/// \brief A kind of the 'default' clause.
- OpenMPDefaultClauseKind Kind;
+ OpenMPDefaultClauseKind Kind = OMPC_DEFAULT_unknown;
+
/// \brief Start location of the kind in source code.
SourceLocation KindKwLoc;
/// \brief Set kind of the clauses.
///
/// \param K Argument of clause.
- ///
void setDefaultKind(OpenMPDefaultClauseKind K) { Kind = K; }
/// \brief Set argument location.
///
/// \param KLoc Argument location.
- ///
void setDefaultKindKwLoc(SourceLocation KLoc) { KindKwLoc = KLoc; }
public:
@@ -604,7 +633,6 @@ public:
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
- ///
OMPDefaultClause(OpenMPDefaultClauseKind A, SourceLocation ALoc,
SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc)
@@ -612,14 +640,12 @@ public:
Kind(A), KindKwLoc(ALoc) {}
/// \brief Build an empty clause.
- ///
OMPDefaultClause()
- : OMPClause(OMPC_default, SourceLocation(), SourceLocation()),
- LParenLoc(SourceLocation()), Kind(OMPC_DEFAULT_unknown),
- KindKwLoc(SourceLocation()) {}
+ : OMPClause(OMPC_default, SourceLocation(), SourceLocation()) {}
/// \brief Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+
/// \brief Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
@@ -629,13 +655,13 @@ public:
/// \brief Returns location of clause kind.
SourceLocation getDefaultKindKwLoc() const { return KindKwLoc; }
- static bool classof(const OMPClause *T) {
- return T->getClauseKind() == OMPC_default;
- }
-
child_range children() {
return child_range(child_iterator(), child_iterator());
}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_default;
+ }
};
/// \brief This represents 'proc_bind' clause in the '#pragma omp ...'
@@ -646,26 +672,26 @@ public:
/// \endcode
/// In this example directive '#pragma omp parallel' has simple 'proc_bind'
/// clause with kind 'master'.
-///
class OMPProcBindClause : public OMPClause {
friend class OMPClauseReader;
+
/// \brief Location of '('.
SourceLocation LParenLoc;
+
/// \brief A kind of the 'proc_bind' clause.
- OpenMPProcBindClauseKind Kind;
+ OpenMPProcBindClauseKind Kind = OMPC_PROC_BIND_unknown;
+
/// \brief Start location of the kind in source code.
SourceLocation KindKwLoc;
/// \brief Set kind of the clause.
///
/// \param K Kind of clause.
- ///
void setProcBindKind(OpenMPProcBindClauseKind K) { Kind = K; }
/// \brief Set clause kind location.
///
/// \param KLoc Kind location.
- ///
void setProcBindKindKwLoc(SourceLocation KLoc) { KindKwLoc = KLoc; }
public:
@@ -677,7 +703,6 @@ public:
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
- ///
OMPProcBindClause(OpenMPProcBindClauseKind A, SourceLocation ALoc,
SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc)
@@ -685,14 +710,12 @@ public:
Kind(A), KindKwLoc(ALoc) {}
/// \brief Build an empty clause.
- ///
OMPProcBindClause()
- : OMPClause(OMPC_proc_bind, SourceLocation(), SourceLocation()),
- LParenLoc(SourceLocation()), Kind(OMPC_PROC_BIND_unknown),
- KindKwLoc(SourceLocation()) {}
+ : OMPClause(OMPC_proc_bind, SourceLocation(), SourceLocation()) {}
/// \brief Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+
/// \brief Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
@@ -702,13 +725,13 @@ public:
/// \brief Returns location of clause kind.
SourceLocation getProcBindKindKwLoc() const { return KindKwLoc; }
- static bool classof(const OMPClause *T) {
- return T->getClauseKind() == OMPC_proc_bind;
- }
-
child_range children() {
return child_range(child_iterator(), child_iterator());
}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_proc_bind;
+ }
};
/// \brief This represents 'schedule' clause in the '#pragma omp ...' directive.
@@ -718,58 +741,63 @@ public:
/// \endcode
/// In this example directive '#pragma omp for' has 'schedule' clause with
/// arguments 'static' and '3'.
-///
class OMPScheduleClause : public OMPClause, public OMPClauseWithPreInit {
friend class OMPClauseReader;
+
/// \brief Location of '('.
SourceLocation LParenLoc;
+
/// \brief A kind of the 'schedule' clause.
- OpenMPScheduleClauseKind Kind;
+ OpenMPScheduleClauseKind Kind = OMPC_SCHEDULE_unknown;
+
/// \brief Modifiers for 'schedule' clause.
enum {FIRST, SECOND, NUM_MODIFIERS};
OpenMPScheduleClauseModifier Modifiers[NUM_MODIFIERS];
+
/// \brief Locations of modifiers.
SourceLocation ModifiersLoc[NUM_MODIFIERS];
+
/// \brief Start location of the schedule ind in source code.
SourceLocation KindLoc;
+
/// \brief Location of ',' (if any).
SourceLocation CommaLoc;
+
/// \brief Chunk size.
- Expr *ChunkSize;
+ Expr *ChunkSize = nullptr;
/// \brief Set schedule kind.
///
/// \param K Schedule kind.
- ///
void setScheduleKind(OpenMPScheduleClauseKind K) { Kind = K; }
+
/// \brief Set the first schedule modifier.
///
/// \param M Schedule modifier.
- ///
void setFirstScheduleModifier(OpenMPScheduleClauseModifier M) {
Modifiers[FIRST] = M;
}
+
/// \brief Set the second schedule modifier.
///
/// \param M Schedule modifier.
- ///
void setSecondScheduleModifier(OpenMPScheduleClauseModifier M) {
Modifiers[SECOND] = M;
}
+
/// \brief Set location of the first schedule modifier.
- ///
void setFirstScheduleModifierLoc(SourceLocation Loc) {
ModifiersLoc[FIRST] = Loc;
}
+
/// \brief Set location of the second schedule modifier.
- ///
void setSecondScheduleModifierLoc(SourceLocation Loc) {
ModifiersLoc[SECOND] = Loc;
}
+
/// \brief Set schedule modifier location.
///
/// \param M Schedule modifier location.
- ///
void setScheduleModifer(OpenMPScheduleClauseModifier M) {
if (Modifiers[FIRST] == OMPC_SCHEDULE_MODIFIER_unknown)
Modifiers[FIRST] = M;
@@ -778,25 +806,25 @@ class OMPScheduleClause : public OMPClause, public OMPClauseWithPreInit {
Modifiers[SECOND] = M;
}
}
+
/// \brief Sets the location of '('.
///
/// \param Loc Location of '('.
- ///
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+
/// \brief Set schedule kind start location.
///
/// \param KLoc Schedule kind location.
- ///
void setScheduleKindLoc(SourceLocation KLoc) { KindLoc = KLoc; }
+
/// \brief Set location of ','.
///
/// \param Loc Location of ','.
- ///
void setCommaLoc(SourceLocation Loc) { CommaLoc = Loc; }
+
/// \brief Set chunk size.
///
/// \param E Chunk size.
- ///
void setChunkSize(Expr *E) { ChunkSize = E; }
public:
@@ -815,7 +843,6 @@ public:
/// \param M1Loc Location of the first modifier
/// \param M2 The second modifier applied to 'schedule' clause.
/// \param M2Loc Location of the second modifier
- ///
OMPScheduleClause(SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation KLoc, SourceLocation CommaLoc,
SourceLocation EndLoc, OpenMPScheduleClauseKind Kind,
@@ -833,62 +860,59 @@ public:
}
/// \brief Build an empty clause.
- ///
explicit OMPScheduleClause()
: OMPClause(OMPC_schedule, SourceLocation(), SourceLocation()),
- OMPClauseWithPreInit(this), Kind(OMPC_SCHEDULE_unknown),
- ChunkSize(nullptr) {
+ OMPClauseWithPreInit(this) {
Modifiers[FIRST] = OMPC_SCHEDULE_MODIFIER_unknown;
Modifiers[SECOND] = OMPC_SCHEDULE_MODIFIER_unknown;
}
/// \brief Get kind of the clause.
- ///
OpenMPScheduleClauseKind getScheduleKind() const { return Kind; }
+
/// \brief Get the first modifier of the clause.
- ///
OpenMPScheduleClauseModifier getFirstScheduleModifier() const {
return Modifiers[FIRST];
}
+
/// \brief Get the second modifier of the clause.
- ///
OpenMPScheduleClauseModifier getSecondScheduleModifier() const {
return Modifiers[SECOND];
}
+
/// \brief Get location of '('.
- ///
SourceLocation getLParenLoc() { return LParenLoc; }
+
/// \brief Get kind location.
- ///
SourceLocation getScheduleKindLoc() { return KindLoc; }
+
/// \brief Get the first modifier location.
- ///
SourceLocation getFirstScheduleModifierLoc() const {
return ModifiersLoc[FIRST];
}
+
/// \brief Get the second modifier location.
- ///
SourceLocation getSecondScheduleModifierLoc() const {
return ModifiersLoc[SECOND];
}
+
/// \brief Get location of ','.
- ///
SourceLocation getCommaLoc() { return CommaLoc; }
+
/// \brief Get chunk size.
- ///
Expr *getChunkSize() { return ChunkSize; }
+
/// \brief Get chunk size.
- ///
const Expr *getChunkSize() const { return ChunkSize; }
- static bool classof(const OMPClause *T) {
- return T->getClauseKind() == OMPC_schedule;
- }
-
child_range children() {
return child_range(reinterpret_cast<Stmt **>(&ChunkSize),
reinterpret_cast<Stmt **>(&ChunkSize) + 1);
}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_schedule;
+ }
};
/// \brief This represents 'ordered' clause in the '#pragma omp ...' directive.
@@ -898,13 +922,14 @@ public:
/// \endcode
/// In this example directive '#pragma omp for' has 'ordered' clause with
/// parameter 2.
-///
class OMPOrderedClause : public OMPClause {
friend class OMPClauseReader;
+
/// \brief Location of '('.
SourceLocation LParenLoc;
+
/// \brief Number of for-loops.
- Stmt *NumForLoops;
+ Stmt *NumForLoops = nullptr;
/// \brief Set the number of associated for-loops.
void setNumForLoops(Expr *Num) { NumForLoops = Num; }
@@ -916,31 +941,29 @@ public:
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
- ///
OMPOrderedClause(Expr *Num, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation EndLoc)
: OMPClause(OMPC_ordered, StartLoc, EndLoc), LParenLoc(LParenLoc),
NumForLoops(Num) {}
/// \brief Build an empty clause.
- ///
explicit OMPOrderedClause()
- : OMPClause(OMPC_ordered, SourceLocation(), SourceLocation()),
- LParenLoc(SourceLocation()), NumForLoops(nullptr) {}
+ : OMPClause(OMPC_ordered, SourceLocation(), SourceLocation()) {}
/// \brief Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+
/// \brief Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
/// \brief Return the number of associated for-loops.
Expr *getNumForLoops() const { return cast_or_null<Expr>(NumForLoops); }
+ child_range children() { return child_range(&NumForLoops, &NumForLoops + 1); }
+
static bool classof(const OMPClause *T) {
return T->getClauseKind() == OMPC_ordered;
}
-
- child_range children() { return child_range(&NumForLoops, &NumForLoops + 1); }
};
/// \brief This represents 'nowait' clause in the '#pragma omp ...' directive.
@@ -949,29 +972,26 @@ public:
/// #pragma omp for nowait
/// \endcode
/// In this example directive '#pragma omp for' has 'nowait' clause.
-///
class OMPNowaitClause : public OMPClause {
public:
/// \brief Build 'nowait' clause.
///
/// \param StartLoc Starting location of the clause.
/// \param EndLoc Ending location of the clause.
- ///
OMPNowaitClause(SourceLocation StartLoc, SourceLocation EndLoc)
: OMPClause(OMPC_nowait, StartLoc, EndLoc) {}
/// \brief Build an empty clause.
- ///
OMPNowaitClause()
: OMPClause(OMPC_nowait, SourceLocation(), SourceLocation()) {}
- static bool classof(const OMPClause *T) {
- return T->getClauseKind() == OMPC_nowait;
- }
-
child_range children() {
return child_range(child_iterator(), child_iterator());
}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_nowait;
+ }
};
/// \brief This represents 'untied' clause in the '#pragma omp ...' directive.
@@ -980,29 +1000,26 @@ public:
/// #pragma omp task untied
/// \endcode
/// In this example directive '#pragma omp task' has 'untied' clause.
-///
class OMPUntiedClause : public OMPClause {
public:
/// \brief Build 'untied' clause.
///
/// \param StartLoc Starting location of the clause.
/// \param EndLoc Ending location of the clause.
- ///
OMPUntiedClause(SourceLocation StartLoc, SourceLocation EndLoc)
: OMPClause(OMPC_untied, StartLoc, EndLoc) {}
/// \brief Build an empty clause.
- ///
OMPUntiedClause()
: OMPClause(OMPC_untied, SourceLocation(), SourceLocation()) {}
- static bool classof(const OMPClause *T) {
- return T->getClauseKind() == OMPC_untied;
- }
-
child_range children() {
return child_range(child_iterator(), child_iterator());
}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_untied;
+ }
};
/// \brief This represents 'mergeable' clause in the '#pragma omp ...'
@@ -1012,29 +1029,26 @@ public:
/// #pragma omp task mergeable
/// \endcode
/// In this example directive '#pragma omp task' has 'mergeable' clause.
-///
class OMPMergeableClause : public OMPClause {
public:
/// \brief Build 'mergeable' clause.
///
/// \param StartLoc Starting location of the clause.
/// \param EndLoc Ending location of the clause.
- ///
OMPMergeableClause(SourceLocation StartLoc, SourceLocation EndLoc)
: OMPClause(OMPC_mergeable, StartLoc, EndLoc) {}
/// \brief Build an empty clause.
- ///
OMPMergeableClause()
: OMPClause(OMPC_mergeable, SourceLocation(), SourceLocation()) {}
- static bool classof(const OMPClause *T) {
- return T->getClauseKind() == OMPC_mergeable;
- }
-
child_range children() {
return child_range(child_iterator(), child_iterator());
}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_mergeable;
+ }
};
/// \brief This represents 'read' clause in the '#pragma omp atomic' directive.
@@ -1043,28 +1057,25 @@ public:
/// #pragma omp atomic read
/// \endcode
/// In this example directive '#pragma omp atomic' has 'read' clause.
-///
class OMPReadClause : public OMPClause {
public:
/// \brief Build 'read' clause.
///
/// \param StartLoc Starting location of the clause.
/// \param EndLoc Ending location of the clause.
- ///
OMPReadClause(SourceLocation StartLoc, SourceLocation EndLoc)
: OMPClause(OMPC_read, StartLoc, EndLoc) {}
/// \brief Build an empty clause.
- ///
OMPReadClause() : OMPClause(OMPC_read, SourceLocation(), SourceLocation()) {}
- static bool classof(const OMPClause *T) {
- return T->getClauseKind() == OMPC_read;
- }
-
child_range children() {
return child_range(child_iterator(), child_iterator());
}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_read;
+ }
};
/// \brief This represents 'write' clause in the '#pragma omp atomic' directive.
@@ -1073,29 +1084,26 @@ public:
/// #pragma omp atomic write
/// \endcode
/// In this example directive '#pragma omp atomic' has 'write' clause.
-///
class OMPWriteClause : public OMPClause {
public:
/// \brief Build 'write' clause.
///
/// \param StartLoc Starting location of the clause.
/// \param EndLoc Ending location of the clause.
- ///
OMPWriteClause(SourceLocation StartLoc, SourceLocation EndLoc)
: OMPClause(OMPC_write, StartLoc, EndLoc) {}
/// \brief Build an empty clause.
- ///
OMPWriteClause()
: OMPClause(OMPC_write, SourceLocation(), SourceLocation()) {}
- static bool classof(const OMPClause *T) {
- return T->getClauseKind() == OMPC_write;
- }
-
child_range children() {
return child_range(child_iterator(), child_iterator());
}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_write;
+ }
};
/// \brief This represents 'update' clause in the '#pragma omp atomic'
@@ -1105,29 +1113,26 @@ public:
/// #pragma omp atomic update
/// \endcode
/// In this example directive '#pragma omp atomic' has 'update' clause.
-///
class OMPUpdateClause : public OMPClause {
public:
/// \brief Build 'update' clause.
///
/// \param StartLoc Starting location of the clause.
/// \param EndLoc Ending location of the clause.
- ///
OMPUpdateClause(SourceLocation StartLoc, SourceLocation EndLoc)
: OMPClause(OMPC_update, StartLoc, EndLoc) {}
/// \brief Build an empty clause.
- ///
OMPUpdateClause()
: OMPClause(OMPC_update, SourceLocation(), SourceLocation()) {}
- static bool classof(const OMPClause *T) {
- return T->getClauseKind() == OMPC_update;
- }
-
child_range children() {
return child_range(child_iterator(), child_iterator());
}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_update;
+ }
};
/// \brief This represents 'capture' clause in the '#pragma omp atomic'
@@ -1137,29 +1142,26 @@ public:
/// #pragma omp atomic capture
/// \endcode
/// In this example directive '#pragma omp atomic' has 'capture' clause.
-///
class OMPCaptureClause : public OMPClause {
public:
/// \brief Build 'capture' clause.
///
/// \param StartLoc Starting location of the clause.
/// \param EndLoc Ending location of the clause.
- ///
OMPCaptureClause(SourceLocation StartLoc, SourceLocation EndLoc)
: OMPClause(OMPC_capture, StartLoc, EndLoc) {}
/// \brief Build an empty clause.
- ///
OMPCaptureClause()
: OMPClause(OMPC_capture, SourceLocation(), SourceLocation()) {}
- static bool classof(const OMPClause *T) {
- return T->getClauseKind() == OMPC_capture;
- }
-
child_range children() {
return child_range(child_iterator(), child_iterator());
}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_capture;
+ }
};
/// \brief This represents 'seq_cst' clause in the '#pragma omp atomic'
@@ -1169,29 +1171,26 @@ public:
/// #pragma omp atomic seq_cst
/// \endcode
/// In this example directive '#pragma omp atomic' has 'seq_cst' clause.
-///
class OMPSeqCstClause : public OMPClause {
public:
/// \brief Build 'seq_cst' clause.
///
/// \param StartLoc Starting location of the clause.
/// \param EndLoc Ending location of the clause.
- ///
OMPSeqCstClause(SourceLocation StartLoc, SourceLocation EndLoc)
: OMPClause(OMPC_seq_cst, StartLoc, EndLoc) {}
/// \brief Build an empty clause.
- ///
OMPSeqCstClause()
: OMPClause(OMPC_seq_cst, SourceLocation(), SourceLocation()) {}
- static bool classof(const OMPClause *T) {
- return T->getClauseKind() == OMPC_seq_cst;
- }
-
child_range children() {
return child_range(child_iterator(), child_iterator());
}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_seq_cst;
+ }
};
/// \brief This represents clause 'private' in the '#pragma omp ...' directives.
@@ -1201,20 +1200,19 @@ public:
/// \endcode
/// In this example directive '#pragma omp parallel' has clause 'private'
/// with the variables 'a' and 'b'.
-///
class OMPPrivateClause final
: public OMPVarListClause<OMPPrivateClause>,
private llvm::TrailingObjects<OMPPrivateClause, Expr *> {
- friend TrailingObjects;
- friend OMPVarListClause;
friend class OMPClauseReader;
+ friend OMPVarListClause;
+ friend TrailingObjects;
+
/// \brief Build clause with number of variables \a N.
///
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
/// \param N Number of the variables in the clause.
- ///
OMPPrivateClause(SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, unsigned N)
: OMPVarListClause<OMPPrivateClause>(OMPC_private, StartLoc, LParenLoc,
@@ -1223,7 +1221,6 @@ class OMPPrivateClause final
/// \brief Build an empty clause.
///
/// \param N Number of variables.
- ///
explicit OMPPrivateClause(unsigned N)
: OMPVarListClause<OMPPrivateClause>(OMPC_private, SourceLocation(),
SourceLocation(), SourceLocation(),
@@ -1252,28 +1249,28 @@ public:
/// \param EndLoc Ending location of the clause.
/// \param VL List of references to the variables.
/// \param PrivateVL List of references to private copies with initializers.
- ///
static OMPPrivateClause *Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc, ArrayRef<Expr *> VL,
ArrayRef<Expr *> PrivateVL);
+
/// \brief Creates an empty clause with the place for \a N variables.
///
/// \param C AST context.
/// \param N The number of variables.
- ///
static OMPPrivateClause *CreateEmpty(const ASTContext &C, unsigned N);
- typedef MutableArrayRef<Expr *>::iterator private_copies_iterator;
- typedef ArrayRef<const Expr *>::iterator private_copies_const_iterator;
- typedef llvm::iterator_range<private_copies_iterator> private_copies_range;
- typedef llvm::iterator_range<private_copies_const_iterator>
- private_copies_const_range;
+ using private_copies_iterator = MutableArrayRef<Expr *>::iterator;
+ using private_copies_const_iterator = ArrayRef<const Expr *>::iterator;
+ using private_copies_range = llvm::iterator_range<private_copies_iterator>;
+ using private_copies_const_range =
+ llvm::iterator_range<private_copies_const_iterator>;
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());
@@ -1297,14 +1294,13 @@ public:
/// \endcode
/// In this example directive '#pragma omp parallel' has clause 'firstprivate'
/// with the variables 'a' and 'b'.
-///
class OMPFirstprivateClause final
: public OMPVarListClause<OMPFirstprivateClause>,
public OMPClauseWithPreInit,
private llvm::TrailingObjects<OMPFirstprivateClause, Expr *> {
- friend TrailingObjects;
- friend OMPVarListClause;
friend class OMPClauseReader;
+ friend OMPVarListClause;
+ friend TrailingObjects;
/// \brief Build clause with number of variables \a N.
///
@@ -1312,7 +1308,6 @@ class OMPFirstprivateClause final
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
/// \param N Number of the variables in the clause.
- ///
OMPFirstprivateClause(SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, unsigned N)
: OMPVarListClause<OMPFirstprivateClause>(OMPC_firstprivate, StartLoc,
@@ -1322,12 +1317,12 @@ class OMPFirstprivateClause final
/// \brief Build an empty clause.
///
/// \param N Number of variables.
- ///
explicit OMPFirstprivateClause(unsigned N)
: OMPVarListClause<OMPFirstprivateClause>(
OMPC_firstprivate, SourceLocation(), SourceLocation(),
SourceLocation(), N),
OMPClauseWithPreInit(this) {}
+
/// \brief Sets the list of references to private copies with initializers for
/// new private variables.
/// \param VL List of references.
@@ -1370,23 +1365,22 @@ public:
/// of array type.
/// \param PreInit Statement that must be executed before entering the OpenMP
/// region with this clause.
- ///
static OMPFirstprivateClause *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> PrivateVL,
ArrayRef<Expr *> InitVL, Stmt *PreInit);
+
/// \brief Creates an empty clause with the place for \a N variables.
///
/// \param C AST context.
/// \param N The number of variables.
- ///
static OMPFirstprivateClause *CreateEmpty(const ASTContext &C, unsigned N);
- typedef MutableArrayRef<Expr *>::iterator private_copies_iterator;
- typedef ArrayRef<const Expr *>::iterator private_copies_const_iterator;
- typedef llvm::iterator_range<private_copies_iterator> private_copies_range;
- typedef llvm::iterator_range<private_copies_const_iterator>
- private_copies_const_range;
+ using private_copies_iterator = MutableArrayRef<Expr *>::iterator;
+ using private_copies_const_iterator = ArrayRef<const Expr *>::iterator;
+ using private_copies_range = llvm::iterator_range<private_copies_iterator>;
+ using private_copies_const_range =
+ llvm::iterator_range<private_copies_const_iterator>;
private_copies_range private_copies() {
return private_copies_range(getPrivateCopies().begin(),
@@ -1397,10 +1391,10 @@ public:
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;
+ using inits_iterator = MutableArrayRef<Expr *>::iterator;
+ using inits_const_iterator = ArrayRef<const Expr *>::iterator;
+ using inits_range = llvm::iterator_range<inits_iterator>;
+ using inits_const_range = llvm::iterator_range<inits_const_iterator>;
inits_range inits() {
return inits_range(getInits().begin(), getInits().end());
@@ -1447,10 +1441,9 @@ class OMPLastprivateClause final
// \endcode
// Required for proper codegen of final assignment performed by the
// lastprivate clause.
- //
- friend TrailingObjects;
- friend OMPVarListClause;
friend class OMPClauseReader;
+ friend OMPVarListClause;
+ friend TrailingObjects;
/// \brief Build clause with number of variables \a N.
///
@@ -1458,7 +1451,6 @@ class OMPLastprivateClause final
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
/// \param N Number of the variables in the clause.
- ///
OMPLastprivateClause(SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, unsigned N)
: OMPVarListClause<OMPLastprivateClause>(OMPC_lastprivate, StartLoc,
@@ -1468,7 +1460,6 @@ class OMPLastprivateClause final
/// \brief Build an empty clause.
///
/// \param N Number of variables.
- ///
explicit OMPLastprivateClause(unsigned N)
: OMPVarListClause<OMPLastprivateClause>(
OMPC_lastprivate, SourceLocation(), SourceLocation(),
@@ -1550,24 +1541,23 @@ public:
/// region with this clause.
/// \param PostUpdate Expression that must be executed after exit from the
/// OpenMP region with this clause.
- ///
static OMPLastprivateClause *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps,
Stmt *PreInit, Expr *PostUpdate);
+
/// \brief Creates an empty clause with the place for \a N variables.
///
/// \param C AST context.
/// \param N The number of variables.
- ///
static OMPLastprivateClause *CreateEmpty(const ASTContext &C, unsigned N);
- typedef MutableArrayRef<Expr *>::iterator helper_expr_iterator;
- typedef ArrayRef<const Expr *>::iterator helper_expr_const_iterator;
- typedef llvm::iterator_range<helper_expr_iterator> helper_expr_range;
- typedef llvm::iterator_range<helper_expr_const_iterator>
- helper_expr_const_range;
+ using helper_expr_iterator = MutableArrayRef<Expr *>::iterator;
+ using helper_expr_const_iterator = ArrayRef<const Expr *>::iterator;
+ using helper_expr_range = llvm::iterator_range<helper_expr_iterator>;
+ using helper_expr_const_range =
+ llvm::iterator_range<helper_expr_const_iterator>;
/// \brief Set list of helper expressions, required for generation of private
/// copies of original lastprivate variables.
@@ -1577,29 +1567,36 @@ public:
return helper_expr_const_range(getPrivateCopies().begin(),
getPrivateCopies().end());
}
+
helper_expr_range private_copies() {
return helper_expr_range(getPrivateCopies().begin(),
getPrivateCopies().end());
}
+
helper_expr_const_range source_exprs() const {
return helper_expr_const_range(getSourceExprs().begin(),
getSourceExprs().end());
}
+
helper_expr_range source_exprs() {
return helper_expr_range(getSourceExprs().begin(), getSourceExprs().end());
}
+
helper_expr_const_range destination_exprs() const {
return helper_expr_const_range(getDestinationExprs().begin(),
getDestinationExprs().end());
}
+
helper_expr_range destination_exprs() {
return helper_expr_range(getDestinationExprs().begin(),
getDestinationExprs().end());
}
+
helper_expr_const_range assignment_ops() const {
return helper_expr_const_range(getAssignmentOps().begin(),
getAssignmentOps().end());
}
+
helper_expr_range assignment_ops() {
return helper_expr_range(getAssignmentOps().begin(),
getAssignmentOps().end());
@@ -1622,19 +1619,18 @@ public:
/// \endcode
/// In this example directive '#pragma omp parallel' has clause 'shared'
/// with the variables 'a' and 'b'.
-///
class OMPSharedClause final
: public OMPVarListClause<OMPSharedClause>,
private llvm::TrailingObjects<OMPSharedClause, Expr *> {
- friend TrailingObjects;
friend OMPVarListClause;
+ friend TrailingObjects;
+
/// \brief Build clause with number of variables \a N.
///
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
/// \param N Number of the variables in the clause.
- ///
OMPSharedClause(SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, unsigned N)
: OMPVarListClause<OMPSharedClause>(OMPC_shared, StartLoc, LParenLoc,
@@ -1643,7 +1639,6 @@ class OMPSharedClause final
/// \brief Build an empty clause.
///
/// \param N Number of variables.
- ///
explicit OMPSharedClause(unsigned N)
: OMPVarListClause<OMPSharedClause>(OMPC_shared, SourceLocation(),
SourceLocation(), SourceLocation(),
@@ -1657,15 +1652,14 @@ public:
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
/// \param VL List of references to the variables.
- ///
static OMPSharedClause *Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc, ArrayRef<Expr *> VL);
+
/// \brief Creates an empty clause with \a N variables.
///
/// \param C AST context.
/// \param N The number of variables.
- ///
static OMPSharedClause *CreateEmpty(const ASTContext &C, unsigned N);
child_range children() {
@@ -1686,18 +1680,20 @@ public:
/// \endcode
/// In this example directive '#pragma omp parallel' has clause 'reduction'
/// with operator '+' and the variables 'a' and 'b'.
-///
class OMPReductionClause final
: public OMPVarListClause<OMPReductionClause>,
public OMPClauseWithPostUpdate,
private llvm::TrailingObjects<OMPReductionClause, Expr *> {
- friend TrailingObjects;
- friend OMPVarListClause;
friend class OMPClauseReader;
+ friend OMPVarListClause;
+ friend TrailingObjects;
+
/// \brief Location of ':'.
SourceLocation ColonLoc;
+
/// \brief Nested name specifier for C++.
NestedNameSpecifierLoc QualifierLoc;
+
/// \brief Name of custom operator.
DeclarationNameInfo NameInfo;
@@ -1710,7 +1706,6 @@ class OMPReductionClause final
/// \param N Number of the variables in the clause.
/// \param QualifierLoc The nested-name qualifier with location information
/// \param NameInfo The full name info for reduction identifier.
- ///
OMPReductionClause(SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation ColonLoc, SourceLocation EndLoc, unsigned N,
NestedNameSpecifierLoc QualifierLoc,
@@ -1723,17 +1718,18 @@ class OMPReductionClause final
/// \brief Build an empty clause.
///
/// \param N Number of variables.
- ///
explicit OMPReductionClause(unsigned N)
: OMPVarListClause<OMPReductionClause>(OMPC_reduction, SourceLocation(),
SourceLocation(), SourceLocation(),
N),
- OMPClauseWithPostUpdate(this), ColonLoc(), QualifierLoc(), NameInfo() {}
+ OMPClauseWithPostUpdate(this) {}
/// \brief Sets location of ':' symbol in clause.
void setColonLoc(SourceLocation CL) { ColonLoc = CL; }
+
/// \brief Sets the name info for specified reduction identifier.
void setNameInfo(DeclarationNameInfo DNI) { NameInfo = DNI; }
+
/// \brief Sets the nested name specifier.
void setQualifierLoc(NestedNameSpecifierLoc NSL) { QualifierLoc = NSL; }
@@ -1825,7 +1821,6 @@ public:
/// region with this clause.
/// \param PostUpdate Expression that must be executed after exit from the
/// OpenMP region with this clause.
- ///
static OMPReductionClause *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL,
@@ -1833,48 +1828,57 @@ public:
const DeclarationNameInfo &NameInfo, ArrayRef<Expr *> Privates,
ArrayRef<Expr *> LHSExprs, ArrayRef<Expr *> RHSExprs,
ArrayRef<Expr *> ReductionOps, Stmt *PreInit, Expr *PostUpdate);
+
/// \brief Creates an empty clause with the place for \a N variables.
///
/// \param C AST context.
/// \param N The number of variables.
- ///
static OMPReductionClause *CreateEmpty(const ASTContext &C, unsigned N);
/// \brief Gets location of ':' symbol in clause.
SourceLocation getColonLoc() const { return ColonLoc; }
+
/// \brief Gets the name info for specified reduction identifier.
const DeclarationNameInfo &getNameInfo() const { return NameInfo; }
+
/// \brief Gets the nested name specifier.
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
- typedef MutableArrayRef<Expr *>::iterator helper_expr_iterator;
- typedef ArrayRef<const Expr *>::iterator helper_expr_const_iterator;
- typedef llvm::iterator_range<helper_expr_iterator> helper_expr_range;
- typedef llvm::iterator_range<helper_expr_const_iterator>
- helper_expr_const_range;
+ using helper_expr_iterator = MutableArrayRef<Expr *>::iterator;
+ using helper_expr_const_iterator = ArrayRef<const Expr *>::iterator;
+ using helper_expr_range = llvm::iterator_range<helper_expr_iterator>;
+ using helper_expr_const_range =
+ llvm::iterator_range<helper_expr_const_iterator>;
helper_expr_const_range privates() const {
return helper_expr_const_range(getPrivates().begin(), getPrivates().end());
}
+
helper_expr_range privates() {
return helper_expr_range(getPrivates().begin(), getPrivates().end());
}
+
helper_expr_const_range lhs_exprs() const {
return helper_expr_const_range(getLHSExprs().begin(), getLHSExprs().end());
}
+
helper_expr_range lhs_exprs() {
return helper_expr_range(getLHSExprs().begin(), getLHSExprs().end());
}
+
helper_expr_const_range rhs_exprs() const {
return helper_expr_const_range(getRHSExprs().begin(), getRHSExprs().end());
}
+
helper_expr_range rhs_exprs() {
return helper_expr_range(getRHSExprs().begin(), getRHSExprs().end());
}
+
helper_expr_const_range reduction_ops() const {
return helper_expr_const_range(getReductionOps().begin(),
getReductionOps().end());
}
+
helper_expr_range reduction_ops() {
return helper_expr_range(getReductionOps().begin(),
getReductionOps().end());
@@ -1898,18 +1902,20 @@ public:
/// \endcode
/// In this example directive '#pragma omp taskgroup' has clause
/// 'task_reduction' with operator '+' and the variables 'a' and 'b'.
-///
class OMPTaskReductionClause final
: public OMPVarListClause<OMPTaskReductionClause>,
public OMPClauseWithPostUpdate,
private llvm::TrailingObjects<OMPTaskReductionClause, Expr *> {
- friend TrailingObjects;
- friend OMPVarListClause;
friend class OMPClauseReader;
+ friend OMPVarListClause;
+ friend TrailingObjects;
+
/// Location of ':'.
SourceLocation ColonLoc;
+
/// Nested name specifier for C++.
NestedNameSpecifierLoc QualifierLoc;
+
/// Name of custom operator.
DeclarationNameInfo NameInfo;
@@ -1922,7 +1928,6 @@ class OMPTaskReductionClause final
/// \param N Number of the variables in the clause.
/// \param QualifierLoc The nested-name qualifier with location information
/// \param NameInfo The full name info for reduction identifier.
- ///
OMPTaskReductionClause(SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation ColonLoc, SourceLocation EndLoc,
unsigned N, NestedNameSpecifierLoc QualifierLoc,
@@ -1935,17 +1940,18 @@ class OMPTaskReductionClause final
/// Build an empty clause.
///
/// \param N Number of variables.
- ///
explicit OMPTaskReductionClause(unsigned N)
: OMPVarListClause<OMPTaskReductionClause>(
OMPC_task_reduction, SourceLocation(), SourceLocation(),
SourceLocation(), N),
- OMPClauseWithPostUpdate(this), ColonLoc(), QualifierLoc(), NameInfo() {}
+ OMPClauseWithPostUpdate(this) {}
/// Sets location of ':' symbol in clause.
void setColonLoc(SourceLocation CL) { ColonLoc = CL; }
+
/// Sets the name info for specified reduction identifier.
void setNameInfo(DeclarationNameInfo DNI) { NameInfo = DNI; }
+
/// Sets the nested name specifier.
void setQualifierLoc(NestedNameSpecifierLoc NSL) { QualifierLoc = NSL; }
@@ -2035,7 +2041,6 @@ public:
/// region with this clause.
/// \param PostUpdate Expression that must be executed after exit from the
/// OpenMP region with this clause.
- ///
static OMPTaskReductionClause *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL,
@@ -2048,44 +2053,52 @@ public:
///
/// \param C AST context.
/// \param N The number of variables.
- ///
static OMPTaskReductionClause *CreateEmpty(const ASTContext &C, unsigned N);
/// Gets location of ':' symbol in clause.
SourceLocation getColonLoc() const { return ColonLoc; }
+
/// Gets the name info for specified reduction identifier.
const DeclarationNameInfo &getNameInfo() const { return NameInfo; }
+
/// Gets the nested name specifier.
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
- typedef MutableArrayRef<Expr *>::iterator helper_expr_iterator;
- typedef ArrayRef<const Expr *>::iterator helper_expr_const_iterator;
- typedef llvm::iterator_range<helper_expr_iterator> helper_expr_range;
- typedef llvm::iterator_range<helper_expr_const_iterator>
- helper_expr_const_range;
+ using helper_expr_iterator = MutableArrayRef<Expr *>::iterator;
+ using helper_expr_const_iterator = ArrayRef<const Expr *>::iterator;
+ using helper_expr_range = llvm::iterator_range<helper_expr_iterator>;
+ using helper_expr_const_range =
+ llvm::iterator_range<helper_expr_const_iterator>;
helper_expr_const_range privates() const {
return helper_expr_const_range(getPrivates().begin(), getPrivates().end());
}
+
helper_expr_range privates() {
return helper_expr_range(getPrivates().begin(), getPrivates().end());
}
+
helper_expr_const_range lhs_exprs() const {
return helper_expr_const_range(getLHSExprs().begin(), getLHSExprs().end());
}
+
helper_expr_range lhs_exprs() {
return helper_expr_range(getLHSExprs().begin(), getLHSExprs().end());
}
+
helper_expr_const_range rhs_exprs() const {
return helper_expr_const_range(getRHSExprs().begin(), getRHSExprs().end());
}
+
helper_expr_range rhs_exprs() {
return helper_expr_range(getRHSExprs().begin(), getRHSExprs().end());
}
+
helper_expr_const_range reduction_ops() const {
return helper_expr_const_range(getReductionOps().begin(),
getReductionOps().end());
}
+
helper_expr_range reduction_ops() {
return helper_expr_range(getReductionOps().begin(),
getReductionOps().end());
@@ -2101,6 +2114,249 @@ public:
}
};
+/// This represents clause 'in_reduction' in the '#pragma omp task' directives.
+///
+/// \code
+/// #pragma omp task in_reduction(+:a,b)
+/// \endcode
+/// In this example directive '#pragma omp task' has clause 'in_reduction' with
+/// operator '+' and the variables 'a' and 'b'.
+class OMPInReductionClause final
+ : public OMPVarListClause<OMPInReductionClause>,
+ public OMPClauseWithPostUpdate,
+ private llvm::TrailingObjects<OMPInReductionClause, Expr *> {
+ friend class OMPClauseReader;
+ friend OMPVarListClause;
+ friend TrailingObjects;
+
+ /// Location of ':'.
+ SourceLocation ColonLoc;
+
+ /// Nested name specifier for C++.
+ NestedNameSpecifierLoc QualifierLoc;
+
+ /// Name of custom operator.
+ DeclarationNameInfo NameInfo;
+
+ /// Build clause with number of variables \a N.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param ColonLoc Location of ':'.
+ /// \param N Number of the variables in the clause.
+ /// \param QualifierLoc The nested-name qualifier with location information
+ /// \param NameInfo The full name info for reduction identifier.
+ OMPInReductionClause(SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation ColonLoc, SourceLocation EndLoc,
+ unsigned N, NestedNameSpecifierLoc QualifierLoc,
+ const DeclarationNameInfo &NameInfo)
+ : OMPVarListClause<OMPInReductionClause>(OMPC_in_reduction, StartLoc,
+ LParenLoc, EndLoc, N),
+ OMPClauseWithPostUpdate(this), ColonLoc(ColonLoc),
+ QualifierLoc(QualifierLoc), NameInfo(NameInfo) {}
+
+ /// Build an empty clause.
+ ///
+ /// \param N Number of variables.
+ explicit OMPInReductionClause(unsigned N)
+ : OMPVarListClause<OMPInReductionClause>(
+ OMPC_in_reduction, SourceLocation(), SourceLocation(),
+ SourceLocation(), N),
+ OMPClauseWithPostUpdate(this) {}
+
+ /// Sets location of ':' symbol in clause.
+ void setColonLoc(SourceLocation CL) { ColonLoc = CL; }
+
+ /// Sets the name info for specified reduction identifier.
+ void setNameInfo(DeclarationNameInfo DNI) { NameInfo = DNI; }
+
+ /// Sets the nested name specifier.
+ void setQualifierLoc(NestedNameSpecifierLoc NSL) { QualifierLoc = NSL; }
+
+ /// Set list of helper expressions, required for proper codegen of the clause.
+ /// These expressions represent private copy of the reduction variable.
+ void setPrivates(ArrayRef<Expr *> Privates);
+
+ /// Get the list of helper privates.
+ MutableArrayRef<Expr *> getPrivates() {
+ return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getPrivates() const {
+ return llvm::makeArrayRef(varlist_end(), varlist_size());
+ }
+
+ /// Set list of helper expressions, required for proper codegen of the clause.
+ /// These expressions represent LHS expression in the final reduction
+ /// expression performed by the reduction clause.
+ void setLHSExprs(ArrayRef<Expr *> LHSExprs);
+
+ /// Get the list of helper LHS expressions.
+ MutableArrayRef<Expr *> getLHSExprs() {
+ return MutableArrayRef<Expr *>(getPrivates().end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getLHSExprs() const {
+ return llvm::makeArrayRef(getPrivates().end(), varlist_size());
+ }
+
+ /// Set list of helper expressions, required for proper codegen of the clause.
+ /// These expressions represent RHS expression in the final reduction
+ /// expression performed by the reduction clause. Also, variables in these
+ /// expressions are used for proper initialization of reduction copies.
+ void setRHSExprs(ArrayRef<Expr *> RHSExprs);
+
+ /// Get the list of helper destination expressions.
+ MutableArrayRef<Expr *> getRHSExprs() {
+ return MutableArrayRef<Expr *>(getLHSExprs().end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getRHSExprs() const {
+ return llvm::makeArrayRef(getLHSExprs().end(), varlist_size());
+ }
+
+ /// Set list of helper reduction expressions, required for proper
+ /// codegen of the clause. These expressions are binary expressions or
+ /// operator/custom reduction call that calculates new value from source
+ /// helper expressions to destination helper expressions.
+ void setReductionOps(ArrayRef<Expr *> ReductionOps);
+
+ /// Get the list of helper reduction expressions.
+ MutableArrayRef<Expr *> getReductionOps() {
+ return MutableArrayRef<Expr *>(getRHSExprs().end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getReductionOps() const {
+ return llvm::makeArrayRef(getRHSExprs().end(), varlist_size());
+ }
+
+ /// Set list of helper reduction taskgroup descriptors.
+ void setTaskgroupDescriptors(ArrayRef<Expr *> ReductionOps);
+
+ /// Get the list of helper reduction taskgroup descriptors.
+ MutableArrayRef<Expr *> getTaskgroupDescriptors() {
+ return MutableArrayRef<Expr *>(getReductionOps().end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getTaskgroupDescriptors() const {
+ return llvm::makeArrayRef(getReductionOps().end(), varlist_size());
+ }
+
+public:
+ /// Creates clause with a list of variables \a VL.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param ColonLoc Location of ':'.
+ /// \param EndLoc Ending location of the clause.
+ /// \param VL The variables in the clause.
+ /// \param QualifierLoc The nested-name qualifier with location information
+ /// \param NameInfo The full name info for reduction identifier.
+ /// \param Privates List of helper expressions for proper generation of
+ /// private copies.
+ /// \param LHSExprs List of helper expressions for proper generation of
+ /// assignment operation required for copyprivate clause. This list represents
+ /// LHSs of the reduction expressions.
+ /// \param RHSExprs List of helper expressions for proper generation of
+ /// assignment operation required for copyprivate clause. This list represents
+ /// RHSs of the reduction expressions.
+ /// Also, variables in these expressions are used for proper initialization of
+ /// reduction copies.
+ /// \param ReductionOps List of helper expressions that represents reduction
+ /// expressions:
+ /// \code
+ /// LHSExprs binop RHSExprs;
+ /// operator binop(LHSExpr, RHSExpr);
+ /// <CutomReduction>(LHSExpr, RHSExpr);
+ /// \endcode
+ /// Required for proper codegen of final reduction operation performed by the
+ /// reduction clause.
+ /// \param TaskgroupDescriptors List of helper taskgroup descriptors for
+ /// corresponding items in parent taskgroup task_reduction clause.
+ /// \param PreInit Statement that must be executed before entering the OpenMP
+ /// region with this clause.
+ /// \param PostUpdate Expression that must be executed after exit from the
+ /// OpenMP region with this clause.
+ static OMPInReductionClause *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL,
+ NestedNameSpecifierLoc QualifierLoc,
+ const DeclarationNameInfo &NameInfo, ArrayRef<Expr *> Privates,
+ ArrayRef<Expr *> LHSExprs, ArrayRef<Expr *> RHSExprs,
+ ArrayRef<Expr *> ReductionOps, ArrayRef<Expr *> TaskgroupDescriptors,
+ Stmt *PreInit, Expr *PostUpdate);
+
+ /// Creates an empty clause with the place for \a N variables.
+ ///
+ /// \param C AST context.
+ /// \param N The number of variables.
+ static OMPInReductionClause *CreateEmpty(const ASTContext &C, unsigned N);
+
+ /// Gets location of ':' symbol in clause.
+ SourceLocation getColonLoc() const { return ColonLoc; }
+
+ /// Gets the name info for specified reduction identifier.
+ const DeclarationNameInfo &getNameInfo() const { return NameInfo; }
+
+ /// Gets the nested name specifier.
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
+ using helper_expr_iterator = MutableArrayRef<Expr *>::iterator;
+ using helper_expr_const_iterator = ArrayRef<const Expr *>::iterator;
+ using helper_expr_range = llvm::iterator_range<helper_expr_iterator>;
+ using helper_expr_const_range =
+ llvm::iterator_range<helper_expr_const_iterator>;
+
+ helper_expr_const_range privates() const {
+ return helper_expr_const_range(getPrivates().begin(), getPrivates().end());
+ }
+
+ helper_expr_range privates() {
+ return helper_expr_range(getPrivates().begin(), getPrivates().end());
+ }
+
+ helper_expr_const_range lhs_exprs() const {
+ return helper_expr_const_range(getLHSExprs().begin(), getLHSExprs().end());
+ }
+
+ helper_expr_range lhs_exprs() {
+ return helper_expr_range(getLHSExprs().begin(), getLHSExprs().end());
+ }
+
+ helper_expr_const_range rhs_exprs() const {
+ return helper_expr_const_range(getRHSExprs().begin(), getRHSExprs().end());
+ }
+
+ helper_expr_range rhs_exprs() {
+ return helper_expr_range(getRHSExprs().begin(), getRHSExprs().end());
+ }
+
+ helper_expr_const_range reduction_ops() const {
+ return helper_expr_const_range(getReductionOps().begin(),
+ getReductionOps().end());
+ }
+
+ helper_expr_range reduction_ops() {
+ return helper_expr_range(getReductionOps().begin(),
+ getReductionOps().end());
+ }
+
+ helper_expr_const_range taskgroup_descriptors() const {
+ return helper_expr_const_range(getTaskgroupDescriptors().begin(),
+ getTaskgroupDescriptors().end());
+ }
+
+ helper_expr_range taskgroup_descriptors() {
+ return helper_expr_range(getTaskgroupDescriptors().begin(),
+ getTaskgroupDescriptors().end());
+ }
+
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
+ }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_in_reduction;
+ }
+};
+
/// \brief This represents clause 'linear' in the '#pragma omp ...'
/// directives.
///
@@ -2109,18 +2365,20 @@ public:
/// \endcode
/// In this example directive '#pragma omp simd' has clause 'linear'
/// with variables 'a', 'b' and linear step '2'.
-///
class OMPLinearClause final
: public OMPVarListClause<OMPLinearClause>,
public OMPClauseWithPostUpdate,
private llvm::TrailingObjects<OMPLinearClause, Expr *> {
- friend TrailingObjects;
- friend OMPVarListClause;
friend class OMPClauseReader;
+ friend OMPVarListClause;
+ friend TrailingObjects;
+
/// \brief Modifier of 'linear' clause.
- OpenMPLinearClauseKind Modifier;
+ OpenMPLinearClauseKind Modifier = OMPC_LINEAR_val;
+
/// \brief Location of linear modifier if any.
SourceLocation ModifierLoc;
+
/// \brief Location of ':'.
SourceLocation ColonLoc;
@@ -2137,7 +2395,6 @@ class OMPLinearClause final
/// \param ColonLoc Location of ':'.
/// \param EndLoc Ending location of the clause.
/// \param NumVars Number of variables.
- ///
OMPLinearClause(SourceLocation StartLoc, SourceLocation LParenLoc,
OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc,
SourceLocation ColonLoc, SourceLocation EndLoc,
@@ -2150,13 +2407,11 @@ class OMPLinearClause final
/// \brief Build an empty clause.
///
/// \param NumVars Number of variables.
- ///
explicit OMPLinearClause(unsigned NumVars)
: OMPVarListClause<OMPLinearClause>(OMPC_linear, SourceLocation(),
SourceLocation(), SourceLocation(),
NumVars),
- OMPClauseWithPostUpdate(this), Modifier(OMPC_LINEAR_val), ModifierLoc(),
- ColonLoc() {}
+ OMPClauseWithPostUpdate(this) {}
/// \brief Gets the list of initial values for linear variables.
///
@@ -2170,7 +2425,6 @@ class OMPLinearClause final
///
/// { Vars[] /* in OMPVarListClause */; Privates[]; Inits[]; Updates[];
/// Finals[]; Step; CalcStep; }
- ///
MutableArrayRef<Expr *> getPrivates() {
return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
}
@@ -2240,30 +2494,35 @@ public:
///
/// \param C AST context.
/// \param NumVars Number of variables.
- ///
static OMPLinearClause *CreateEmpty(const ASTContext &C, unsigned NumVars);
/// \brief Set modifier.
void setModifier(OpenMPLinearClauseKind Kind) { Modifier = Kind; }
+
/// \brief Return modifier.
OpenMPLinearClauseKind getModifier() const { return Modifier; }
/// \brief Set modifier location.
void setModifierLoc(SourceLocation Loc) { ModifierLoc = Loc; }
+
/// \brief Return modifier location.
SourceLocation getModifierLoc() const { return ModifierLoc; }
/// \brief Sets the location of ':'.
void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
+
/// \brief Returns the location of ':'.
SourceLocation getColonLoc() const { return ColonLoc; }
/// \brief Returns linear step.
Expr *getStep() { return *(getFinals().end()); }
+
/// \brief Returns linear step.
const Expr *getStep() const { return *(getFinals().end()); }
+
/// \brief Returns expression to calculate linear step.
Expr *getCalcStep() { return *(getFinals().end() + 1); }
+
/// \brief Returns expression to calculate linear step.
const Expr *getCalcStep() const { return *(getFinals().end() + 1); }
@@ -2275,50 +2534,54 @@ public:
/// \param FL List of expressions.
void setFinals(ArrayRef<Expr *> FL);
- typedef MutableArrayRef<Expr *>::iterator privates_iterator;
- typedef ArrayRef<const Expr *>::iterator privates_const_iterator;
- typedef llvm::iterator_range<privates_iterator> privates_range;
- typedef llvm::iterator_range<privates_const_iterator> privates_const_range;
+ using privates_iterator = MutableArrayRef<Expr *>::iterator;
+ using privates_const_iterator = ArrayRef<const Expr *>::iterator;
+ using privates_range = llvm::iterator_range<privates_iterator>;
+ using privates_const_range = llvm::iterator_range<privates_const_iterator>;
privates_range privates() {
return privates_range(getPrivates().begin(), getPrivates().end());
}
+
privates_const_range privates() const {
return privates_const_range(getPrivates().begin(), getPrivates().end());
}
- typedef MutableArrayRef<Expr *>::iterator inits_iterator;
- typedef ArrayRef<const Expr *>::iterator inits_const_iterator;
- typedef llvm::iterator_range<inits_iterator> inits_range;
- typedef llvm::iterator_range<inits_const_iterator> inits_const_range;
+ using inits_iterator = MutableArrayRef<Expr *>::iterator;
+ using inits_const_iterator = ArrayRef<const Expr *>::iterator;
+ using inits_range = llvm::iterator_range<inits_iterator>;
+ using inits_const_range = llvm::iterator_range<inits_const_iterator>;
inits_range inits() {
return inits_range(getInits().begin(), getInits().end());
}
+
inits_const_range inits() const {
return inits_const_range(getInits().begin(), getInits().end());
}
- typedef MutableArrayRef<Expr *>::iterator updates_iterator;
- typedef ArrayRef<const Expr *>::iterator updates_const_iterator;
- typedef llvm::iterator_range<updates_iterator> updates_range;
- typedef llvm::iterator_range<updates_const_iterator> updates_const_range;
+ using updates_iterator = MutableArrayRef<Expr *>::iterator;
+ using updates_const_iterator = ArrayRef<const Expr *>::iterator;
+ using updates_range = llvm::iterator_range<updates_iterator>;
+ using updates_const_range = llvm::iterator_range<updates_const_iterator>;
updates_range updates() {
return updates_range(getUpdates().begin(), getUpdates().end());
}
+
updates_const_range updates() const {
return updates_const_range(getUpdates().begin(), getUpdates().end());
}
- typedef MutableArrayRef<Expr *>::iterator finals_iterator;
- typedef ArrayRef<const Expr *>::iterator finals_const_iterator;
- typedef llvm::iterator_range<finals_iterator> finals_range;
- typedef llvm::iterator_range<finals_const_iterator> finals_const_range;
+ using finals_iterator = MutableArrayRef<Expr *>::iterator;
+ using finals_const_iterator = ArrayRef<const Expr *>::iterator;
+ using finals_range = llvm::iterator_range<finals_iterator>;
+ using finals_const_range = llvm::iterator_range<finals_const_iterator>;
finals_range finals() {
return finals_range(getFinals().begin(), getFinals().end());
}
+
finals_const_range finals() const {
return finals_const_range(getFinals().begin(), getFinals().end());
}
@@ -2341,13 +2604,13 @@ public:
/// \endcode
/// In this example directive '#pragma omp simd' has clause 'aligned'
/// with variables 'a', 'b' and alignment '8'.
-///
class OMPAlignedClause final
: public OMPVarListClause<OMPAlignedClause>,
private llvm::TrailingObjects<OMPAlignedClause, Expr *> {
- friend TrailingObjects;
- friend OMPVarListClause;
friend class OMPClauseReader;
+ friend OMPVarListClause;
+ friend TrailingObjects;
+
/// \brief Location of ':'.
SourceLocation ColonLoc;
@@ -2361,7 +2624,6 @@ class OMPAlignedClause final
/// \param ColonLoc Location of ':'.
/// \param EndLoc Ending location of the clause.
/// \param NumVars Number of variables.
- ///
OMPAlignedClause(SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation ColonLoc, SourceLocation EndLoc,
unsigned NumVars)
@@ -2372,12 +2634,10 @@ class OMPAlignedClause final
/// \brief Build an empty clause.
///
/// \param NumVars Number of variables.
- ///
explicit OMPAlignedClause(unsigned NumVars)
: OMPVarListClause<OMPAlignedClause>(OMPC_aligned, SourceLocation(),
SourceLocation(), SourceLocation(),
- NumVars),
- ColonLoc(SourceLocation()) {}
+ NumVars) {}
public:
/// \brief Creates clause with a list of variables \a VL and alignment \a A.
@@ -2399,16 +2659,17 @@ public:
///
/// \param C AST context.
/// \param NumVars Number of variables.
- ///
static OMPAlignedClause *CreateEmpty(const ASTContext &C, unsigned NumVars);
/// \brief Sets the location of ':'.
void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
+
/// \brief Returns the location of ':'.
SourceLocation getColonLoc() const { return ColonLoc; }
/// \brief Returns alignment.
Expr *getAlignment() { return *varlist_end(); }
+
/// \brief Returns alignment.
const Expr *getAlignment() const { return *varlist_end(); }
@@ -2429,7 +2690,6 @@ public:
/// \endcode
/// In this example directive '#pragma omp parallel' has clause 'copyin'
/// with the variables 'a' and 'b'.
-///
class OMPCopyinClause final
: public OMPVarListClause<OMPCopyinClause>,
private llvm::TrailingObjects<OMPCopyinClause, Expr *> {
@@ -2446,16 +2706,16 @@ class OMPCopyinClause final
// threadprivate variables to local instances of that variables in other
// implicit threads.
- friend TrailingObjects;
- friend OMPVarListClause;
friend class OMPClauseReader;
+ friend OMPVarListClause;
+ friend TrailingObjects;
+
/// \brief Build clause with number of variables \a N.
///
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
/// \param N Number of the variables in the clause.
- ///
OMPCopyinClause(SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, unsigned N)
: OMPVarListClause<OMPCopyinClause>(OMPC_copyin, StartLoc, LParenLoc,
@@ -2464,7 +2724,6 @@ class OMPCopyinClause final
/// \brief Build an empty clause.
///
/// \param N Number of variables.
- ///
explicit OMPCopyinClause(unsigned N)
: OMPVarListClause<OMPCopyinClause>(OMPC_copyin, SourceLocation(),
SourceLocation(), SourceLocation(),
@@ -2532,43 +2791,47 @@ public:
/// Required for proper codegen of propagation of master's thread values of
/// threadprivate variables to local instances of that variables in other
/// implicit threads.
- ///
static OMPCopyinClause *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps);
+
/// \brief Creates an empty clause with \a N variables.
///
/// \param C AST context.
/// \param N The number of variables.
- ///
static OMPCopyinClause *CreateEmpty(const ASTContext &C, unsigned N);
- typedef MutableArrayRef<Expr *>::iterator helper_expr_iterator;
- typedef ArrayRef<const Expr *>::iterator helper_expr_const_iterator;
- typedef llvm::iterator_range<helper_expr_iterator> helper_expr_range;
- typedef llvm::iterator_range<helper_expr_const_iterator>
- helper_expr_const_range;
+ using helper_expr_iterator = MutableArrayRef<Expr *>::iterator;
+ using helper_expr_const_iterator = ArrayRef<const Expr *>::iterator;
+ using helper_expr_range = llvm::iterator_range<helper_expr_iterator>;
+ using helper_expr_const_range =
+ llvm::iterator_range<helper_expr_const_iterator>;
helper_expr_const_range source_exprs() const {
return helper_expr_const_range(getSourceExprs().begin(),
getSourceExprs().end());
}
+
helper_expr_range source_exprs() {
return helper_expr_range(getSourceExprs().begin(), getSourceExprs().end());
}
+
helper_expr_const_range destination_exprs() const {
return helper_expr_const_range(getDestinationExprs().begin(),
getDestinationExprs().end());
}
+
helper_expr_range destination_exprs() {
return helper_expr_range(getDestinationExprs().begin(),
getDestinationExprs().end());
}
+
helper_expr_const_range assignment_ops() const {
return helper_expr_const_range(getAssignmentOps().begin(),
getAssignmentOps().end());
}
+
helper_expr_range assignment_ops() {
return helper_expr_range(getAssignmentOps().begin(),
getAssignmentOps().end());
@@ -2592,20 +2855,19 @@ public:
/// \endcode
/// In this example directive '#pragma omp single' has clause 'copyprivate'
/// with the variables 'a' and 'b'.
-///
class OMPCopyprivateClause final
: public OMPVarListClause<OMPCopyprivateClause>,
private llvm::TrailingObjects<OMPCopyprivateClause, Expr *> {
- friend TrailingObjects;
- friend OMPVarListClause;
friend class OMPClauseReader;
+ friend OMPVarListClause;
+ friend TrailingObjects;
+
/// \brief Build clause with number of variables \a N.
///
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
/// \param N Number of the variables in the clause.
- ///
OMPCopyprivateClause(SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, unsigned N)
: OMPVarListClause<OMPCopyprivateClause>(OMPC_copyprivate, StartLoc,
@@ -2614,7 +2876,6 @@ class OMPCopyprivateClause final
/// \brief Build an empty clause.
///
/// \param N Number of variables.
- ///
explicit OMPCopyprivateClause(unsigned N)
: OMPVarListClause<OMPCopyprivateClause>(
OMPC_copyprivate, SourceLocation(), SourceLocation(),
@@ -2681,43 +2942,47 @@ public:
/// \endcode
/// Required for proper codegen of final assignment performed by the
/// copyprivate clause.
- ///
static OMPCopyprivateClause *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps);
+
/// \brief Creates an empty clause with \a N variables.
///
/// \param C AST context.
/// \param N The number of variables.
- ///
static OMPCopyprivateClause *CreateEmpty(const ASTContext &C, unsigned N);
- typedef MutableArrayRef<Expr *>::iterator helper_expr_iterator;
- typedef ArrayRef<const Expr *>::iterator helper_expr_const_iterator;
- typedef llvm::iterator_range<helper_expr_iterator> helper_expr_range;
- typedef llvm::iterator_range<helper_expr_const_iterator>
- helper_expr_const_range;
+ using helper_expr_iterator = MutableArrayRef<Expr *>::iterator;
+ using helper_expr_const_iterator = ArrayRef<const Expr *>::iterator;
+ using helper_expr_range = llvm::iterator_range<helper_expr_iterator>;
+ using helper_expr_const_range =
+ llvm::iterator_range<helper_expr_const_iterator>;
helper_expr_const_range source_exprs() const {
return helper_expr_const_range(getSourceExprs().begin(),
getSourceExprs().end());
}
+
helper_expr_range source_exprs() {
return helper_expr_range(getSourceExprs().begin(), getSourceExprs().end());
}
+
helper_expr_const_range destination_exprs() const {
return helper_expr_const_range(getDestinationExprs().begin(),
getDestinationExprs().end());
}
+
helper_expr_range destination_exprs() {
return helper_expr_range(getDestinationExprs().begin(),
getDestinationExprs().end());
}
+
helper_expr_const_range assignment_ops() const {
return helper_expr_const_range(getAssignmentOps().begin(),
getAssignmentOps().end());
}
+
helper_expr_range assignment_ops() {
return helper_expr_range(getAssignmentOps().begin(),
getAssignmentOps().end());
@@ -2745,19 +3010,18 @@ public:
/// \endcode
/// In this example directive '#pragma omp flush' has implicit clause 'flush'
/// with the variables 'a' and 'b'.
-///
class OMPFlushClause final
: public OMPVarListClause<OMPFlushClause>,
private llvm::TrailingObjects<OMPFlushClause, Expr *> {
- friend TrailingObjects;
friend OMPVarListClause;
+ friend TrailingObjects;
+
/// \brief Build clause with number of variables \a N.
///
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
/// \param N Number of the variables in the clause.
- ///
OMPFlushClause(SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, unsigned N)
: OMPVarListClause<OMPFlushClause>(OMPC_flush, StartLoc, LParenLoc,
@@ -2766,7 +3030,6 @@ class OMPFlushClause final
/// \brief Build an empty clause.
///
/// \param N Number of variables.
- ///
explicit OMPFlushClause(unsigned N)
: OMPVarListClause<OMPFlushClause>(OMPC_flush, SourceLocation(),
SourceLocation(), SourceLocation(),
@@ -2780,15 +3043,14 @@ public:
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
/// \param VL List of references to the variables.
- ///
static OMPFlushClause *Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation EndLoc,
ArrayRef<Expr *> VL);
+
/// \brief Creates an empty clause with \a N variables.
///
/// \param C AST context.
/// \param N The number of variables.
- ///
static OMPFlushClause *CreateEmpty(const ASTContext &C, unsigned N);
child_range children() {
@@ -2809,41 +3071,41 @@ public:
/// \endcode
/// In this example directive '#pragma omp task' with clause 'depend' with the
/// variables 'a' and 'b' with dependency 'in'.
-///
class OMPDependClause final
: public OMPVarListClause<OMPDependClause>,
private llvm::TrailingObjects<OMPDependClause, Expr *> {
- friend TrailingObjects;
- friend OMPVarListClause;
friend class OMPClauseReader;
+ friend OMPVarListClause;
+ friend TrailingObjects;
+
/// \brief Dependency type (one of in, out, inout).
- OpenMPDependClauseKind DepKind;
+ OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown;
+
/// \brief Dependency type location.
SourceLocation DepLoc;
+
/// \brief Colon location.
SourceLocation ColonLoc;
+
/// \brief Build clause with number of variables \a N.
///
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
/// \param N Number of the variables in the clause.
- ///
OMPDependClause(SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, unsigned N)
: OMPVarListClause<OMPDependClause>(OMPC_depend, StartLoc, LParenLoc,
- EndLoc, N),
- DepKind(OMPC_DEPEND_unknown) {}
+ EndLoc, N) {}
/// \brief Build an empty clause.
///
/// \param N Number of variables.
- ///
explicit OMPDependClause(unsigned N)
: OMPVarListClause<OMPDependClause>(OMPC_depend, SourceLocation(),
SourceLocation(), SourceLocation(),
- N),
- DepKind(OMPC_DEPEND_unknown) {}
+ N) {}
+
/// \brief Set dependency kind.
void setDependencyKind(OpenMPDependClauseKind K) { DepKind = K; }
@@ -2868,25 +3130,29 @@ public:
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, OpenMPDependClauseKind DepKind,
SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL);
+
/// \brief Creates an empty clause with \a N variables.
///
/// \param C AST context.
/// \param N The number of variables.
- ///
static OMPDependClause *CreateEmpty(const ASTContext &C, unsigned N);
/// \brief Get dependency type.
OpenMPDependClauseKind getDependencyKind() const { return DepKind; }
+
/// \brief Get dependency type location.
SourceLocation getDependencyLoc() const { return DepLoc; }
+
/// \brief Get colon location.
SourceLocation getColonLoc() const { return ColonLoc; }
/// Set the loop counter value for the depend clauses with 'sink|source' kind
/// of dependency. Required for codegen.
void setCounterValue(Expr *V);
+
/// Get the loop counter value.
Expr *getCounterValue();
+
/// Get the loop counter value.
const Expr *getCounterValue() const;
@@ -2908,17 +3174,18 @@ public:
/// \endcode
/// In this example directive '#pragma omp target' has clause 'device'
/// with single expression 'a'.
-///
-class OMPDeviceClause : public OMPClause {
+class OMPDeviceClause : public OMPClause, public OMPClauseWithPreInit {
friend class OMPClauseReader;
+
/// \brief Location of '('.
SourceLocation LParenLoc;
+
/// \brief Device number.
- Stmt *Device;
+ Stmt *Device = nullptr;
+
/// \brief Set the device number.
///
/// \param E Device number.
- ///
void setDevice(Expr *E) { Device = E; }
public:
@@ -2928,31 +3195,35 @@ public:
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
- ///
- OMPDeviceClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation EndLoc)
- : OMPClause(OMPC_device, StartLoc, EndLoc), LParenLoc(LParenLoc),
- Device(E) {}
+ OMPDeviceClause(Expr *E, Stmt *HelperE, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_device, StartLoc, EndLoc), OMPClauseWithPreInit(this),
+ LParenLoc(LParenLoc), Device(E) {
+ setPreInitStmt(HelperE);
+ }
/// \brief Build an empty clause.
- ///
OMPDeviceClause()
- : OMPClause(OMPC_device, SourceLocation(), SourceLocation()),
- LParenLoc(SourceLocation()), Device(nullptr) {}
+ : OMPClause(OMPC_device, SourceLocation(), SourceLocation()),
+ OMPClauseWithPreInit(this) {}
+
/// \brief Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+
/// \brief Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
+
/// \brief Return device number.
Expr *getDevice() { return cast<Expr>(Device); }
+
/// \brief Return device number.
Expr *getDevice() const { return cast<Expr>(Device); }
+ child_range children() { return child_range(&Device, &Device + 1); }
+
static bool classof(const OMPClause *T) {
return T->getClauseKind() == OMPC_device;
}
-
- child_range children() { return child_range(&Device, &Device + 1); }
};
/// \brief This represents 'threads' clause in the '#pragma omp ...' directive.
@@ -2961,29 +3232,26 @@ public:
/// #pragma omp ordered threads
/// \endcode
/// In this example directive '#pragma omp ordered' has simple 'threads' clause.
-///
class OMPThreadsClause : public OMPClause {
public:
/// \brief Build 'threads' clause.
///
/// \param StartLoc Starting location of the clause.
/// \param EndLoc Ending location of the clause.
- ///
OMPThreadsClause(SourceLocation StartLoc, SourceLocation EndLoc)
: OMPClause(OMPC_threads, StartLoc, EndLoc) {}
/// \brief Build an empty clause.
- ///
OMPThreadsClause()
: OMPClause(OMPC_threads, SourceLocation(), SourceLocation()) {}
- static bool classof(const OMPClause *T) {
- return T->getClauseKind() == OMPC_threads;
- }
-
child_range children() {
return child_range(child_iterator(), child_iterator());
}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_threads;
+ }
};
/// \brief This represents 'simd' clause in the '#pragma omp ...' directive.
@@ -2992,28 +3260,25 @@ public:
/// #pragma omp ordered simd
/// \endcode
/// In this example directive '#pragma omp ordered' has simple 'simd' clause.
-///
class OMPSIMDClause : public OMPClause {
public:
/// \brief Build 'simd' clause.
///
/// \param StartLoc Starting location of the clause.
/// \param EndLoc Ending location of the clause.
- ///
OMPSIMDClause(SourceLocation StartLoc, SourceLocation EndLoc)
: OMPClause(OMPC_simd, StartLoc, EndLoc) {}
/// \brief Build an empty clause.
- ///
OMPSIMDClause() : OMPClause(OMPC_simd, SourceLocation(), SourceLocation()) {}
- static bool classof(const OMPClause *T) {
- return T->getClauseKind() == OMPC_simd;
- }
-
child_range children() {
return child_range(child_iterator(), child_iterator());
}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_simd;
+ }
};
/// \brief Struct that defines common infrastructure to handle mappable
@@ -3029,13 +3294,14 @@ public:
class MappableComponent {
// \brief Expression associated with the component.
Expr *AssociatedExpression = nullptr;
+
// \brief Declaration associated with the declaration. If the component does
// not have a declaration (e.g. array subscripts or section), this is set to
// nullptr.
ValueDecl *AssociatedDeclaration = nullptr;
public:
- explicit MappableComponent() {}
+ explicit MappableComponent() = default;
explicit MappableComponent(Expr *AssociatedExpression,
ValueDecl *AssociatedDeclaration)
: AssociatedExpression(AssociatedExpression),
@@ -3045,6 +3311,7 @@ public:
: nullptr) {}
Expr *getAssociatedExpression() const { return AssociatedExpression; }
+
ValueDecl *getAssociatedDeclaration() const {
return AssociatedDeclaration;
}
@@ -3052,14 +3319,14 @@ public:
// \brief List of components of an expression. This first one is the whole
// expression and the last one is the base expression.
- typedef SmallVector<MappableComponent, 8> MappableExprComponentList;
- typedef ArrayRef<MappableComponent> MappableExprComponentListRef;
+ using MappableExprComponentList = SmallVector<MappableComponent, 8>;
+ using MappableExprComponentListRef = ArrayRef<MappableComponent>;
// \brief List of all component lists associated to the same base declaration.
// E.g. if both 'S.a' and 'S.b' are a mappable expressions, each will have
// their component list but the same base declaration 'S'.
- typedef SmallVector<MappableExprComponentList, 8> MappableExprComponentLists;
- typedef ArrayRef<MappableExprComponentList> MappableExprComponentListsRef;
+ using MappableExprComponentLists = SmallVector<MappableExprComponentList, 8>;
+ using MappableExprComponentListsRef = ArrayRef<MappableExprComponentList>;
protected:
// \brief Return the total number of elements in a list of component lists.
@@ -3091,6 +3358,28 @@ class OMPMappableExprListClause : public OMPVarListClause<T>,
unsigned NumComponents;
protected:
+ /// \brief Build a clause for \a NumUniqueDeclarations declarations, \a
+ /// NumComponentLists total component lists, and \a NumComponents total
+ /// components.
+ ///
+ /// \param K Kind of the clause.
+ /// \param StartLoc Starting location of the clause (the clause keyword).
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param NumVars Number of expressions listed in the clause.
+ /// \param NumUniqueDeclarations Number of unique base declarations in this
+ /// clause.
+ /// \param NumComponentLists Number of component lists in this clause - one
+ /// list for each expression in the clause.
+ /// \param NumComponents Total number of expression components in the clause.
+ OMPMappableExprListClause(OpenMPClauseKind K, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc,
+ unsigned NumVars, unsigned NumUniqueDeclarations,
+ unsigned NumComponentLists, unsigned NumComponents)
+ : OMPVarListClause<T>(K, StartLoc, LParenLoc, EndLoc, NumVars),
+ NumUniqueDeclarations(NumUniqueDeclarations),
+ NumComponentLists(NumComponentLists), NumComponents(NumComponents) {}
+
/// \brief Get the unique declarations that are in the trailing objects of the
/// class.
MutableArrayRef<ValueDecl *> getUniqueDeclsRef() {
@@ -3270,34 +3559,13 @@ protected:
}
}
- /// \brief Build a clause for \a NumUniqueDeclarations declarations, \a
- /// NumComponentLists total component lists, and \a NumComponents total
- /// components.
- ///
- /// \param K Kind of the clause.
- /// \param StartLoc Starting location of the clause (the clause keyword).
- /// \param LParenLoc Location of '('.
- /// \param EndLoc Ending location of the clause.
- /// \param NumVars Number of expressions listed in the clause.
- /// \param NumUniqueDeclarations Number of unique base declarations in this
- /// clause.
- /// \param NumComponentLists Number of component lists in this clause - one
- /// list for each expression in the clause.
- /// \param NumComponents Total number of expression components in the clause.
- ///
- OMPMappableExprListClause(OpenMPClauseKind K, SourceLocation StartLoc,
- SourceLocation LParenLoc, SourceLocation EndLoc,
- unsigned NumVars, unsigned NumUniqueDeclarations,
- unsigned NumComponentLists, unsigned NumComponents)
- : OMPVarListClause<T>(K, StartLoc, LParenLoc, EndLoc, NumVars),
- NumUniqueDeclarations(NumUniqueDeclarations),
- NumComponentLists(NumComponentLists), NumComponents(NumComponents) {}
-
public:
/// \brief Return the number of unique base declarations in this clause.
unsigned getUniqueDeclarationsNum() const { return NumUniqueDeclarations; }
+
/// \brief Return the number of lists derived from the clause expressions.
unsigned getTotalComponentListNum() const { return NumComponentLists; }
+
/// \brief Return the total number of components in all lists derived from the
/// clause.
unsigned getTotalComponentsNum() const { return NumComponents; }
@@ -3317,11 +3585,11 @@ public:
ArrayRef<unsigned>::iterator NumListsCur;
// Remaining lists for the current declaration.
- unsigned RemainingLists;
+ unsigned RemainingLists = 0;
// The cumulative size of the previous list, or zero if there is no previous
// list.
- unsigned PrevListSize;
+ unsigned PrevListSize = 0;
// The cumulative sizes of the current list - it will delimit the remaining
// range of interest.
@@ -3340,7 +3608,6 @@ public:
: const_component_lists_iterator::iterator_adaptor_base(
Components.begin()),
DeclCur(UniqueDecls.begin()), NumListsCur(DeclsListNum.begin()),
- RemainingLists(0u), PrevListSize(0u),
ListSizeCur(CumulativeListSizes.begin()),
ListSizeEnd(CumulativeListSizes.end()), End(Components.end()) {
assert(UniqueDecls.size() == DeclsListNum.size() &&
@@ -3357,7 +3624,6 @@ public:
MappableExprComponentListRef Components)
: const_component_lists_iterator(UniqueDecls, DeclsListNum,
CumulativeListSizes, Components) {
-
// Look for the desired declaration. While we are looking for it, we
// update the state so that we know the component where a given list
// starts.
@@ -3437,8 +3703,8 @@ public:
}
};
- typedef llvm::iterator_range<const_component_lists_iterator>
- const_component_lists_range;
+ using const_component_lists_range =
+ llvm::iterator_range<const_component_lists_iterator>;
/// \brief Iterators for all component lists.
const_component_lists_iterator component_lists_begin() const {
@@ -3473,32 +3739,36 @@ public:
/// Iterators to access all the declarations, number of lists, list sizes, and
/// components.
- typedef ArrayRef<ValueDecl *>::iterator const_all_decls_iterator;
- typedef llvm::iterator_range<const_all_decls_iterator> const_all_decls_range;
+ using const_all_decls_iterator = ArrayRef<ValueDecl *>::iterator;
+ using const_all_decls_range = llvm::iterator_range<const_all_decls_iterator>;
+
const_all_decls_range all_decls() const {
auto A = getUniqueDeclsRef();
return const_all_decls_range(A.begin(), A.end());
}
- typedef ArrayRef<unsigned>::iterator const_all_num_lists_iterator;
- typedef llvm::iterator_range<const_all_num_lists_iterator>
- const_all_num_lists_range;
+ using const_all_num_lists_iterator = ArrayRef<unsigned>::iterator;
+ using const_all_num_lists_range =
+ llvm::iterator_range<const_all_num_lists_iterator>;
+
const_all_num_lists_range all_num_lists() const {
auto A = getDeclNumListsRef();
return const_all_num_lists_range(A.begin(), A.end());
}
- typedef ArrayRef<unsigned>::iterator const_all_lists_sizes_iterator;
- typedef llvm::iterator_range<const_all_lists_sizes_iterator>
- const_all_lists_sizes_range;
+ using const_all_lists_sizes_iterator = ArrayRef<unsigned>::iterator;
+ using const_all_lists_sizes_range =
+ llvm::iterator_range<const_all_lists_sizes_iterator>;
+
const_all_lists_sizes_range all_lists_sizes() const {
auto A = getComponentListSizesRef();
return const_all_lists_sizes_range(A.begin(), A.end());
}
- typedef ArrayRef<MappableComponent>::iterator const_all_components_iterator;
- typedef llvm::iterator_range<const_all_components_iterator>
- const_all_components_range;
+ using const_all_components_iterator = ArrayRef<MappableComponent>::iterator;
+ using const_all_components_range =
+ llvm::iterator_range<const_all_components_iterator>;
+
const_all_components_range all_components() const {
auto A = getComponentsRef();
return const_all_components_range(A.begin(), A.end());
@@ -3513,15 +3783,14 @@ public:
/// \endcode
/// In this example directive '#pragma omp target' has clause 'map'
/// with the variables 'a' and 'b'.
-///
class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>,
private llvm::TrailingObjects<
OMPMapClause, Expr *, ValueDecl *, unsigned,
OMPClauseMappableExprCommon::MappableComponent> {
- friend TrailingObjects;
- friend OMPVarListClause;
- friend OMPMappableExprListClause;
friend class OMPClauseReader;
+ friend OMPMappableExprListClause;
+ friend OMPVarListClause;
+ friend TrailingObjects;
/// Define the sizes of each trailing object array except the last one. This
/// is required for TrailingObjects to work properly.
@@ -3536,37 +3805,20 @@ class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>,
}
/// \brief Map type modifier for the 'map' clause.
- OpenMPMapClauseKind MapTypeModifier;
+ OpenMPMapClauseKind MapTypeModifier = OMPC_MAP_unknown;
+
/// \brief Map type for the 'map' clause.
- OpenMPMapClauseKind MapType;
+ OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
+
/// \brief Is this an implicit map type or not.
- bool MapTypeIsImplicit;
+ bool MapTypeIsImplicit = false;
+
/// \brief Location of the map type.
SourceLocation MapLoc;
+
/// \brief Colon location.
SourceLocation ColonLoc;
- /// \brief Set type modifier for the clause.
- ///
- /// \param T Type Modifier for the clause.
- ///
- void setMapTypeModifier(OpenMPMapClauseKind T) { MapTypeModifier = T; }
-
- /// \brief Set type for the clause.
- ///
- /// \param T Type for the clause.
- ///
- void setMapType(OpenMPMapClauseKind T) { MapType = T; }
-
- /// \brief Set type location.
- ///
- /// \param TLoc Type location.
- ///
- void setMapLoc(SourceLocation TLoc) { MapLoc = TLoc; }
-
- /// \brief Set colon location.
- void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
-
/// \brief Build a clause for \a NumVars listed expressions, \a
/// NumUniqueDeclarations declarations, \a NumComponentLists total component
/// lists, and \a NumComponents total expression components.
@@ -3582,7 +3834,6 @@ class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>,
/// clause.
/// \param NumComponentLists Number of component lists in this clause.
/// \param NumComponents Total number of expression components in the clause.
- ///
explicit OMPMapClause(OpenMPMapClauseKind MapTypeModifier,
OpenMPMapClauseKind MapType, bool MapTypeIsImplicit,
SourceLocation MapLoc, SourceLocation StartLoc,
@@ -3602,14 +3853,29 @@ class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>,
/// clause.
/// \param NumComponentLists Number of component lists in this clause.
/// \param NumComponents Total number of expression components in the clause.
- ///
explicit OMPMapClause(unsigned NumVars, unsigned NumUniqueDeclarations,
unsigned NumComponentLists, unsigned NumComponents)
: OMPMappableExprListClause(
OMPC_map, SourceLocation(), SourceLocation(), SourceLocation(),
- NumVars, NumUniqueDeclarations, NumComponentLists, NumComponents),
- MapTypeModifier(OMPC_MAP_unknown), MapType(OMPC_MAP_unknown),
- MapTypeIsImplicit(false), MapLoc() {}
+ NumVars, NumUniqueDeclarations, NumComponentLists, NumComponents) {}
+
+ /// \brief Set type modifier for the clause.
+ ///
+ /// \param T Type Modifier for the clause.
+ void setMapTypeModifier(OpenMPMapClauseKind T) { MapTypeModifier = T; }
+
+ /// \brief Set type for the clause.
+ ///
+ /// \param T Type for the clause.
+ void setMapType(OpenMPMapClauseKind T) { MapType = T; }
+
+ /// \brief Set type location.
+ ///
+ /// \param TLoc Type location.
+ void setMapLoc(SourceLocation TLoc) { MapLoc = TLoc; }
+
+ /// \brief Set colon location.
+ void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
public:
/// \brief Creates clause with a list of variables \a VL.
@@ -3624,7 +3890,6 @@ public:
/// \param Type Map type.
/// \param TypeIsImplicit Map type is inferred implicitly.
/// \param TypeLoc Location of the map type.
- ///
static OMPMapClause *Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation EndLoc,
ArrayRef<Expr *> Vars,
@@ -3633,6 +3898,7 @@ public:
OpenMPMapClauseKind TypeModifier,
OpenMPMapClauseKind Type, bool TypeIsImplicit,
SourceLocation TypeLoc);
+
/// \brief Creates an empty clause with the place for for \a NumVars original
/// expressions, \a NumUniqueDeclarations declarations, \NumComponentLists
/// lists, and \a NumComponents expression components.
@@ -3644,7 +3910,6 @@ public:
/// \param NumComponentLists Number of unique base declarations in this
/// clause.
/// \param NumComponents Total number of expression components in the clause.
- ///
static OMPMapClause *CreateEmpty(const ASTContext &C, unsigned NumVars,
unsigned NumUniqueDeclarations,
unsigned NumComponentLists,
@@ -3671,15 +3936,15 @@ public:
/// \brief Get colon location.
SourceLocation getColonLoc() const { return ColonLoc; }
- static bool classof(const OMPClause *T) {
- return T->getClauseKind() == OMPC_map;
- }
-
child_range children() {
return child_range(
reinterpret_cast<Stmt **>(varlist_begin()),
reinterpret_cast<Stmt **>(varlist_end()));
}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_map;
+ }
};
/// \brief This represents 'num_teams' clause in the '#pragma omp ...'
@@ -3690,17 +3955,18 @@ public:
/// \endcode
/// In this example directive '#pragma omp teams' has clause 'num_teams'
/// with single expression 'n'.
-///
class OMPNumTeamsClause : public OMPClause, public OMPClauseWithPreInit {
friend class OMPClauseReader;
+
/// \brief Location of '('.
SourceLocation LParenLoc;
+
/// \brief NumTeams number.
- Stmt *NumTeams;
+ Stmt *NumTeams = nullptr;
+
/// \brief Set the NumTeams number.
///
/// \param E NumTeams number.
- ///
void setNumTeams(Expr *E) { NumTeams = E; }
public:
@@ -3713,7 +3979,6 @@ public:
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
- ///
OMPNumTeamsClause(Expr *E, Stmt *HelperE, OpenMPDirectiveKind CaptureRegion,
SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc)
@@ -3723,25 +3988,27 @@ public:
}
/// \brief Build an empty clause.
- ///
OMPNumTeamsClause()
: OMPClause(OMPC_num_teams, SourceLocation(), SourceLocation()),
- OMPClauseWithPreInit(this), LParenLoc(SourceLocation()),
- NumTeams(nullptr) {}
+ OMPClauseWithPreInit(this) {}
+
/// \brief Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+
/// \brief Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
+
/// \brief Return NumTeams number.
Expr *getNumTeams() { return cast<Expr>(NumTeams); }
+
/// \brief Return NumTeams number.
Expr *getNumTeams() const { return cast<Expr>(NumTeams); }
+ child_range children() { return child_range(&NumTeams, &NumTeams + 1); }
+
static bool classof(const OMPClause *T) {
return T->getClauseKind() == OMPC_num_teams;
}
-
- child_range children() { return child_range(&NumTeams, &NumTeams + 1); }
};
/// \brief This represents 'thread_limit' clause in the '#pragma omp ...'
@@ -3752,17 +4019,18 @@ public:
/// \endcode
/// In this example directive '#pragma omp teams' has clause 'thread_limit'
/// with single expression 'n'.
-///
class OMPThreadLimitClause : public OMPClause, public OMPClauseWithPreInit {
friend class OMPClauseReader;
+
/// \brief Location of '('.
SourceLocation LParenLoc;
+
/// \brief ThreadLimit number.
- Stmt *ThreadLimit;
+ Stmt *ThreadLimit = nullptr;
+
/// \brief Set the ThreadLimit number.
///
/// \param E ThreadLimit number.
- ///
void setThreadLimit(Expr *E) { ThreadLimit = E; }
public:
@@ -3775,7 +4043,6 @@ public:
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
- ///
OMPThreadLimitClause(Expr *E, Stmt *HelperE,
OpenMPDirectiveKind CaptureRegion,
SourceLocation StartLoc, SourceLocation LParenLoc,
@@ -3786,25 +4053,27 @@ public:
}
/// \brief Build an empty clause.
- ///
OMPThreadLimitClause()
: OMPClause(OMPC_thread_limit, SourceLocation(), SourceLocation()),
- OMPClauseWithPreInit(this), LParenLoc(SourceLocation()),
- ThreadLimit(nullptr) {}
+ OMPClauseWithPreInit(this) {}
+
/// \brief Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+
/// \brief Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
+
/// \brief Return ThreadLimit number.
Expr *getThreadLimit() { return cast<Expr>(ThreadLimit); }
+
/// \brief Return ThreadLimit number.
Expr *getThreadLimit() const { return cast<Expr>(ThreadLimit); }
+ child_range children() { return child_range(&ThreadLimit, &ThreadLimit + 1); }
+
static bool classof(const OMPClause *T) {
return T->getClauseKind() == OMPC_thread_limit;
}
-
- child_range children() { return child_range(&ThreadLimit, &ThreadLimit + 1); }
};
/// \brief This represents 'priority' clause in the '#pragma omp ...'
@@ -3815,17 +4084,18 @@ public:
/// \endcode
/// In this example directive '#pragma omp teams' has clause 'priority' with
/// single expression 'n'.
-///
class OMPPriorityClause : public OMPClause {
friend class OMPClauseReader;
+
/// \brief Location of '('.
SourceLocation LParenLoc;
+
/// \brief Priority number.
- Stmt *Priority;
+ Stmt *Priority = nullptr;
+
/// \brief Set the Priority number.
///
/// \param E Priority number.
- ///
void setPriority(Expr *E) { Priority = E; }
public:
@@ -3835,31 +4105,32 @@ public:
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
- ///
OMPPriorityClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc)
: OMPClause(OMPC_priority, StartLoc, EndLoc), LParenLoc(LParenLoc),
Priority(E) {}
/// \brief Build an empty clause.
- ///
OMPPriorityClause()
- : OMPClause(OMPC_priority, SourceLocation(), SourceLocation()),
- LParenLoc(SourceLocation()), Priority(nullptr) {}
+ : OMPClause(OMPC_priority, SourceLocation(), SourceLocation()) {}
+
/// \brief Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+
/// \brief Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
+
/// \brief Return Priority number.
Expr *getPriority() { return cast<Expr>(Priority); }
+
/// \brief Return Priority number.
Expr *getPriority() const { return cast<Expr>(Priority); }
+ child_range children() { return child_range(&Priority, &Priority + 1); }
+
static bool classof(const OMPClause *T) {
return T->getClauseKind() == OMPC_priority;
}
-
- child_range children() { return child_range(&Priority, &Priority + 1); }
};
/// \brief This represents 'grainsize' clause in the '#pragma omp ...'
@@ -3870,13 +4141,14 @@ public:
/// \endcode
/// In this example directive '#pragma omp taskloop' has clause 'grainsize'
/// with single expression '4'.
-///
class OMPGrainsizeClause : public OMPClause {
friend class OMPClauseReader;
+
/// \brief Location of '('.
SourceLocation LParenLoc;
+
/// \brief Safe iteration space distance.
- Stmt *Grainsize;
+ Stmt *Grainsize = nullptr;
/// \brief Set safelen.
void setGrainsize(Expr *Size) { Grainsize = Size; }
@@ -3887,31 +4159,29 @@ public:
/// \param Size Expression associated with this clause.
/// \param StartLoc Starting location of the clause.
/// \param EndLoc Ending location of the clause.
- ///
OMPGrainsizeClause(Expr *Size, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation EndLoc)
: OMPClause(OMPC_grainsize, StartLoc, EndLoc), LParenLoc(LParenLoc),
Grainsize(Size) {}
/// \brief Build an empty clause.
- ///
explicit OMPGrainsizeClause()
- : OMPClause(OMPC_grainsize, SourceLocation(), SourceLocation()),
- LParenLoc(SourceLocation()), Grainsize(nullptr) {}
+ : OMPClause(OMPC_grainsize, SourceLocation(), SourceLocation()) {}
/// \brief Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+
/// \brief Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
/// \brief Return safe iteration space distance.
Expr *getGrainsize() const { return cast_or_null<Expr>(Grainsize); }
+ child_range children() { return child_range(&Grainsize, &Grainsize + 1); }
+
static bool classof(const OMPClause *T) {
return T->getClauseKind() == OMPC_grainsize;
}
-
- child_range children() { return child_range(&Grainsize, &Grainsize + 1); }
};
/// \brief This represents 'nogroup' clause in the '#pragma omp ...' directive.
@@ -3920,29 +4190,26 @@ public:
/// #pragma omp taskloop nogroup
/// \endcode
/// In this example directive '#pragma omp taskloop' has 'nogroup' clause.
-///
class OMPNogroupClause : public OMPClause {
public:
/// \brief Build 'nogroup' clause.
///
/// \param StartLoc Starting location of the clause.
/// \param EndLoc Ending location of the clause.
- ///
OMPNogroupClause(SourceLocation StartLoc, SourceLocation EndLoc)
: OMPClause(OMPC_nogroup, StartLoc, EndLoc) {}
/// \brief Build an empty clause.
- ///
OMPNogroupClause()
: OMPClause(OMPC_nogroup, SourceLocation(), SourceLocation()) {}
- static bool classof(const OMPClause *T) {
- return T->getClauseKind() == OMPC_nogroup;
- }
-
child_range children() {
return child_range(child_iterator(), child_iterator());
}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_nogroup;
+ }
};
/// \brief This represents 'num_tasks' clause in the '#pragma omp ...'
@@ -3953,13 +4220,14 @@ public:
/// \endcode
/// In this example directive '#pragma omp taskloop' has clause 'num_tasks'
/// with single expression '4'.
-///
class OMPNumTasksClause : public OMPClause {
friend class OMPClauseReader;
+
/// \brief Location of '('.
SourceLocation LParenLoc;
+
/// \brief Safe iteration space distance.
- Stmt *NumTasks;
+ Stmt *NumTasks = nullptr;
/// \brief Set safelen.
void setNumTasks(Expr *Size) { NumTasks = Size; }
@@ -3970,31 +4238,29 @@ public:
/// \param Size Expression associated with this clause.
/// \param StartLoc Starting location of the clause.
/// \param EndLoc Ending location of the clause.
- ///
OMPNumTasksClause(Expr *Size, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation EndLoc)
: OMPClause(OMPC_num_tasks, StartLoc, EndLoc), LParenLoc(LParenLoc),
NumTasks(Size) {}
/// \brief Build an empty clause.
- ///
explicit OMPNumTasksClause()
- : OMPClause(OMPC_num_tasks, SourceLocation(), SourceLocation()),
- LParenLoc(SourceLocation()), NumTasks(nullptr) {}
+ : OMPClause(OMPC_num_tasks, SourceLocation(), SourceLocation()) {}
/// \brief Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+
/// \brief Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
/// \brief Return safe iteration space distance.
Expr *getNumTasks() const { return cast_or_null<Expr>(NumTasks); }
+ child_range children() { return child_range(&NumTasks, &NumTasks + 1); }
+
static bool classof(const OMPClause *T) {
return T->getClauseKind() == OMPC_num_tasks;
}
-
- child_range children() { return child_range(&NumTasks, &NumTasks + 1); }
};
/// \brief This represents 'hint' clause in the '#pragma omp ...' directive.
@@ -4004,16 +4270,16 @@ public:
/// \endcode
/// In this example directive '#pragma omp critical' has name 'name' and clause
/// 'hint' with argument '6'.
-///
class OMPHintClause : public OMPClause {
friend class OMPClauseReader;
+
/// \brief Location of '('.
SourceLocation LParenLoc;
+
/// \brief Hint expression of the 'hint' clause.
- Stmt *Hint;
+ Stmt *Hint = nullptr;
/// \brief Set hint expression.
- ///
void setHint(Expr *H) { Hint = H; }
public:
@@ -4023,31 +4289,28 @@ public:
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
- ///
OMPHintClause(Expr *Hint, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc)
: OMPClause(OMPC_hint, StartLoc, EndLoc), LParenLoc(LParenLoc),
Hint(Hint) {}
/// \brief Build an empty clause.
- ///
- OMPHintClause()
- : OMPClause(OMPC_hint, SourceLocation(), SourceLocation()),
- LParenLoc(SourceLocation()), Hint(nullptr) {}
+ OMPHintClause() : OMPClause(OMPC_hint, SourceLocation(), SourceLocation()) {}
/// \brief Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+
/// \brief Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
/// \brief Returns number of threads.
Expr *getHint() const { return cast_or_null<Expr>(Hint); }
+ child_range children() { return child_range(&Hint, &Hint + 1); }
+
static bool classof(const OMPClause *T) {
return T->getClauseKind() == OMPC_hint;
}
-
- child_range children() { return child_range(&Hint, &Hint + 1); }
};
/// \brief This represents 'dist_schedule' clause in the '#pragma omp ...'
@@ -4058,44 +4321,47 @@ public:
/// \endcode
/// In this example directive '#pragma omp distribute' has 'dist_schedule'
/// clause with arguments 'static' and '3'.
-///
class OMPDistScheduleClause : public OMPClause, public OMPClauseWithPreInit {
friend class OMPClauseReader;
+
/// \brief Location of '('.
SourceLocation LParenLoc;
+
/// \brief A kind of the 'schedule' clause.
- OpenMPDistScheduleClauseKind Kind;
+ OpenMPDistScheduleClauseKind Kind = OMPC_DIST_SCHEDULE_unknown;
+
/// \brief Start location of the schedule kind in source code.
SourceLocation KindLoc;
+
/// \brief Location of ',' (if any).
SourceLocation CommaLoc;
+
/// \brief Chunk size.
- Expr *ChunkSize;
+ Expr *ChunkSize = nullptr;
/// \brief Set schedule kind.
///
/// \param K Schedule kind.
- ///
void setDistScheduleKind(OpenMPDistScheduleClauseKind K) { Kind = K; }
+
/// \brief Sets the location of '('.
///
/// \param Loc Location of '('.
- ///
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+
/// \brief Set schedule kind start location.
///
/// \param KLoc Schedule kind location.
- ///
void setDistScheduleKindLoc(SourceLocation KLoc) { KindLoc = KLoc; }
+
/// \brief Set location of ','.
///
/// \param Loc Location of ','.
- ///
void setCommaLoc(SourceLocation Loc) { CommaLoc = Loc; }
+
/// \brief Set chunk size.
///
/// \param E Chunk size.
- ///
void setChunkSize(Expr *E) { ChunkSize = E; }
public:
@@ -4110,7 +4376,6 @@ public:
/// \param Kind DistSchedule kind.
/// \param ChunkSize Chunk size.
/// \param HelperChunkSize Helper chunk size for combined directives.
- ///
OMPDistScheduleClause(SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation KLoc, SourceLocation CommaLoc,
SourceLocation EndLoc,
@@ -4123,39 +4388,36 @@ public:
}
/// \brief Build an empty clause.
- ///
explicit OMPDistScheduleClause()
: OMPClause(OMPC_dist_schedule, SourceLocation(), SourceLocation()),
- OMPClauseWithPreInit(this), Kind(OMPC_DIST_SCHEDULE_unknown),
- ChunkSize(nullptr) {}
+ OMPClauseWithPreInit(this) {}
/// \brief Get kind of the clause.
- ///
OpenMPDistScheduleClauseKind getDistScheduleKind() const { return Kind; }
+
/// \brief Get location of '('.
- ///
SourceLocation getLParenLoc() { return LParenLoc; }
+
/// \brief Get kind location.
- ///
SourceLocation getDistScheduleKindLoc() { return KindLoc; }
+
/// \brief Get location of ','.
- ///
SourceLocation getCommaLoc() { return CommaLoc; }
+
/// \brief Get chunk size.
- ///
Expr *getChunkSize() { return ChunkSize; }
+
/// \brief Get chunk size.
- ///
const Expr *getChunkSize() const { return ChunkSize; }
- static bool classof(const OMPClause *T) {
- return T->getClauseKind() == OMPC_dist_schedule;
- }
-
child_range children() {
return child_range(reinterpret_cast<Stmt **>(&ChunkSize),
reinterpret_cast<Stmt **>(&ChunkSize) + 1);
}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_dist_schedule;
+ }
};
/// \brief This represents 'defaultmap' clause in the '#pragma omp ...' directive.
@@ -4165,46 +4427,49 @@ public:
/// \endcode
/// In this example directive '#pragma omp target' has 'defaultmap' clause of kind
/// 'scalar' with modifier 'tofrom'.
-///
class OMPDefaultmapClause : public OMPClause {
friend class OMPClauseReader;
+
/// \brief Location of '('.
SourceLocation LParenLoc;
+
/// \brief Modifiers for 'defaultmap' clause.
- OpenMPDefaultmapClauseModifier Modifier;
+ OpenMPDefaultmapClauseModifier Modifier = OMPC_DEFAULTMAP_MODIFIER_unknown;
+
/// \brief Locations of modifiers.
SourceLocation ModifierLoc;
+
/// \brief A kind of the 'defaultmap' clause.
- OpenMPDefaultmapClauseKind Kind;
+ OpenMPDefaultmapClauseKind Kind = OMPC_DEFAULTMAP_unknown;
+
/// \brief Start location of the defaultmap kind in source code.
SourceLocation KindLoc;
/// \brief Set defaultmap kind.
///
/// \param K Defaultmap kind.
- ///
void setDefaultmapKind(OpenMPDefaultmapClauseKind K) { Kind = K; }
+
/// \brief Set the defaultmap modifier.
///
/// \param M Defaultmap modifier.
- ///
void setDefaultmapModifier(OpenMPDefaultmapClauseModifier M) {
Modifier = M;
}
+
/// \brief Set location of the defaultmap modifier.
- ///
void setDefaultmapModifierLoc(SourceLocation Loc) {
ModifierLoc = Loc;
}
+
/// \brief Sets the location of '('.
///
/// \param Loc Location of '('.
- ///
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+
/// \brief Set defaultmap kind start location.
///
/// \param KLoc Defaultmap kind location.
- ///
void setDefaultmapKindLoc(SourceLocation KLoc) { KindLoc = KLoc; }
public:
@@ -4217,7 +4482,6 @@ public:
/// \param Kind Defaultmap kind.
/// \param M The modifier applied to 'defaultmap' clause.
/// \param MLoc Location of the modifier
- ///
OMPDefaultmapClause(SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation MLoc, SourceLocation KLoc,
SourceLocation EndLoc, OpenMPDefaultmapClauseKind Kind,
@@ -4226,39 +4490,35 @@ public:
Modifier(M), ModifierLoc(MLoc), Kind(Kind), KindLoc(KLoc) {}
/// \brief Build an empty clause.
- ///
explicit OMPDefaultmapClause()
- : OMPClause(OMPC_defaultmap, SourceLocation(), SourceLocation()),
- Modifier(OMPC_DEFAULTMAP_MODIFIER_unknown),
- Kind(OMPC_DEFAULTMAP_unknown) {}
+ : OMPClause(OMPC_defaultmap, SourceLocation(), SourceLocation()) {}
/// \brief Get kind of the clause.
- ///
OpenMPDefaultmapClauseKind getDefaultmapKind() const { return Kind; }
+
/// \brief Get the modifier of the clause.
- ///
OpenMPDefaultmapClauseModifier getDefaultmapModifier() const {
return Modifier;
}
+
/// \brief Get location of '('.
- ///
SourceLocation getLParenLoc() { return LParenLoc; }
+
/// \brief Get kind location.
- ///
SourceLocation getDefaultmapKindLoc() { return KindLoc; }
+
/// \brief Get the modifier location.
- ///
SourceLocation getDefaultmapModifierLoc() const {
return ModifierLoc;
}
- static bool classof(const OMPClause *T) {
- return T->getClauseKind() == OMPC_defaultmap;
- }
-
child_range children() {
return child_range(child_iterator(), child_iterator());
}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_defaultmap;
+ }
};
/// \brief This represents clause 'to' in the '#pragma omp ...'
@@ -4269,27 +4529,14 @@ public:
/// \endcode
/// In this example directive '#pragma omp target update' has clause 'to'
/// with the variables 'a' and 'b'.
-///
class OMPToClause final : public OMPMappableExprListClause<OMPToClause>,
private llvm::TrailingObjects<
OMPToClause, Expr *, ValueDecl *, unsigned,
OMPClauseMappableExprCommon::MappableComponent> {
- friend TrailingObjects;
- friend OMPVarListClause;
- friend OMPMappableExprListClause;
friend class OMPClauseReader;
-
- /// Define the sizes of each trailing object array except the last one. This
- /// is required for TrailingObjects to work properly.
- size_t numTrailingObjects(OverloadToken<Expr *>) const {
- return varlist_size();
- }
- size_t numTrailingObjects(OverloadToken<ValueDecl *>) const {
- return getUniqueDeclarationsNum();
- }
- size_t numTrailingObjects(OverloadToken<unsigned>) const {
- return getUniqueDeclarationsNum() + getTotalComponentListNum();
- }
+ friend OMPMappableExprListClause;
+ friend OMPVarListClause;
+ friend TrailingObjects;
/// \brief Build clause with number of variables \a NumVars.
///
@@ -4300,7 +4547,6 @@ class OMPToClause final : public OMPMappableExprListClause<OMPToClause>,
/// clause.
/// \param NumComponentLists Number of component lists in this clause.
/// \param NumComponents Total number of expression components in the clause.
- ///
explicit OMPToClause(SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, unsigned NumVars,
unsigned NumUniqueDeclarations,
@@ -4316,13 +4562,24 @@ class OMPToClause final : public OMPMappableExprListClause<OMPToClause>,
/// clause.
/// \param NumComponentLists Number of component lists in this clause.
/// \param NumComponents Total number of expression components in the clause.
- ///
explicit OMPToClause(unsigned NumVars, unsigned NumUniqueDeclarations,
unsigned NumComponentLists, unsigned NumComponents)
: OMPMappableExprListClause(
OMPC_to, SourceLocation(), SourceLocation(), SourceLocation(),
NumVars, NumUniqueDeclarations, NumComponentLists, NumComponents) {}
+ /// Define the sizes of each trailing object array except the last one. This
+ /// is required for TrailingObjects to work properly.
+ size_t numTrailingObjects(OverloadToken<Expr *>) const {
+ return varlist_size();
+ }
+ size_t numTrailingObjects(OverloadToken<ValueDecl *>) const {
+ return getUniqueDeclarationsNum();
+ }
+ size_t numTrailingObjects(OverloadToken<unsigned>) const {
+ return getUniqueDeclarationsNum() + getTotalComponentListNum();
+ }
+
public:
/// \brief Creates clause with a list of variables \a Vars.
///
@@ -4332,7 +4589,6 @@ public:
/// \param Vars The original expression used in the clause.
/// \param Declarations Declarations used in the clause.
/// \param ComponentLists Component lists used in the clause.
- ///
static OMPToClause *Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation EndLoc,
ArrayRef<Expr *> Vars,
@@ -4348,20 +4604,19 @@ public:
/// \param NumComponentLists Number of unique base declarations in this
/// clause.
/// \param NumComponents Total number of expression components in the clause.
- ///
static OMPToClause *CreateEmpty(const ASTContext &C, unsigned NumVars,
unsigned NumUniqueDeclarations,
unsigned NumComponentLists,
unsigned NumComponents);
- static bool classof(const OMPClause *T) {
- return T->getClauseKind() == OMPC_to;
- }
-
child_range children() {
return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
reinterpret_cast<Stmt **>(varlist_end()));
}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_to;
+ }
};
/// \brief This represents clause 'from' in the '#pragma omp ...'
@@ -4372,28 +4627,15 @@ public:
/// \endcode
/// In this example directive '#pragma omp target update' has clause 'from'
/// with the variables 'a' and 'b'.
-///
class OMPFromClause final
: public OMPMappableExprListClause<OMPFromClause>,
private llvm::TrailingObjects<
OMPFromClause, Expr *, ValueDecl *, unsigned,
OMPClauseMappableExprCommon::MappableComponent> {
- friend TrailingObjects;
- friend OMPVarListClause;
- friend OMPMappableExprListClause;
friend class OMPClauseReader;
-
- /// Define the sizes of each trailing object array except the last one. This
- /// is required for TrailingObjects to work properly.
- size_t numTrailingObjects(OverloadToken<Expr *>) const {
- return varlist_size();
- }
- size_t numTrailingObjects(OverloadToken<ValueDecl *>) const {
- return getUniqueDeclarationsNum();
- }
- size_t numTrailingObjects(OverloadToken<unsigned>) const {
- return getUniqueDeclarationsNum() + getTotalComponentListNum();
- }
+ friend OMPMappableExprListClause;
+ friend OMPVarListClause;
+ friend TrailingObjects;
/// \brief Build clause with number of variables \a NumVars.
///
@@ -4404,7 +4646,6 @@ class OMPFromClause final
/// clause.
/// \param NumComponentLists Number of component lists in this clause.
/// \param NumComponents Total number of expression components in the clause.
- ///
explicit OMPFromClause(SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, unsigned NumVars,
unsigned NumUniqueDeclarations,
@@ -4420,13 +4661,24 @@ class OMPFromClause final
/// clause.
/// \param NumComponentLists Number of component lists in this clause.
/// \param NumComponents Total number of expression components in the clause.
- ///
explicit OMPFromClause(unsigned NumVars, unsigned NumUniqueDeclarations,
unsigned NumComponentLists, unsigned NumComponents)
: OMPMappableExprListClause(
OMPC_from, SourceLocation(), SourceLocation(), SourceLocation(),
NumVars, NumUniqueDeclarations, NumComponentLists, NumComponents) {}
+ /// Define the sizes of each trailing object array except the last one. This
+ /// is required for TrailingObjects to work properly.
+ size_t numTrailingObjects(OverloadToken<Expr *>) const {
+ return varlist_size();
+ }
+ size_t numTrailingObjects(OverloadToken<ValueDecl *>) const {
+ return getUniqueDeclarationsNum();
+ }
+ size_t numTrailingObjects(OverloadToken<unsigned>) const {
+ return getUniqueDeclarationsNum() + getTotalComponentListNum();
+ }
+
public:
/// \brief Creates clause with a list of variables \a Vars.
///
@@ -4436,7 +4688,6 @@ public:
/// \param Vars The original expression used in the clause.
/// \param Declarations Declarations used in the clause.
/// \param ComponentLists Component lists used in the clause.
- ///
static OMPFromClause *Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation EndLoc,
ArrayRef<Expr *> Vars,
@@ -4452,20 +4703,19 @@ public:
/// \param NumComponentLists Number of unique base declarations in this
/// clause.
/// \param NumComponents Total number of expression components in the clause.
- ///
static OMPFromClause *CreateEmpty(const ASTContext &C, unsigned NumVars,
unsigned NumUniqueDeclarations,
unsigned NumComponentLists,
unsigned NumComponents);
- static bool classof(const OMPClause *T) {
- return T->getClauseKind() == OMPC_from;
- }
-
child_range children() {
return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
reinterpret_cast<Stmt **>(varlist_end()));
}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_from;
+ }
};
/// This represents clause 'use_device_ptr' in the '#pragma omp ...'
@@ -4476,28 +4726,15 @@ public:
/// \endcode
/// In this example directive '#pragma omp target data' has clause
/// 'use_device_ptr' with the variables 'a' and 'b'.
-///
class OMPUseDevicePtrClause final
: public OMPMappableExprListClause<OMPUseDevicePtrClause>,
private llvm::TrailingObjects<
OMPUseDevicePtrClause, Expr *, ValueDecl *, unsigned,
OMPClauseMappableExprCommon::MappableComponent> {
- friend TrailingObjects;
- friend OMPVarListClause;
- friend OMPMappableExprListClause;
friend class OMPClauseReader;
-
- /// Define the sizes of each trailing object array except the last one. This
- /// is required for TrailingObjects to work properly.
- size_t numTrailingObjects(OverloadToken<Expr *>) const {
- return 3 * varlist_size();
- }
- size_t numTrailingObjects(OverloadToken<ValueDecl *>) const {
- return getUniqueDeclarationsNum();
- }
- size_t numTrailingObjects(OverloadToken<unsigned>) const {
- return getUniqueDeclarationsNum() + getTotalComponentListNum();
- }
+ friend OMPMappableExprListClause;
+ friend OMPVarListClause;
+ friend TrailingObjects;
/// Build clause with number of variables \a NumVars.
///
@@ -4508,7 +4745,6 @@ class OMPUseDevicePtrClause final
/// clause.
/// \param NumComponentLists Number of component lists in this clause.
/// \param NumComponents Total number of expression components in the clause.
- ///
explicit OMPUseDevicePtrClause(SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc, unsigned NumVars,
@@ -4526,7 +4762,6 @@ class OMPUseDevicePtrClause final
/// clause.
/// \param NumComponentLists Number of component lists in this clause.
/// \param NumComponents Total number of expression components in the clause.
- ///
explicit OMPUseDevicePtrClause(unsigned NumVars,
unsigned NumUniqueDeclarations,
unsigned NumComponentLists,
@@ -4536,6 +4771,18 @@ class OMPUseDevicePtrClause final
NumUniqueDeclarations, NumComponentLists,
NumComponents) {}
+ /// Define the sizes of each trailing object array except the last one. This
+ /// is required for TrailingObjects to work properly.
+ size_t numTrailingObjects(OverloadToken<Expr *>) const {
+ return 3 * varlist_size();
+ }
+ size_t numTrailingObjects(OverloadToken<ValueDecl *>) const {
+ return getUniqueDeclarationsNum();
+ }
+ size_t numTrailingObjects(OverloadToken<unsigned>) const {
+ return getUniqueDeclarationsNum() + getTotalComponentListNum();
+ }
+
/// Sets the list of references to private copies with initializers for new
/// private variables.
/// \param VL List of references.
@@ -4575,7 +4822,6 @@ public:
/// \param Inits Expressions referring to private copy initializers.
/// \param Declarations Declarations used in the clause.
/// \param ComponentLists Component lists used in the clause.
- ///
static OMPUseDevicePtrClause *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, ArrayRef<Expr *> Vars,
@@ -4592,36 +4838,37 @@ public:
/// \param NumComponentLists Number of unique base declarations in this
/// clause.
/// \param NumComponents Total number of expression components in the clause.
- ///
static OMPUseDevicePtrClause *CreateEmpty(const ASTContext &C,
unsigned NumVars,
unsigned NumUniqueDeclarations,
unsigned NumComponentLists,
unsigned NumComponents);
- 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;
+ using private_copies_iterator = MutableArrayRef<Expr *>::iterator;
+ using private_copies_const_iterator = ArrayRef<const Expr *>::iterator;
+ using private_copies_range = llvm::iterator_range<private_copies_iterator>;
+ using private_copies_const_range =
+ llvm::iterator_range<private_copies_const_iterator>;
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;
+ using inits_iterator = MutableArrayRef<Expr *>::iterator;
+ using inits_const_iterator = ArrayRef<const Expr *>::iterator;
+ using inits_range = llvm::iterator_range<inits_iterator>;
+ using inits_const_range = llvm::iterator_range<inits_const_iterator>;
inits_range inits() {
return inits_range(getInits().begin(), getInits().end());
}
+
inits_const_range inits() const {
return inits_const_range(getInits().begin(), getInits().end());
}
@@ -4644,28 +4891,16 @@ public:
/// \endcode
/// In this example directive '#pragma omp target' has clause
/// 'is_device_ptr' with the variables 'a' and 'b'.
-///
class OMPIsDevicePtrClause final
: public OMPMappableExprListClause<OMPIsDevicePtrClause>,
private llvm::TrailingObjects<
OMPIsDevicePtrClause, Expr *, ValueDecl *, unsigned,
OMPClauseMappableExprCommon::MappableComponent> {
- friend TrailingObjects;
- friend OMPVarListClause;
- friend OMPMappableExprListClause;
friend class OMPClauseReader;
+ friend OMPMappableExprListClause;
+ friend OMPVarListClause;
+ friend TrailingObjects;
- /// Define the sizes of each trailing object array except the last one. This
- /// is required for TrailingObjects to work properly.
- size_t numTrailingObjects(OverloadToken<Expr *>) const {
- return varlist_size();
- }
- size_t numTrailingObjects(OverloadToken<ValueDecl *>) const {
- return getUniqueDeclarationsNum();
- }
- size_t numTrailingObjects(OverloadToken<unsigned>) const {
- return getUniqueDeclarationsNum() + getTotalComponentListNum();
- }
/// Build clause with number of variables \a NumVars.
///
/// \param StartLoc Starting location of the clause.
@@ -4675,7 +4910,6 @@ class OMPIsDevicePtrClause final
/// clause.
/// \param NumComponentLists Number of component lists in this clause.
/// \param NumComponents Total number of expression components in the clause.
- ///
explicit OMPIsDevicePtrClause(SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation EndLoc,
unsigned NumVars,
@@ -4693,7 +4927,6 @@ class OMPIsDevicePtrClause final
/// clause.
/// \param NumComponentLists Number of component lists in this clause.
/// \param NumComponents Total number of expression components in the clause.
- ///
explicit OMPIsDevicePtrClause(unsigned NumVars,
unsigned NumUniqueDeclarations,
unsigned NumComponentLists,
@@ -4703,6 +4936,18 @@ class OMPIsDevicePtrClause final
NumUniqueDeclarations, NumComponentLists,
NumComponents) {}
+ /// Define the sizes of each trailing object array except the last one. This
+ /// is required for TrailingObjects to work properly.
+ size_t numTrailingObjects(OverloadToken<Expr *>) const {
+ return varlist_size();
+ }
+ size_t numTrailingObjects(OverloadToken<ValueDecl *>) const {
+ return getUniqueDeclarationsNum();
+ }
+ size_t numTrailingObjects(OverloadToken<unsigned>) const {
+ return getUniqueDeclarationsNum() + getTotalComponentListNum();
+ }
+
public:
/// Creates clause with a list of variables \a Vars.
///
@@ -4712,7 +4957,6 @@ public:
/// \param Vars The original expression used in the clause.
/// \param Declarations Declarations used in the clause.
/// \param ComponentLists Component lists used in the clause.
- ///
static OMPIsDevicePtrClause *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, ArrayRef<Expr *> Vars,
@@ -4728,7 +4972,6 @@ public:
/// \param NumComponentLists Number of unique base declarations in this
/// clause.
/// \param NumComponents Total number of expression components in the clause.
- ///
static OMPIsDevicePtrClause *CreateEmpty(const ASTContext &C,
unsigned NumVars,
unsigned NumUniqueDeclarations,
@@ -4744,6 +4987,7 @@ public:
return T->getClauseKind() == OMPC_is_device_ptr;
}
};
-} // end namespace clang
+
+} // namespace clang
#endif // LLVM_CLANG_AST_OPENMPCLAUSE_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.def b/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.def
index 2d48a7df47b7a..b13cf3b63276f 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.def
+++ b/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.def
@@ -327,12 +327,13 @@ CAST_OPERATION(ZeroToOCLQueue)
// Convert a pointer to a different address space.
CAST_OPERATION(AddressSpaceConversion)
-// Convert an integer initializer to an OpenCL sampler.
+// Convert an integer initializer to an OpenCL sampler.
CAST_OPERATION(IntToOCLSampler)
//===- Binary Operations -------------------------------------------------===//
// Operators listed in order of precedence.
-// Note that additions to this should also update the StmtVisitor class.
+// Note that additions to this should also update the StmtVisitor class and
+// BinaryOperator::getOverloadedOperator.
// [C++ 5.5] Pointer-to-member operators.
BINARY_OPERATION(PtrMemD, ".*")
@@ -347,6 +348,8 @@ BINARY_OPERATION(Sub, "-")
// [C99 6.5.7] Bitwise shift operators.
BINARY_OPERATION(Shl, "<<")
BINARY_OPERATION(Shr, ">>")
+// C++20 [expr.spaceship] Three-way comparison operator.
+BINARY_OPERATION(Cmp, "<=>")
// [C99 6.5.8] Relational operators.
BINARY_OPERATION(LT, "<")
BINARY_OPERATION(GT, ">")
@@ -382,7 +385,8 @@ BINARY_OPERATION(Comma, ",")
//===- Unary Operations ---------------------------------------------------===//
-// Note that additions to this should also update the StmtVisitor class.
+// Note that additions to this should also update the StmtVisitor class and
+// UnaryOperator::getOverloadedOperator.
// [C99 6.5.2.4] Postfix increment and decrement
UNARY_OPERATION(PostInc, "++")
diff --git a/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.h b/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.h
index 00f060fe9e3d0..e3832689d64b8 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.h
@@ -23,8 +23,6 @@ enum CastKind {
#include "clang/AST/OperationKinds.def"
};
-static const CastKind CK_Invalid = static_cast<CastKind>(-1);
-
enum BinaryOperatorKind {
#define BINARY_OPERATION(Name, Spelling) BO_##Name,
#include "clang/AST/OperationKinds.def"
diff --git a/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h b/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h
index 274df220e160e..e831b903cbae6 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h
@@ -30,8 +30,8 @@ public:
virtual bool handledStmt(Stmt* E, raw_ostream& OS) = 0;
};
-/// \brief Describes how types, statements, expressions, and
-/// declarations should be printed.
+/// Describes how types, statements, expressions, and declarations should be
+/// printed.
///
/// This type is intended to be small and suitable for passing by value.
/// It is very frequently copied.
@@ -50,22 +50,24 @@ struct PrintingPolicy {
UseVoidForZeroParams(!LO.CPlusPlus),
TerseOutput(false), PolishForDeclaration(false),
Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar),
- IncludeNewlines(true), MSVCFormatting(false) { }
+ IncludeNewlines(true), MSVCFormatting(false),
+ ConstantsAsWritten(false), SuppressImplicitBase(false),
+ FullyQualifiedName(false) { }
- /// \brief Adjust this printing policy for cases where it's known that
- /// we're printing C++ code (for instance, if AST dumping reaches a
- /// C++-only construct). This should not be used if a real LangOptions
- /// object is available.
+ /// Adjust this printing policy for cases where it's known that we're
+ /// printing C++ code (for instance, if AST dumping reaches a C++-only
+ /// construct). This should not be used if a real LangOptions object is
+ /// available.
void adjustForCPlusPlus() {
SuppressTagKeyword = true;
Bool = true;
UseVoidForZeroParams = false;
}
- /// \brief The number of spaces to use to indent each line.
+ /// The number of spaces to use to indent each line.
unsigned Indentation : 8;
- /// \brief Whether we should suppress printing of the actual specifiers for
+ /// Whether we should suppress printing of the actual specifiers for
/// the given type or declaration.
///
/// This flag is only used when we are printing declarators beyond
@@ -81,7 +83,7 @@ struct PrintingPolicy {
/// "const int" type specifier and instead only print the "*y".
bool SuppressSpecifiers : 1;
- /// \brief Whether type printing should skip printing the tag keyword.
+ /// Whether type printing should skip printing the tag keyword.
///
/// This is used when printing the inner type of elaborated types,
/// (as the tag keyword is part of the elaborated type):
@@ -91,7 +93,7 @@ struct PrintingPolicy {
/// \endcode
bool SuppressTagKeyword : 1;
- /// \brief When true, include the body of a tag definition.
+ /// When true, include the body of a tag definition.
///
/// This is used to place the definition of a struct
/// in the middle of another declaration as with:
@@ -101,14 +103,14 @@ struct PrintingPolicy {
/// \endcode
bool IncludeTagDefinition : 1;
- /// \brief Suppresses printing of scope specifiers.
+ /// Suppresses printing of scope specifiers.
bool SuppressScope : 1;
- /// \brief Suppress printing parts of scope specifiers that don't need
+ /// Suppress printing parts of scope specifiers that don't need
/// to be written, e.g., for inline or anonymous namespaces.
bool SuppressUnwrittenScope : 1;
- /// \brief Suppress printing of variable initializers.
+ /// Suppress printing of variable initializers.
///
/// This flag is used when printing the loop variable in a for-range
/// statement. For example, given:
@@ -121,8 +123,8 @@ struct PrintingPolicy {
/// internal initializer constructed for x will not be printed.
bool SuppressInitializers : 1;
- /// \brief Whether we should print the sizes of constant array expressions
- /// as written in the sources.
+ /// Whether we should print the sizes of constant array expressions as written
+ /// in the sources.
///
/// This flag determines whether array types declared as
///
@@ -139,67 +141,90 @@ struct PrintingPolicy {
/// \endcode
bool ConstantArraySizeAsWritten : 1;
- /// \brief When printing an anonymous tag name, also print the location of
- /// that entity (e.g., "enum <anonymous at t.h:10:5>"). Otherwise, just
- /// prints "(anonymous)" for the name.
+ /// When printing an anonymous tag name, also print the location of that
+ /// entity (e.g., "enum <anonymous at t.h:10:5>"). Otherwise, just prints
+ /// "(anonymous)" for the name.
bool AnonymousTagLocations : 1;
- /// \brief When true, suppress printing of the __strong lifetime qualifier in
- /// ARC.
+ /// When true, suppress printing of the __strong lifetime qualifier in ARC.
unsigned SuppressStrongLifetime : 1;
- /// \brief When true, suppress printing of lifetime qualifier in
- /// ARC.
+ /// When true, suppress printing of lifetime qualifier in ARC.
unsigned SuppressLifetimeQualifiers : 1;
/// When true, suppresses printing template arguments in names of C++
/// constructors.
unsigned SuppressTemplateArgsInCXXConstructors : 1;
- /// \brief Whether we can use 'bool' rather than '_Bool' (even if the language
+ /// Whether we can use 'bool' rather than '_Bool' (even if the language
/// doesn't actually have 'bool', because, e.g., it is defined as a macro).
unsigned Bool : 1;
- /// \brief Whether we can use 'restrict' rather than '__restrict'.
+ /// Whether we can use 'restrict' rather than '__restrict'.
unsigned Restrict : 1;
- /// \brief Whether we can use 'alignof' rather than '__alignof'.
+ /// Whether we can use 'alignof' rather than '__alignof'.
unsigned Alignof : 1;
- /// \brief Whether we can use '_Alignof' rather than '__alignof'.
+ /// Whether we can use '_Alignof' rather than '__alignof'.
unsigned UnderscoreAlignof : 1;
- /// \brief Whether we should use '(void)' rather than '()' for a function
- /// prototype with zero parameters.
+ /// Whether we should use '(void)' rather than '()' for a function prototype
+ /// with zero parameters.
unsigned UseVoidForZeroParams : 1;
- /// \brief Provide a 'terse' output.
+ /// Provide a 'terse' output.
///
/// For example, in this mode we don't print function bodies, class members,
/// declarations inside namespaces etc. Effectively, this should print
/// only the requested declaration.
unsigned TerseOutput : 1;
- /// \brief When true, do certain refinement needed for producing proper
- /// declaration tag; such as, do not print attributes attached to the declaration.
+ /// When true, do certain refinement needed for producing proper declaration
+ /// tag; such as, do not print attributes attached to the declaration.
///
unsigned PolishForDeclaration : 1;
- /// \brief When true, print the half-precision floating-point type as 'half'
+ /// When true, print the half-precision floating-point type as 'half'
/// instead of '__fp16'
unsigned Half : 1;
- /// \brief When true, print the built-in wchar_t type as __wchar_t. For use in
+ /// When true, print the built-in wchar_t type as __wchar_t. For use in
/// Microsoft mode when wchar_t is not available.
unsigned MSWChar : 1;
- /// \brief When true, include newlines after statements like "break", etc.
+ /// When true, include newlines after statements like "break", etc.
unsigned IncludeNewlines : 1;
- /// \brief Use whitespace and punctuation like MSVC does. In particular, this
- /// prints anonymous namespaces as `anonymous namespace' and does not insert
- /// spaces after template arguments.
+ /// Use whitespace and punctuation like MSVC does. In particular, this prints
+ /// anonymous namespaces as `anonymous namespace' and does not insert spaces
+ /// after template arguments.
bool MSVCFormatting : 1;
+
+ /// Whether we should print the constant expressions as written in the
+ /// sources.
+ ///
+ /// This flag determines whether constants expressions like
+ ///
+ /// \code
+ /// 0x10
+ /// 2.5e3
+ /// \endcode
+ ///
+ /// will be printed as written or as follows:
+ ///
+ /// \code
+ /// 0x10
+ /// 2.5e3
+ /// \endcode
+ bool ConstantsAsWritten : 1;
+
+ /// When true, don't print the implicit 'self' or 'this' expressions.
+ bool SuppressImplicitBase : 1;
+
+ /// When true, print the fully qualified name of function declarations.
+ /// This is the opposite of SuppressScope and thus overrules it.
+ bool FullyQualifiedName : 1;
};
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Core/QualTypeNames.h b/contrib/llvm/tools/clang/include/clang/AST/QualTypeNames.h
index 7248356e748e8..86d805feeed76 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/Core/QualTypeNames.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/QualTypeNames.h
@@ -56,8 +56,8 @@
//
// ===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_TOOLING_CORE_QUALTYPENAMES_H
-#define LLVM_CLANG_TOOLING_CORE_QUALTYPENAMES_H
+#ifndef LLVM_CLANG_AST_QUALTYPENAMES_H
+#define LLVM_CLANG_AST_QUALTYPENAMES_H
#include "clang/AST/ASTContext.h"
@@ -71,9 +71,20 @@ namespace TypeName {
/// \param[in] Ctx - the ASTContext to be used.
/// \param[in] WithGlobalNsPrefix - If true, then the global namespace
/// specifier "::" will be prepended to the fully qualified name.
-std::string getFullyQualifiedName(QualType QT,
- const ASTContext &Ctx,
+std::string getFullyQualifiedName(QualType QT, const ASTContext &Ctx,
bool WithGlobalNsPrefix = false);
-} // end namespace TypeName
-} // end namespace clang
-#endif // LLVM_CLANG_TOOLING_CORE_QUALTYPENAMES_H
+
+/// \brief Generates a QualType that can be used to name the same type
+/// if used at the end of the current translation unit. This ignores
+/// issues such as type shadowing.
+///
+/// \param[in] QT - the type for which the fully qualified type will be
+/// returned.
+/// \param[in] Ctx - the ASTContext to be used.
+/// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace
+/// specifier "::" should be prepended or not.
+QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx,
+ bool WithGlobalNsPrefix = false);
+} // end namespace TypeName
+} // end namespace clang
+#endif // LLVM_CLANG_TOOLING_CORE_QUALTYPENAMES_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/RecordLayout.h b/contrib/llvm/tools/clang/include/clang/AST/RecordLayout.h
index 7a39c3b2539df..696d44efa0d9d 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/RecordLayout.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/RecordLayout.h
@@ -1,4 +1,4 @@
-//===--- RecordLayout.h - Layout information for a struct/union -*- C++ -*-===//
+//===- RecordLayout.h - Layout information for a struct/union ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,15 +14,20 @@
#ifndef LLVM_CLANG_AST_RECORDLAYOUT_H
#define LLVM_CLANG_AST_RECORDLAYOUT_H
+#include "clang/AST/ASTVector.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include <cassert>
+#include <cstdint>
namespace clang {
- class ASTContext;
- class FieldDecl;
- class RecordDecl;
- class CXXRecordDecl;
+
+class ASTContext;
+class CXXRecordDecl;
/// ASTRecordLayout -
/// This class contains layout information for one RecordDecl,
@@ -42,21 +47,21 @@ public:
/// Whether this virtual base requires a vtordisp field in the
/// Microsoft ABI. These fields are required for certain operations
/// in constructors and destructors.
- bool HasVtorDisp;
+ bool HasVtorDisp = false;
public:
- bool hasVtorDisp() const { return HasVtorDisp; }
-
- VBaseInfo() : HasVtorDisp(false) {}
+ VBaseInfo() = default;
+ VBaseInfo(CharUnits VBaseOffset, bool hasVtorDisp)
+ : VBaseOffset(VBaseOffset), HasVtorDisp(hasVtorDisp) {}
- VBaseInfo(CharUnits VBaseOffset, bool hasVtorDisp) :
- VBaseOffset(VBaseOffset), HasVtorDisp(hasVtorDisp) {}
+ bool hasVtorDisp() const { return HasVtorDisp; }
};
- typedef llvm::DenseMap<const CXXRecordDecl *, VBaseInfo>
- VBaseOffsetsMapTy;
+ using VBaseOffsetsMapTy = llvm::DenseMap<const CXXRecordDecl *, VBaseInfo>;
private:
+ friend class ASTContext;
+
/// Size - Size of record in characters.
CharUnits Size;
@@ -117,7 +122,7 @@ private:
const CXXRecordDecl *BaseSharingVBPtr;
/// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :)
- typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
+ using BaseOffsetsMapTy = llvm::DenseMap<const CXXRecordDecl *, CharUnits>;
/// BaseOffsets - Contains a map from base classes to their offset.
BaseOffsetsMapTy BaseOffsets;
@@ -128,16 +133,15 @@ private:
/// CXXInfo - If the record layout is for a C++ record, this will have
/// C++ specific information about the record.
- CXXRecordLayoutInfo *CXXInfo;
-
- friend class ASTContext;
+ CXXRecordLayoutInfo *CXXInfo = nullptr;
ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment,
CharUnits requiredAlignment, CharUnits datasize,
ArrayRef<uint64_t> fieldoffsets);
+ using BaseOffsetsMapTy = CXXRecordLayoutInfo::BaseOffsetsMapTy;
+
// Constructor for C++ records.
- typedef CXXRecordLayoutInfo::BaseOffsetsMapTy BaseOffsetsMapTy;
ASTRecordLayout(const ASTContext &Ctx,
CharUnits size, CharUnits alignment,
CharUnits requiredAlignment,
@@ -159,9 +163,9 @@ private:
void Destroy(ASTContext &Ctx);
- ASTRecordLayout(const ASTRecordLayout &) = delete;
- void operator=(const ASTRecordLayout &) = delete;
public:
+ ASTRecordLayout(const ASTRecordLayout &) = delete;
+ ASTRecordLayout &operator=(const ASTRecordLayout &) = delete;
/// getAlignment - Get the record alignment in characters.
CharUnits getAlignment() const { return Alignment; }
@@ -305,6 +309,6 @@ public:
}
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_AST_RECORDLAYOUT_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h
index e7f271cc0812d..ba76ea0a0df55 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -63,8 +63,8 @@
OPERATOR(PtrMemD) OPERATOR(PtrMemI) OPERATOR(Mul) OPERATOR(Div) \
OPERATOR(Rem) OPERATOR(Add) OPERATOR(Sub) OPERATOR(Shl) OPERATOR(Shr) \
OPERATOR(LT) OPERATOR(GT) OPERATOR(LE) OPERATOR(GE) OPERATOR(EQ) \
- OPERATOR(NE) OPERATOR(And) OPERATOR(Xor) OPERATOR(Or) OPERATOR(LAnd) \
- OPERATOR(LOr) OPERATOR(Assign) OPERATOR(Comma)
+ OPERATOR(NE) OPERATOR(Cmp) OPERATOR(And) OPERATOR(Xor) OPERATOR(Or) \
+ OPERATOR(LAnd) OPERATOR(LOr) OPERATOR(Assign) OPERATOR(Comma)
// All compound assign operators.
#define CAO_LIST() \
@@ -83,7 +83,7 @@ namespace clang {
return false; \
} while (false)
-/// \brief A class that does preordor or postorder
+/// \brief A class that does preorder or postorder
/// depth-first traversal on the entire Clang AST and visits each node.
///
/// This class performs three distinct tasks:
@@ -267,6 +267,12 @@ public:
bool TraverseTemplateArguments(const TemplateArgument *Args,
unsigned NumArgs);
+ /// \brief Recursively visit a base specifier. This can be overridden by a
+ /// subclass.
+ ///
+ /// \returns false if the visitation was terminated early, true otherwise.
+ bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &Base);
+
/// \brief Recursively visit a constructor initializer. This
/// automatically dispatches to another visitor for the initializer
/// expression, but not for the name of the initializer, so may
@@ -309,6 +315,8 @@ public:
// ---- Methods on Stmts ----
+ Stmt::child_range getStmtChildren(Stmt *S) { return S->children(); }
+
private:
template<typename T, typename U>
struct has_same_member_pointer_type : std::false_type {};
@@ -491,6 +499,8 @@ public:
bool Visit##CLASS##Decl(CLASS##Decl *D) { return true; }
#include "clang/AST/DeclNodes.inc"
+ bool canIgnoreChildDeclWhileTraversingDeclContext(const Decl *Child);
+
private:
// These are helper methods used by more than one Traverse* method.
bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL);
@@ -978,6 +988,11 @@ DEF_TRAVERSE_TYPE(DependentSizedArrayType, {
TRY_TO(TraverseStmt(T->getSizeExpr()));
})
+DEF_TRAVERSE_TYPE(DependentAddressSpaceType, {
+ TRY_TO(TraverseStmt(T->getAddrSpaceExpr()));
+ TRY_TO(TraverseType(T->getPointeeType()));
+})
+
DEF_TRAVERSE_TYPE(DependentSizedExtVectorType, {
if (T->getSizeExpr())
TRY_TO(TraverseStmt(T->getSizeExpr()));
@@ -1188,6 +1203,11 @@ DEF_TRAVERSE_TYPELOC(DependentSizedArrayType, {
return TraverseArrayTypeLocHelper(TL);
})
+DEF_TRAVERSE_TYPELOC(DependentAddressSpaceType, {
+ TRY_TO(TraverseStmt(TL.getTypePtr()->getAddrSpaceExpr()));
+ TRY_TO(TraverseType(TL.getTypePtr()->getPointeeType()));
+})
+
// FIXME: order? why not size expr first?
// FIXME: base VectorTypeLoc is unfinished
DEF_TRAVERSE_TYPELOC(DependentSizedExtVectorType, {
@@ -1339,14 +1359,20 @@ DEF_TRAVERSE_TYPELOC(PipeType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); })
// than those.
template <typename Derived>
+bool RecursiveASTVisitor<Derived>::canIgnoreChildDeclWhileTraversingDeclContext(
+ const Decl *Child) {
+ // BlockDecls and CapturedDecls are traversed through BlockExprs and
+ // CapturedStmts respectively.
+ return isa<BlockDecl>(Child) || isa<CapturedDecl>(Child);
+}
+
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseDeclContextHelper(DeclContext *DC) {
if (!DC)
return true;
for (auto *Child : DC->decls()) {
- // BlockDecls and CapturedDecls are traversed through BlockExprs and
- // CapturedStmts respectively.
- if (!isa<BlockDecl>(Child) && !isa<CapturedDecl>(Child))
+ if (!canIgnoreChildDeclWhileTraversingDeclContext(Child))
TRY_TO(TraverseDecl(Child));
}
@@ -1674,8 +1700,8 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations(
// template declarations.
#define DEF_TRAVERSE_TMPL_DECL(TMPLDECLKIND) \
DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateDecl, { \
- TRY_TO(TraverseDecl(D->getTemplatedDecl())); \
TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); \
+ TRY_TO(TraverseDecl(D->getTemplatedDecl())); \
\
/* By default, we do not traverse the instantiations of \
class templates since they do not appear in the user code. The \
@@ -1769,12 +1795,19 @@ bool RecursiveASTVisitor<Derived>::TraverseRecordHelper(RecordDecl *D) {
}
template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseCXXBaseSpecifier(
+ const CXXBaseSpecifier &Base) {
+ TRY_TO(TraverseTypeLoc(Base.getTypeSourceInfo()->getTypeLoc()));
+ return true;
+}
+
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseCXXRecordHelper(CXXRecordDecl *D) {
if (!TraverseRecordHelper(D))
return false;
if (D->isCompleteDefinition()) {
for (const auto &I : D->bases()) {
- TRY_TO(TraverseTypeLoc(I.getTypeSourceInfo()->getTypeLoc()));
+ TRY_TO(TraverseCXXBaseSpecifier(I));
}
// We don't traverse the friends or the conversions, as they are
// already in decls_begin()/decls_end().
@@ -2057,7 +2090,7 @@ DEF_TRAVERSE_DECL(ParmVarDecl, {
TRY_TO(WalkUpFrom##STMT(S)); \
{ CODE; } \
if (ShouldVisitChildren) { \
- for (Stmt *SubStmt : S->children()) { \
+ for (Stmt * SubStmt : getDerived().getStmtChildren(S)) { \
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(SubStmt); \
} \
} \
@@ -3039,6 +3072,30 @@ bool RecursiveASTVisitor<Derived>::VisitOMPTaskReductionClause(
}
template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPInReductionClause(
+ OMPInReductionClause *C) {
+ TRY_TO(TraverseNestedNameSpecifierLoc(C->getQualifierLoc()));
+ TRY_TO(TraverseDeclarationNameInfo(C->getNameInfo()));
+ TRY_TO(VisitOMPClauseList(C));
+ TRY_TO(VisitOMPClauseWithPostUpdate(C));
+ for (auto *E : C->privates()) {
+ TRY_TO(TraverseStmt(E));
+ }
+ for (auto *E : C->lhs_exprs()) {
+ TRY_TO(TraverseStmt(E));
+ }
+ for (auto *E : C->rhs_exprs()) {
+ TRY_TO(TraverseStmt(E));
+ }
+ for (auto *E : C->reduction_ops()) {
+ TRY_TO(TraverseStmt(E));
+ }
+ for (auto *E : C->taskgroup_descriptors())
+ TRY_TO(TraverseStmt(E));
+ return true;
+}
+
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPFlushClause(OMPFlushClause *C) {
TRY_TO(VisitOMPClauseList(C));
return true;
@@ -3052,6 +3109,7 @@ bool RecursiveASTVisitor<Derived>::VisitOMPDependClause(OMPDependClause *C) {
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPDeviceClause(OMPDeviceClause *C) {
+ TRY_TO(VisitOMPClauseWithPreInit(C));
TRY_TO(TraverseStmt(C->getDevice()));
return true;
}
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h b/contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h
index 89a9d3c4cc212..86b0f356e7b53 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h
@@ -1,4 +1,4 @@
-//===-- Redeclarable.h - Base for Decls that can be redeclared -*- C++ -*-====//
+//===- Redeclarable.h - Base for Decls that can be redeclared --*- C++ -*-====//
//
// The LLVM Compiler Infrastructure
//
@@ -15,11 +15,18 @@
#define LLVM_CLANG_AST_REDECLARABLE_H
#include "clang/AST/ExternalASTSource.h"
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Casting.h"
+#include <cassert>
+#include <cstddef>
#include <iterator>
namespace clang {
+
class ASTContext;
+class Decl;
// Some notes on redeclarables:
//
@@ -82,21 +89,21 @@ protected:
class DeclLink {
/// A pointer to a known latest declaration, either statically known or
/// generationally updated as decls are added by an external source.
- typedef LazyGenerationalUpdatePtr<const Decl*, Decl*,
- &ExternalASTSource::CompleteRedeclChain>
- KnownLatest;
+ using KnownLatest =
+ LazyGenerationalUpdatePtr<const Decl *, Decl *,
+ &ExternalASTSource::CompleteRedeclChain>;
/// We store a pointer to the ASTContext in the UninitializedLatest
/// pointer, but to avoid circular type dependencies when we steal the low
/// bits of this pointer, we use a raw void* here.
- typedef const void *UninitializedLatest;
+ using UninitializedLatest = const void *;
- typedef Decl *Previous;
+ using Previous = Decl *;
/// A pointer to either an uninitialized latest declaration (where either
/// we've not yet set the previous decl or there isn't one), or to a known
/// previous declaration.
- typedef llvm::PointerUnion<Previous, UninitializedLatest> NotKnownLatest;
+ using NotKnownLatest = llvm::PointerUnion<Previous, UninitializedLatest>;
mutable llvm::PointerUnion<NotKnownLatest, KnownLatest> Next;
@@ -106,8 +113,7 @@ protected:
DeclLink(LatestTag, const ASTContext &Ctx)
: Next(NotKnownLatest(reinterpret_cast<UninitializedLatest>(&Ctx))) {}
- DeclLink(PreviousTag, decl_type *D)
- : Next(NotKnownLatest(Previous(D))) {}
+ DeclLink(PreviousTag, decl_type *D) : Next(NotKnownLatest(Previous(D))) {}
bool NextIsPrevious() const {
return Next.is<NotKnownLatest>() &&
@@ -182,6 +188,7 @@ protected:
///
/// If there is only one declaration, it is <pointer to self, true>
DeclLink RedeclLink;
+
decl_type *First;
decl_type *getNextRedeclaration() const {
@@ -189,8 +196,12 @@ protected:
}
public:
- Redeclarable(const ASTContext &Ctx)
- : RedeclLink(LatestDeclLink(Ctx)), First(static_cast<decl_type *>(this)) {}
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+
+ Redeclarable(const ASTContext &Ctx)
+ : RedeclLink(LatestDeclLink(Ctx)),
+ First(static_cast<decl_type *>(this)) {}
/// \brief Return the previous declaration of this declaration or NULL if this
/// is the first declaration.
@@ -232,20 +243,19 @@ public:
/// \brief Iterates through all the redeclarations of the same decl.
class redecl_iterator {
/// Current - The current declaration.
- decl_type *Current;
+ decl_type *Current = nullptr;
decl_type *Starter;
- bool PassedFirst;
+ bool PassedFirst = false;
public:
- typedef decl_type* value_type;
- typedef decl_type* reference;
- typedef decl_type* pointer;
- typedef std::forward_iterator_tag iterator_category;
- typedef std::ptrdiff_t difference_type;
+ using value_type = decl_type *;
+ using reference = decl_type *;
+ using pointer = decl_type *;
+ using iterator_category = std::forward_iterator_tag;
+ using difference_type = std::ptrdiff_t;
- redecl_iterator() : Current(nullptr) { }
- explicit redecl_iterator(decl_type *C)
- : Current(C), Starter(C), PassedFirst(false) { }
+ redecl_iterator() = default;
+ explicit redecl_iterator(decl_type *C) : Current(C), Starter(C) {}
reference operator*() const { return Current; }
pointer operator->() const { return Current; }
@@ -282,7 +292,7 @@ public:
}
};
- typedef llvm::iterator_range<redecl_iterator> redecl_range;
+ using redecl_range = llvm::iterator_range<redecl_iterator>;
/// \brief Returns an iterator range for all the redeclarations of the same
/// decl. It will iterate at least once (when this decl is the only one).
@@ -294,9 +304,6 @@ public:
redecl_iterator redecls_begin() const { return redecls().begin(); }
redecl_iterator redecls_end() const { return redecls().end(); }
-
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
};
/// \brief Get the primary declaration for a declaration from an AST file. That
@@ -309,7 +316,7 @@ Decl *getPrimaryMergedDecl(Decl *D);
template<typename decl_type>
class Mergeable {
public:
- Mergeable() {}
+ Mergeable() = default;
/// \brief Return the first declaration of this declaration or itself if this
/// is the only declaration.
@@ -344,7 +351,7 @@ public:
/// remember to call getCanonicalDecl() everywhere.
template <typename decl_type> class CanonicalDeclPtr {
public:
- CanonicalDeclPtr() : Ptr(nullptr) {}
+ CanonicalDeclPtr() = default;
CanonicalDeclPtr(decl_type *Ptr)
: Ptr(Ptr ? Ptr->getCanonicalDecl() : nullptr) {}
CanonicalDeclPtr(const CanonicalDeclPtr &) = default;
@@ -362,11 +369,13 @@ public:
private:
friend struct llvm::DenseMapInfo<CanonicalDeclPtr<decl_type>>;
- decl_type *Ptr;
+ decl_type *Ptr = nullptr;
};
+
} // namespace clang
namespace llvm {
+
template <typename decl_type>
struct DenseMapInfo<clang::CanonicalDeclPtr<decl_type>> {
using CanonicalDeclPtr = clang::CanonicalDeclPtr<decl_type>;
@@ -395,6 +404,7 @@ struct DenseMapInfo<clang::CanonicalDeclPtr<decl_type>> {
return BaseInfo::isEqual(LHS, RHS);
}
};
+
} // namespace llvm
-#endif
+#endif // LLVM_CLANG_AST_REDECLARABLE_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Stmt.h b/contrib/llvm/tools/clang/include/clang/AST/Stmt.h
index c210bd1cec2e3..6bd07af1affa5 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/Stmt.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/Stmt.h
@@ -1,4 +1,4 @@
-//===--- Stmt.h - Classes for representing statements -----------*- C++ -*-===//
+//===- Stmt.h - Classes for representing statements -------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -22,34 +22,40 @@
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <iterator>
#include <string>
namespace llvm {
- class FoldingSetNodeID;
-}
+
+class FoldingSetNodeID;
+
+} // namespace llvm
namespace clang {
- class ASTContext;
- class Attr;
- class CapturedDecl;
- class Decl;
- class Expr;
- class IdentifierInfo;
- class LabelDecl;
- class ODRHash;
- class ParmVarDecl;
- class PrinterHelper;
- struct PrintingPolicy;
- class QualType;
- class RecordDecl;
- class SourceManager;
- class StringLiteral;
- class SwitchStmt;
- class Token;
- class VarDecl;
+
+class ASTContext;
+class Attr;
+class CapturedDecl;
+class Decl;
+class Expr;
+class LabelDecl;
+class ODRHash;
+class PrinterHelper;
+struct PrintingPolicy;
+class RecordDecl;
+class SourceManager;
+class StringLiteral;
+class Token;
+class VarDecl;
//===----------------------------------------------------------------------===//
// AST classes for statements.
@@ -72,9 +78,13 @@ public:
// Make vanilla 'new' and 'delete' illegal for Stmts.
protected:
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
void *operator new(size_t bytes) noexcept {
llvm_unreachable("Stmts cannot be allocated with regular 'new'.");
}
+
void operator delete(void *data) noexcept {
llvm_unreachable("Stmts cannot be released with regular 'delete'.");
}
@@ -89,6 +99,7 @@ protected:
class CompoundStmtBitfields {
friend class CompoundStmt;
+
unsigned : NumStmtBits;
unsigned NumStmts : 32 - NumStmtBits;
@@ -96,34 +107,36 @@ protected:
class IfStmtBitfields {
friend class IfStmt;
+
unsigned : NumStmtBits;
unsigned IsConstexpr : 1;
};
class ExprBitfields {
- friend class Expr;
- friend class DeclRefExpr; // computeDependence
- friend class InitListExpr; // ctor
- friend class DesignatedInitExpr; // ctor
- friend class BlockDeclRefExpr; // ctor
friend class ASTStmtReader; // deserialization
+ friend class AtomicExpr; // ctor
+ friend class BlockDeclRefExpr; // ctor
+ friend class CallExpr; // ctor
+ friend class CXXConstructExpr; // ctor
+ friend class CXXDependentScopeMemberExpr; // ctor
friend class CXXNewExpr; // ctor
+ friend class CXXUnresolvedConstructExpr; // ctor
+ friend class DeclRefExpr; // computeDependence
friend class DependentScopeDeclRefExpr; // ctor
- friend class CXXConstructExpr; // ctor
- friend class CallExpr; // ctor
- friend class OffsetOfExpr; // ctor
- friend class ObjCMessageExpr; // ctor
+ friend class DesignatedInitExpr; // ctor
+ friend class Expr;
+ friend class InitListExpr; // ctor
friend class ObjCArrayLiteral; // ctor
friend class ObjCDictionaryLiteral; // ctor
- friend class ShuffleVectorExpr; // ctor
- friend class ParenListExpr; // ctor
- friend class CXXUnresolvedConstructExpr; // ctor
- friend class CXXDependentScopeMemberExpr; // ctor
+ friend class ObjCMessageExpr; // ctor
+ friend class OffsetOfExpr; // ctor
+ friend class OpaqueValueExpr; // ctor
friend class OverloadExpr; // ctor
+ friend class ParenListExpr; // ctor
friend class PseudoObjectExpr; // ctor
- friend class AtomicExpr; // ctor
- friend class OpaqueValueExpr; // ctor
+ friend class ShuffleVectorExpr; // ctor
+
unsigned : NumStmtBits;
unsigned ValueKind : 2;
@@ -137,6 +150,7 @@ protected:
class CharacterLiteralBitfields {
friend class CharacterLiteral;
+
unsigned : NumExprBits;
unsigned Kind : 3;
@@ -153,6 +167,7 @@ protected:
class FloatingLiteralBitfields {
friend class FloatingLiteral;
+
unsigned : NumExprBits;
unsigned Semantics : 3; // Provides semantics for APFloat construction
@@ -161,6 +176,7 @@ protected:
class UnaryExprOrTypeTraitExprBitfields {
friend class UnaryExprOrTypeTraitExpr;
+
unsigned : NumExprBits;
unsigned Kind : 2;
@@ -168,8 +184,9 @@ protected:
};
class DeclRefExprBitfields {
- friend class DeclRefExpr;
friend class ASTStmtReader; // deserialization
+ friend class DeclRefExpr;
+
unsigned : NumExprBits;
unsigned HasQualifier : 1;
@@ -181,6 +198,7 @@ protected:
class CastExprBitfields {
friend class CastExpr;
+
unsigned : NumExprBits;
unsigned Kind : 6;
@@ -189,14 +207,15 @@ protected:
class CallExprBitfields {
friend class CallExpr;
+
unsigned : NumExprBits;
unsigned NumPreArgs : 1;
};
class ExprWithCleanupsBitfields {
- friend class ExprWithCleanups;
friend class ASTStmtReader; // deserialization
+ friend class ExprWithCleanups;
unsigned : NumExprBits;
@@ -207,8 +226,8 @@ protected:
};
class PseudoObjectExprBitfields {
- friend class PseudoObjectExpr;
friend class ASTStmtReader; // deserialization
+ friend class PseudoObjectExpr;
unsigned : NumExprBits;
@@ -220,6 +239,7 @@ protected:
class ObjCIndirectCopyRestoreExprBitfields {
friend class ObjCIndirectCopyRestoreExpr;
+
unsigned : NumExprBits;
unsigned ShouldCopy : 1;
@@ -236,9 +256,9 @@ protected:
};
class TypeTraitExprBitfields {
- friend class TypeTraitExpr;
friend class ASTStmtReader;
friend class ASTStmtWriter;
+ friend class TypeTraitExpr;
unsigned : NumExprBits;
@@ -280,9 +300,6 @@ protected:
CoawaitExprBitfields CoawaitBits;
};
- friend class ASTStmtReader;
- friend class ASTStmtWriter;
-
public:
// Only allow allocation of Stmts using the allocator in ASTContext
// or by doing a placement new.
@@ -305,7 +322,7 @@ public:
/// \brief A placeholder type used to construct an empty shell of a
/// type, that will be filled in later (e.g., by some
/// de-serialization).
- struct EmptyShell { };
+ struct EmptyShell {};
protected:
/// Iterator for iterating over Stmt * arrays that contain only Expr *
@@ -361,6 +378,7 @@ public:
StmtClass getStmtClass() const {
return static_cast<StmtClass>(StmtBits.sClass);
}
+
const char *getStmtClassName() const;
/// SourceLocation tokens are not useful in isolation - they are low level
@@ -389,8 +407,8 @@ public:
/// back to its original source language syntax.
void dumpPretty(const ASTContext &Context) const;
void printPretty(raw_ostream &OS, PrinterHelper *Helper,
- const PrintingPolicy &Policy,
- unsigned Indentation = 0) const;
+ const PrintingPolicy &Policy, unsigned Indentation = 0,
+ const ASTContext *Context = nullptr) const;
/// viewAST - Visualize an AST rooted at this Stmt* using GraphViz. Only
/// works on systems with GraphViz (Mac OS X) or dot+gv installed.
@@ -406,6 +424,9 @@ public:
/// \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 *IgnoreContainers(bool IgnoreCaptured = false) const {
+ return const_cast<Stmt *>(this)->IgnoreContainers(IgnoreCaptured);
+ }
const Stmt *stripLabelLikeStatements() const;
Stmt *stripLabelLikeStatements() {
@@ -416,11 +437,11 @@ public:
/// Child Iterators: All subclasses must implement 'children'
/// to permit easy iteration over the substatements/subexpessions of an
/// AST node. This permits easy iteration over all nodes in the AST.
- typedef StmtIterator child_iterator;
- typedef ConstStmtIterator const_child_iterator;
+ using child_iterator = StmtIterator;
+ using const_child_iterator = ConstStmtIterator;
- typedef llvm::iterator_range<child_iterator> child_range;
- typedef llvm::iterator_range<const_child_iterator> const_child_range;
+ using child_range = llvm::iterator_range<child_iterator>;
+ using const_child_range = llvm::iterator_range<const_child_iterator>;
child_range children();
const_child_range children() const {
@@ -463,18 +484,16 @@ public:
/// expressions. For example, CompoundStmt mixes statements, expressions
/// and declarations (variables, types). Another example is ForStmt, where
/// the first statement can be an expression or a declaration.
-///
class DeclStmt : public Stmt {
DeclGroupRef DG;
SourceLocation StartLoc, EndLoc;
public:
- DeclStmt(DeclGroupRef dg, SourceLocation startLoc,
- SourceLocation endLoc) : Stmt(DeclStmtClass), DG(dg),
- StartLoc(startLoc), EndLoc(endLoc) {}
+ DeclStmt(DeclGroupRef dg, SourceLocation startLoc, SourceLocation endLoc)
+ : Stmt(DeclStmtClass), DG(dg), StartLoc(startLoc), EndLoc(endLoc) {}
/// \brief Build an empty declaration statement.
- explicit DeclStmt(EmptyShell Empty) : Stmt(DeclStmtClass, Empty) { }
+ explicit DeclStmt(EmptyShell Empty) : Stmt(DeclStmtClass, Empty) {}
/// isSingleDecl - This method returns true if this DeclStmt refers
/// to a single Decl.
@@ -507,10 +526,10 @@ public:
child_iterator(DG.end(), DG.end()));
}
- typedef DeclGroupRef::iterator decl_iterator;
- typedef DeclGroupRef::const_iterator const_decl_iterator;
- typedef llvm::iterator_range<decl_iterator> decl_range;
- typedef llvm::iterator_range<const_decl_iterator> decl_const_range;
+ using decl_iterator = DeclGroupRef::iterator;
+ using const_decl_iterator = DeclGroupRef::const_iterator;
+ using decl_range = llvm::iterator_range<decl_iterator>;
+ using decl_const_range = llvm::iterator_range<const_decl_iterator>;
decl_range decls() { return decl_range(decl_begin(), decl_end()); }
decl_const_range decls() const {
@@ -521,10 +540,12 @@ public:
const_decl_iterator decl_begin() const { return DG.begin(); }
const_decl_iterator decl_end() const { return DG.end(); }
- typedef std::reverse_iterator<decl_iterator> reverse_decl_iterator;
+ using reverse_decl_iterator = std::reverse_iterator<decl_iterator>;
+
reverse_decl_iterator decl_rbegin() {
return reverse_decl_iterator(decl_end());
}
+
reverse_decl_iterator decl_rend() {
return reverse_decl_iterator(decl_begin());
}
@@ -540,15 +561,18 @@ class NullStmt : public Stmt {
/// #define CALL(x)
/// CALL(0);
/// @endcode
- bool HasLeadingEmptyMacro;
+ bool HasLeadingEmptyMacro = false;
+
public:
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
NullStmt(SourceLocation L, bool hasLeadingEmptyMacro = false)
- : Stmt(NullStmtClass), SemiLoc(L),
- HasLeadingEmptyMacro(hasLeadingEmptyMacro) {}
+ : Stmt(NullStmtClass), SemiLoc(L),
+ HasLeadingEmptyMacro(hasLeadingEmptyMacro) {}
/// \brief Build an empty null statement.
- explicit NullStmt(EmptyShell Empty) : Stmt(NullStmtClass, Empty),
- HasLeadingEmptyMacro(false) { }
+ explicit NullStmt(EmptyShell Empty) : Stmt(NullStmtClass, Empty) {}
SourceLocation getSemiLoc() const { return SemiLoc; }
void setSemiLoc(SourceLocation L) { SemiLoc = L; }
@@ -565,32 +589,27 @@ public:
child_range children() {
return child_range(child_iterator(), child_iterator());
}
-
- friend class ASTStmtReader;
- friend class ASTStmtWriter;
};
/// CompoundStmt - This represents a group of statements like { stmt stmt }.
-///
class CompoundStmt : public Stmt {
- Stmt** Body;
- SourceLocation LBraceLoc, RBraceLoc;
-
friend class ASTStmtReader;
+ Stmt** Body = nullptr;
+ SourceLocation LBraceLoc, RBraceLoc;
+
public:
CompoundStmt(const ASTContext &C, ArrayRef<Stmt*> Stmts,
SourceLocation LB, SourceLocation RB);
// \brief Build an empty compound statement with a location.
explicit CompoundStmt(SourceLocation Loc)
- : Stmt(CompoundStmtClass), Body(nullptr), LBraceLoc(Loc), RBraceLoc(Loc) {
+ : Stmt(CompoundStmtClass), LBraceLoc(Loc), RBraceLoc(Loc) {
CompoundStmtBits.NumStmts = 0;
}
// \brief Build an empty compound statement.
- explicit CompoundStmt(EmptyShell Empty)
- : Stmt(CompoundStmtClass, Empty), Body(nullptr) {
+ explicit CompoundStmt(EmptyShell Empty) : Stmt(CompoundStmtClass, Empty) {
CompoundStmtBits.NumStmts = 0;
}
@@ -599,8 +618,8 @@ public:
bool body_empty() const { return CompoundStmtBits.NumStmts == 0; }
unsigned size() const { return CompoundStmtBits.NumStmts; }
- typedef Stmt** body_iterator;
- typedef llvm::iterator_range<body_iterator> body_range;
+ using body_iterator = Stmt **;
+ using body_range = llvm::iterator_range<body_iterator>;
body_range body() { return body_range(body_begin(), body_end()); }
body_iterator body_begin() { return Body; }
@@ -613,31 +632,36 @@ public:
Body[size()-1] = S;
}
- typedef Stmt* const * const_body_iterator;
- typedef llvm::iterator_range<const_body_iterator> body_const_range;
+ using const_body_iterator = Stmt* const *;
+ using body_const_range = llvm::iterator_range<const_body_iterator>;
body_const_range body() const {
return body_const_range(body_begin(), body_end());
}
+
const_body_iterator body_begin() const { return Body; }
const_body_iterator body_end() const { return Body + size(); }
+
const Stmt *body_front() const {
return !body_empty() ? Body[0] : nullptr;
}
+
const Stmt *body_back() const {
return !body_empty() ? Body[size() - 1] : nullptr;
}
- typedef std::reverse_iterator<body_iterator> reverse_body_iterator;
+ using reverse_body_iterator = std::reverse_iterator<body_iterator>;
+
reverse_body_iterator body_rbegin() {
return reverse_body_iterator(body_end());
}
+
reverse_body_iterator body_rend() {
return reverse_body_iterator(body_begin());
}
- typedef std::reverse_iterator<const_body_iterator>
- const_reverse_body_iterator;
+ using const_reverse_body_iterator =
+ std::reverse_iterator<const_body_iterator>;
const_reverse_body_iterator body_rbegin() const {
return const_reverse_body_iterator(body_end());
@@ -673,16 +697,14 @@ class SwitchCase : public Stmt {
protected:
// A pointer to the following CaseStmt or DefaultStmt class,
// used by SwitchStmt.
- SwitchCase *NextSwitchCase;
+ SwitchCase *NextSwitchCase = nullptr;
SourceLocation KeywordLoc;
SourceLocation ColonLoc;
SwitchCase(StmtClass SC, SourceLocation KWLoc, SourceLocation ColonLoc)
- : Stmt(SC), NextSwitchCase(nullptr), KeywordLoc(KWLoc), ColonLoc(ColonLoc) {
- }
+ : Stmt(SC), KeywordLoc(KWLoc), ColonLoc(ColonLoc) {}
- SwitchCase(StmtClass SC, EmptyShell)
- : Stmt(SC), NextSwitchCase(nullptr) {}
+ SwitchCase(StmtClass SC, EmptyShell) : Stmt(SC) {}
public:
const SwitchCase *getNextSwitchCase() const { return NextSwitchCase; }
@@ -715,6 +737,7 @@ class CaseStmt : public SwitchCase {
enum { LHS, RHS, SUBSTMT, END_EXPR };
Stmt* SubExprs[END_EXPR]; // The expression for the RHS is Non-null for
// GNU "case 1 ... 4" extension
+
public:
CaseStmt(Expr *lhs, Expr *rhs, SourceLocation caseLoc,
SourceLocation ellipsisLoc, SourceLocation colonLoc)
@@ -726,7 +749,7 @@ public:
}
/// \brief Build an empty switch case statement.
- explicit CaseStmt(EmptyShell Empty) : SwitchCase(CaseStmtClass, Empty) { }
+ explicit CaseStmt(EmptyShell Empty) : SwitchCase(CaseStmtClass, Empty) {}
SourceLocation getCaseLoc() const { return KeywordLoc; }
void setCaseLoc(SourceLocation L) { KeywordLoc = L; }
@@ -742,9 +765,11 @@ public:
const Expr *getLHS() const {
return reinterpret_cast<const Expr*>(SubExprs[LHS]);
}
+
const Expr *getRHS() const {
return reinterpret_cast<const Expr*>(SubExprs[RHS]);
}
+
const Stmt *getSubStmt() const { return SubExprs[SUBSTMT]; }
void setSubStmt(Stmt *S) { SubExprs[SUBSTMT] = S; }
@@ -752,6 +777,7 @@ public:
void setRHS(Expr *Val) { SubExprs[RHS] = reinterpret_cast<Stmt*>(Val); }
SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; }
+
SourceLocation getLocEnd() const LLVM_READONLY {
// Handle deeply nested case statements with iteration instead of recursion.
const CaseStmt *CS = this;
@@ -773,13 +799,14 @@ public:
class DefaultStmt : public SwitchCase {
Stmt* SubStmt;
+
public:
DefaultStmt(SourceLocation DL, SourceLocation CL, Stmt *substmt) :
SwitchCase(DefaultStmtClass, DL, CL), SubStmt(substmt) {}
/// \brief Build an empty default statement.
explicit DefaultStmt(EmptyShell Empty)
- : SwitchCase(DefaultStmtClass, Empty) { }
+ : SwitchCase(DefaultStmtClass, Empty) {}
Stmt *getSubStmt() { return SubStmt; }
const Stmt *getSubStmt() const { return SubStmt; }
@@ -809,7 +836,6 @@ inline SourceLocation SwitchCase::getLocEnd() const {
/// LabelStmt - Represents a label, which has a substatement. For example:
/// foo: return;
-///
class LabelStmt : public Stmt {
SourceLocation IdentLoc;
LabelDecl *TheDecl;
@@ -824,7 +850,7 @@ public:
}
// \brief Build an empty label statement.
- explicit LabelStmt(EmptyShell Empty) : Stmt(LabelStmtClass, Empty) { }
+ explicit LabelStmt(EmptyShell Empty) : Stmt(LabelStmtClass, Empty) {}
SourceLocation getIdentLoc() const { return IdentLoc; }
LabelDecl *getDecl() const { return TheDecl; }
@@ -845,19 +871,17 @@ public:
}
};
-
/// \brief Represents an attribute applied to a statement.
///
/// Represents an attribute applied to a statement. For example:
/// [[omp::for(...)]] for (...) { ... }
-///
class AttributedStmt : public Stmt {
+ friend class ASTStmtReader;
+
Stmt *SubStmt;
SourceLocation AttrLoc;
unsigned NumAttrs;
- friend class ASTStmtReader;
-
AttributedStmt(SourceLocation Loc, ArrayRef<const Attr*> Attrs, Stmt *SubStmt)
: Stmt(AttributedStmtClass), SubStmt(SubStmt), AttrLoc(Loc),
NumAttrs(Attrs.size()) {
@@ -879,6 +903,7 @@ class AttributedStmt : public Stmt {
public:
static AttributedStmt *Create(const ASTContext &C, SourceLocation Loc,
ArrayRef<const Attr*> Attrs, Stmt *SubStmt);
+
// \brief Build an empty attributed statement.
static AttributedStmt *CreateEmpty(const ASTContext &C, unsigned NumAttrs);
@@ -886,6 +911,7 @@ public:
ArrayRef<const Attr*> getAttrs() const {
return llvm::makeArrayRef(getAttrArrayPtr(), NumAttrs);
}
+
Stmt *getSubStmt() { return SubStmt; }
const Stmt *getSubStmt() const { return SubStmt; }
@@ -899,9 +925,7 @@ public:
}
};
-
/// IfStmt - This represents an if/then/else.
-///
class IfStmt : public Stmt {
enum { INIT, VAR, COND, THEN, ELSE, END_EXPR };
Stmt* SubExprs[END_EXPR];
@@ -916,7 +940,7 @@ public:
Stmt *elsev = nullptr);
/// \brief Build an empty if/then/else statement
- explicit IfStmt(EmptyShell Empty) : Stmt(IfStmtClass, Empty) { }
+ explicit IfStmt(EmptyShell Empty) : Stmt(IfStmtClass, Empty) {}
/// \brief Retrieve the variable declared in this "if" statement, if any.
///
@@ -960,6 +984,7 @@ public:
bool isObjCAvailabilityCheck() const;
SourceLocation getLocStart() const LLVM_READONLY { return IfLoc; }
+
SourceLocation getLocEnd() const LLVM_READONLY {
if (SubExprs[ELSE])
return SubExprs[ELSE]->getLocEnd();
@@ -979,11 +1004,11 @@ public:
};
/// SwitchStmt - This represents a 'switch' stmt.
-///
class SwitchStmt : public Stmt {
SourceLocation SwitchLoc;
enum { INIT, VAR, COND, BODY, END_EXPR };
Stmt* SubExprs[END_EXPR];
+
// This points to a linked list of case and default statements and, if the
// SwitchStmt is a switch on an enum value, records whether all the enum
// values were covered by CaseStmts. The coverage information value is meant
@@ -994,7 +1019,7 @@ public:
SwitchStmt(const ASTContext &C, Stmt *Init, VarDecl *Var, Expr *cond);
/// \brief Build a empty switch statement.
- explicit SwitchStmt(EmptyShell Empty) : Stmt(SwitchStmtClass, Empty) { }
+ explicit SwitchStmt(EmptyShell Empty) : Stmt(SwitchStmtClass, Empty) {}
/// \brief Retrieve the variable declared in this "switch" statement, if any.
///
@@ -1037,6 +1062,7 @@ public:
SubExprs[BODY] = S;
SwitchLoc = SL;
}
+
void addSwitchCase(SwitchCase *SC) {
assert(!SC->getNextSwitchCase()
&& "case/default already added to a switch");
@@ -1053,6 +1079,7 @@ public:
bool isAllEnumCasesCovered() const { return FirstCase.getInt(); }
SourceLocation getLocStart() const LLVM_READONLY { return SwitchLoc; }
+
SourceLocation getLocEnd() const LLVM_READONLY {
return SubExprs[BODY] ? SubExprs[BODY]->getLocEnd() : SubExprs[COND]->getLocEnd();
}
@@ -1067,19 +1094,18 @@ public:
}
};
-
/// WhileStmt - This represents a 'while' stmt.
-///
class WhileStmt : public Stmt {
SourceLocation WhileLoc;
enum { VAR, COND, BODY, END_EXPR };
Stmt* SubExprs[END_EXPR];
+
public:
WhileStmt(const ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body,
SourceLocation WL);
/// \brief Build an empty while statement.
- explicit WhileStmt(EmptyShell Empty) : Stmt(WhileStmtClass, Empty) { }
+ explicit WhileStmt(EmptyShell Empty) : Stmt(WhileStmtClass, Empty) {}
/// \brief Retrieve the variable declared in this "while" statement, if any.
///
@@ -1109,6 +1135,7 @@ public:
void setWhileLoc(SourceLocation L) { WhileLoc = L; }
SourceLocation getLocStart() const LLVM_READONLY { return WhileLoc; }
+
SourceLocation getLocEnd() const LLVM_READONLY {
return SubExprs[BODY]->getLocEnd();
}
@@ -1124,7 +1151,6 @@ public:
};
/// DoStmt - This represents a 'do/while' stmt.
-///
class DoStmt : public Stmt {
SourceLocation DoLoc;
enum { BODY, COND, END_EXPR };
@@ -1141,7 +1167,7 @@ public:
}
/// \brief Build an empty do-while statement.
- explicit DoStmt(EmptyShell Empty) : Stmt(DoStmtClass, Empty) { }
+ explicit DoStmt(EmptyShell Empty) : Stmt(DoStmtClass, Empty) {}
Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
@@ -1171,11 +1197,9 @@ public:
}
};
-
/// ForStmt - This represents a 'for (init;cond;inc)' stmt. Note that any of
/// the init/cond/inc parts of the ForStmt will be null if they were not
/// specified in the source.
-///
class ForStmt : public Stmt {
SourceLocation ForLoc;
enum { INIT, CONDVAR, COND, INC, BODY, END_EXPR };
@@ -1188,7 +1212,7 @@ public:
SourceLocation RP);
/// \brief Build an empty for statement.
- explicit ForStmt(EmptyShell Empty) : Stmt(ForStmtClass, Empty) { }
+ explicit ForStmt(EmptyShell Empty) : Stmt(ForStmtClass, Empty) {}
Stmt *getInit() { return SubExprs[INIT]; }
@@ -1231,6 +1255,7 @@ public:
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
SourceLocation getLocStart() const LLVM_READONLY { return ForLoc; }
+
SourceLocation getLocEnd() const LLVM_READONLY {
return SubExprs[BODY]->getLocEnd();
}
@@ -1246,17 +1271,17 @@ public:
};
/// GotoStmt - This represents a direct goto.
-///
class GotoStmt : public Stmt {
LabelDecl *Label;
SourceLocation GotoLoc;
SourceLocation LabelLoc;
+
public:
GotoStmt(LabelDecl *label, SourceLocation GL, SourceLocation LL)
- : Stmt(GotoStmtClass), Label(label), GotoLoc(GL), LabelLoc(LL) {}
+ : Stmt(GotoStmtClass), Label(label), GotoLoc(GL), LabelLoc(LL) {}
/// \brief Build an empty goto statement.
- explicit GotoStmt(EmptyShell Empty) : Stmt(GotoStmtClass, Empty) { }
+ explicit GotoStmt(EmptyShell Empty) : Stmt(GotoStmtClass, Empty) {}
LabelDecl *getLabel() const { return Label; }
void setLabel(LabelDecl *D) { Label = D; }
@@ -1280,11 +1305,11 @@ public:
};
/// IndirectGotoStmt - This represents an indirect goto.
-///
class IndirectGotoStmt : public Stmt {
SourceLocation GotoLoc;
SourceLocation StarLoc;
Stmt *Target;
+
public:
IndirectGotoStmt(SourceLocation gotoLoc, SourceLocation starLoc,
Expr *target)
@@ -1293,7 +1318,7 @@ public:
/// \brief Build an empty indirect goto statement.
explicit IndirectGotoStmt(EmptyShell Empty)
- : Stmt(IndirectGotoStmtClass, Empty) { }
+ : Stmt(IndirectGotoStmtClass, Empty) {}
void setGotoLoc(SourceLocation L) { GotoLoc = L; }
SourceLocation getGotoLoc() const { return GotoLoc; }
@@ -1322,16 +1347,15 @@ public:
child_range children() { return child_range(&Target, &Target+1); }
};
-
/// ContinueStmt - This represents a continue.
-///
class ContinueStmt : public Stmt {
SourceLocation ContinueLoc;
+
public:
ContinueStmt(SourceLocation CL) : Stmt(ContinueStmtClass), ContinueLoc(CL) {}
/// \brief Build an empty continue statement.
- explicit ContinueStmt(EmptyShell Empty) : Stmt(ContinueStmtClass, Empty) { }
+ explicit ContinueStmt(EmptyShell Empty) : Stmt(ContinueStmtClass, Empty) {}
SourceLocation getContinueLoc() const { return ContinueLoc; }
void setContinueLoc(SourceLocation L) { ContinueLoc = L; }
@@ -1350,7 +1374,6 @@ public:
};
/// BreakStmt - This represents a break.
-///
class BreakStmt : public Stmt {
SourceLocation BreakLoc;
@@ -1361,7 +1384,7 @@ public:
}
/// \brief Build an empty break statement.
- explicit BreakStmt(EmptyShell Empty) : Stmt(BreakStmtClass, Empty) { }
+ explicit BreakStmt(EmptyShell Empty) : Stmt(BreakStmtClass, Empty) {}
SourceLocation getBreakLoc() const { return BreakLoc; }
void setBreakLoc(SourceLocation L) { BreakLoc = L; }
@@ -1379,7 +1402,6 @@ public:
}
};
-
/// ReturnStmt - This represents a return, optionally of an expression:
/// return;
/// return 4;
@@ -1388,7 +1410,6 @@ public:
/// return a value, and it allows returning a value in functions declared to
/// return void. We explicitly model this in the AST, which means you can't
/// depend on the return type of the function and the presence of an argument.
-///
class ReturnStmt : public Stmt {
SourceLocation RetLoc;
Stmt *RetExpr;
@@ -1402,7 +1423,7 @@ public:
NRVOCandidate(NRVOCandidate) {}
/// \brief Build an empty return expression.
- explicit ReturnStmt(EmptyShell Empty) : Stmt(ReturnStmtClass, Empty) { }
+ explicit ReturnStmt(EmptyShell Empty) : Stmt(ReturnStmtClass, Empty) {}
const Expr *getRetValue() const;
Expr *getRetValue();
@@ -1420,6 +1441,7 @@ public:
void setNRVOCandidate(const VarDecl *Var) { NRVOCandidate = Var; }
SourceLocation getLocStart() const LLVM_READONLY { return RetLoc; }
+
SourceLocation getLocEnd() const LLVM_READONLY {
return RetExpr ? RetExpr->getLocEnd() : RetLoc;
}
@@ -1436,10 +1458,12 @@ public:
};
/// AsmStmt is the base class for GCCAsmStmt and MSAsmStmt.
-///
class AsmStmt : public Stmt {
protected:
+ friend class ASTStmtReader;
+
SourceLocation AsmLoc;
+
/// \brief True if the assembly statement does not have any input or output
/// operands.
bool IsSimple;
@@ -1452,19 +1476,17 @@ protected:
unsigned NumInputs;
unsigned NumClobbers;
- Stmt **Exprs;
+ Stmt **Exprs = nullptr;
AsmStmt(StmtClass SC, SourceLocation asmloc, bool issimple, bool isvolatile,
- unsigned numoutputs, unsigned numinputs, unsigned numclobbers) :
- Stmt (SC), AsmLoc(asmloc), IsSimple(issimple), IsVolatile(isvolatile),
- NumOutputs(numoutputs), NumInputs(numinputs), NumClobbers(numclobbers) { }
-
- friend class ASTStmtReader;
+ unsigned numoutputs, unsigned numinputs, unsigned numclobbers)
+ : Stmt (SC), AsmLoc(asmloc), IsSimple(issimple), IsVolatile(isvolatile),
+ NumOutputs(numoutputs), NumInputs(numinputs),
+ NumClobbers(numclobbers) {}
public:
/// \brief Build an empty inline-assembly statement.
- explicit AsmStmt(StmtClass SC, EmptyShell Empty) :
- Stmt(SC, Empty), Exprs(nullptr) { }
+ explicit AsmStmt(StmtClass SC, EmptyShell Empty) : Stmt(SC, Empty) {}
SourceLocation getAsmLoc() const { return AsmLoc; }
void setAsmLoc(SourceLocation L) { AsmLoc = L; }
@@ -1527,10 +1549,10 @@ public:
// Input expr iterators.
- typedef ExprIterator inputs_iterator;
- typedef ConstExprIterator const_inputs_iterator;
- typedef llvm::iterator_range<inputs_iterator> inputs_range;
- typedef llvm::iterator_range<const_inputs_iterator> inputs_const_range;
+ using inputs_iterator = ExprIterator;
+ using const_inputs_iterator = ConstExprIterator;
+ using inputs_range = llvm::iterator_range<inputs_iterator>;
+ using inputs_const_range = llvm::iterator_range<const_inputs_iterator>;
inputs_iterator begin_inputs() {
return &Exprs[0] + NumOutputs;
@@ -1556,17 +1578,19 @@ public:
// Output expr iterators.
- typedef ExprIterator outputs_iterator;
- typedef ConstExprIterator const_outputs_iterator;
- typedef llvm::iterator_range<outputs_iterator> outputs_range;
- typedef llvm::iterator_range<const_outputs_iterator> outputs_const_range;
+ using outputs_iterator = ExprIterator;
+ using const_outputs_iterator = ConstExprIterator;
+ using outputs_range = llvm::iterator_range<outputs_iterator>;
+ using outputs_const_range = llvm::iterator_range<const_outputs_iterator>;
outputs_iterator begin_outputs() {
return &Exprs[0];
}
+
outputs_iterator end_outputs() {
return &Exprs[0] + NumOutputs;
}
+
outputs_range outputs() {
return outputs_range(begin_outputs(), end_outputs());
}
@@ -1574,9 +1598,11 @@ public:
const_outputs_iterator begin_outputs() const {
return &Exprs[0];
}
+
const_outputs_iterator end_outputs() const {
return &Exprs[0] + NumOutputs;
}
+
outputs_const_range outputs() const {
return outputs_const_range(begin_outputs(), end_outputs());
}
@@ -1587,17 +1613,16 @@ public:
};
/// This represents a GCC inline-assembly statement extension.
-///
class GCCAsmStmt : public AsmStmt {
+ friend class ASTStmtReader;
+
SourceLocation RParenLoc;
StringLiteral *AsmStr;
// FIXME: If we wanted to, we could allocate all of these in one big array.
- StringLiteral **Constraints;
- StringLiteral **Clobbers;
- IdentifierInfo **Names;
-
- friend class ASTStmtReader;
+ StringLiteral **Constraints = nullptr;
+ StringLiteral **Clobbers = nullptr;
+ IdentifierInfo **Names = nullptr;
public:
GCCAsmStmt(const ASTContext &C, SourceLocation asmloc, bool issimple,
@@ -1607,8 +1632,7 @@ public:
StringLiteral **clobbers, SourceLocation rparenloc);
/// \brief Build an empty inline-assembly statement.
- explicit GCCAsmStmt(EmptyShell Empty) : AsmStmt(GCCAsmStmtClass, Empty),
- Constraints(nullptr), Clobbers(nullptr), Names(nullptr) { }
+ explicit GCCAsmStmt(EmptyShell Empty) : AsmStmt(GCCAsmStmtClass, Empty) {}
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
@@ -1628,6 +1652,7 @@ public:
String, // String in .ll asm string form, "$" -> "$$" and "%%" -> "%".
Operand // Operand reference, with optional modifier %c4.
};
+
private:
Kind MyKind;
std::string Str;
@@ -1635,13 +1660,13 @@ public:
// Source range for operand references.
CharSourceRange Range;
+
public:
AsmStringPiece(const std::string &S) : MyKind(String), Str(S) {}
AsmStringPiece(unsigned OpNo, const std::string &S, SourceLocation Begin,
SourceLocation End)
- : MyKind(Operand), Str(S), OperandNo(OpNo),
- Range(CharSourceRange::getCharRange(Begin, End)) {
- }
+ : MyKind(Operand), Str(S), OperandNo(OpNo),
+ Range(CharSourceRange::getCharRange(Begin, End)) {}
bool isString() const { return MyKind == String; }
bool isOperand() const { return MyKind == Operand; }
@@ -1742,8 +1767,8 @@ private:
unsigned NumInputs,
StringLiteral **Clobbers,
unsigned NumClobbers);
-public:
+public:
//===--- Other ---===//
/// getNamedOperand - Given a symbolic operand reference like %[foo],
@@ -1752,6 +1777,7 @@ public:
int getNamedOperand(StringRef SymbolicName) const;
StringRef getClobber(unsigned i) const;
+
StringLiteral *getClobberStringLiteral(unsigned i) { return Clobbers[i]; }
const StringLiteral *getClobberStringLiteral(unsigned i) const {
return Clobbers[i];
@@ -1766,18 +1792,17 @@ public:
};
/// This represents a Microsoft inline-assembly statement extension.
-///
class MSAsmStmt : public AsmStmt {
+ friend class ASTStmtReader;
+
SourceLocation LBraceLoc, EndLoc;
StringRef AsmStr;
- unsigned NumAsmToks;
-
- Token *AsmToks;
- StringRef *Constraints;
- StringRef *Clobbers;
+ unsigned NumAsmToks = 0;
- friend class ASTStmtReader;
+ Token *AsmToks = nullptr;
+ StringRef *Constraints = nullptr;
+ StringRef *Clobbers = nullptr;
public:
MSAsmStmt(const ASTContext &C, SourceLocation asmloc,
@@ -1788,8 +1813,7 @@ public:
ArrayRef<StringRef> clobbers, SourceLocation endloc);
/// \brief Build an empty MS-style inline-assembly statement.
- explicit MSAsmStmt(EmptyShell Empty) : AsmStmt(MSAsmStmtClass, Empty),
- NumAsmToks(0), AsmToks(nullptr), Constraints(nullptr), Clobbers(nullptr) { }
+ explicit MSAsmStmt(EmptyShell Empty) : AsmStmt(MSAsmStmtClass, Empty) {}
SourceLocation getLBraceLoc() const { return LBraceLoc; }
void setLBraceLoc(SourceLocation L) { LBraceLoc = L; }
@@ -1839,9 +1863,11 @@ public:
ArrayRef<StringRef> getAllConstraints() const {
return llvm::makeArrayRef(Constraints, NumInputs + NumOutputs);
}
+
ArrayRef<StringRef> getClobbers() const {
return llvm::makeArrayRef(Clobbers, NumClobbers);
}
+
ArrayRef<Expr*> getAllExprs() const {
return llvm::makeArrayRef(reinterpret_cast<Expr**>(Exprs),
NumInputs + NumOutputs);
@@ -1853,8 +1879,8 @@ private:
void initialize(const ASTContext &C, StringRef AsmString,
ArrayRef<Token> AsmToks, ArrayRef<StringRef> Constraints,
ArrayRef<Expr*> Exprs, ArrayRef<StringRef> Clobbers);
-public:
+public:
SourceLocation getLocStart() const LLVM_READONLY { return AsmLoc; }
SourceLocation getLocEnd() const LLVM_READONLY { return EndLoc; }
@@ -1868,18 +1894,16 @@ public:
};
class SEHExceptStmt : public Stmt {
+ friend class ASTReader;
+ friend class ASTStmtReader;
+
SourceLocation Loc;
- Stmt *Children[2];
+ Stmt *Children[2];
enum { FILTER_EXPR, BLOCK };
- SEHExceptStmt(SourceLocation Loc,
- Expr *FilterExpr,
- Stmt *Block);
-
- friend class ASTReader;
- friend class ASTStmtReader;
- explicit SEHExceptStmt(EmptyShell E) : Stmt(SEHExceptStmtClass, E) { }
+ SEHExceptStmt(SourceLocation Loc, Expr *FilterExpr, Stmt *Block);
+ explicit SEHExceptStmt(EmptyShell E) : Stmt(SEHExceptStmtClass, E) {}
public:
static SEHExceptStmt* Create(const ASTContext &C,
@@ -1908,19 +1932,17 @@ public:
static bool classof(const Stmt *T) {
return T->getStmtClass() == SEHExceptStmtClass;
}
-
};
class SEHFinallyStmt : public Stmt {
- SourceLocation Loc;
- Stmt *Block;
-
- SEHFinallyStmt(SourceLocation Loc,
- Stmt *Block);
-
friend class ASTReader;
friend class ASTStmtReader;
- explicit SEHFinallyStmt(EmptyShell E) : Stmt(SEHFinallyStmtClass, E) { }
+
+ SourceLocation Loc;
+ Stmt *Block;
+
+ SEHFinallyStmt(SourceLocation Loc, Stmt *Block);
+ explicit SEHFinallyStmt(EmptyShell E) : Stmt(SEHFinallyStmtClass, E) {}
public:
static SEHFinallyStmt* Create(const ASTContext &C,
@@ -1942,13 +1964,15 @@ public:
static bool classof(const Stmt *T) {
return T->getStmtClass() == SEHFinallyStmtClass;
}
-
};
class SEHTryStmt : public Stmt {
- bool IsCXXTry;
+ friend class ASTReader;
+ friend class ASTStmtReader;
+
+ bool IsCXXTry;
SourceLocation TryLoc;
- Stmt *Children[2];
+ Stmt *Children[2];
enum { TRY = 0, HANDLER = 1 };
@@ -1957,9 +1981,7 @@ class SEHTryStmt : public Stmt {
Stmt *TryBlock,
Stmt *Handler);
- friend class ASTReader;
- friend class ASTStmtReader;
- explicit SEHTryStmt(EmptyShell E) : Stmt(SEHTryStmtClass, E) { }
+ explicit SEHTryStmt(EmptyShell E) : Stmt(SEHTryStmtClass, E) {}
public:
static SEHTryStmt* Create(const ASTContext &C, bool isCXXTry,
@@ -1994,15 +2016,15 @@ public:
};
/// Represents a __leave statement.
-///
class SEHLeaveStmt : public Stmt {
SourceLocation LeaveLoc;
+
public:
explicit SEHLeaveStmt(SourceLocation LL)
: Stmt(SEHLeaveStmtClass), LeaveLoc(LL) {}
/// \brief Build an empty __leave statement.
- explicit SEHLeaveStmt(EmptyShell Empty) : Stmt(SEHLeaveStmtClass, Empty) { }
+ explicit SEHLeaveStmt(EmptyShell Empty) : Stmt(SEHLeaveStmtClass, Empty) {}
SourceLocation getLeaveLoc() const { return LeaveLoc; }
void setLeaveLoc(SourceLocation L) { LeaveLoc = L; }
@@ -2047,6 +2069,8 @@ public:
SourceLocation Loc;
public:
+ friend class ASTStmtReader;
+
/// \brief Create a new capture.
///
/// \param Loc The source location associated with this capture.
@@ -2054,7 +2078,6 @@ public:
/// \param Kind The kind of capture (this, ByRef, ...).
///
/// \param Var The variable being captured, or null if capturing this.
- ///
Capture(SourceLocation Loc, VariableCaptureKind Kind,
VarDecl *Var = nullptr);
@@ -2086,8 +2109,6 @@ public:
///
/// This operation is only valid if this capture captures a variable.
VarDecl *getCapturedVar() const;
-
- friend class ASTStmtReader;
};
private:
@@ -2099,7 +2120,7 @@ private:
llvm::PointerIntPair<CapturedDecl *, 1, CapturedRegionKind> CapDeclAndKind;
/// \brief The record for captured variables, a RecordDecl or CXXRecordDecl.
- RecordDecl *TheRecordDecl;
+ RecordDecl *TheRecordDecl = nullptr;
/// \brief Construct a captured statement.
CapturedStmt(Stmt *S, CapturedRegionKind Kind, ArrayRef<Capture> Captures,
@@ -2119,6 +2140,8 @@ private:
void setCapturedStmt(Stmt *S) { getStoredStmts()[NumCaptures] = S; }
public:
+ friend class ASTStmtReader;
+
static CapturedStmt *Create(const ASTContext &Context, Stmt *S,
CapturedRegionKind Kind,
ArrayRef<Capture> Captures,
@@ -2158,10 +2181,10 @@ public:
bool capturesVariable(const VarDecl *Var) const;
/// \brief An iterator that walks over the captures.
- typedef Capture *capture_iterator;
- typedef const Capture *const_capture_iterator;
- typedef llvm::iterator_range<capture_iterator> capture_range;
- typedef llvm::iterator_range<const_capture_iterator> capture_const_range;
+ using capture_iterator = Capture *;
+ using const_capture_iterator = const Capture *;
+ using capture_range = llvm::iterator_range<capture_iterator>;
+ using capture_const_range = llvm::iterator_range<const_capture_iterator>;
capture_range captures() {
return capture_range(capture_begin(), capture_end());
@@ -2184,14 +2207,14 @@ public:
unsigned capture_size() const { return NumCaptures; }
/// \brief Iterator that walks over the capture initialization arguments.
- typedef Expr **capture_init_iterator;
- typedef llvm::iterator_range<capture_init_iterator> capture_init_range;
+ using capture_init_iterator = Expr **;
+ using capture_init_range = llvm::iterator_range<capture_init_iterator>;
/// \brief Const iterator that walks over the capture initialization
/// arguments.
- typedef Expr *const *const_capture_init_iterator;
- typedef llvm::iterator_range<const_capture_init_iterator>
- const_capture_init_range;
+ using const_capture_init_iterator = Expr *const *;
+ using const_capture_init_range =
+ llvm::iterator_range<const_capture_init_iterator>;
capture_init_range capture_inits() {
return capture_init_range(capture_init_begin(), capture_init_end());
@@ -2223,9 +2246,11 @@ public:
SourceLocation getLocStart() const LLVM_READONLY {
return getCapturedStmt()->getLocStart();
}
+
SourceLocation getLocEnd() const LLVM_READONLY {
return getCapturedStmt()->getLocEnd();
}
+
SourceRange getSourceRange() const LLVM_READONLY {
return getCapturedStmt()->getSourceRange();
}
@@ -2235,10 +2260,8 @@ public:
}
child_range children();
-
- friend class ASTStmtReader;
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_AST_STMT_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtDataCollectors.td b/contrib/llvm/tools/clang/include/clang/AST/StmtDataCollectors.td
new file mode 100644
index 0000000000000..bf5f8c21707f9
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/StmtDataCollectors.td
@@ -0,0 +1,242 @@
+class Stmt {
+ code Code = [{
+ addData(S->getStmtClass());
+ // This ensures that non-macro-generated code isn't identical to
+ // macro-generated code.
+ addData(data_collection::getMacroStack(S->getLocStart(), Context));
+ addData(data_collection::getMacroStack(S->getLocEnd(), Context));
+ }];
+}
+
+class Expr {
+ code Code = [{
+ addData(S->getType());
+ }];
+}
+
+//--- Builtin functionality ----------------------------------------------//
+class ArrayTypeTraitExpr {
+ code Code = [{
+ addData(S->getTrait());
+ }];
+}
+class ExpressionTraitExpr {
+ code Code = [{
+ addData(S->getTrait());
+ }];
+}
+class PredefinedExpr {
+ code Code = [{
+ addData(S->getIdentType());
+ }];
+}
+class TypeTraitExpr {
+ code Code = [{
+ addData(S->getTrait());
+ for (unsigned i = 0; i < S->getNumArgs(); ++i)
+ addData(S->getArg(i)->getType());
+ }];
+}
+
+//--- Calls --------------------------------------------------------------//
+class CallExpr {
+ code Code = [{
+ // Function pointers don't have a callee and we just skip hashing it.
+ if (const FunctionDecl *D = S->getDirectCallee()) {
+ // If the function is a template specialization, we also need to handle
+ // the template arguments as they are not included in the qualified name.
+ if (auto Args = D->getTemplateSpecializationArgs()) {
+ std::string ArgString;
+
+ // Print all template arguments into ArgString
+ llvm::raw_string_ostream OS(ArgString);
+ for (unsigned i = 0; i < Args->size(); ++i) {
+ Args->get(i).print(Context.getLangOpts(), OS);
+ // Add a padding character so that 'foo<X, XX>()' != 'foo<XX, X>()'.
+ OS << '\n';
+ }
+ OS.flush();
+
+ addData(ArgString);
+ }
+ addData(D->getQualifiedNameAsString());
+ }
+ }];
+}
+
+//--- Value references ---------------------------------------------------//
+class DeclRefExpr {
+ code Code = [{
+ addData(S->getDecl()->getQualifiedNameAsString());
+ }];
+}
+class MemberExpr {
+ code Code = [{
+ addData(S->getMemberDecl()->getName());
+ }];
+}
+
+//--- Literals -----------------------------------------------------------//
+class IntegerLiteral {
+ code Code = [{
+ addData(llvm::hash_value(S->getValue()));
+ }];
+}
+class FloatingLiteral {
+ code Code = [{
+ addData(llvm::hash_value(S->getValue()));
+ }];
+}
+class StringLiteral {
+ code Code = [{
+ addData(S->getString());
+}];
+}
+class CXXBoolLiteralExpr {
+ code Code = [{
+ addData(S->getValue());
+ }];
+}
+class CharacterLiteral {
+ code Code = [{
+ addData(S->getValue());
+ }];
+}
+
+//--- Exceptions ---------------------------------------------------------//
+class CXXCatchStmt {
+ code Code = [{
+ addData(S->getCaughtType());
+ }];
+}
+
+//--- C++ OOP Stmts ------------------------------------------------------//
+class CXXDeleteExpr {
+ code Code = [{
+ addData(S->isArrayFormAsWritten()); addData(S->isGlobalDelete());
+ }];
+}
+
+//--- Casts --------------------------------------------------------------//
+class ObjCBridgedCastExpr {
+ code Code = [{
+ addData(S->getBridgeKind());
+ }];
+}
+
+//--- Miscellaneous Exprs ------------------------------------------------//
+class BinaryOperator {
+ code Code = [{
+ addData(S->getOpcode());
+ }];
+}
+class UnaryOperator {
+ code Code = [{
+ addData(S->getOpcode());
+ }];
+}
+
+//--- Control flow -------------------------------------------------------//
+class GotoStmt {
+ code Code = [{
+ addData(S->getLabel()->getName());
+ }];
+}
+class IndirectGotoStmt {
+ code Code = [{
+ if (S->getConstantTarget())
+ addData(S->getConstantTarget()->getName());
+ }];
+}
+class LabelStmt {
+ code Code = [{
+ addData(S->getDecl()->getName());
+ }];
+}
+class MSDependentExistsStmt {
+ code Code = [{
+ addData(S->isIfExists());
+ }];
+}
+class AddrLabelExpr {
+ code Code = [{
+ addData(S->getLabel()->getName());
+ }];
+}
+
+//--- Objective-C --------------------------------------------------------//
+class ObjCIndirectCopyRestoreExpr {
+ code Code = [{
+ addData(S->shouldCopy());
+ }];
+}
+class ObjCPropertyRefExpr {
+ code Code = [{
+ addData(S->isSuperReceiver()); addData(S->isImplicitProperty());
+ }];
+}
+class ObjCAtCatchStmt {
+ code Code = [{
+ addData(S->hasEllipsis());
+ }];
+}
+
+//--- Miscellaneous Stmts ------------------------------------------------//
+class CXXFoldExpr {
+ code Code = [{
+ addData(S->isRightFold()); addData(S->getOperator());
+ }];
+}
+class GenericSelectionExpr {
+ code Code = [{
+ for (unsigned i = 0; i < S->getNumAssocs(); ++i) {
+ addData(S->getAssocType(i));
+ }
+ }];
+}
+class LambdaExpr {
+ code Code = [{
+ for (const LambdaCapture &C : S->captures()) {
+ addData(C.isPackExpansion());
+ addData(C.getCaptureKind());
+ if (C.capturesVariable())
+ addData(C.getCapturedVar()->getType());
+ }
+ addData(S->isGenericLambda());
+ addData(S->isMutable());
+ }];
+}
+class DeclStmt {
+ code Code = [{
+ auto numDecls = std::distance(S->decl_begin(), S->decl_end());
+ addData(static_cast<unsigned>(numDecls));
+ for (const Decl *D : S->decls()) {
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ addData(VD->getType());
+ }
+ }
+ }];
+}
+class AsmStmt {
+ code Code = [{
+ addData(S->isSimple());
+ addData(S->isVolatile());
+ addData(S->generateAsmString(Context));
+ for (unsigned i = 0; i < S->getNumInputs(); ++i) {
+ addData(S->getInputConstraint(i));
+ }
+ for (unsigned i = 0; i < S->getNumOutputs(); ++i) {
+ addData(S->getOutputConstraint(i));
+ }
+ for (unsigned i = 0; i < S->getNumClobbers(); ++i) {
+ addData(S->getClobber(i));
+ }
+ }];
+}
+class AttributedStmt {
+ code Code = [{
+ for (const Attr *A : S->getAttrs()) {
+ addData(std::string(A->getSpelling()));
+ }
+ }];
+}
diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtGraphTraits.h b/contrib/llvm/tools/clang/include/clang/AST/StmtGraphTraits.h
index 92eb64430f73e..02c77b242c7c8 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/StmtGraphTraits.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/StmtGraphTraits.h
@@ -1,4 +1,4 @@
-//===--- StmtGraphTraits.h - Graph Traits for the class Stmt ----*- C++ -*-===//
+//===- StmtGraphTraits.h - Graph Traits for the class Stmt ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -21,13 +21,10 @@
namespace llvm {
-//template <typename T> struct GraphTraits;
-
-
-template <> struct GraphTraits<clang::Stmt*> {
- typedef clang::Stmt * NodeRef;
- typedef clang::Stmt::child_iterator ChildIteratorType;
- typedef llvm::df_iterator<clang::Stmt*> nodes_iterator;
+template <> struct GraphTraits<clang::Stmt *> {
+ using NodeRef = clang::Stmt *;
+ using ChildIteratorType = clang::Stmt::child_iterator;
+ using nodes_iterator = llvm::df_iterator<clang::Stmt *>;
static NodeRef getEntryNode(clang::Stmt *S) { return S; }
@@ -50,11 +47,10 @@ template <> struct GraphTraits<clang::Stmt*> {
}
};
-
-template <> struct GraphTraits<const clang::Stmt*> {
- typedef const clang::Stmt * NodeRef;
- typedef clang::Stmt::const_child_iterator ChildIteratorType;
- typedef llvm::df_iterator<const clang::Stmt*> nodes_iterator;
+template <> struct GraphTraits<const clang::Stmt *> {
+ using NodeRef = const clang::Stmt *;
+ using ChildIteratorType = clang::Stmt::const_child_iterator;
+ using nodes_iterator = llvm::df_iterator<const clang::Stmt *>;
static NodeRef getEntryNode(const clang::Stmt *S) { return S; }
@@ -77,7 +73,6 @@ template <> struct GraphTraits<const clang::Stmt*> {
}
};
+} // namespace llvm
-} // end namespace llvm
-
-#endif
+#endif // LLVM_CLANG_AST_STMTGRAPHTRAITS_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h b/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h
index 5d3bce8d83bae..33aab08bbb713 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h
@@ -1,4 +1,4 @@
-//===--- StmtIterator.h - Iterators for Statements --------------*- C++ -*-===//
+//===- StmtIterator.h - Iterators for Statements ----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,31 +14,38 @@
#ifndef LLVM_CLANG_AST_STMTITERATOR_H
#define LLVM_CLANG_AST_STMTITERATOR_H
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/DataTypes.h"
#include <cassert>
#include <cstddef>
+#include <cstdint>
#include <iterator>
-#include <utility>
namespace clang {
-class Stmt;
class Decl;
+class Stmt;
class VariableArrayType;
class StmtIteratorBase {
protected:
- enum { StmtMode = 0x0, SizeOfTypeVAMode = 0x1, DeclGroupMode = 0x2,
- Flags = 0x3 };
+ enum {
+ StmtMode = 0x0,
+ SizeOfTypeVAMode = 0x1,
+ DeclGroupMode = 0x2,
+ Flags = 0x3
+ };
union {
Stmt **stmt;
Decl **DGI;
};
- uintptr_t RawVAPtr;
+ uintptr_t RawVAPtr = 0;
Decl **DGE;
+ StmtIteratorBase(Stmt **s) : stmt(s) {}
+ StmtIteratorBase(const VariableArrayType *t);
+ StmtIteratorBase(Decl **dgi, Decl **dge);
+ StmtIteratorBase() : stmt(nullptr) {}
+
bool inDeclGroup() const {
return (RawVAPtr & Flags) == DeclGroupMode;
}
@@ -56,7 +63,7 @@ protected:
}
void setVAPtr(const VariableArrayType *P) {
- assert (inDeclGroup() || inSizeOfTypeVA());
+ assert(inDeclGroup() || inSizeOfTypeVA());
RawVAPtr = reinterpret_cast<uintptr_t>(P) | (RawVAPtr & Flags);
}
@@ -65,14 +72,8 @@ protected:
void NextVA();
Stmt*& GetDeclExpr() const;
-
- StmtIteratorBase(Stmt **s) : stmt(s), RawVAPtr(0) {}
- StmtIteratorBase(const VariableArrayType *t);
- StmtIteratorBase(Decl **dgi, Decl **dge);
- StmtIteratorBase() : stmt(nullptr), RawVAPtr(0) {}
};
-
template <typename DERIVED, typename REFERENCE>
class StmtIteratorImpl : public StmtIteratorBase,
public std::iterator<std::forward_iterator_tag,
@@ -80,8 +81,9 @@ class StmtIteratorImpl : public StmtIteratorBase,
REFERENCE, REFERENCE> {
protected:
StmtIteratorImpl(const StmtIteratorBase& RHS) : StmtIteratorBase(RHS) {}
+
public:
- StmtIteratorImpl() {}
+ StmtIteratorImpl() = default;
StmtIteratorImpl(Stmt **s) : StmtIteratorBase(s) {}
StmtIteratorImpl(Decl **dgi, Decl **dge) : StmtIteratorBase(dgi, dge) {}
StmtIteratorImpl(const VariableArrayType *t) : StmtIteratorBase(t) {}
@@ -120,16 +122,13 @@ public:
struct ConstStmtIterator;
-struct StmtIterator : public StmtIteratorImpl<StmtIterator,Stmt*&> {
- explicit StmtIterator() : StmtIteratorImpl<StmtIterator,Stmt*&>() {}
-
- StmtIterator(Stmt** S) : StmtIteratorImpl<StmtIterator,Stmt*&>(S) {}
-
+struct StmtIterator : public StmtIteratorImpl<StmtIterator, Stmt*&> {
+ explicit StmtIterator() = default;
+ StmtIterator(Stmt** S) : StmtIteratorImpl<StmtIterator, Stmt*&>(S) {}
StmtIterator(Decl** dgi, Decl** dge)
- : StmtIteratorImpl<StmtIterator,Stmt*&>(dgi, dge) {}
-
+ : StmtIteratorImpl<StmtIterator, Stmt*&>(dgi, dge) {}
StmtIterator(const VariableArrayType *t)
- : StmtIteratorImpl<StmtIterator,Stmt*&>(t) {}
+ : StmtIteratorImpl<StmtIterator, Stmt*&>(t) {}
private:
StmtIterator(const StmtIteratorBase &RHS)
@@ -141,11 +140,9 @@ private:
struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator,
const Stmt*> {
- explicit ConstStmtIterator() :
- StmtIteratorImpl<ConstStmtIterator,const Stmt*>() {}
-
- ConstStmtIterator(const StmtIterator& RHS) :
- StmtIteratorImpl<ConstStmtIterator,const Stmt*>(RHS) {}
+ explicit ConstStmtIterator() = default;
+ ConstStmtIterator(const StmtIterator& RHS)
+ : StmtIteratorImpl<ConstStmtIterator, const Stmt*>(RHS) {}
ConstStmtIterator(Stmt * const *S)
: StmtIteratorImpl<ConstStmtIterator, const Stmt *>(
@@ -155,6 +152,7 @@ struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator,
inline StmtIterator cast_away_const(const ConstStmtIterator &RHS) {
return RHS;
}
-} // end namespace clang
-#endif
+} // namespace clang
+
+#endif // LLVM_CLANG_AST_STMTITERATOR_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtOpenMP.h b/contrib/llvm/tools/clang/include/clang/AST/StmtOpenMP.h
index 09dd87fdc8bc0..66fb037fc33cb 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/StmtOpenMP.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/StmtOpenMP.h
@@ -899,7 +899,9 @@ public:
}
const Stmt *getBody() const {
// This relies on the loop form is already checked by Sema.
- Stmt *Body = getAssociatedStmt()->IgnoreContainers(true);
+ const Stmt *Body = getAssociatedStmt()->IgnoreContainers(true);
+ while(const auto *CS = dyn_cast<CapturedStmt>(Body))
+ Body = CS->getCapturedStmt();
Body = cast<ForStmt>(Body)->getBody();
for (unsigned Cnt = 1; Cnt < CollapsedNum; ++Cnt) {
Body = Body->IgnoreContainers();
@@ -955,8 +957,15 @@ public:
T->getStmtClass() == OMPTargetSimdDirectiveClass ||
T->getStmtClass() == OMPTeamsDistributeDirectiveClass ||
T->getStmtClass() == OMPTeamsDistributeSimdDirectiveClass ||
- T->getStmtClass() == OMPTeamsDistributeParallelForSimdDirectiveClass ||
- T->getStmtClass() == OMPTeamsDistributeParallelForDirectiveClass;
+ T->getStmtClass() ==
+ OMPTeamsDistributeParallelForSimdDirectiveClass ||
+ T->getStmtClass() == OMPTeamsDistributeParallelForDirectiveClass ||
+ T->getStmtClass() ==
+ OMPTargetTeamsDistributeParallelForDirectiveClass ||
+ T->getStmtClass() ==
+ OMPTargetTeamsDistributeParallelForSimdDirectiveClass ||
+ T->getStmtClass() == OMPTargetTeamsDistributeDirectiveClass ||
+ T->getStmtClass() == OMPTargetTeamsDistributeSimdDirectiveClass;
}
};
@@ -1912,7 +1921,7 @@ class OMPTaskgroupDirective : public OMPExecutableDirective {
OMPTaskgroupDirective(SourceLocation StartLoc, SourceLocation EndLoc,
unsigned NumClauses)
: OMPExecutableDirective(this, OMPTaskgroupDirectiveClass, OMPD_taskgroup,
- StartLoc, EndLoc, NumClauses, 1) {}
+ StartLoc, EndLoc, NumClauses, 2) {}
/// Build an empty directive.
/// \param NumClauses Number of clauses.
@@ -1920,7 +1929,12 @@ class OMPTaskgroupDirective : public OMPExecutableDirective {
explicit OMPTaskgroupDirective(unsigned NumClauses)
: OMPExecutableDirective(this, OMPTaskgroupDirectiveClass, OMPD_taskgroup,
SourceLocation(), SourceLocation(), NumClauses,
- 1) {}
+ 2) {}
+
+ /// Sets the task_reduction return variable.
+ void setReductionRef(Expr *RR) {
+ *std::next(child_begin(), 1) = RR;
+ }
public:
/// Creates directive.
@@ -1930,10 +1944,12 @@ public:
/// \param EndLoc Ending Location of the directive.
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
+ /// \param ReductionRef Reference to the task_reduction return variable.
///
static OMPTaskgroupDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
- ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ Expr *ReductionRef);
/// Creates an empty directive.
///
@@ -1943,6 +1959,15 @@ public:
static OMPTaskgroupDirective *CreateEmpty(const ASTContext &C,
unsigned NumClauses, EmptyShell);
+
+ /// Returns reference to the task_reduction return variable.
+ const Expr *getReductionRef() const {
+ return static_cast<const Expr *>(*std::next(child_begin(), 1));
+ }
+ Expr *getReductionRef() {
+ return static_cast<Expr *>(*std::next(child_begin(), 1));
+ }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPTaskgroupDirectiveClass;
}
@@ -2330,7 +2355,7 @@ class OMPTargetEnterDataDirective : public OMPExecutableDirective {
unsigned NumClauses)
: OMPExecutableDirective(this, OMPTargetEnterDataDirectiveClass,
OMPD_target_enter_data, StartLoc, EndLoc,
- NumClauses, /*NumChildren=*/0) {}
+ NumClauses, /*NumChildren=*/1) {}
/// \brief Build an empty directive.
///
@@ -2340,7 +2365,7 @@ class OMPTargetEnterDataDirective : public OMPExecutableDirective {
: OMPExecutableDirective(this, OMPTargetEnterDataDirectiveClass,
OMPD_target_enter_data, SourceLocation(),
SourceLocation(), NumClauses,
- /*NumChildren=*/0) {}
+ /*NumChildren=*/1) {}
public:
/// \brief Creates directive with a list of \a Clauses.
@@ -2349,11 +2374,11 @@ public:
/// \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 OMPTargetEnterDataDirective *Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation EndLoc,
- ArrayRef<OMPClause *> Clauses);
+ static OMPTargetEnterDataDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
/// \brief Creates an empty directive with the place for \a N clauses.
///
@@ -2389,7 +2414,7 @@ class OMPTargetExitDataDirective : public OMPExecutableDirective {
unsigned NumClauses)
: OMPExecutableDirective(this, OMPTargetExitDataDirectiveClass,
OMPD_target_exit_data, StartLoc, EndLoc,
- NumClauses, /*NumChildren=*/0) {}
+ NumClauses, /*NumChildren=*/1) {}
/// \brief Build an empty directive.
///
@@ -2399,7 +2424,7 @@ class OMPTargetExitDataDirective : public OMPExecutableDirective {
: OMPExecutableDirective(this, OMPTargetExitDataDirectiveClass,
OMPD_target_exit_data, SourceLocation(),
SourceLocation(), NumClauses,
- /*NumChildren=*/0) {}
+ /*NumChildren=*/1) {}
public:
/// \brief Creates directive with a list of \a Clauses.
@@ -2408,11 +2433,11 @@ public:
/// \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 OMPTargetExitDataDirective *Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation EndLoc,
- ArrayRef<OMPClause *> Clauses);
+ static OMPTargetExitDataDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
/// \brief Creates an empty directive with the place for \a N clauses.
///
@@ -2966,7 +2991,7 @@ class OMPTargetUpdateDirective : public OMPExecutableDirective {
unsigned NumClauses)
: OMPExecutableDirective(this, OMPTargetUpdateDirectiveClass,
OMPD_target_update, StartLoc, EndLoc, NumClauses,
- 0) {}
+ 1) {}
/// \brief Build an empty directive.
///
@@ -2975,7 +3000,7 @@ class OMPTargetUpdateDirective : public OMPExecutableDirective {
explicit OMPTargetUpdateDirective(unsigned NumClauses)
: OMPExecutableDirective(this, OMPTargetUpdateDirectiveClass,
OMPD_target_update, SourceLocation(),
- SourceLocation(), NumClauses, 0) {}
+ SourceLocation(), NumClauses, 1) {}
public:
/// \brief Creates directive with a list of \a Clauses.
@@ -2984,11 +3009,11 @@ public:
/// \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 OMPTargetUpdateDirective *Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation EndLoc,
- ArrayRef<OMPClause *> Clauses);
+ static OMPTargetUpdateDirective *
+ 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.
@@ -3015,6 +3040,8 @@ public:
///
class OMPDistributeParallelForDirective : public OMPLoopDirective {
friend class ASTStmtReader;
+ /// true if the construct has inner cancel directive.
+ bool HasCancel = false;
/// \brief Build directive with the given start and end location.
///
@@ -3028,7 +3055,7 @@ class OMPDistributeParallelForDirective : public OMPLoopDirective {
unsigned CollapsedNum, unsigned NumClauses)
: OMPLoopDirective(this, OMPDistributeParallelForDirectiveClass,
OMPD_distribute_parallel_for, StartLoc, EndLoc,
- CollapsedNum, NumClauses) {}
+ CollapsedNum, NumClauses), HasCancel(false) {}
/// \brief Build an empty directive.
///
@@ -3039,7 +3066,11 @@ class OMPDistributeParallelForDirective : public OMPLoopDirective {
unsigned NumClauses)
: OMPLoopDirective(this, OMPDistributeParallelForDirectiveClass,
OMPD_distribute_parallel_for, SourceLocation(),
- SourceLocation(), CollapsedNum, NumClauses) {}
+ SourceLocation(), CollapsedNum, NumClauses),
+ HasCancel(false) {}
+
+ /// Set cancel state.
+ void setHasCancel(bool Has) { HasCancel = Has; }
public:
/// \brief Creates directive with a list of \a Clauses.
@@ -3051,11 +3082,12 @@ public:
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
/// \param Exprs Helper expressions for CodeGen.
+ /// \param HasCancel true if this directive has inner cancel directive.
///
static OMPDistributeParallelForDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
- Stmt *AssociatedStmt, const HelperExprs &Exprs);
+ Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
/// \brief Creates an empty directive with the place
/// for \a NumClauses clauses.
@@ -3069,6 +3101,9 @@ public:
unsigned CollapsedNum,
EmptyShell);
+ /// Return true if current directive has inner cancel directive.
+ bool hasCancel() const { return HasCancel; }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPDistributeParallelForDirectiveClass;
}
@@ -3565,6 +3600,8 @@ public:
///
class OMPTeamsDistributeParallelForDirective final : public OMPLoopDirective {
friend class ASTStmtReader;
+ /// true if the construct has inner cancel directive.
+ bool HasCancel = false;
/// Build directive with the given start and end location.
///
@@ -3579,7 +3616,7 @@ class OMPTeamsDistributeParallelForDirective final : public OMPLoopDirective {
unsigned NumClauses)
: OMPLoopDirective(this, OMPTeamsDistributeParallelForDirectiveClass,
OMPD_teams_distribute_parallel_for, StartLoc, EndLoc,
- CollapsedNum, NumClauses) {}
+ CollapsedNum, NumClauses), HasCancel(false) {}
/// Build an empty directive.
///
@@ -3590,7 +3627,11 @@ class OMPTeamsDistributeParallelForDirective final : public OMPLoopDirective {
unsigned NumClauses)
: OMPLoopDirective(this, OMPTeamsDistributeParallelForDirectiveClass,
OMPD_teams_distribute_parallel_for, SourceLocation(),
- SourceLocation(), CollapsedNum, NumClauses) {}
+ SourceLocation(), CollapsedNum, NumClauses),
+ HasCancel(false) {}
+
+ /// Set cancel state.
+ void setHasCancel(bool Has) { HasCancel = Has; }
public:
/// Creates directive with a list of \a Clauses.
@@ -3602,11 +3643,12 @@ public:
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
/// \param Exprs Helper expressions for CodeGen.
+ /// \param HasCancel true if this directive has inner cancel directive.
///
static OMPTeamsDistributeParallelForDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
- Stmt *AssociatedStmt, const HelperExprs &Exprs);
+ Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
/// Creates an empty directive with the place for \a NumClauses clauses.
///
@@ -3618,6 +3660,9 @@ public:
CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
EmptyShell);
+ /// Return true if current directive has inner cancel directive.
+ bool hasCancel() const { return HasCancel; }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPTeamsDistributeParallelForDirectiveClass;
}
@@ -3761,6 +3806,8 @@ public:
class OMPTargetTeamsDistributeParallelForDirective final
: public OMPLoopDirective {
friend class ASTStmtReader;
+ /// true if the construct has inner cancel directive.
+ bool HasCancel = false;
/// Build directive with the given start and end location.
///
@@ -3776,7 +3823,8 @@ class OMPTargetTeamsDistributeParallelForDirective final
: OMPLoopDirective(this,
OMPTargetTeamsDistributeParallelForDirectiveClass,
OMPD_target_teams_distribute_parallel_for, StartLoc,
- EndLoc, CollapsedNum, NumClauses) {}
+ EndLoc, CollapsedNum, NumClauses),
+ HasCancel(false) {}
/// Build an empty directive.
///
@@ -3788,7 +3836,11 @@ class OMPTargetTeamsDistributeParallelForDirective final
: OMPLoopDirective(
this, OMPTargetTeamsDistributeParallelForDirectiveClass,
OMPD_target_teams_distribute_parallel_for, SourceLocation(),
- SourceLocation(), CollapsedNum, NumClauses) {}
+ SourceLocation(), CollapsedNum, NumClauses),
+ HasCancel(false) {}
+
+ /// Set cancel state.
+ void setHasCancel(bool Has) { HasCancel = Has; }
public:
/// Creates directive with a list of \a Clauses.
@@ -3800,11 +3852,12 @@ public:
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
/// \param Exprs Helper expressions for CodeGen.
+ /// \param HasCancel true if this directive has inner cancel directive.
///
static OMPTargetTeamsDistributeParallelForDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
- Stmt *AssociatedStmt, const HelperExprs &Exprs);
+ Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
/// Creates an empty directive with the place for \a NumClauses clauses.
///
@@ -3816,6 +3869,9 @@ public:
CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
EmptyShell);
+ /// Return true if current directive has inner cancel directive.
+ bool hasCancel() const { return HasCancel; }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() ==
OMPTargetTeamsDistributeParallelForDirectiveClass;
diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/StmtVisitor.h
index df4a2d8bc3d7b..98fa113274069 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/StmtVisitor.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/StmtVisitor.h
@@ -1,4 +1,4 @@
-//===--- StmtVisitor.h - Visitor for Stmt subclasses ------------*- C++ -*-===//
+//===- StmtVisitor.h - Visitor for Stmt subclasses --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,28 +17,33 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExprOpenMP.h"
+#include "clang/AST/Stmt.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/AST/StmtOpenMP.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <utility>
namespace clang {
-template <typename T> struct make_ptr { typedef T *type; };
-template <typename T> struct make_const_ptr { typedef const T *type; };
+template <typename T> struct make_ptr { using type = T *; };
+template <typename T> struct make_const_ptr { using type = const T *; };
/// StmtVisitorBase - This class implements a simple visitor for Stmt
/// subclasses. Since Expr derives from Stmt, this also includes support for
/// visiting Exprs.
-template<template <typename> class Ptr, typename ImplClass, typename RetTy=void>
+template<template <typename> class Ptr, typename ImplClass, typename RetTy=void,
+ class... ParamTys>
class StmtVisitorBase {
public:
-
#define PTR(CLASS) typename Ptr<CLASS>::type
#define DISPATCH(NAME, CLASS) \
- return static_cast<ImplClass*>(this)->Visit ## NAME(static_cast<PTR(CLASS)>(S))
-
- RetTy Visit(PTR(Stmt) S) {
+ return static_cast<ImplClass*>(this)->Visit ## NAME( \
+ static_cast<PTR(CLASS)>(S), std::forward<ParamTys>(P)...)
+ RetTy Visit(PTR(Stmt) S, ParamTys... P) {
// If we have a binary expr, dispatch to the subcode of the binop. A smart
// optimizer (e.g. LLVM) will fold this comparison into the switch stmt
// below.
@@ -60,6 +65,7 @@ public:
case BO_GE: DISPATCH(BinGE, BinaryOperator);
case BO_EQ: DISPATCH(BinEQ, BinaryOperator);
case BO_NE: DISPATCH(BinNE, BinaryOperator);
+ case BO_Cmp: DISPATCH(BinCmp, BinaryOperator);
case BO_And: DISPATCH(BinAnd, BinaryOperator);
case BO_Xor: DISPATCH(BinXor, BinaryOperator);
@@ -111,13 +117,13 @@ public:
// If the implementation chooses not to implement a certain visit method, fall
// back on VisitExpr or whatever else is the superclass.
#define STMT(CLASS, PARENT) \
- RetTy Visit ## CLASS(PTR(CLASS) S) { DISPATCH(PARENT, PARENT); }
+ RetTy Visit ## CLASS(PTR(CLASS) S, ParamTys... P) { DISPATCH(PARENT, PARENT); }
#include "clang/AST/StmtNodes.inc"
// If the implementation doesn't implement binary operator methods, fall back
// on VisitBinaryOperator.
#define BINOP_FALLBACK(NAME) \
- RetTy VisitBin ## NAME(PTR(BinaryOperator) S) { \
+ RetTy VisitBin ## NAME(PTR(BinaryOperator) S, ParamTys... P) { \
DISPATCH(BinaryOperator, BinaryOperator); \
}
BINOP_FALLBACK(PtrMemD) BINOP_FALLBACK(PtrMemI)
@@ -127,6 +133,8 @@ public:
BINOP_FALLBACK(LT) BINOP_FALLBACK(GT) BINOP_FALLBACK(LE)
BINOP_FALLBACK(GE) BINOP_FALLBACK(EQ) BINOP_FALLBACK(NE)
+ BINOP_FALLBACK(Cmp)
+
BINOP_FALLBACK(And) BINOP_FALLBACK(Xor) BINOP_FALLBACK(Or)
BINOP_FALLBACK(LAnd) BINOP_FALLBACK(LOr)
@@ -137,7 +145,7 @@ public:
// If the implementation doesn't implement compound assignment operator
// methods, fall back on VisitCompoundAssignOperator.
#define CAO_FALLBACK(NAME) \
- RetTy VisitBin ## NAME(PTR(CompoundAssignOperator) S) { \
+ RetTy VisitBin ## NAME(PTR(CompoundAssignOperator) S, ParamTys... P) { \
DISPATCH(CompoundAssignOperator, CompoundAssignOperator); \
}
CAO_FALLBACK(MulAssign) CAO_FALLBACK(DivAssign) CAO_FALLBACK(RemAssign)
@@ -149,7 +157,7 @@ public:
// If the implementation doesn't implement unary operator methods, fall back
// on VisitUnaryOperator.
#define UNARYOP_FALLBACK(NAME) \
- RetTy VisitUnary ## NAME(PTR(UnaryOperator) S) { \
+ RetTy VisitUnary ## NAME(PTR(UnaryOperator) S, ParamTys... P) { \
DISPATCH(UnaryOperator, UnaryOperator); \
}
UNARYOP_FALLBACK(PostInc) UNARYOP_FALLBACK(PostDec)
@@ -163,7 +171,7 @@ public:
#undef UNARYOP_FALLBACK
// Base case, ignore it. :)
- RetTy VisitStmt(PTR(Stmt) Node) { return RetTy(); }
+ RetTy VisitStmt(PTR(Stmt) Node, ParamTys... P) { return RetTy(); }
#undef PTR
#undef DISPATCH
@@ -174,18 +182,18 @@ public:
///
/// This class does not preserve constness of Stmt pointers (see also
/// ConstStmtVisitor).
-template<typename ImplClass, typename RetTy=void>
+template<typename ImplClass, typename RetTy=void, typename... ParamTys>
class StmtVisitor
- : public StmtVisitorBase<make_ptr, ImplClass, RetTy> {};
+ : public StmtVisitorBase<make_ptr, ImplClass, RetTy, ParamTys...> {};
/// ConstStmtVisitor - This class implements a simple visitor for Stmt
/// subclasses. Since Expr derives from Stmt, this also includes support for
/// visiting Exprs.
///
/// This class preserves constness of Stmt pointers (see also StmtVisitor).
-template<typename ImplClass, typename RetTy=void>
+template<typename ImplClass, typename RetTy=void, typename... ParamTys>
class ConstStmtVisitor
- : public StmtVisitorBase<make_const_ptr, ImplClass, RetTy> {};
+ : public StmtVisitorBase<make_const_ptr, ImplClass, RetTy, ParamTys...> {};
/// \brief This class implements a simple visitor for OMPClause
/// subclasses.
@@ -222,6 +230,6 @@ template<class ImplClass, typename RetTy = void>
class ConstOMPClauseVisitor :
public OMPClauseVisitorBase <ImplClass, make_const_ptr, RetTy> {};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_AST_STMTVISITOR_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h b/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h
index 84fbcda6e0873..850250b9c0a21 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h
@@ -1,4 +1,4 @@
-//===-- TemplateBase.h - Core classes for C++ templates ---------*- C++ -*-===//
+//===- TemplateBase.h - Core classes for C++ templates ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,21 +15,32 @@
#ifndef LLVM_CLANG_AST_TEMPLATEBASE_H
#define LLVM_CLANG_AST_TEMPLATEBASE_H
+#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/APInt.h"
#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Compiler.h"
-#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TrailingObjects.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
namespace llvm {
- class FoldingSetNodeID;
-}
+
+class FoldingSetNodeID;
+
+} // namespace llvm
namespace clang {
+class ASTContext;
class DiagnosticBuilder;
class Expr;
struct PrintingPolicy;
@@ -44,29 +55,37 @@ public:
/// \brief Represents an empty template argument, e.g., one that has not
/// been deduced.
Null = 0,
+
/// The template argument is a type.
Type,
+
/// The template argument is a declaration that was provided for a pointer,
/// reference, or pointer to member non-type template parameter.
Declaration,
+
/// The template argument is a null pointer or null pointer to member that
/// was provided for a non-type template parameter.
NullPtr,
+
/// The template argument is an integral value stored in an llvm::APSInt
/// that was provided for an integral non-type template parameter.
Integral,
+
/// The template argument is a template name that was provided for a
/// template template parameter.
Template,
+
/// The template argument is a pack expansion of a template name that was
/// provided for a template template parameter.
TemplateExpansion,
+
/// The template argument is an expression, and we've not resolved it to one
/// of the other forms yet, either because it's dependent or because we're
/// representing a non-canonical template argument (for instance, in a
/// TemplateSpecializationType). Also used to represent a non-dependent
/// __uuidof expression (a Microsoft extension).
Expression,
+
/// The template argument is actually a parameter pack. Arguments are stored
/// in the Args struct.
Pack
@@ -88,8 +107,11 @@ private:
unsigned BitWidth : 31;
unsigned IsUnsigned : 1;
union {
- uint64_t VAL; ///< Used to store the <= 64 bits integer value.
- const uint64_t *pVal; ///< Used to store the >64 bits integer value.
+ /// Used to store the <= 64 bits integer value.
+ uint64_t VAL;
+
+ /// Used to store the >64 bits integer value.
+ const uint64_t *pVal;
};
void *Type;
};
@@ -115,8 +137,6 @@ private:
struct TV TypeOrValue;
};
- TemplateArgument(TemplateName, bool) = delete;
-
public:
/// \brief Construct an empty, invalid template argument.
constexpr TemplateArgument() : TypeOrValue({Null, 0}) {}
@@ -202,6 +222,8 @@ public:
this->Args.NumArgs = Args.size();
}
+ TemplateArgument(TemplateName, bool) = delete;
+
static TemplateArgument getEmptyPack() { return TemplateArgument(None); }
/// \brief Create a new template argument pack by copying the given set of
@@ -278,7 +300,9 @@ public:
// FIXME: Provide a way to read the integral data without copying the value.
llvm::APSInt getAsIntegral() const {
assert(getKind() == Integral && "Unexpected kind");
+
using namespace llvm;
+
if (Integer.BitWidth <= 64)
return APSInt(APInt(Integer.BitWidth, Integer.VAL), Integer.IsUnsigned);
@@ -309,7 +333,7 @@ public:
}
/// \brief Iterator that traverses the elements of a template argument pack.
- typedef const TemplateArgument * pack_iterator;
+ using pack_iterator = const TemplateArgument *;
/// \brief Iterator referencing the first argument of a template argument
/// pack.
@@ -368,7 +392,6 @@ public:
/// Location information for a TemplateArgument.
struct TemplateArgumentLocInfo {
private:
-
struct T {
// FIXME: We'd like to just use the qualifier in the TemplateName,
// but template arguments get canonicalized too quickly.
@@ -393,8 +416,7 @@ public:
TemplateArgumentLocInfo(NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateNameLoc,
- SourceLocation EllipsisLoc)
- {
+ SourceLocation EllipsisLoc) {
Template.Qualifier = QualifierLoc.getNestedNameSpecifier();
Template.QualifierLocData = QualifierLoc.getOpaqueData();
Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding();
@@ -434,16 +456,15 @@ public:
TemplateArgumentLoc(const TemplateArgument &Argument,
TemplateArgumentLocInfo Opaque)
- : Argument(Argument), LocInfo(Opaque) {
- }
+ : Argument(Argument), LocInfo(Opaque) {}
TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo)
- : Argument(Argument), LocInfo(TInfo) {
+ : Argument(Argument), LocInfo(TInfo) {
assert(Argument.getKind() == TemplateArgument::Type);
}
TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E)
- : Argument(Argument), LocInfo(E) {
+ : Argument(Argument), LocInfo(E) {
assert(Argument.getKind() == TemplateArgument::Expression);
}
@@ -451,7 +472,8 @@ public:
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateNameLoc,
SourceLocation EllipsisLoc = SourceLocation())
- : Argument(Argument), LocInfo(QualifierLoc, TemplateNameLoc, EllipsisLoc) {
+ : Argument(Argument),
+ LocInfo(QualifierLoc, TemplateNameLoc, EllipsisLoc) {
assert(Argument.getKind() == TemplateArgument::Template ||
Argument.getKind() == TemplateArgument::TemplateExpansion);
}
@@ -526,16 +548,16 @@ class TemplateArgumentListInfo {
SourceLocation LAngleLoc;
SourceLocation RAngleLoc;
- // This can leak if used in an AST node, use ASTTemplateArgumentListInfo
- // instead.
- void *operator new(size_t bytes, ASTContext &C) = delete;
-
public:
- TemplateArgumentListInfo() {}
+ TemplateArgumentListInfo() = default;
TemplateArgumentListInfo(SourceLocation LAngleLoc,
SourceLocation RAngleLoc)
- : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {}
+ : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {}
+
+ // This can leak if used in an AST node, use ASTTemplateArgumentListInfo
+ // instead.
+ void *operator new(size_t bytes, ASTContext &C) = delete;
SourceLocation getLAngleLoc() const { return LAngleLoc; }
SourceLocation getRAngleLoc() const { return RAngleLoc; }
@@ -574,8 +596,8 @@ struct ASTTemplateArgumentListInfo final
: private llvm::TrailingObjects<ASTTemplateArgumentListInfo,
TemplateArgumentLoc> {
private:
- friend TrailingObjects;
friend class ASTNodeImporter;
+ friend TrailingObjects;
ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List);
@@ -668,6 +690,6 @@ inline const TemplateArgument &
return getArgs()[Idx];
}
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_AST_TEMPLATEBASE_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/TemplateName.h b/contrib/llvm/tools/clang/include/clang/AST/TemplateName.h
index bf4d008ee807a..fb33cf58d7960 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/TemplateName.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/TemplateName.h
@@ -1,4 +1,4 @@
-//===--- TemplateName.h - C++ Template Name Representation-------*- C++ -*-===//
+//===- TemplateName.h - C++ Template Name Representation --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,10 +14,12 @@
#ifndef LLVM_CLANG_AST_TEMPLATENAME_H
#define LLVM_CLANG_AST_TEMPLATENAME_H
-#include "clang/AST/NestedNameSpecifier.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
+#include <cassert>
namespace clang {
@@ -94,7 +96,7 @@ class OverloadedTemplateStorage : public UncommonTemplateNameStorage {
friend class ASTContext;
OverloadedTemplateStorage(unsigned size)
- : UncommonTemplateNameStorage(Overloaded, size) { }
+ : UncommonTemplateNameStorage(Overloaded, size) {}
NamedDecl **getStorage() {
return reinterpret_cast<NamedDecl **>(this + 1);
@@ -104,7 +106,7 @@ class OverloadedTemplateStorage : public UncommonTemplateNameStorage {
}
public:
- typedef NamedDecl *const *iterator;
+ using iterator = NamedDecl *const *;
iterator begin() const { return getStorage(); }
iterator end() const { return getStorage() + size(); }
@@ -126,8 +128,8 @@ public:
SubstTemplateTemplateParmPackStorage(TemplateTemplateParmDecl *Parameter,
unsigned Size,
const TemplateArgument *Arguments)
- : UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Size),
- Parameter(Parameter), Arguments(Arguments) { }
+ : UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Size),
+ Parameter(Parameter), Arguments(Arguments) {}
/// \brief Retrieve the template template parameter pack being substituted.
TemplateTemplateParmDecl *getParameterPack() const {
@@ -174,10 +176,9 @@ public:
/// specifier in the typedef. "apply" is a nested template, and can
/// only be understood in the context of
class TemplateName {
- typedef llvm::PointerUnion4<TemplateDecl *,
- UncommonTemplateNameStorage *,
- QualifiedTemplateName *,
- DependentTemplateName *> StorageType;
+ using StorageType =
+ llvm::PointerUnion4<TemplateDecl *, UncommonTemplateNameStorage *,
+ QualifiedTemplateName *, DependentTemplateName *>;
StorageType Storage;
@@ -188,24 +189,29 @@ public:
enum NameKind {
/// \brief A single template declaration.
Template,
+
/// \brief A set of overloaded template declarations.
OverloadedTemplate,
+
/// \brief A qualified template name, where the qualification is kept
/// to describe the source code as written.
QualifiedTemplate,
+
/// \brief A dependent template name that has not been resolved to a
/// template (or set of templates).
DependentTemplate,
+
/// \brief A template template parameter that has been substituted
/// for some other template name.
SubstTemplateTemplateParm,
+
/// \brief A template template parameter pack that has been substituted for
/// a template template argument pack, but has not yet been expanded into
/// individual arguments.
SubstTemplateTemplateParmPack
};
- TemplateName() : Storage() { }
+ TemplateName() = default;
explicit TemplateName(TemplateDecl *Template);
explicit TemplateName(OverloadedTemplateStorage *Storage);
explicit TemplateName(SubstTemplateTemplateParmStorage *Storage);
@@ -262,6 +268,11 @@ public:
TemplateName getUnderlying() const;
+ /// Get the template name to substitute when this template name is used as a
+ /// template template argument. This refers to the most recent declaration of
+ /// the template, including any default template arguments.
+ TemplateName getNameToSubstitute() const;
+
/// \brief Determines whether this is a dependent template name.
bool isDependent() const;
@@ -320,8 +331,8 @@ class SubstTemplateTemplateParmStorage
SubstTemplateTemplateParmStorage(TemplateTemplateParmDecl *parameter,
TemplateName replacement)
- : UncommonTemplateNameStorage(SubstTemplateTemplateParm, 0),
- Parameter(parameter), Replacement(replacement) {}
+ : UncommonTemplateNameStorage(SubstTemplateTemplateParm, 0),
+ Parameter(parameter), Replacement(replacement) {}
public:
TemplateTemplateParmDecl *getParameter() const { return Parameter; }
@@ -353,6 +364,8 @@ inline TemplateName TemplateName::getUnderlying() const {
/// manner, it is to TemplateName what ElaboratedType is to Type,
/// providing extra syntactic sugar for downstream clients.
class QualifiedTemplateName : public llvm::FoldingSetNode {
+ friend class ASTContext;
+
/// \brief The nested name specifier that qualifies the template name.
///
/// The bit is used to indicate whether the "template" keyword was
@@ -366,12 +379,9 @@ class QualifiedTemplateName : public llvm::FoldingSetNode {
/// that this qualified name refers to.
TemplateDecl *Template;
- friend class ASTContext;
-
QualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword,
TemplateDecl *Template)
- : Qualifier(NNS, TemplateKeyword? 1 : 0),
- Template(Template) { }
+ : Qualifier(NNS, TemplateKeyword? 1 : 0), Template(Template) {}
public:
/// \brief Return the nested name specifier that qualifies this name.
@@ -410,6 +420,8 @@ public:
/// where "MetaFun::" is the nested name specifier and "apply" is the
/// template name referenced. The "template" keyword is implied.
class DependentTemplateName : public llvm::FoldingSetNode {
+ friend class ASTContext;
+
/// \brief The nested name specifier that qualifies the template
/// name.
///
@@ -439,29 +451,27 @@ class DependentTemplateName : public llvm::FoldingSetNode {
/// canonical.
TemplateName CanonicalTemplateName;
- friend class ASTContext;
-
DependentTemplateName(NestedNameSpecifier *Qualifier,
const IdentifierInfo *Identifier)
- : Qualifier(Qualifier, false), Identifier(Identifier),
- CanonicalTemplateName(this) { }
+ : Qualifier(Qualifier, false), Identifier(Identifier),
+ CanonicalTemplateName(this) {}
DependentTemplateName(NestedNameSpecifier *Qualifier,
const IdentifierInfo *Identifier,
TemplateName Canon)
- : Qualifier(Qualifier, false), Identifier(Identifier),
- CanonicalTemplateName(Canon) { }
+ : Qualifier(Qualifier, false), Identifier(Identifier),
+ CanonicalTemplateName(Canon) {}
DependentTemplateName(NestedNameSpecifier *Qualifier,
OverloadedOperatorKind Operator)
- : Qualifier(Qualifier, true), Operator(Operator),
- CanonicalTemplateName(this) { }
+ : Qualifier(Qualifier, true), Operator(Operator),
+ CanonicalTemplateName(this) {}
DependentTemplateName(NestedNameSpecifier *Qualifier,
OverloadedOperatorKind Operator,
TemplateName Canon)
- : Qualifier(Qualifier, true), Operator(Operator),
- CanonicalTemplateName(Canon) { }
+ : Qualifier(Qualifier, true), Operator(Operator),
+ CanonicalTemplateName(Canon) {}
public:
/// \brief Return the nested name specifier that qualifies this name.
@@ -509,14 +519,13 @@ public:
}
};
-} // end namespace clang.
+} // namespace clang.
namespace llvm {
/// \brief The clang::TemplateName class is effectively a pointer.
template<>
-class PointerLikeTypeTraits<clang::TemplateName> {
-public:
+struct PointerLikeTypeTraits<clang::TemplateName> {
static inline void *getAsVoidPointer(clang::TemplateName TN) {
return TN.getAsVoidPointer();
}
@@ -529,6 +538,6 @@ public:
enum { NumLowBitsAvailable = 0 };
};
-} // end namespace llvm.
+} // namespace llvm.
-#endif
+#endif // LLVM_CLANG_AST_TEMPLATENAME_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Type.h b/contrib/llvm/tools/clang/include/clang/AST/Type.h
index 984096ffa9877..7247838947a2e 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/Type.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/Type.h
@@ -1,4 +1,4 @@
-//===--- Type.h - C Language Family Type Representation ---------*- C++ -*-===//
+//===- Type.h - C Language Family Type Representation -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,12 +6,13 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+//
/// \file
/// \brief C Language Family Type Representation
///
/// This file defines the clang::Type interface and subclasses, used to
/// represent types for languages in the C family.
-///
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_TYPE_H
@@ -25,85 +26,118 @@
#include "clang/Basic/LLVM.h"
#include "clang/Basic/Linkage.h"
#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/Visibility.h"
#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
+#include "llvm/Support/type_traits.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <string>
+#include <type_traits>
+#include <utility>
namespace clang {
- enum {
- TypeAlignmentInBits = 4,
- TypeAlignment = 1 << TypeAlignmentInBits
- };
- class Type;
- class ExtQuals;
- class QualType;
-}
+
+class ExtQuals;
+class QualType;
+class Type;
+
+enum {
+ TypeAlignmentInBits = 4,
+ TypeAlignment = 1 << TypeAlignmentInBits
+};
+
+} // namespace clang
namespace llvm {
+
template <typename T>
- class PointerLikeTypeTraits;
+ struct PointerLikeTypeTraits;
template<>
- class PointerLikeTypeTraits< ::clang::Type*> {
- public:
+ struct PointerLikeTypeTraits< ::clang::Type*> {
static inline void *getAsVoidPointer(::clang::Type *P) { return P; }
+
static inline ::clang::Type *getFromVoidPointer(void *P) {
return static_cast< ::clang::Type*>(P);
}
+
enum { NumLowBitsAvailable = clang::TypeAlignmentInBits };
};
+
template<>
- class PointerLikeTypeTraits< ::clang::ExtQuals*> {
- public:
+ struct PointerLikeTypeTraits< ::clang::ExtQuals*> {
static inline void *getAsVoidPointer(::clang::ExtQuals *P) { return P; }
+
static inline ::clang::ExtQuals *getFromVoidPointer(void *P) {
return static_cast< ::clang::ExtQuals*>(P);
}
+
enum { NumLowBitsAvailable = clang::TypeAlignmentInBits };
};
template <>
struct isPodLike<clang::QualType> { static const bool value = true; };
-}
+
+} // namespace llvm
namespace clang {
- class ASTContext;
- class TypedefNameDecl;
- class TemplateDecl;
- class TemplateTypeParmDecl;
- class NonTypeTemplateParmDecl;
- class TemplateTemplateParmDecl;
- class TagDecl;
- class RecordDecl;
- class CXXRecordDecl;
- class EnumDecl;
- class FieldDecl;
- class FunctionDecl;
- class ObjCInterfaceDecl;
- class ObjCProtocolDecl;
- class ObjCMethodDecl;
- class ObjCTypeParamDecl;
- class UnresolvedUsingTypenameDecl;
- class Expr;
- class Stmt;
- class SourceLocation;
- class StmtIteratorBase;
- class TemplateArgument;
- class TemplateArgumentLoc;
- class TemplateArgumentListInfo;
- class ElaboratedType;
- class ExtQuals;
- class ExtQualsTypeCommonBase;
- struct PrintingPolicy;
- template <typename> class CanQual;
- typedef CanQual<Type> CanQualType;
+class ArrayType;
+class ASTContext;
+class AttributedType;
+class AutoType;
+class BuiltinType;
+template <typename> class CanQual;
+class ComplexType;
+class CXXRecordDecl;
+class DeclContext;
+class DeducedType;
+class EnumDecl;
+class Expr;
+class ExtQualsTypeCommonBase;
+class FunctionDecl;
+class FunctionNoProtoType;
+class FunctionProtoType;
+class IdentifierInfo;
+class InjectedClassNameType;
+class NamedDecl;
+class ObjCInterfaceDecl;
+class ObjCObjectPointerType;
+class ObjCObjectType;
+class ObjCProtocolDecl;
+class ObjCTypeParamDecl;
+class ParenType;
+struct PrintingPolicy;
+class RecordDecl;
+class RecordType;
+class Stmt;
+class TagDecl;
+class TemplateArgument;
+class TemplateArgumentListInfo;
+class TemplateArgumentLoc;
+class TemplateSpecializationType;
+class TemplateTypeParmDecl;
+class TypedefNameDecl;
+class TypedefType;
+class UnresolvedUsingTypenameDecl;
+
+using CanQualType = CanQual<Type>;
// Provide forward declarations for all of the *Type classes
#define TYPE(Class, Base) class Class##Type;
@@ -164,8 +198,6 @@ public:
FastMask = (1 << FastWidth) - 1
};
- Qualifiers() : Mask(0) {}
-
/// Returns the common set of qualifiers while removing them from
/// the given sets.
static Qualifiers removeCommonQualifiers(Qualifiers &L, Qualifiers &R) {
@@ -332,9 +364,11 @@ public:
}
bool hasAddressSpace() const { return Mask & AddressSpaceMask; }
- unsigned getAddressSpace() const { return Mask >> AddressSpaceShift; }
+ LangAS getAddressSpace() const {
+ return static_cast<LangAS>(Mask >> AddressSpaceShift);
+ }
bool hasTargetSpecificAddressSpace() const {
- return getAddressSpace() >= LangAS::FirstTargetAddressSpace;
+ return isTargetAddressSpace(getAddressSpace());
}
/// Get the address space attribute value to be printed by diagnostics.
unsigned getAddressSpaceAttributePrintValue() const {
@@ -342,22 +376,22 @@ public:
// This function is not supposed to be used with language specific
// address spaces. If that happens, the diagnostic message should consider
// printing the QualType instead of the address space value.
- assert(Addr == 0 || hasTargetSpecificAddressSpace());
- if (Addr)
- return Addr - LangAS::FirstTargetAddressSpace;
+ assert(Addr == LangAS::Default || hasTargetSpecificAddressSpace());
+ if (Addr != LangAS::Default)
+ return toTargetAddressSpace(Addr);
// TODO: The diagnostic messages where Addr may be 0 should be fixed
// since it cannot differentiate the situation where 0 denotes the default
// address space or user specified __attribute__((address_space(0))).
return 0;
}
- void setAddressSpace(unsigned space) {
- assert(space <= MaxAddressSpace);
+ void setAddressSpace(LangAS space) {
+ assert((unsigned)space <= MaxAddressSpace);
Mask = (Mask & ~AddressSpaceMask)
| (((uint32_t) space) << AddressSpaceShift);
}
- void removeAddressSpace() { setAddressSpace(0); }
- void addAddressSpace(unsigned space) {
- assert(space);
+ void removeAddressSpace() { setAddressSpace(LangAS::Default); }
+ void addAddressSpace(LangAS space) {
+ assert(space != LangAS::Default);
setAddressSpace(space);
}
@@ -538,10 +572,9 @@ public:
}
private:
-
// bits: |0 1 2|3|4 .. 5|6 .. 8|9 ... 31|
// |C R V|U|GCAttr|Lifetime|AddressSpace|
- uint32_t Mask;
+ uint32_t Mask = 0;
static const uint32_t UMask = 0x8;
static const uint32_t UShift = 3;
@@ -558,12 +591,12 @@ private:
/// into its local qualifiers and its locally-unqualified type.
struct SplitQualType {
/// The locally-unqualified type.
- const Type *Ty;
+ const Type *Ty = nullptr;
/// The local qualifiers.
Qualifiers Quals;
- SplitQualType() : Ty(nullptr), Quals() {}
+ SplitQualType() = default;
SplitQualType(const Type *ty, Qualifiers qs) : Ty(ty), Quals(qs) {}
SplitQualType getSingleStepDesugaredType() const; // end of this file
@@ -589,12 +622,16 @@ struct SplitQualType {
enum class ObjCSubstitutionContext {
/// An ordinary type.
Ordinary,
+
/// The result type of a method or function.
Result,
+
/// The parameter type of a method or function.
Parameter,
+
/// The type of a property.
Property,
+
/// The superclass of a type.
Superclass,
};
@@ -614,8 +651,10 @@ enum class ObjCSubstitutionContext {
/// indicates whether there are extended qualifiers present, in which
/// case the pointer points to a special structure.
class QualType {
+ friend class QualifierCollector;
+
// Thankfully, these are efficiently composable.
- llvm::PointerIntPair<llvm::PointerUnion<const Type*,const ExtQuals*>,
+ llvm::PointerIntPair<llvm::PointerUnion<const Type *, const ExtQuals *>,
Qualifiers::FastWidth> Value;
const ExtQuals *getExtQualsUnsafe() const {
@@ -634,14 +673,10 @@ class QualType {
return reinterpret_cast<ExtQualsTypeCommonBase*>(CommonPtrVal);
}
- friend class QualifierCollector;
public:
- QualType() {}
-
- QualType(const Type *Ptr, unsigned Quals)
- : Value(Ptr, Quals) {}
- QualType(const ExtQuals *Ptr, unsigned Quals)
- : Value(Ptr, Quals) {}
+ QualType() = default;
+ QualType(const Type *Ptr, unsigned Quals) : Value(Ptr, Quals) {}
+ QualType(const ExtQuals *Ptr, unsigned Quals) : Value(Ptr, Quals) {}
unsigned getLocalFastQualifiers() const { return Value.getInt(); }
void setLocalFastQualifiers(unsigned Quals) { Value.setInt(Quals); }
@@ -662,6 +697,7 @@ public:
SplitQualType split() const;
void *getAsOpaquePtr() const { return Value.getOpaqueValue(); }
+
static QualType getFromOpaquePtr(const void *Ptr) {
QualType T;
T.Value.setFromOpaqueValue(const_cast<void*>(Ptr));
@@ -939,12 +975,15 @@ public:
friend bool operator!=(const QualType &LHS, const QualType &RHS) {
return LHS.Value != RHS.Value;
}
+
std::string getAsString() const {
return getAsString(split());
}
+
static std::string getAsString(SplitQualType split) {
return getAsString(split.Ty, split.Quals);
}
+
static std::string getAsString(const Type *ty, Qualifiers qs);
std::string getAsString(const PrintingPolicy &Policy) const;
@@ -954,11 +993,13 @@ public:
unsigned Indentation = 0) const {
print(split(), OS, Policy, PlaceHolder, Indentation);
}
+
static void print(SplitQualType split, raw_ostream &OS,
const PrintingPolicy &policy, const Twine &PlaceHolder,
unsigned Indentation = 0) {
return print(split.Ty, split.Quals, OS, policy, PlaceHolder, Indentation);
}
+
static void print(const Type *ty, Qualifiers qs,
raw_ostream &OS, const PrintingPolicy &policy,
const Twine &PlaceHolder,
@@ -968,10 +1009,12 @@ public:
const PrintingPolicy &Policy) const {
return getAsStringInternal(split(), Str, Policy);
}
+
static void getAsStringInternal(SplitQualType split, std::string &out,
const PrintingPolicy &policy) {
return getAsStringInternal(split.Ty, split.Quals, out, policy);
}
+
static void getAsStringInternal(const Type *ty, Qualifiers qs,
std::string &out,
const PrintingPolicy &policy);
@@ -981,11 +1024,12 @@ public:
const PrintingPolicy &Policy;
const Twine &PlaceHolder;
unsigned Indentation;
+
public:
StreamedQualTypeHelper(const QualType &T, const PrintingPolicy &Policy,
const Twine &PlaceHolder, unsigned Indentation)
- : T(T), Policy(Policy), PlaceHolder(PlaceHolder),
- Indentation(Indentation) { }
+ : T(T), Policy(Policy), PlaceHolder(PlaceHolder),
+ Indentation(Indentation) {}
friend raw_ostream &operator<<(raw_ostream &OS,
const StreamedQualTypeHelper &SQT) {
@@ -1009,7 +1053,7 @@ public:
}
/// Return the address space of this type.
- inline unsigned getAddressSpace() const;
+ inline LangAS getAddressSpace() const;
/// Returns gc attribute of this type.
inline Qualifiers::GC getObjCGCAttr() const;
@@ -1129,13 +1173,15 @@ private:
static DestructionKind isDestructedTypeImpl(QualType type);
};
-} // end clang.
+} // namespace clang
namespace llvm {
+
/// Implement simplify_type for QualType, so that we can dyn_cast from QualType
/// to a specific Type class.
template<> struct simplify_type< ::clang::QualType> {
- typedef const ::clang::Type *SimpleType;
+ using SimpleType = const ::clang::Type *;
+
static SimpleType getSimplifiedValue(::clang::QualType Val) {
return Val.getTypePtr();
}
@@ -1143,29 +1189,30 @@ template<> struct simplify_type< ::clang::QualType> {
// Teach SmallPtrSet that QualType is "basically a pointer".
template<>
-class PointerLikeTypeTraits<clang::QualType> {
-public:
+struct PointerLikeTypeTraits<clang::QualType> {
static inline void *getAsVoidPointer(clang::QualType P) {
return P.getAsOpaquePtr();
}
+
static inline clang::QualType getFromVoidPointer(void *P) {
return clang::QualType::getFromOpaquePtr(P);
}
+
// Various qualifiers go in low bits.
enum { NumLowBitsAvailable = 0 };
};
-} // end namespace llvm
+} // namespace llvm
namespace clang {
/// \brief Base class that is common to both the \c ExtQuals and \c Type
/// classes, which allows \c QualType to access the common fields between the
/// two.
-///
class ExtQualsTypeCommonBase {
- ExtQualsTypeCommonBase(const Type *baseType, QualType canon)
- : BaseType(baseType), CanonicalType(canon) {}
+ friend class ExtQuals;
+ friend class QualType;
+ friend class Type;
/// \brief The "base" type of an extended qualifiers type (\c ExtQuals) or
/// a self-referential pointer (for \c Type).
@@ -1177,9 +1224,8 @@ class ExtQualsTypeCommonBase {
/// \brief The canonical type of this type. A QualType.
QualType CanonicalType;
- friend class QualType;
- friend class Type;
- friend class ExtQuals;
+ ExtQualsTypeCommonBase(const Type *baseType, QualType canon)
+ : BaseType(baseType), CanonicalType(canon) {}
};
/// We can encode up to four bits in the low bits of a
@@ -1214,10 +1260,9 @@ class ExtQuals : public ExtQualsTypeCommonBase, public llvm::FoldingSetNode {
public:
ExtQuals(const Type *baseType, QualType canon, Qualifiers quals)
- : ExtQualsTypeCommonBase(baseType,
- canon.isNull() ? QualType(this_(), 0) : canon),
- Quals(quals)
- {
+ : ExtQualsTypeCommonBase(baseType,
+ canon.isNull() ? QualType(this_(), 0) : canon),
+ Quals(quals) {
assert(Quals.hasNonFastQualifiers()
&& "ExtQuals created with no fast qualifiers");
assert(!Quals.hasFastQualifiers()
@@ -1235,7 +1280,7 @@ public:
}
bool hasAddressSpace() const { return Quals.hasAddressSpace(); }
- unsigned getAddressSpace() const { return Quals.getAddressSpace(); }
+ LangAS getAddressSpace() const { return Quals.getAddressSpace(); }
const Type *getBaseType() const { return BaseType; }
@@ -1243,6 +1288,7 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) const {
Profile(ID, getBaseType(), Quals);
}
+
static void Profile(llvm::FoldingSetNodeID &ID,
const Type *BaseType,
Qualifiers Quals) {
@@ -1258,8 +1304,10 @@ public:
enum RefQualifierKind {
/// \brief No ref-qualifier was provided.
RQ_None = 0,
+
/// \brief An lvalue ref-qualifier was provided (\c &).
RQ_LValue,
+
/// \brief An rvalue ref-qualifier was provided (\c &&).
RQ_RValue
};
@@ -1268,8 +1316,10 @@ enum RefQualifierKind {
enum class AutoTypeKeyword {
/// \brief auto
Auto,
+
/// \brief decltype(auto)
DecltypeAuto,
+
/// \brief __auto_type (GNU extension)
GNUAutoType
};
@@ -1311,9 +1361,6 @@ public:
};
private:
- Type(const Type &) = delete;
- void operator=(const Type &) = delete;
-
/// Bitfields required by the Type class.
class TypeBitfields {
friend class Type;
@@ -1352,10 +1399,12 @@ private:
bool isCacheValid() const {
return CacheValid;
}
+
Linkage getLinkage() const {
assert(isCacheValid() && "getting linkage from invalid cache");
return static_cast<Linkage>(CachedLinkage);
}
+
bool hasLocalOrUnnamedType() const {
assert(isCacheValid() && "getting linkage from invalid cache");
return CachedLocalOrUnnamed;
@@ -1392,8 +1441,8 @@ protected:
};
class FunctionTypeBitfields {
- friend class FunctionType;
friend class FunctionProtoType;
+ friend class FunctionType;
unsigned : NumTypeBits;
@@ -1429,6 +1478,7 @@ protected:
/// Whether this is a "kindof" type.
unsigned IsKindOf : 1;
};
+
static_assert(NumTypeBits + 7 + 6 + 1 <= 32, "Does not fit in an unsigned");
class ReferenceTypeBitfields {
@@ -1511,21 +1561,21 @@ protected:
};
private:
+ template <class T> friend class TypePropertyCache;
+
/// \brief Set whether this type comes from an AST file.
void setFromAST(bool V = true) const {
TypeBits.FromAST = V;
}
- template <class T> friend class TypePropertyCache;
-
protected:
- // silence VC++ warning C4355: 'this' : used in base member initializer list
- Type *this_() { return this; }
+ friend class ASTContext;
+
Type(TypeClass tc, QualType canon, bool Dependent,
bool InstantiationDependent, bool VariablyModified,
bool ContainsUnexpandedParameterPack)
- : ExtQualsTypeCommonBase(this,
- canon.isNull() ? QualType(this_(), 0) : canon) {
+ : ExtQualsTypeCommonBase(this,
+ canon.isNull() ? QualType(this_(), 0) : canon) {
TypeBits.TC = tc;
TypeBits.Dependent = Dependent;
TypeBits.InstantiationDependent = Dependent || InstantiationDependent;
@@ -1536,22 +1586,32 @@ protected:
TypeBits.CachedLinkage = NoLinkage;
TypeBits.FromAST = false;
}
- friend class ASTContext;
+
+ // silence VC++ warning C4355: 'this' : used in base member initializer list
+ Type *this_() { return this; }
void setDependent(bool D = true) {
TypeBits.Dependent = D;
if (D)
TypeBits.InstantiationDependent = true;
}
+
void setInstantiationDependent(bool D = true) {
TypeBits.InstantiationDependent = D; }
- void setVariablyModified(bool VM = true) { TypeBits.VariablyModified = VM;
- }
+
+ void setVariablyModified(bool VM = true) { TypeBits.VariablyModified = VM; }
+
void setContainsUnexpandedParameterPack(bool PP = true) {
TypeBits.ContainsUnexpandedParameterPack = PP;
}
public:
+ friend class ASTReader;
+ friend class ASTWriter;
+
+ Type(const Type &) = delete;
+ Type &operator=(const Type &) = delete;
+
TypeClass getTypeClass() const { return static_cast<TypeClass>(TypeBits.TC); }
/// \brief Whether this type comes from an AST file.
@@ -1658,6 +1718,7 @@ public:
/// Determine whether this type is an integral or enumeration type.
bool isIntegralOrEnumerationType() const;
+
/// Determine whether this type is an integral or unscoped enumeration type.
bool isIntegralOrUnscopedEnumerationType() const;
@@ -1708,6 +1769,7 @@ public:
bool isComplexIntegerType() const; // GCC _Complex integer type.
bool isVectorType() const; // GCC vector type.
bool isExtVectorType() const; // Extended vector type.
+ bool isDependentAddressSpaceType() const; // value-dependent address space qualifier
bool isObjCObjectPointerType() const; // pointer to ObjC object
bool isObjCRetainableType() const; // ObjC object or block pointer
bool isObjCLifetimeType() const; // (array of)* retainable type
@@ -1789,6 +1851,7 @@ public:
STK_IntegralComplex,
STK_FloatingComplex
};
+
/// Given that this is a scalar type, classify it.
ScalarTypeKind getScalarTypeKind() const;
@@ -1859,6 +1922,7 @@ public:
const RecordType *getAsUnionType() const;
const ComplexType *getAsComplexIntegerType() const; // GCC complex int type.
const ObjCObjectType *getAsObjCInterfaceType() const;
+
// The following is a convenience method that returns an ObjCObjectPointerType
// for object declared using an interface.
const ObjCObjectPointerType *getAsObjCInterfacePointerType() const;
@@ -2045,12 +2109,10 @@ public:
QualType getCanonicalTypeInternal() const {
return CanonicalType;
}
+
CanQualType getCanonicalTypeUnqualified() const; // in CanonicalType.h
void dump() const;
void dump(llvm::raw_ostream &OS) const;
-
- friend class ASTReader;
- friend class ASTWriter;
};
/// \brief This will check for a TypedefType by removing any existing sugar
@@ -2078,7 +2140,6 @@ template <> inline const Class##Type *Type::castAs() const { \
}
#include "clang/AST/TypeNodes.def"
-
/// This class is used for builtin types like 'int'. Builtin
/// types are always canonical and have a literal name field.
class BuiltinType : public Type {
@@ -2095,15 +2156,16 @@ public:
public:
BuiltinType(Kind K)
- : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent),
- /*InstantiationDependent=*/(K == Dependent),
- /*VariablyModified=*/false,
- /*Unexpanded parameter pack=*/false) {
+ : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent),
+ /*InstantiationDependent=*/(K == Dependent),
+ /*VariablyModified=*/false,
+ /*Unexpanded parameter pack=*/false) {
BuiltinTypeBits.Kind = K;
}
Kind getKind() const { return static_cast<Kind>(BuiltinTypeBits.Kind); }
StringRef getName(const PrintingPolicy &Policy) const;
+
const char *getNameAsCString(const PrintingPolicy &Policy) const {
// The StringRef is null-terminated.
StringRef str = getName(Policy);
@@ -2160,17 +2222,17 @@ public:
/// Complex values, per C99 6.2.5p11. This supports the C99 complex
/// types (_Complex float etc) as well as the GCC integer complex extensions.
-///
class ComplexType : public Type, public llvm::FoldingSetNode {
+ friend class ASTContext; // ASTContext creates these.
+
QualType ElementType;
- ComplexType(QualType Element, QualType CanonicalPtr) :
- Type(Complex, CanonicalPtr, Element->isDependentType(),
- Element->isInstantiationDependentType(),
- Element->isVariablyModifiedType(),
- Element->containsUnexpandedParameterPack()),
- ElementType(Element) {
- }
- friend class ASTContext; // ASTContext creates these.
+
+ ComplexType(QualType Element, QualType CanonicalPtr)
+ : Type(Complex, CanonicalPtr, Element->isDependentType(),
+ Element->isInstantiationDependentType(),
+ Element->isVariablyModifiedType(),
+ Element->containsUnexpandedParameterPack()),
+ ElementType(Element) {}
public:
QualType getElementType() const { return ElementType; }
@@ -2181,6 +2243,7 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getElementType());
}
+
static void Profile(llvm::FoldingSetNodeID &ID, QualType Element) {
ID.AddPointer(Element.getAsOpaquePtr());
}
@@ -2189,21 +2252,19 @@ public:
};
/// Sugar for parentheses used when specifying types.
-///
class ParenType : public Type, public llvm::FoldingSetNode {
+ friend class ASTContext; // ASTContext creates these.
+
QualType Inner;
- ParenType(QualType InnerType, QualType CanonType) :
- Type(Paren, CanonType, InnerType->isDependentType(),
- InnerType->isInstantiationDependentType(),
- InnerType->isVariablyModifiedType(),
- InnerType->containsUnexpandedParameterPack()),
- Inner(InnerType) {
- }
- friend class ASTContext; // ASTContext creates these.
+ ParenType(QualType InnerType, QualType CanonType)
+ : Type(Paren, CanonType, InnerType->isDependentType(),
+ InnerType->isInstantiationDependentType(),
+ InnerType->isVariablyModifiedType(),
+ InnerType->containsUnexpandedParameterPack()),
+ Inner(InnerType) {}
public:
-
QualType getInnerType() const { return Inner; }
bool isSugared() const { return true; }
@@ -2212,6 +2273,7 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getInnerType());
}
+
static void Profile(llvm::FoldingSetNodeID &ID, QualType Inner) {
Inner.Profile(ID);
}
@@ -2220,21 +2282,19 @@ public:
};
/// PointerType - C99 6.7.5.1 - Pointer Declarators.
-///
class PointerType : public Type, public llvm::FoldingSetNode {
+ friend class ASTContext; // ASTContext creates these.
+
QualType PointeeType;
- PointerType(QualType Pointee, QualType CanonicalPtr) :
- Type(Pointer, CanonicalPtr, Pointee->isDependentType(),
- Pointee->isInstantiationDependentType(),
- Pointee->isVariablyModifiedType(),
- Pointee->containsUnexpandedParameterPack()),
- PointeeType(Pointee) {
- }
- friend class ASTContext; // ASTContext creates these.
+ PointerType(QualType Pointee, QualType CanonicalPtr)
+ : Type(Pointer, CanonicalPtr, Pointee->isDependentType(),
+ Pointee->isInstantiationDependentType(),
+ Pointee->isVariablyModifiedType(),
+ Pointee->containsUnexpandedParameterPack()),
+ PointeeType(Pointee) {}
public:
-
QualType getPointeeType() const { return PointeeType; }
/// Returns true if address spaces of pointers overlap.
@@ -2259,6 +2319,7 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getPointeeType());
}
+
static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee) {
ID.AddPointer(Pointee.getAsOpaquePtr());
}
@@ -2274,6 +2335,8 @@ class AdjustedType : public Type, public llvm::FoldingSetNode {
QualType AdjustedTy;
protected:
+ friend class ASTContext; // ASTContext creates these.
+
AdjustedType(TypeClass TC, QualType OriginalTy, QualType AdjustedTy,
QualType CanonicalPtr)
: Type(TC, CanonicalPtr, OriginalTy->isDependentType(),
@@ -2282,8 +2345,6 @@ protected:
OriginalTy->containsUnexpandedParameterPack()),
OriginalTy(OriginalTy), AdjustedTy(AdjustedTy) {}
- friend class ASTContext; // ASTContext creates these.
-
public:
QualType getOriginalType() const { return OriginalTy; }
QualType getAdjustedType() const { return AdjustedTy; }
@@ -2294,6 +2355,7 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, OriginalTy, AdjustedTy);
}
+
static void Profile(llvm::FoldingSetNodeID &ID, QualType Orig, QualType New) {
ID.AddPointer(Orig.getAsOpaquePtr());
ID.AddPointer(New.getAsOpaquePtr());
@@ -2306,12 +2368,11 @@ public:
/// Represents a pointer type decayed from an array or function type.
class DecayedType : public AdjustedType {
+ friend class ASTContext; // ASTContext creates these.
inline
DecayedType(QualType OriginalType, QualType Decayed, QualType Canonical);
- friend class ASTContext; // ASTContext creates these.
-
public:
QualType getDecayedType() const { return getAdjustedType(); }
@@ -2323,20 +2384,20 @@ public:
/// Pointer to a block type.
/// This type is to represent types syntactically represented as
/// "void (^)(int)", etc. Pointee is required to always be a function type.
-///
class BlockPointerType : public Type, public llvm::FoldingSetNode {
- QualType PointeeType; // Block is some kind of pointer type
- BlockPointerType(QualType Pointee, QualType CanonicalCls) :
- Type(BlockPointer, CanonicalCls, Pointee->isDependentType(),
- Pointee->isInstantiationDependentType(),
- Pointee->isVariablyModifiedType(),
- Pointee->containsUnexpandedParameterPack()),
- PointeeType(Pointee) {
- }
- friend class ASTContext; // ASTContext creates these.
+ friend class ASTContext; // ASTContext creates these.
-public:
+ // Block is some kind of pointer type
+ QualType PointeeType;
+ BlockPointerType(QualType Pointee, QualType CanonicalCls)
+ : Type(BlockPointer, CanonicalCls, Pointee->isDependentType(),
+ Pointee->isInstantiationDependentType(),
+ Pointee->isVariablyModifiedType(),
+ Pointee->containsUnexpandedParameterPack()),
+ PointeeType(Pointee) {}
+
+public:
// Get the pointee type. Pointee is required to always be a function type.
QualType getPointeeType() const { return PointeeType; }
@@ -2346,6 +2407,7 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getPointeeType());
}
+
static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee) {
ID.AddPointer(Pointee.getAsOpaquePtr());
}
@@ -2356,19 +2418,17 @@ public:
};
/// Base for LValueReferenceType and RValueReferenceType
-///
class ReferenceType : public Type, public llvm::FoldingSetNode {
QualType PointeeType;
protected:
ReferenceType(TypeClass tc, QualType Referencee, QualType CanonicalRef,
- bool SpelledAsLValue) :
- Type(tc, CanonicalRef, Referencee->isDependentType(),
- Referencee->isInstantiationDependentType(),
- Referencee->isVariablyModifiedType(),
- Referencee->containsUnexpandedParameterPack()),
- PointeeType(Referencee)
- {
+ bool SpelledAsLValue)
+ : Type(tc, CanonicalRef, Referencee->isDependentType(),
+ Referencee->isInstantiationDependentType(),
+ Referencee->isVariablyModifiedType(),
+ Referencee->containsUnexpandedParameterPack()),
+ PointeeType(Referencee) {
ReferenceTypeBits.SpelledAsLValue = SpelledAsLValue;
ReferenceTypeBits.InnerRef = Referencee->isReferenceType();
}
@@ -2378,6 +2438,7 @@ public:
bool isInnerRef() const { return ReferenceTypeBits.InnerRef; }
QualType getPointeeTypeAsWritten() const { return PointeeType; }
+
QualType getPointeeType() const {
// FIXME: this might strip inner qualifiers; okay?
const ReferenceType *T = this;
@@ -2389,6 +2450,7 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, PointeeType, isSpelledAsLValue());
}
+
static void Profile(llvm::FoldingSetNodeID &ID,
QualType Referencee,
bool SpelledAsLValue) {
@@ -2403,13 +2465,14 @@ public:
};
/// An lvalue reference type, per C++11 [dcl.ref].
-///
class LValueReferenceType : public ReferenceType {
- LValueReferenceType(QualType Referencee, QualType CanonicalRef,
- bool SpelledAsLValue) :
- ReferenceType(LValueReference, Referencee, CanonicalRef, SpelledAsLValue)
- {}
friend class ASTContext; // ASTContext creates these
+
+ LValueReferenceType(QualType Referencee, QualType CanonicalRef,
+ bool SpelledAsLValue)
+ : ReferenceType(LValueReference, Referencee, CanonicalRef,
+ SpelledAsLValue) {}
+
public:
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -2420,12 +2483,12 @@ public:
};
/// An rvalue reference type, per C++11 [dcl.ref].
-///
class RValueReferenceType : public ReferenceType {
- RValueReferenceType(QualType Referencee, QualType CanonicalRef) :
- ReferenceType(RValueReference, Referencee, CanonicalRef, false) {
- }
friend class ASTContext; // ASTContext creates these
+
+ RValueReferenceType(QualType Referencee, QualType CanonicalRef)
+ : ReferenceType(RValueReference, Referencee, CanonicalRef, false) {}
+
public:
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -2438,24 +2501,24 @@ public:
/// A pointer to member type per C++ 8.3.3 - Pointers to members.
///
/// This includes both pointers to data members and pointer to member functions.
-///
class MemberPointerType : public Type, public llvm::FoldingSetNode {
+ friend class ASTContext; // ASTContext creates these.
+
QualType PointeeType;
+
/// The class of which the pointee is a member. Must ultimately be a
/// RecordType, but could be a typedef or a template parameter too.
const Type *Class;
- MemberPointerType(QualType Pointee, const Type *Cls, QualType CanonicalPtr) :
- Type(MemberPointer, CanonicalPtr,
- Cls->isDependentType() || Pointee->isDependentType(),
- (Cls->isInstantiationDependentType() ||
- Pointee->isInstantiationDependentType()),
- Pointee->isVariablyModifiedType(),
- (Cls->containsUnexpandedParameterPack() ||
- Pointee->containsUnexpandedParameterPack())),
- PointeeType(Pointee), Class(Cls) {
- }
- friend class ASTContext; // ASTContext creates these.
+ MemberPointerType(QualType Pointee, const Type *Cls, QualType CanonicalPtr)
+ : Type(MemberPointer, CanonicalPtr,
+ Cls->isDependentType() || Pointee->isDependentType(),
+ (Cls->isInstantiationDependentType() ||
+ Pointee->isInstantiationDependentType()),
+ Pointee->isVariablyModifiedType(),
+ (Cls->containsUnexpandedParameterPack() ||
+ Pointee->containsUnexpandedParameterPack())),
+ PointeeType(Pointee), Class(Cls) {}
public:
QualType getPointeeType() const { return PointeeType; }
@@ -2481,6 +2544,7 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getPointeeType(), getClass());
}
+
static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee,
const Type *Class) {
ID.AddPointer(Pointee.getAsOpaquePtr());
@@ -2493,7 +2557,6 @@ public:
};
/// Represents an array type, per C99 6.7.5.2 - Array Declarators.
-///
class ArrayType : public Type, public llvm::FoldingSetNode {
public:
/// Capture whether this is a normal array (e.g. int X[4])
@@ -2503,11 +2566,14 @@ public:
enum ArraySizeModifier {
Normal, Static, Star
};
+
private:
/// The element type of the array.
QualType ElementType;
protected:
+ friend class ASTContext; // ASTContext creates these.
+
// C++ [temp.dep.type]p1:
// A type is dependent if it is...
// - an array type constructed from any dependent type or whose
@@ -2516,25 +2582,26 @@ protected:
ArrayType(TypeClass tc, QualType et, QualType can,
ArraySizeModifier sm, unsigned tq,
bool ContainsUnexpandedParameterPack)
- : Type(tc, can, et->isDependentType() || tc == DependentSizedArray,
- et->isInstantiationDependentType() || tc == DependentSizedArray,
- (tc == VariableArray || et->isVariablyModifiedType()),
- ContainsUnexpandedParameterPack),
- ElementType(et) {
+ : Type(tc, can, et->isDependentType() || tc == DependentSizedArray,
+ et->isInstantiationDependentType() || tc == DependentSizedArray,
+ (tc == VariableArray || et->isVariablyModifiedType()),
+ ContainsUnexpandedParameterPack),
+ ElementType(et) {
ArrayTypeBits.IndexTypeQuals = tq;
ArrayTypeBits.SizeModifier = sm;
}
- friend class ASTContext; // ASTContext creates these.
-
public:
QualType getElementType() const { return ElementType; }
+
ArraySizeModifier getSizeModifier() const {
return ArraySizeModifier(ArrayTypeBits.SizeModifier);
}
+
Qualifiers getIndexTypeQualifiers() const {
return Qualifiers::fromCVRMask(getIndexTypeCVRQualifiers());
}
+
unsigned getIndexTypeCVRQualifiers() const {
return ArrayTypeBits.IndexTypeQuals;
}
@@ -2555,21 +2622,23 @@ class ConstantArrayType : public ArrayType {
ConstantArrayType(QualType et, QualType can, const llvm::APInt &size,
ArraySizeModifier sm, unsigned tq)
- : ArrayType(ConstantArray, et, can, sm, tq,
- et->containsUnexpandedParameterPack()),
- Size(size) {}
+ : ArrayType(ConstantArray, et, can, sm, tq,
+ et->containsUnexpandedParameterPack()),
+ Size(size) {}
+
protected:
+ friend class ASTContext; // ASTContext creates these.
+
ConstantArrayType(TypeClass tc, QualType et, QualType can,
const llvm::APInt &size, ArraySizeModifier sm, unsigned tq)
- : ArrayType(tc, et, can, sm, tq, et->containsUnexpandedParameterPack()),
- Size(size) {}
- friend class ASTContext; // ASTContext creates these.
+ : ArrayType(tc, et, can, sm, tq, et->containsUnexpandedParameterPack()),
+ Size(size) {}
+
public:
const llvm::APInt &getSize() const { return Size; }
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
-
/// \brief Determine the number of bits required to address a member of
// an array with the given element type and number of elements.
static unsigned getNumAddressingBits(const ASTContext &Context,
@@ -2584,6 +2653,7 @@ public:
Profile(ID, getElementType(), getSize(),
getSizeModifier(), getIndexTypeCVRQualifiers());
}
+
static void Profile(llvm::FoldingSetNodeID &ID, QualType ET,
const llvm::APInt &ArraySize, ArraySizeModifier SizeMod,
unsigned TypeQuals) {
@@ -2592,6 +2662,7 @@ public:
ID.AddInteger(SizeMod);
ID.AddInteger(TypeQuals);
}
+
static bool classof(const Type *T) {
return T->getTypeClass() == ConstantArray;
}
@@ -2601,13 +2672,16 @@ public:
/// an IncompleteArrayType where the element type is 'int' and the size is
/// unspecified.
class IncompleteArrayType : public ArrayType {
+ friend class ASTContext; // ASTContext creates these.
IncompleteArrayType(QualType et, QualType can,
ArraySizeModifier sm, unsigned tq)
- : ArrayType(IncompleteArray, et, can, sm, tq,
- et->containsUnexpandedParameterPack()) {}
- friend class ASTContext; // ASTContext creates these.
+ : ArrayType(IncompleteArray, et, can, sm, tq,
+ et->containsUnexpandedParameterPack()) {}
+
public:
+ friend class StmtIteratorBase;
+
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -2615,8 +2689,6 @@ public:
return T->getTypeClass() == IncompleteArray;
}
- friend class StmtIteratorBase;
-
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getElementType(), getSizeModifier(),
getIndexTypeCVRQualifiers());
@@ -2644,28 +2716,32 @@ public:
/// ++x;
/// int Z[x];
/// }
-///
class VariableArrayType : public ArrayType {
+ friend class ASTContext; // ASTContext creates these.
+
/// An assignment-expression. VLA's are only permitted within
/// a function block.
Stmt *SizeExpr;
+
/// The range spanned by the left and right array brackets.
SourceRange Brackets;
VariableArrayType(QualType et, QualType can, Expr *e,
ArraySizeModifier sm, unsigned tq,
SourceRange brackets)
- : ArrayType(VariableArray, et, can, sm, tq,
- et->containsUnexpandedParameterPack()),
- SizeExpr((Stmt*) e), Brackets(brackets) {}
- friend class ASTContext; // ASTContext creates these.
+ : ArrayType(VariableArray, et, can, sm, tq,
+ et->containsUnexpandedParameterPack()),
+ SizeExpr((Stmt*) e), Brackets(brackets) {}
public:
+ friend class StmtIteratorBase;
+
Expr *getSizeExpr() const {
// We use C-style casts instead of cast<> here because we do not wish
// to have a dependency of Type.h on Stmt.h/Expr.h.
return (Expr*) SizeExpr;
}
+
SourceRange getBracketsRange() const { return Brackets; }
SourceLocation getLBracketLoc() const { return Brackets.getBegin(); }
SourceLocation getRBracketLoc() const { return Brackets.getEnd(); }
@@ -2677,8 +2753,6 @@ public:
return T->getTypeClass() == VariableArray;
}
- friend class StmtIteratorBase;
-
void Profile(llvm::FoldingSetNodeID &ID) {
llvm_unreachable("Cannot unique VariableArrayTypes.");
}
@@ -2698,6 +2772,8 @@ public:
/// until template instantiation occurs, at which point this will
/// become either a ConstantArrayType or a VariableArrayType.
class DependentSizedArrayType : public ArrayType {
+ friend class ASTContext; // ASTContext creates these.
+
const ASTContext &Context;
/// \brief An assignment expression that will instantiate to the
@@ -2714,14 +2790,15 @@ class DependentSizedArrayType : public ArrayType {
Expr *e, ArraySizeModifier sm, unsigned tq,
SourceRange brackets);
- friend class ASTContext; // ASTContext creates these.
-
public:
+ friend class StmtIteratorBase;
+
Expr *getSizeExpr() const {
// We use C-style casts instead of cast<> here because we do not wish
// to have a dependency of Type.h on Stmt.h/Expr.h.
return (Expr*) SizeExpr;
}
+
SourceRange getBracketsRange() const { return Brackets; }
SourceLocation getLBracketLoc() const { return Brackets.getBegin(); }
SourceLocation getRBracketLoc() const { return Brackets.getEnd(); }
@@ -2733,9 +2810,6 @@ public:
return T->getTypeClass() == DependentSizedArray;
}
- friend class StmtIteratorBase;
-
-
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, Context, getElementType(),
getSizeModifier(), getIndexTypeCVRQualifiers(), getSizeExpr());
@@ -2746,6 +2820,49 @@ public:
unsigned TypeQuals, Expr *E);
};
+/// Represents an extended address space qualifier where the input address space
+/// value is dependent. Non-dependent address spaces are not represented with a
+/// special Type subclass; they are stored on an ExtQuals node as part of a QualType.
+///
+/// For example:
+/// \code
+/// template<typename T, int AddrSpace>
+/// class AddressSpace {
+/// typedef T __attribute__((address_space(AddrSpace))) type;
+/// }
+/// \endcode
+class DependentAddressSpaceType : public Type, public llvm::FoldingSetNode {
+ friend class ASTContext;
+
+ const ASTContext &Context;
+ Expr *AddrSpaceExpr;
+ QualType PointeeType;
+ SourceLocation loc;
+
+ DependentAddressSpaceType(const ASTContext &Context, QualType PointeeType,
+ QualType can, Expr *AddrSpaceExpr,
+ SourceLocation loc);
+
+public:
+ Expr *getAddrSpaceExpr() const { return AddrSpaceExpr; }
+ QualType getPointeeType() const { return PointeeType; }
+ SourceLocation getAttributeLoc() const { return loc; }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == DependentAddressSpace;
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, Context, getPointeeType(), getAddrSpaceExpr());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
+ QualType PointeeType, Expr *AddrSpaceExpr);
+};
+
/// Represents an extended vector type where either the type or size is
/// dependent.
///
@@ -2757,17 +2874,19 @@ public:
/// }
/// \endcode
class DependentSizedExtVectorType : public Type, public llvm::FoldingSetNode {
+ friend class ASTContext;
+
const ASTContext &Context;
Expr *SizeExpr;
+
/// The element type of the array.
QualType ElementType;
+
SourceLocation loc;
DependentSizedExtVectorType(const ASTContext &Context, QualType ElementType,
QualType can, Expr *SizeExpr, SourceLocation loc);
- friend class ASTContext;
-
public:
Expr *getSizeExpr() const { return SizeExpr; }
QualType getElementType() const { return ElementType; }
@@ -2797,14 +2916,28 @@ public:
class VectorType : public Type, public llvm::FoldingSetNode {
public:
enum VectorKind {
- GenericVector, ///< not a target-specific vector type
- AltiVecVector, ///< is AltiVec vector
- AltiVecPixel, ///< is AltiVec 'vector Pixel'
- AltiVecBool, ///< is AltiVec 'vector bool ...'
- NeonVector, ///< is ARM Neon vector
- NeonPolyVector ///< is ARM Neon polynomial vector
+ /// not a target-specific vector type
+ GenericVector,
+
+ /// is AltiVec vector
+ AltiVecVector,
+
+ /// is AltiVec 'vector Pixel'
+ AltiVecPixel,
+
+ /// is AltiVec 'vector bool ...'
+ AltiVecBool,
+
+ /// is ARM Neon vector
+ NeonVector,
+
+ /// is ARM Neon polynomial vector
+ NeonPolyVector
};
+
protected:
+ friend class ASTContext; // ASTContext creates these.
+
/// The element type of the vector.
QualType ElementType;
@@ -2814,12 +2947,10 @@ protected:
VectorType(TypeClass tc, QualType vecType, unsigned nElements,
QualType canonType, VectorKind vecKind);
- friend class ASTContext; // ASTContext creates these.
-
public:
-
QualType getElementType() const { return ElementType; }
unsigned getNumElements() const { return VectorTypeBits.NumElements; }
+
static bool isVectorSizeTooLarge(unsigned NumElements) {
return NumElements > VectorTypeBitfields::MaxNumElements;
}
@@ -2835,6 +2966,7 @@ public:
Profile(ID, getElementType(), getNumElements(),
getTypeClass(), getVectorKind());
}
+
static void Profile(llvm::FoldingSetNodeID &ID, QualType ElementType,
unsigned NumElements, TypeClass TypeClass,
VectorKind VecKind) {
@@ -2856,9 +2988,11 @@ public:
/// points (as .xyzw), colors (as .rgba), and textures (modeled after OpenGL
/// Shading Language).
class ExtVectorType : public VectorType {
- ExtVectorType(QualType vecType, unsigned nElements, QualType canonType) :
- VectorType(ExtVector, vecType, nElements, canonType, GenericVector) {}
- friend class ASTContext; // ASTContext creates these.
+ friend class ASTContext; // ASTContext creates these.
+
+ ExtVectorType(QualType vecType, unsigned nElements, QualType canonType)
+ : VectorType(ExtVector, vecType, nElements, canonType, GenericVector) {}
+
public:
static int getPointAccessorIdx(char c) {
switch (c) {
@@ -2869,6 +3003,7 @@ public:
case 'w': case 'a': return 3;
}
}
+
static int getNumericAccessorIdx(char c) {
switch (c) {
default: return -1;
@@ -2909,6 +3044,7 @@ public:
return unsigned(idx-1) < getNumElements();
return false;
}
+
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -2919,12 +3055,11 @@ public:
/// FunctionType - C99 6.7.5.3 - Function Declarators. This is the common base
/// class of FunctionNoProtoType and FunctionProtoType.
-///
class FunctionType : public Type {
// The type returned by the function.
QualType ResultType;
- public:
+public:
/// A class which abstracts out some details necessary for
/// making a call.
///
@@ -2946,6 +3081,8 @@ class FunctionType : public Type {
// * AST read and write
// * Codegen
class ExtInfo {
+ friend class FunctionType;
+
// Feel free to rearrange or add bits, but if you go over 11,
// you'll need to adjust both the Bits field below and
// Type::FunctionTypeBitfields.
@@ -2964,15 +3101,13 @@ class FunctionType : public Type {
RegParmOffset = 8
}; // Assumed to be the last field
- uint16_t Bits;
+ uint16_t Bits = CC_C;
ExtInfo(unsigned Bits) : Bits(static_cast<uint16_t>(Bits)) {}
- friend class FunctionType;
-
public:
- // Constructor with no defaults. Use this when you know that you
- // have all the elements (when reading an AST file for example).
+ // Constructor with no defaults. Use this when you know that you
+ // have all the elements (when reading an AST file for example).
ExtInfo(bool noReturn, bool hasRegParm, unsigned regParm, CallingConv cc,
bool producesResult, bool noCallerSavedRegs) {
assert((!hasRegParm || regParm < 7) && "Invalid regparm value");
@@ -2984,22 +3119,24 @@ class FunctionType : public Type {
// Constructor with all defaults. Use when for example creating a
// function known to use defaults.
- ExtInfo() : Bits(CC_C) { }
+ ExtInfo() = default;
// Constructor with just the calling convention, which is an important part
// of the canonical type.
- ExtInfo(CallingConv CC) : Bits(CC) { }
+ ExtInfo(CallingConv CC) : Bits(CC) {}
bool getNoReturn() const { return Bits & NoReturnMask; }
bool getProducesResult() const { return Bits & ProducesResultMask; }
bool getNoCallerSavedRegs() const { return Bits & NoCallerSavedRegsMask; }
bool getHasRegParm() const { return (Bits >> RegParmOffset) != 0; }
+
unsigned getRegParm() const {
unsigned RegParm = Bits >> RegParmOffset;
if (RegParm > 0)
--RegParm;
return RegParm;
}
+
CallingConv getCC() const { return CallingConv(Bits & CallConvMask); }
bool operator==(ExtInfo Other) const {
@@ -3054,11 +3191,12 @@ protected:
bool InstantiationDependent,
bool VariablyModified, bool ContainsUnexpandedParameterPack,
ExtInfo Info)
- : Type(tc, Canonical, Dependent, InstantiationDependent, VariablyModified,
- ContainsUnexpandedParameterPack),
- ResultType(res) {
+ : Type(tc, Canonical, Dependent, InstantiationDependent, VariablyModified,
+ ContainsUnexpandedParameterPack),
+ ResultType(res) {
FunctionTypeBits.ExtInfo = Info.Bits;
}
+
unsigned getTypeQuals() const { return FunctionTypeBits.TypeQuals; }
public:
@@ -3066,10 +3204,12 @@ public:
bool getHasRegParm() const { return getExtInfo().getHasRegParm(); }
unsigned getRegParmType() const { return getExtInfo().getRegParm(); }
+
/// Determine whether this function type includes the GNU noreturn
/// attribute. The C++11 [[noreturn]] attribute does not affect the function
/// type.
bool getNoReturnAttr() const { return getExtInfo().getNoReturn(); }
+
CallingConv getCallConv() const { return getExtInfo().getCC(); }
ExtInfo getExtInfo() const { return ExtInfo(FunctionTypeBits.ExtInfo); }
bool isConst() const { return getTypeQuals() & Qualifiers::Const; }
@@ -3093,13 +3233,13 @@ public:
/// Represents a K&R-style 'int foo()' function, which has
/// no information available about its arguments.
class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode {
- FunctionNoProtoType(QualType Result, QualType Canonical, ExtInfo Info)
- : FunctionType(FunctionNoProto, Result, Canonical,
- /*Dependent=*/false, /*InstantiationDependent=*/false,
- Result->isVariablyModifiedType(),
- /*ContainsUnexpandedParameterPack=*/false, Info) {}
+ friend class ASTContext; // ASTContext creates these.
- friend class ASTContext; // ASTContext creates these.
+ FunctionNoProtoType(QualType Result, QualType Canonical, ExtInfo Info)
+ : FunctionType(FunctionNoProto, Result, Canonical,
+ /*Dependent=*/false, /*InstantiationDependent=*/false,
+ Result->isVariablyModifiedType(),
+ /*ContainsUnexpandedParameterPack=*/false, Info) {}
public:
// No additional state past what FunctionType provides.
@@ -3110,6 +3250,7 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getReturnType(), getExtInfo());
}
+
static void Profile(llvm::FoldingSetNodeID &ID, QualType ResultType,
ExtInfo Info) {
Info.Profile(ID);
@@ -3152,11 +3293,12 @@ public:
ABIMask = 0x0F,
IsConsumed = 0x10,
HasPassObjSize = 0x20,
+ IsNoEscape = 0x40,
};
- unsigned char Data;
+ unsigned char Data = 0;
public:
- ExtParameterInfo() : Data(0) {}
+ ExtParameterInfo() = default;
/// Return the ABI treatment of this parameter.
ParameterABI getABI() const {
@@ -3192,6 +3334,19 @@ public:
return Copy;
}
+ bool isNoEscape() const {
+ return Data & IsNoEscape;
+ }
+
+ ExtParameterInfo withIsNoEscape(bool NoEscape) const {
+ ExtParameterInfo Copy = *this;
+ if (NoEscape)
+ Copy.Data |= IsNoEscape;
+ else
+ Copy.Data &= ~IsNoEscape;
+ return Copy;
+ }
+
unsigned char getOpaqueValue() const { return Data; }
static ExtParameterInfo getFromOpaqueValue(unsigned char data) {
ExtParameterInfo result;
@@ -3208,54 +3363,54 @@ 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;
+ ExceptionSpecificationType Type = EST_None;
+
/// Explicitly-specified list of exception types.
ArrayRef<QualType> Exceptions;
+
/// Noexcept expression, if this is EST_ComputedNoexcept.
- Expr *NoexceptExpr;
+ Expr *NoexceptExpr = nullptr;
+
/// The function whose exception specification this is, for
/// EST_Unevaluated and EST_Uninstantiated.
- FunctionDecl *SourceDecl;
+ FunctionDecl *SourceDecl = nullptr;
+
/// The function template whose exception specification this is instantiated
/// from, for EST_Uninstantiated.
- FunctionDecl *SourceTemplate;
+ FunctionDecl *SourceTemplate = nullptr;
+
+ ExceptionSpecInfo() = default;
+
+ ExceptionSpecInfo(ExceptionSpecificationType EST) : Type(EST) {}
};
/// Extra information about a function prototype.
struct ExtProtoInfo {
+ FunctionType::ExtInfo ExtInfo;
+ bool Variadic : 1;
+ bool HasTrailingReturn : 1;
+ unsigned char TypeQuals = 0;
+ RefQualifierKind RefQualifier = RQ_None;
+ ExceptionSpecInfo ExceptionSpec;
+ const ExtParameterInfo *ExtParameterInfos = nullptr;
+
ExtProtoInfo()
- : Variadic(false), HasTrailingReturn(false), TypeQuals(0),
- RefQualifier(RQ_None), ExtParameterInfos(nullptr) {}
+ : Variadic(false), HasTrailingReturn(false) {}
ExtProtoInfo(CallingConv CC)
- : ExtInfo(CC), Variadic(false), HasTrailingReturn(false), TypeQuals(0),
- RefQualifier(RQ_None), ExtParameterInfos(nullptr) {}
+ : ExtInfo(CC), Variadic(false), HasTrailingReturn(false) {}
ExtProtoInfo withExceptionSpec(const ExceptionSpecInfo &O) {
ExtProtoInfo Result(*this);
Result.ExceptionSpec = O;
return Result;
}
-
- FunctionType::ExtInfo ExtInfo;
- bool Variadic : 1;
- bool HasTrailingReturn : 1;
- unsigned char TypeQuals;
- RefQualifierKind RefQualifier;
- ExceptionSpecInfo ExceptionSpec;
- const ExtParameterInfo *ExtParameterInfos;
};
private:
+ friend class ASTContext; // ASTContext creates these.
+
/// \brief Determine whether there are any argument types that
/// contain an unexpanded parameter pack.
static bool containsAnyUnexpandedParameterPack(const QualType *ArgArray,
@@ -3307,8 +3462,6 @@ private:
// for each of the parameters. This only appears if HasExtParameterInfos
// is true.
- friend class ASTContext; // ASTContext creates these.
-
const ExtParameterInfo *getExtParameterInfosBuffer() const {
assert(hasExtParameterInfos());
@@ -3336,10 +3489,12 @@ private:
public:
unsigned getNumParams() const { return NumParams; }
+
QualType getParamType(unsigned i) const {
assert(i < NumParams && "invalid parameter index");
return param_type_begin()[i];
}
+
ArrayRef<QualType> getParamTypes() const {
return llvm::makeArrayRef(param_type_begin(), param_type_end());
}
@@ -3371,31 +3526,47 @@ public:
ExceptionSpecificationType getExceptionSpecType() const {
return static_cast<ExceptionSpecificationType>(ExceptionSpecType);
}
+
/// Return whether this function has any kind of exception spec.
bool hasExceptionSpec() const {
return getExceptionSpecType() != EST_None;
}
+
/// Return whether this function has a dynamic (throw) exception spec.
bool hasDynamicExceptionSpec() const {
return isDynamicExceptionSpec(getExceptionSpecType());
}
+
/// Return whether this function has a noexcept exception spec.
bool hasNoexceptExceptionSpec() const {
return isNoexceptExceptionSpec(getExceptionSpecType());
}
+
/// Return whether this function has a dependent exception spec.
bool hasDependentExceptionSpec() const;
+
/// Return whether this function has an instantiation-dependent exception
/// spec.
bool hasInstantiationDependentExceptionSpec() const;
+
/// Result type of getNoexceptSpec().
enum NoexceptResult {
- NR_NoNoexcept, ///< There is no noexcept specifier.
- NR_BadNoexcept, ///< The noexcept specifier has a bad expression.
- NR_Dependent, ///< The noexcept specifier is dependent.
- NR_Throw, ///< The noexcept specifier evaluates to false.
- NR_Nothrow ///< The noexcept specifier evaluates to true.
+ /// There is no noexcept specifier.
+ NR_NoNoexcept,
+
+ /// The noexcept specifier has a bad expression.
+ NR_BadNoexcept,
+
+ /// The noexcept specifier is dependent.
+ NR_Dependent,
+
+ /// The noexcept specifier evaluates to false.
+ NR_Throw,
+
+ /// The noexcept specifier evaluates to true.
+ NR_Nothrow
};
+
/// Get the meaning of the noexcept spec on this function, if any.
NoexceptResult getNoexceptSpec(const ASTContext &Ctx) const;
unsigned getNumExceptions() const { return NumExceptions; }
@@ -3409,6 +3580,7 @@ public:
// NoexceptExpr sits where the arguments end.
return *reinterpret_cast<Expr *const *>(param_type_end());
}
+
/// \brief If this function type has an exception specification which hasn't
/// been determined yet (either because it has not been evaluated or because
/// it has not been instantiated), this is the function whose exception
@@ -3419,6 +3591,7 @@ public:
return nullptr;
return reinterpret_cast<FunctionDecl *const *>(param_type_end())[0];
}
+
/// \brief If this function type has an uninstantiated exception
/// specification, this is the function whose exception specification
/// should be instantiated to find the exception specification for
@@ -3428,9 +3601,11 @@ public:
return nullptr;
return reinterpret_cast<FunctionDecl *const *>(param_type_end())[1];
}
+
/// Determine whether this function type has a non-throwing exception
/// specification.
CanThrowResult canThrow(const ASTContext &Ctx) const;
+
/// Determine whether this function type has a non-throwing exception
/// specification. If this depends on template arguments, returns
/// \c ResultIfDependent.
@@ -3453,34 +3628,37 @@ public:
unsigned getTypeQuals() const { return FunctionType::getTypeQuals(); }
-
/// Retrieve the ref-qualifier associated with this function type.
RefQualifierKind getRefQualifier() const {
return static_cast<RefQualifierKind>(FunctionTypeBits.RefQualifier);
}
- typedef const QualType *param_type_iterator;
- typedef llvm::iterator_range<param_type_iterator> param_type_range;
+ using param_type_iterator = const QualType *;
+ using param_type_range = llvm::iterator_range<param_type_iterator>;
param_type_range param_types() const {
return param_type_range(param_type_begin(), param_type_end());
}
+
param_type_iterator param_type_begin() const {
return reinterpret_cast<const QualType *>(this+1);
}
+
param_type_iterator param_type_end() const {
return param_type_begin() + NumParams;
}
- typedef const QualType *exception_iterator;
+ using exception_iterator = const QualType *;
ArrayRef<QualType> exceptions() const {
return llvm::makeArrayRef(exception_begin(), exception_end());
}
+
exception_iterator exception_begin() const {
// exceptions begin where arguments end
return param_type_end();
}
+
exception_iterator exception_end() const {
if (getExceptionSpecType() != EST_Dynamic)
return exception_begin();
@@ -3495,6 +3673,7 @@ public:
return ArrayRef<ExtParameterInfo>(getExtParameterInfosBuffer(),
getNumParams());
}
+
/// Return a pointer to the beginning of the array of extra parameter
/// information, if present, or else null if none of the parameters
/// carry it. This is equivalent to getExtProtoInfo().ExtParameterInfos.
@@ -3548,15 +3727,16 @@ public:
///
/// Template instantiation turns these into the underlying type.
class UnresolvedUsingType : public Type {
+ friend class ASTContext; // ASTContext creates these.
+
UnresolvedUsingTypenameDecl *Decl;
UnresolvedUsingType(const UnresolvedUsingTypenameDecl *D)
- : Type(UnresolvedUsing, QualType(), true, true, false,
- /*ContainsUnexpandedParameterPack=*/false),
- Decl(const_cast<UnresolvedUsingTypenameDecl*>(D)) {}
- friend class ASTContext; // ASTContext creates these.
-public:
+ : Type(UnresolvedUsing, QualType(), true, true, false,
+ /*ContainsUnexpandedParameterPack=*/false),
+ Decl(const_cast<UnresolvedUsingTypenameDecl*>(D)) {}
+public:
UnresolvedUsingTypenameDecl *getDecl() const { return Decl; }
bool isSugared() const { return false; }
@@ -3569,27 +3749,29 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) {
return Profile(ID, Decl);
}
+
static void Profile(llvm::FoldingSetNodeID &ID,
UnresolvedUsingTypenameDecl *D) {
ID.AddPointer(D);
}
};
-
class TypedefType : public Type {
TypedefNameDecl *Decl;
+
protected:
+ friend class ASTContext; // ASTContext creates these.
+
TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType can)
- : Type(tc, can, can->isDependentType(),
- can->isInstantiationDependentType(),
- can->isVariablyModifiedType(),
- /*ContainsUnexpandedParameterPack=*/false),
- Decl(const_cast<TypedefNameDecl*>(D)) {
+ : Type(tc, can, can->isDependentType(),
+ can->isInstantiationDependentType(),
+ can->isVariablyModifiedType(),
+ /*ContainsUnexpandedParameterPack=*/false),
+ Decl(const_cast<TypedefNameDecl*>(D)) {
assert(!isa<TypedefType>(can) && "Invalid canonical type");
}
- friend class ASTContext; // ASTContext creates these.
-public:
+public:
TypedefNameDecl *getDecl() const { return Decl; }
bool isSugared() const { return true; }
@@ -3603,8 +3785,10 @@ class TypeOfExprType : public Type {
Expr *TOExpr;
protected:
+ friend class ASTContext; // ASTContext creates these.
+
TypeOfExprType(Expr *E, QualType can = QualType());
- friend class ASTContext; // ASTContext creates these.
+
public:
Expr *getUnderlyingExpr() const { return TOExpr; }
@@ -3629,7 +3813,7 @@ class DependentTypeOfExprType
public:
DependentTypeOfExprType(const ASTContext &Context, Expr *E)
- : TypeOfExprType(E), Context(Context) { }
+ : TypeOfExprType(E), Context(Context) {}
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, Context, getUnderlyingExpr());
@@ -3641,16 +3825,19 @@ public:
/// Represents `typeof(type)`, a GCC extension.
class TypeOfType : public Type {
+ friend class ASTContext; // ASTContext creates these.
+
QualType TOType;
+
TypeOfType(QualType T, QualType can)
- : Type(TypeOf, can, T->isDependentType(),
- T->isInstantiationDependentType(),
- T->isVariablyModifiedType(),
- T->containsUnexpandedParameterPack()),
- TOType(T) {
+ : Type(TypeOf, can, T->isDependentType(),
+ T->isInstantiationDependentType(),
+ T->isVariablyModifiedType(),
+ T->containsUnexpandedParameterPack()),
+ TOType(T) {
assert(!isa<TypedefType>(can) && "Invalid canonical type");
}
- friend class ASTContext; // ASTContext creates these.
+
public:
QualType getUnderlyingType() const { return TOType; }
@@ -3669,8 +3856,10 @@ class DecltypeType : public Type {
QualType UnderlyingType;
protected:
+ friend class ASTContext; // ASTContext creates these.
+
DecltypeType(Expr *E, QualType underlyingType, QualType can = QualType());
- friend class ASTContext; // ASTContext creates these.
+
public:
Expr *getUnderlyingExpr() const { return E; }
QualType getUnderlyingType() const { return UnderlyingType; }
@@ -3714,14 +3903,18 @@ public:
private:
/// The untransformed type.
QualType BaseType;
+
/// The transformed type if not dependent, otherwise the same as BaseType.
QualType UnderlyingType;
UTTKind UKind;
+
protected:
+ friend class ASTContext;
+
UnaryTransformType(QualType BaseTy, QualType UnderlyingTy, UTTKind UKind,
QualType CanonicalTy);
- friend class ASTContext;
+
public:
bool isSugared() const { return !isDependentType(); }
QualType desugar() const { return UnderlyingType; }
@@ -3747,6 +3940,7 @@ class DependentUnaryTransformType : public UnaryTransformType,
public:
DependentUnaryTransformType(const ASTContext &C, QualType BaseType,
UTTKind UKind);
+
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getBaseType(), getUTTKind());
}
@@ -3759,11 +3953,11 @@ public:
};
class TagType : public Type {
+ friend class ASTReader;
+
/// Stores the TagDecl associated with this type. The decl may point to any
/// TagDecl that declares the entity.
- TagDecl * decl;
-
- friend class ASTReader;
+ TagDecl *decl;
protected:
TagType(TypeClass TC, const TagDecl *D, QualType can);
@@ -3783,21 +3977,21 @@ public:
/// to detect TagType objects of structs/unions/classes.
class RecordType : public TagType {
protected:
+ friend class ASTContext; // ASTContext creates these.
+
explicit RecordType(const RecordDecl *D)
- : TagType(Record, reinterpret_cast<const TagDecl*>(D), QualType()) { }
+ : TagType(Record, reinterpret_cast<const TagDecl*>(D), QualType()) {}
explicit RecordType(TypeClass TC, RecordDecl *D)
- : TagType(TC, reinterpret_cast<const TagDecl*>(D), QualType()) { }
- friend class ASTContext; // ASTContext creates these.
-public:
+ : TagType(TC, reinterpret_cast<const TagDecl*>(D), QualType()) {}
+public:
RecordDecl *getDecl() const {
return reinterpret_cast<RecordDecl*>(TagType::getDecl());
}
- // FIXME: This predicate is a helper to QualType/Type. It needs to
- // recursively check all fields for const-ness. If any field is declared
- // const, it needs to return false.
- bool hasConstFields() const { return false; }
+ /// Recursively check all fields in the record for const-ness. If any field
+ /// is declared const, return true. Otherwise, return false.
+ bool hasConstFields() const;
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -3808,11 +4002,12 @@ public:
/// A helper class that allows the use of isa/cast/dyncast
/// to detect TagType objects of enums.
class EnumType : public TagType {
+ friend class ASTContext; // ASTContext creates these.
+
explicit EnumType(const EnumDecl *D)
- : TagType(Enum, reinterpret_cast<const TagDecl*>(D), QualType()) { }
- friend class ASTContext; // ASTContext creates these.
-public:
+ : TagType(Enum, reinterpret_cast<const TagDecl*>(D), QualType()) {}
+public:
EnumDecl *getDecl() const {
return reinterpret_cast<EnumDecl*>(TagType::getDecl());
}
@@ -3887,11 +4082,11 @@ public:
};
private:
+ friend class ASTContext; // ASTContext creates these
+
QualType ModifiedType;
QualType EquivalentType;
- friend class ASTContext; // creates these
-
AttributedType(QualType canon, Kind attrKind, QualType modified,
QualType equivalent)
: Type(Attributed, canon, equivalent->isDependentType(),
@@ -3980,6 +4175,8 @@ public:
};
class TemplateTypeParmType : public Type, public llvm::FoldingSetNode {
+ friend class ASTContext; // ASTContext creates these
+
// Helper data collector for canonical types.
struct CanonicalTTPTInfo {
unsigned Depth : 15;
@@ -3990,31 +4187,30 @@ class TemplateTypeParmType : public Type, public llvm::FoldingSetNode {
union {
// Info for the canonical type.
CanonicalTTPTInfo CanTTPTInfo;
+
// Info for the non-canonical type.
TemplateTypeParmDecl *TTPDecl;
};
/// Build a non-canonical type.
TemplateTypeParmType(TemplateTypeParmDecl *TTPDecl, QualType Canon)
- : Type(TemplateTypeParm, Canon, /*Dependent=*/true,
- /*InstantiationDependent=*/true,
- /*VariablyModified=*/false,
- Canon->containsUnexpandedParameterPack()),
- TTPDecl(TTPDecl) { }
+ : Type(TemplateTypeParm, Canon, /*Dependent=*/true,
+ /*InstantiationDependent=*/true,
+ /*VariablyModified=*/false,
+ Canon->containsUnexpandedParameterPack()),
+ TTPDecl(TTPDecl) {}
/// Build the canonical type.
TemplateTypeParmType(unsigned D, unsigned I, bool PP)
- : Type(TemplateTypeParm, QualType(this, 0),
- /*Dependent=*/true,
- /*InstantiationDependent=*/true,
- /*VariablyModified=*/false, PP) {
+ : Type(TemplateTypeParm, QualType(this, 0),
+ /*Dependent=*/true,
+ /*InstantiationDependent=*/true,
+ /*VariablyModified=*/false, PP) {
CanTTPTInfo.Depth = D;
CanTTPTInfo.Index = I;
CanTTPTInfo.ParameterPack = PP;
}
- friend class ASTContext; // ASTContext creates these
-
const CanonicalTTPTInfo& getCanTTPTInfo() const {
QualType Can = getCanonicalTypeInternal();
return Can->castAs<TemplateTypeParmType>()->CanTTPTInfo;
@@ -4060,17 +4256,17 @@ public:
/// type was originally written as a template type parameter;
/// therefore they are never canonical.
class SubstTemplateTypeParmType : public Type, public llvm::FoldingSetNode {
+ friend class ASTContext;
+
// The original type parameter.
const TemplateTypeParmType *Replaced;
SubstTemplateTypeParmType(const TemplateTypeParmType *Param, QualType Canon)
- : Type(SubstTemplateTypeParm, Canon, Canon->isDependentType(),
- Canon->isInstantiationDependentType(),
- Canon->isVariablyModifiedType(),
- Canon->containsUnexpandedParameterPack()),
- Replaced(Param) { }
-
- friend class ASTContext;
+ : Type(SubstTemplateTypeParm, Canon, Canon->isDependentType(),
+ Canon->isInstantiationDependentType(),
+ Canon->isVariablyModifiedType(),
+ Canon->containsUnexpandedParameterPack()),
+ Replaced(Param) {}
public:
/// Gets the template parameter that was substituted for.
@@ -4090,6 +4286,7 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getReplacedParameter(), getReplacementType());
}
+
static void Profile(llvm::FoldingSetNodeID &ID,
const TemplateTypeParmType *Replaced,
QualType Replacement) {
@@ -4115,6 +4312,8 @@ public:
/// arguments), this type will be replaced with the \c SubstTemplateTypeParmType
/// at the current pack substitution index.
class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode {
+ friend class ASTContext;
+
/// \brief The original type parameter.
const TemplateTypeParmType *Replaced;
@@ -4129,8 +4328,6 @@ class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode {
QualType Canon,
const TemplateArgument &ArgPack);
- friend class ASTContext;
-
public:
IdentifierInfo *getIdentifier() const { return Replaced->getIdentifier(); }
@@ -4204,6 +4401,8 @@ public:
/// \brief Represents a C++11 auto or C++14 decltype(auto) type.
class AutoType : public DeducedType, public llvm::FoldingSetNode {
+ friend class ASTContext; // ASTContext creates these
+
AutoType(QualType DeducedAsType, AutoTypeKeyword Keyword,
bool IsDeducedAsDependent)
: DeducedType(Auto, DeducedAsType, IsDeducedAsDependent,
@@ -4211,12 +4410,11 @@ class AutoType : public DeducedType, public llvm::FoldingSetNode {
AutoTypeBits.Keyword = (unsigned)Keyword;
}
- friend class ASTContext; // ASTContext creates these
-
public:
bool isDecltypeAuto() const {
return getKeyword() == AutoTypeKeyword::DecltypeAuto;
}
+
AutoTypeKeyword getKeyword() const {
return (AutoTypeKeyword)AutoTypeBits.Keyword;
}
@@ -4240,6 +4438,8 @@ public:
/// \brief Represents a C++17 deduced template specialization type.
class DeducedTemplateSpecializationType : public DeducedType,
public llvm::FoldingSetNode {
+ friend class ASTContext; // ASTContext creates these
+
/// The name of the template whose arguments will be deduced.
TemplateName Template;
@@ -4252,8 +4452,6 @@ class DeducedTemplateSpecializationType : public DeducedType,
Template.containsUnexpandedParameterPack()),
Template(Template) {}
- friend class ASTContext; // ASTContext creates these
-
public:
/// Retrieve the name of the template that we are deducing.
TemplateName getTemplateName() const { return Template;}
@@ -4297,6 +4495,8 @@ public:
class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) TemplateSpecializationType
: public Type,
public llvm::FoldingSetNode {
+ friend class ASTContext; // ASTContext creates these
+
/// The name of the template being specialized. This is
/// either a TemplateName::Template (in which case it is a
/// ClassTemplateDecl*, a TemplateTemplateParmDecl*, or a
@@ -4318,8 +4518,6 @@ class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) TemplateSpecializationType
QualType Canon,
QualType Aliased);
- friend class ASTContext; // ASTContext creates these
-
public:
/// Determine whether any of the given template arguments are dependent.
static bool anyDependentTemplateArguments(ArrayRef<TemplateArgumentLoc> Args,
@@ -4328,21 +4526,6 @@ public:
static bool anyDependentTemplateArguments(const TemplateArgumentListInfo &,
bool &InstantiationDependent);
- /// \brief Print a template argument list, including the '<' and '>'
- /// enclosing the template arguments.
- static void PrintTemplateArgumentList(raw_ostream &OS,
- ArrayRef<TemplateArgument> Args,
- const PrintingPolicy &Policy,
- bool SkipBrackets = false);
-
- static void PrintTemplateArgumentList(raw_ostream &OS,
- ArrayRef<TemplateArgumentLoc> Args,
- const PrintingPolicy &Policy);
-
- static void PrintTemplateArgumentList(raw_ostream &OS,
- const TemplateArgumentListInfo &,
- const PrintingPolicy &Policy);
-
/// True if this template specialization type matches a current
/// instantiation in the context in which it is found.
bool isCurrentInstantiation() const {
@@ -4373,7 +4556,7 @@ public:
return *reinterpret_cast<const QualType*>(end());
}
- typedef const TemplateArgument * iterator;
+ using iterator = const TemplateArgument *;
iterator begin() const { return getArgs(); }
iterator end() const; // defined inline in TemplateBase.h
@@ -4400,6 +4583,7 @@ public:
bool isSugared() const {
return !isDependentType() || isCurrentInstantiation() || isTypeAlias();
}
+
QualType desugar() const { return getCanonicalTypeInternal(); }
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) {
@@ -4417,6 +4601,20 @@ public:
}
};
+/// \brief Print a template argument list, including the '<' and '>'
+/// enclosing the template arguments.
+void printTemplateArgumentList(raw_ostream &OS,
+ ArrayRef<TemplateArgument> Args,
+ const PrintingPolicy &Policy);
+
+void printTemplateArgumentList(raw_ostream &OS,
+ ArrayRef<TemplateArgumentLoc> Args,
+ const PrintingPolicy &Policy);
+
+void printTemplateArgumentList(raw_ostream &OS,
+ const TemplateArgumentListInfo &Args,
+ const PrintingPolicy &Policy);
+
/// The injected class name of a C++ class template or class
/// template partial specialization. Used to record that a type was
/// spelled with a bare identifier rather than as a template-id; the
@@ -4435,6 +4633,12 @@ public:
/// will canonicalize to the injected class name (when appropriate
/// according to the rules of the language).
class InjectedClassNameType : public Type {
+ friend class ASTContext; // ASTContext creates these.
+ friend class ASTNodeImporter;
+ friend class ASTReader; // FIXME: ASTContext::getInjectedClassNameType is not
+ // currently suitable for AST reading, too much
+ // interdependencies.
+
CXXRecordDecl *Decl;
/// The template specialization which this type represents.
@@ -4448,18 +4652,12 @@ class InjectedClassNameType : public Type {
/// and always dependent.
QualType InjectedType;
- friend class ASTContext; // ASTContext creates these.
- friend class ASTReader; // FIXME: ASTContext::getInjectedClassNameType is not
- // currently suitable for AST reading, too much
- // interdependencies.
- friend class ASTNodeImporter;
-
InjectedClassNameType(CXXRecordDecl *D, QualType TST)
- : Type(InjectedClassName, QualType(), /*Dependent=*/true,
- /*InstantiationDependent=*/true,
- /*VariablyModified=*/false,
- /*ContainsUnexpandedParameterPack=*/false),
- Decl(D), InjectedType(TST) {
+ : Type(InjectedClassName, QualType(), /*Dependent=*/true,
+ /*InstantiationDependent=*/true,
+ /*VariablyModified=*/false,
+ /*ContainsUnexpandedParameterPack=*/false),
+ Decl(D), InjectedType(TST) {
assert(isa<TemplateSpecializationType>(TST));
assert(!TST.hasQualifiers());
assert(TST->isDependentType());
@@ -4467,9 +4665,11 @@ class InjectedClassNameType : public Type {
public:
QualType getInjectedSpecializationType() const { return InjectedType; }
+
const TemplateSpecializationType *getInjectedTST() const {
return cast<TemplateSpecializationType>(InjectedType.getTypePtr());
}
+
TemplateName getTemplateName() const {
return getInjectedTST()->getTemplateName();
}
@@ -4488,12 +4688,16 @@ public:
enum TagTypeKind {
/// \brief The "struct" keyword.
TTK_Struct,
+
/// \brief The "__interface" keyword.
TTK_Interface,
+
/// \brief The "union" keyword.
TTK_Union,
+
/// \brief The "class" keyword.
TTK_Class,
+
/// \brief The "enum" keyword.
TTK_Enum
};
@@ -4503,17 +4707,23 @@ enum TagTypeKind {
enum ElaboratedTypeKeyword {
/// \brief The "struct" keyword introduces the elaborated-type-specifier.
ETK_Struct,
+
/// \brief The "__interface" keyword introduces the elaborated-type-specifier.
ETK_Interface,
+
/// \brief The "union" keyword introduces the elaborated-type-specifier.
ETK_Union,
+
/// \brief The "class" keyword introduces the elaborated-type-specifier.
ETK_Class,
+
/// \brief The "enum" keyword introduces the elaborated-type-specifier.
ETK_Enum,
+
/// \brief The "typename" keyword precedes the qualified type name, e.g.,
/// \c typename T::type.
ETK_Typename,
+
/// \brief No keyword precedes the qualified type name.
ETK_None
};
@@ -4528,8 +4738,8 @@ protected:
QualType Canonical, bool Dependent,
bool InstantiationDependent, bool VariablyModified,
bool ContainsUnexpandedParameterPack)
- : Type(tc, Canonical, Dependent, InstantiationDependent, VariablyModified,
- ContainsUnexpandedParameterPack) {
+ : Type(tc, Canonical, Dependent, InstantiationDependent, VariablyModified,
+ ContainsUnexpandedParameterPack) {
TypeWithKeywordBits.Keyword = Keyword;
}
@@ -4574,6 +4784,7 @@ public:
/// The type itself is always "sugar", used to express what was written
/// in the source code but containing no additional semantic information.
class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode {
+ friend class ASTContext; // ASTContext creates these
/// The nested name specifier containing the qualifier.
NestedNameSpecifier *NNS;
@@ -4594,8 +4805,6 @@ class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode {
"and name qualifier both null.");
}
- friend class ASTContext; // ASTContext creates these
-
public:
~ElaboratedType();
@@ -4640,6 +4849,7 @@ public:
/// mode, this type is used with non-dependent names to delay name lookup until
/// instantiation.
class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode {
+ friend class ASTContext; // ASTContext creates these
/// \brief The nested name specifier containing the qualifier.
NestedNameSpecifier *NNS;
@@ -4649,13 +4859,11 @@ class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode {
DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
const IdentifierInfo *Name, QualType CanonType)
- : TypeWithKeyword(Keyword, DependentName, CanonType, /*Dependent=*/true,
- /*InstantiationDependent=*/true,
- /*VariablyModified=*/false,
- NNS->containsUnexpandedParameterPack()),
- NNS(NNS), Name(Name) {}
-
- friend class ASTContext; // ASTContext creates these
+ : TypeWithKeyword(Keyword, DependentName, CanonType, /*Dependent=*/true,
+ /*InstantiationDependent=*/true,
+ /*VariablyModified=*/false,
+ NNS->containsUnexpandedParameterPack()),
+ NNS(NNS), Name(Name) {}
public:
/// Retrieve the qualification on this type.
@@ -4695,6 +4903,7 @@ public:
class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) DependentTemplateSpecializationType
: public TypeWithKeyword,
public llvm::FoldingSetNode {
+ friend class ASTContext; // ASTContext creates these
/// The nested name specifier containing the qualifier.
NestedNameSpecifier *NNS;
@@ -4706,20 +4915,19 @@ class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) DependentTemplateSpecializationType
/// specialization.
unsigned NumArgs;
- const TemplateArgument *getArgBuffer() const {
- return reinterpret_cast<const TemplateArgument*>(this+1);
- }
- TemplateArgument *getArgBuffer() {
- return reinterpret_cast<TemplateArgument*>(this+1);
- }
-
DependentTemplateSpecializationType(ElaboratedTypeKeyword Keyword,
NestedNameSpecifier *NNS,
const IdentifierInfo *Name,
ArrayRef<TemplateArgument> Args,
QualType Canon);
- friend class ASTContext; // ASTContext creates these
+ const TemplateArgument *getArgBuffer() const {
+ return reinterpret_cast<const TemplateArgument*>(this+1);
+ }
+
+ TemplateArgument *getArgBuffer() {
+ return reinterpret_cast<TemplateArgument*>(this+1);
+ }
public:
NestedNameSpecifier *getQualifier() const { return NNS; }
@@ -4739,7 +4947,8 @@ public:
return {getArgs(), NumArgs};
}
- typedef const TemplateArgument * iterator;
+ using iterator = const TemplateArgument *;
+
iterator begin() const { return getArgs(); }
iterator end() const; // inline in TemplateBase.h
@@ -4785,6 +4994,8 @@ public:
/// Here, the pack expansion \c Types&... is represented via a
/// PackExpansionType whose pattern is Types&.
class PackExpansionType : public Type, public llvm::FoldingSetNode {
+ friend class ASTContext; // ASTContext creates these
+
/// \brief The pattern of the pack expansion.
QualType Pattern;
@@ -4798,14 +5009,12 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode {
PackExpansionType(QualType Pattern, QualType Canon,
Optional<unsigned> NumExpansions)
- : Type(PackExpansion, Canon, /*Dependent=*/Pattern->isDependentType(),
- /*InstantiationDependent=*/true,
- /*VariablyModified=*/Pattern->isVariablyModifiedType(),
- /*ContainsUnexpandedParameterPack=*/false),
- Pattern(Pattern),
- NumExpansions(NumExpansions? *NumExpansions + 1: 0) { }
-
- friend class ASTContext; // ASTContext creates these
+ : Type(PackExpansion, Canon, /*Dependent=*/Pattern->isDependentType(),
+ /*InstantiationDependent=*/true,
+ /*VariablyModified=*/Pattern->isVariablyModifiedType(),
+ /*ContainsUnexpandedParameterPack=*/false),
+ Pattern(Pattern),
+ NumExpansions(NumExpansions ? *NumExpansions + 1 : 0) {}
public:
/// \brief Retrieve the pattern of this pack expansion, which is the
@@ -4847,7 +5056,8 @@ public:
template <class T>
class ObjCProtocolQualifiers {
protected:
- ObjCProtocolQualifiers() {}
+ ObjCProtocolQualifiers() = default;
+
ObjCProtocolDecl * const *getProtocolStorage() const {
return const_cast<ObjCProtocolQualifiers*>(this)->getProtocolStorage();
}
@@ -4855,9 +5065,11 @@ protected:
ObjCProtocolDecl **getProtocolStorage() {
return static_cast<T*>(this)->getProtocolStorageImpl();
}
+
void setNumProtocols(unsigned N) {
static_cast<T*>(this)->setNumProtocolsImpl(N);
}
+
void initialize(ArrayRef<ObjCProtocolDecl *> protocols) {
setNumProtocols(protocols.size());
assert(getNumProtocols() == protocols.size() &&
@@ -4868,8 +5080,8 @@ protected:
}
public:
- typedef ObjCProtocolDecl * const *qual_iterator;
- typedef llvm::iterator_range<qual_iterator> qual_range;
+ using qual_iterator = ObjCProtocolDecl * const *;
+ using qual_range = llvm::iterator_range<qual_iterator>;
qual_range quals() const { return qual_range(qual_begin(), qual_end()); }
qual_iterator qual_begin() const { return getProtocolStorage(); }
@@ -4907,21 +5119,26 @@ class ObjCTypeParamType : public Type,
unsigned NumProtocols : 6;
ObjCTypeParamDecl *OTPDecl;
+
/// The protocols are stored after the ObjCTypeParamType node. In the
/// canonical type, the list of protocols are sorted alphabetically
/// and uniqued.
ObjCProtocolDecl **getProtocolStorageImpl();
+
/// Return the number of qualifying protocols in this interface type,
/// or 0 if there are none.
unsigned getNumProtocolsImpl() const {
return NumProtocols;
}
+
void setNumProtocolsImpl(unsigned N) {
NumProtocols = N;
}
+
ObjCTypeParamType(const ObjCTypeParamDecl *D,
QualType can,
ArrayRef<ObjCProtocolDecl *> protocols);
+
public:
bool isSugared() const { return true; }
QualType desugar() const { return getCanonicalTypeInternal(); }
@@ -4969,6 +5186,7 @@ public:
class ObjCObjectType : public Type,
public ObjCProtocolQualifiers<ObjCObjectType> {
friend class ObjCProtocolQualifiers<ObjCObjectType>;
+
// ObjCObjectType.NumTypeArgs - the number of type arguments stored
// after the ObjCObjectPointerType node.
// ObjCObjectType.NumProtocols - the number of protocols stored
@@ -5004,15 +5222,16 @@ class ObjCObjectType : public Type,
}
protected:
+ enum Nonce_ObjCInterface { Nonce_ObjCInterface };
+
ObjCObjectType(QualType Canonical, QualType Base,
ArrayRef<QualType> typeArgs,
ArrayRef<ObjCProtocolDecl *> protocols,
bool isKindOf);
- enum Nonce_ObjCInterface { Nonce_ObjCInterface };
ObjCObjectType(enum Nonce_ObjCInterface)
: Type(ObjCInterface, QualType(), false, false, false, false),
- BaseType(QualType(this_(), 0)) {
+ BaseType(QualType(this_(), 0)) {
ObjCObjectTypeBits.NumProtocols = 0;
ObjCObjectTypeBits.NumTypeArgs = 0;
ObjCObjectTypeBits.IsKindOf = 0;
@@ -5032,9 +5251,11 @@ public:
bool isObjCId() const {
return getBaseType()->isSpecificBuiltinType(BuiltinType::ObjCId);
}
+
bool isObjCClass() const {
return getBaseType()->isSpecificBuiltinType(BuiltinType::ObjCClass);
}
+
bool isObjCUnqualifiedId() const { return qual_empty() && isObjCId(); }
bool isObjCUnqualifiedClass() const { return qual_empty() && isObjCClass(); }
bool isObjCUnqualifiedIdOrClass() const {
@@ -5125,7 +5346,7 @@ class ObjCObjectTypeImpl : public ObjCObjectType, public llvm::FoldingSetNode {
ArrayRef<QualType> typeArgs,
ArrayRef<ObjCProtocolDecl *> protocols,
bool isKindOf)
- : ObjCObjectType(Canonical, Base, typeArgs, protocols, isKindOf) {}
+ : ObjCObjectType(Canonical, Base, typeArgs, protocols, isKindOf) {}
public:
void Profile(llvm::FoldingSetNodeID &ID);
@@ -5163,14 +5384,15 @@ inline ObjCProtocolDecl **ObjCTypeParamType::getProtocolStorageImpl() {
/// - It is its own base type. That is, if T is an ObjCInterfaceType*,
/// T->getBaseType() == QualType(T, 0).
class ObjCInterfaceType : public ObjCObjectType {
+ friend class ASTContext; // ASTContext creates these.
+ friend class ASTReader;
+ friend class ObjCInterfaceDecl;
+
mutable ObjCInterfaceDecl *Decl;
ObjCInterfaceType(const ObjCInterfaceDecl *D)
- : ObjCObjectType(Nonce_ObjCInterface),
- Decl(const_cast<ObjCInterfaceDecl*>(D)) {}
- friend class ASTContext; // ASTContext creates these.
- friend class ASTReader;
- friend class ObjCInterfaceDecl;
+ : ObjCObjectType(Nonce_ObjCInterface),
+ Decl(const_cast<ObjCInterfaceDecl*>(D)) {}
public:
/// Get the declaration of this interface.
@@ -5218,16 +5440,17 @@ inline ObjCInterfaceDecl *ObjCObjectType::getInterface() const {
/// Pointers to pointers to Objective C objects are still PointerTypes;
/// only the first level of pointer gets it own type implementation.
class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
+ friend class ASTContext; // ASTContext creates these.
+
QualType PointeeType;
ObjCObjectPointerType(QualType Canonical, QualType Pointee)
- : Type(ObjCObjectPointer, Canonical,
- Pointee->isDependentType(),
- Pointee->isInstantiationDependentType(),
- Pointee->isVariablyModifiedType(),
- Pointee->containsUnexpandedParameterPack()),
- PointeeType(Pointee) {}
- friend class ASTContext; // ASTContext creates these.
+ : Type(ObjCObjectPointer, Canonical,
+ Pointee->isDependentType(),
+ Pointee->isInstantiationDependentType(),
+ Pointee->isVariablyModifiedType(),
+ Pointee->containsUnexpandedParameterPack()),
+ PointeeType(Pointee) {}
public:
/// Gets the type pointed to by this ObjC pointer.
@@ -5336,16 +5559,19 @@ public:
/// An iterator over the qualifiers on the object type. Provided
/// for convenience. This will always iterate over the full set of
/// protocols on a type, not just those provided directly.
- typedef ObjCObjectType::qual_iterator qual_iterator;
- typedef llvm::iterator_range<qual_iterator> qual_range;
+ using qual_iterator = ObjCObjectType::qual_iterator;
+ using qual_range = llvm::iterator_range<qual_iterator>;
qual_range quals() const { return qual_range(qual_begin(), qual_end()); }
+
qual_iterator qual_begin() const {
return getObjectType()->qual_begin();
}
+
qual_iterator qual_end() const {
return getObjectType()->qual_end();
}
+
bool qual_empty() const { return getObjectType()->qual_empty(); }
/// Return the number of qualifying protocols on the object type.
@@ -5377,26 +5603,29 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getPointeeType());
}
+
static void Profile(llvm::FoldingSetNodeID &ID, QualType T) {
ID.AddPointer(T.getAsOpaquePtr());
}
+
static bool classof(const Type *T) {
return T->getTypeClass() == ObjCObjectPointer;
}
};
class AtomicType : public Type, public llvm::FoldingSetNode {
+ friend class ASTContext; // ASTContext creates these.
+
QualType ValueType;
AtomicType(QualType ValTy, QualType Canonical)
- : Type(Atomic, Canonical, ValTy->isDependentType(),
- ValTy->isInstantiationDependentType(),
- ValTy->isVariablyModifiedType(),
- ValTy->containsUnexpandedParameterPack()),
- ValueType(ValTy) {}
- friend class ASTContext; // ASTContext creates these.
+ : Type(Atomic, Canonical, ValTy->isDependentType(),
+ ValTy->isInstantiationDependentType(),
+ ValTy->isVariablyModifiedType(),
+ ValTy->containsUnexpandedParameterPack()),
+ ValueType(ValTy) {}
- public:
+public:
/// Gets the type contained by this atomic type, i.e.
/// the type returned by performing an atomic load of this atomic type.
QualType getValueType() const { return ValueType; }
@@ -5407,9 +5636,11 @@ class AtomicType : public Type, public llvm::FoldingSetNode {
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getValueType());
}
+
static void Profile(llvm::FoldingSetNodeID &ID, QualType T) {
ID.AddPointer(T.getAsOpaquePtr());
}
+
static bool classof(const Type *T) {
return T->getTypeClass() == Atomic;
}
@@ -5417,16 +5648,17 @@ class AtomicType : public Type, public llvm::FoldingSetNode {
/// PipeType - OpenCL20.
class PipeType : public Type, public llvm::FoldingSetNode {
+ friend class ASTContext; // ASTContext creates these.
+
QualType ElementType;
bool isRead;
- PipeType(QualType elemType, QualType CanonicalPtr, bool isRead) :
- Type(Pipe, CanonicalPtr, elemType->isDependentType(),
- elemType->isInstantiationDependentType(),
- elemType->isVariablyModifiedType(),
- elemType->containsUnexpandedParameterPack()),
- ElementType(elemType), isRead(isRead) {}
- friend class ASTContext; // ASTContext creates these.
+ PipeType(QualType elemType, QualType CanonicalPtr, bool isRead)
+ : Type(Pipe, CanonicalPtr, elemType->isDependentType(),
+ elemType->isInstantiationDependentType(),
+ elemType->isVariablyModifiedType(),
+ elemType->containsUnexpandedParameterPack()),
+ ElementType(elemType), isRead(isRead) {}
public:
QualType getElementType() const { return ElementType; }
@@ -5476,7 +5708,6 @@ public:
QualType apply(const ASTContext &Context, const Type* T) const;
};
-
// Inline function definitions.
inline SplitQualType SplitQualType::getSingleStepDesugaredType() const {
@@ -5602,7 +5833,7 @@ inline void QualType::removeLocalCVRQualifiers(unsigned Mask) {
}
/// Return the address space of this type.
-inline unsigned QualType::getAddressSpace() const {
+inline LangAS QualType::getAddressSpace() const {
return getQualifiers().getAddressSpace();
}
@@ -5709,88 +5940,117 @@ inline bool Type::isCompoundType() const {
inline bool Type::isFunctionType() const {
return isa<FunctionType>(CanonicalType);
}
+
inline bool Type::isPointerType() const {
return isa<PointerType>(CanonicalType);
}
+
inline bool Type::isAnyPointerType() const {
return isPointerType() || isObjCObjectPointerType();
}
+
inline bool Type::isBlockPointerType() const {
return isa<BlockPointerType>(CanonicalType);
}
+
inline bool Type::isReferenceType() const {
return isa<ReferenceType>(CanonicalType);
}
+
inline bool Type::isLValueReferenceType() const {
return isa<LValueReferenceType>(CanonicalType);
}
+
inline bool Type::isRValueReferenceType() const {
return isa<RValueReferenceType>(CanonicalType);
}
+
inline bool Type::isFunctionPointerType() const {
if (const PointerType *T = getAs<PointerType>())
return T->getPointeeType()->isFunctionType();
else
return false;
}
+
inline bool Type::isMemberPointerType() const {
return isa<MemberPointerType>(CanonicalType);
}
+
inline bool Type::isMemberFunctionPointerType() const {
if (const MemberPointerType* T = getAs<MemberPointerType>())
return T->isMemberFunctionPointer();
else
return false;
}
+
inline bool Type::isMemberDataPointerType() const {
if (const MemberPointerType* T = getAs<MemberPointerType>())
return T->isMemberDataPointer();
else
return false;
}
+
inline bool Type::isArrayType() const {
return isa<ArrayType>(CanonicalType);
}
+
inline bool Type::isConstantArrayType() const {
return isa<ConstantArrayType>(CanonicalType);
}
+
inline bool Type::isIncompleteArrayType() const {
return isa<IncompleteArrayType>(CanonicalType);
}
+
inline bool Type::isVariableArrayType() const {
return isa<VariableArrayType>(CanonicalType);
}
+
inline bool Type::isDependentSizedArrayType() const {
return isa<DependentSizedArrayType>(CanonicalType);
}
+
inline bool Type::isBuiltinType() const {
return isa<BuiltinType>(CanonicalType);
}
+
inline bool Type::isRecordType() const {
return isa<RecordType>(CanonicalType);
}
+
inline bool Type::isEnumeralType() const {
return isa<EnumType>(CanonicalType);
}
+
inline bool Type::isAnyComplexType() const {
return isa<ComplexType>(CanonicalType);
}
+
inline bool Type::isVectorType() const {
return isa<VectorType>(CanonicalType);
}
+
inline bool Type::isExtVectorType() const {
return isa<ExtVectorType>(CanonicalType);
}
+
+inline bool Type::isDependentAddressSpaceType() const {
+ return isa<DependentAddressSpaceType>(CanonicalType);
+}
+
inline bool Type::isObjCObjectPointerType() const {
return isa<ObjCObjectPointerType>(CanonicalType);
}
+
inline bool Type::isObjCObjectType() const {
return isa<ObjCObjectType>(CanonicalType);
}
+
inline bool Type::isObjCObjectOrInterfaceType() const {
return isa<ObjCInterfaceType>(CanonicalType) ||
isa<ObjCObjectType>(CanonicalType);
}
+
inline bool Type::isAtomicType() const {
return isa<AtomicType>(CanonicalType);
}
@@ -5800,26 +6060,31 @@ inline bool Type::isObjCQualifiedIdType() const {
return OPT->isObjCQualifiedIdType();
return false;
}
+
inline bool Type::isObjCQualifiedClassType() const {
if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>())
return OPT->isObjCQualifiedClassType();
return false;
}
+
inline bool Type::isObjCIdType() const {
if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>())
return OPT->isObjCIdType();
return false;
}
+
inline bool Type::isObjCClassType() const {
if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>())
return OPT->isObjCClassType();
return false;
}
+
inline bool Type::isObjCSelType() const {
if (const PointerType *OPT = getAs<PointerType>())
return OPT->getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCSel);
return false;
}
+
inline bool Type::isObjCBuiltinType() const {
return isObjCIdType() || isObjCClassType() || isObjCSelType();
}
@@ -5854,7 +6119,7 @@ inline bool Type::isImageType() const {
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) is##Id##Type() ||
return
#include "clang/Basic/OpenCLImageTypes.def"
- 0; // end boolean or operation
+ false; // end boolean or operation
}
inline bool Type::isPipeType() const {
@@ -6133,7 +6398,6 @@ QualType DecayedType::getPointeeType() const {
return cast<PointerType>(Decayed)->getPointeeType();
}
+} // namespace clang
-} // end namespace clang
-
-#endif
+#endif // LLVM_CLANG_AST_TYPE_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h b/contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h
index ad95f6f8effaa..b805160a27807 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h
@@ -1,4 +1,4 @@
-//===--- TypeLoc.h - Type Source Info Wrapper -------------------*- C++ -*-===//
+//===- TypeLoc.h - Type Source Info Wrapper ---------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,26 +6,42 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
/// \brief Defines the clang::TypeLoc interface and its subclasses.
-///
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_TYPELOC_H
#define LLVM_CLANG_AST_TYPELOC_H
#include "clang/AST/Decl.h"
+#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/Type.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/MathExtras.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <cstring>
namespace clang {
- class ASTContext;
- class ParmVarDecl;
- class TypeSourceInfo;
- class UnqualTypeLoc;
+
+class ASTContext;
+class CXXRecordDecl;
+class Expr;
+class ObjCInterfaceDecl;
+class ObjCProtocolDecl;
+class ObjCTypeParamDecl;
+class TemplateTypeParmDecl;
+class UnqualTypeLoc;
+class UnresolvedUsingTypenameDecl;
// Predeclare all the type nodes.
#define ABSTRACT_TYPELOC(Class, Base)
@@ -41,10 +57,16 @@ class TypeLoc {
protected:
// The correctness of this relies on the property that, for Type *Ty,
// QualType(Ty, 0).getAsOpaquePtr() == (void*) Ty
- const void *Ty;
- void *Data;
+ const void *Ty = nullptr;
+ void *Data = nullptr;
public:
+ TypeLoc() = default;
+ TypeLoc(QualType ty, void *opaqueData)
+ : Ty(ty.getAsOpaquePtr()), Data(opaqueData) {}
+ TypeLoc(const Type *ty, void *opaqueData)
+ : Ty(ty), Data(opaqueData) {}
+
/// \brief Convert to the specified TypeLoc type, asserting that this TypeLoc
/// is of the desired type.
///
@@ -88,12 +110,6 @@ public:
Qualified
};
- TypeLoc() : Ty(nullptr), Data(nullptr) { }
- TypeLoc(QualType ty, void *opaqueData)
- : Ty(ty.getAsOpaquePtr()), Data(opaqueData) { }
- TypeLoc(const Type *ty, void *opaqueData)
- : Ty(ty), Data(opaqueData) { }
-
TypeLocClass getTypeLocClass() const {
if (getType().hasLocalQualifiers()) return Qualified;
return (TypeLocClass) getType()->getTypeClass();
@@ -134,6 +150,7 @@ public:
SourceRange getSourceRange() const LLVM_READONLY {
return SourceRange(getBeginLoc(), getEndLoc());
}
+
SourceLocation getLocStart() const LLVM_READONLY { return getBeginLoc(); }
SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); }
@@ -228,7 +245,7 @@ inline TypeLoc TypeSourceInfo::getTypeLoc() const {
/// no direct qualifiers.
class UnqualTypeLoc : public TypeLoc {
public:
- UnqualTypeLoc() {}
+ UnqualTypeLoc() = default;
UnqualTypeLoc(const Type *Ty, void *Data) : TypeLoc(Ty, Data) {}
const Type *getTypePtr() const {
@@ -241,6 +258,7 @@ public:
private:
friend class TypeLoc;
+
static bool isKind(const TypeLoc &TL) {
return !TL.getType().hasLocalQualifiers();
}
@@ -253,9 +271,7 @@ private:
/// type qualifiers.
class QualifiedTypeLoc : public TypeLoc {
public:
- SourceRange getLocalSourceRange() const {
- return SourceRange();
- }
+ SourceRange getLocalSourceRange() const { return {}; }
UnqualTypeLoc getUnqualifiedLoc() const {
unsigned align =
@@ -296,6 +312,7 @@ public:
private:
friend class TypeLoc;
+
static bool isKind(const TypeLoc &TL) {
return TL.getType().hasLocalQualifiers();
}
@@ -337,12 +354,12 @@ inline UnqualTypeLoc TypeLoc::getUnqualifiedLoc() const {
/// InheritingConcreteTypeLoc instead.
template <class Base, class Derived, class TypeClass, class LocalData>
class ConcreteTypeLoc : public Base {
+ friend class TypeLoc;
const Derived *asDerived() const {
return static_cast<const Derived*>(this);
}
- friend class TypeLoc;
static bool isKind(const TypeLoc &TL) {
return !TL.getType().hasLocalQualifiers() &&
Derived::classofType(TL.getTypePtr());
@@ -357,6 +374,7 @@ public:
return std::max(unsigned(alignof(LocalData)),
asDerived()->getExtraLocalDataAlignment());
}
+
unsigned getLocalDataSize() const {
unsigned size = sizeof(LocalData);
unsigned extraAlign = asDerived()->getExtraLocalDataAlignment();
@@ -449,9 +467,7 @@ private:
return TypeLoc::getLocalAlignmentForType(T);
}
- TypeLoc getNextTypeLoc(HasNoInnerType _) const {
- return TypeLoc();
- }
+ TypeLoc getNextTypeLoc(HasNoInnerType _) const { return {}; }
TypeLoc getNextTypeLoc(QualType T) const {
return TypeLoc(T, getNonLocalData());
@@ -464,6 +480,7 @@ private:
template <class Base, class Derived, class TypeClass>
class InheritingConcreteTypeLoc : public Base {
friend class TypeLoc;
+
static bool classofType(const Type *Ty) {
return TypeClass::classof(Ty);
}
@@ -482,7 +499,6 @@ public:
}
};
-
struct TypeSpecLocInfo {
SourceLocation NameLoc;
};
@@ -502,22 +518,25 @@ public:
SourceLocation getNameLoc() const {
return this->getLocalData()->NameLoc;
}
+
void setNameLoc(SourceLocation Loc) {
this->getLocalData()->NameLoc = Loc;
}
+
SourceRange getLocalSourceRange() const {
return SourceRange(getNameLoc(), getNameLoc());
}
+
void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setNameLoc(Loc);
}
private:
friend class TypeLoc;
+
static bool isKind(const TypeLoc &TL);
};
-
struct BuiltinLocInfo {
SourceRange BuiltinRange;
};
@@ -531,9 +550,11 @@ public:
SourceLocation getBuiltinLoc() const {
return getLocalData()->BuiltinRange.getBegin();
}
+
void setBuiltinLoc(SourceLocation Loc) {
getLocalData()->BuiltinRange = Loc;
}
+
void expandBuiltinRange(SourceRange Range) {
SourceRange &BuiltinRange = getLocalData()->BuiltinRange;
if (!BuiltinRange.getBegin().isValid()) {
@@ -579,9 +600,11 @@ public:
else
return TSS_unspecified;
}
+
bool hasWrittenSignSpec() const {
return getWrittenSignSpec() != TSS_unspecified;
}
+
void setWrittenSignSpec(TypeSpecifierSign written) {
if (needsExtraLocalData())
getWrittenBuiltinSpecs().Sign = written;
@@ -593,18 +616,22 @@ public:
else
return TSW_unspecified;
}
+
bool hasWrittenWidthSpec() const {
return getWrittenWidthSpec() != TSW_unspecified;
}
+
void setWrittenWidthSpec(TypeSpecifierWidth written) {
if (needsExtraLocalData())
getWrittenBuiltinSpecs().Width = written;
}
TypeSpecifierType getWrittenTypeSpec() const;
+
bool hasWrittenTypeSpec() const {
return getWrittenTypeSpec() != TST_unspecified;
}
+
void setWrittenTypeSpec(TypeSpecifierType written) {
if (needsExtraLocalData())
getWrittenBuiltinSpecs().Type = written;
@@ -616,6 +643,7 @@ public:
else
return false;
}
+
void setModeAttr(bool written) {
if (needsExtraLocalData())
getWrittenBuiltinSpecs().ModeAttr = written;
@@ -633,7 +661,6 @@ public:
}
};
-
/// \brief Wrapper for source info for typedefs.
class TypedefTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
TypedefTypeLoc,
@@ -742,6 +769,7 @@ public:
*((SourceLocation*)this->getExtraLocalData()) :
SourceLocation();
}
+
void setProtocolLAngleLoc(SourceLocation Loc) {
*((SourceLocation*)this->getExtraLocalData()) = Loc;
}
@@ -751,6 +779,7 @@ public:
*((SourceLocation*)this->getExtraLocalData() + 1) :
SourceLocation();
}
+
void setProtocolRAngleLoc(SourceLocation Loc) {
*((SourceLocation*)this->getExtraLocalData() + 1) = Loc;
}
@@ -763,6 +792,7 @@ public:
assert(i < getNumProtocols() && "Index is out of bounds!");
return getProtocolLocArray()[i];
}
+
void setProtocolLoc(unsigned i, SourceLocation Loc) {
assert(i < getNumProtocols() && "Index is out of bounds!");
getProtocolLocArray()[i] = Loc;
@@ -785,9 +815,11 @@ public:
// as well.
return (this->getNumProtocols() + 2) * sizeof(SourceLocation) ;
}
+
unsigned getExtraLocalDataAlignment() const {
return alignof(SourceLocation);
}
+
SourceRange getLocalSourceRange() const {
SourceLocation start = getNameLoc();
SourceLocation end = getProtocolRAngleLoc();
@@ -938,7 +970,6 @@ public:
}
};
-
struct ObjCObjectTypeLocInfo {
SourceLocation TypeArgsLAngleLoc;
SourceLocation TypeArgsRAngleLoc;
@@ -971,6 +1002,7 @@ public:
SourceLocation getTypeArgsLAngleLoc() const {
return this->getLocalData()->TypeArgsLAngleLoc;
}
+
void setTypeArgsLAngleLoc(SourceLocation Loc) {
this->getLocalData()->TypeArgsLAngleLoc = Loc;
}
@@ -978,6 +1010,7 @@ public:
SourceLocation getTypeArgsRAngleLoc() const {
return this->getLocalData()->TypeArgsRAngleLoc;
}
+
void setTypeArgsRAngleLoc(SourceLocation Loc) {
this->getLocalData()->TypeArgsRAngleLoc = Loc;
}
@@ -999,6 +1032,7 @@ public:
SourceLocation getProtocolLAngleLoc() const {
return this->getLocalData()->ProtocolLAngleLoc;
}
+
void setProtocolLAngleLoc(SourceLocation Loc) {
this->getLocalData()->ProtocolLAngleLoc = Loc;
}
@@ -1006,6 +1040,7 @@ public:
SourceLocation getProtocolRAngleLoc() const {
return this->getLocalData()->ProtocolRAngleLoc;
}
+
void setProtocolRAngleLoc(SourceLocation Loc) {
this->getLocalData()->ProtocolRAngleLoc = Loc;
}
@@ -1018,6 +1053,7 @@ public:
assert(i < getNumProtocols() && "Index is out of bounds!");
return getProtocolLocArray()[i];
}
+
void setProtocolLoc(unsigned i, SourceLocation Loc) {
assert(i < getNumProtocols() && "Index is out of bounds!");
getProtocolLocArray()[i] = Loc;
@@ -1073,7 +1109,6 @@ public:
}
};
-
struct ObjCInterfaceLocInfo {
SourceLocation NameLoc;
SourceLocation NameEndLoc;
@@ -1127,12 +1162,15 @@ public:
SourceLocation getLParenLoc() const {
return this->getLocalData()->LParenLoc;
}
+
SourceLocation getRParenLoc() const {
return this->getLocalData()->RParenLoc;
}
+
void setLParenLoc(SourceLocation Loc) {
this->getLocalData()->LParenLoc = Loc;
}
+
void setRParenLoc(SourceLocation Loc) {
this->getLocalData()->RParenLoc = Loc;
}
@@ -1161,8 +1199,7 @@ inline TypeLoc TypeLoc::IgnoreParens() const {
return *this;
}
-
-struct AdjustedLocInfo { }; // Nothing.
+struct AdjustedLocInfo {}; // Nothing.
class AdjustedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, AdjustedTypeLoc,
AdjustedType, AdjustedLocInfo> {
@@ -1181,9 +1218,7 @@ public:
return getTypePtr()->getOriginalType();
}
- SourceRange getLocalSourceRange() const {
- return SourceRange();
- }
+ SourceRange getLocalSourceRange() const { return {}; }
unsigned getLocalDataSize() const {
// sizeof(AdjustedLocInfo) is 1, but we don't need its address to be unique
@@ -1210,6 +1245,7 @@ public:
SourceLocation getSigilLoc() const {
return this->getLocalData()->StarLoc;
}
+
void setSigilLoc(SourceLocation Loc) {
this->getLocalData()->StarLoc = Loc;
}
@@ -1231,7 +1267,6 @@ public:
}
};
-
/// \brief Wrapper for source info for pointers.
class PointerTypeLoc : public PointerLikeTypeLoc<PointerTypeLoc,
PointerType> {
@@ -1239,12 +1274,12 @@ public:
SourceLocation getStarLoc() const {
return getSigilLoc();
}
+
void setStarLoc(SourceLocation Loc) {
setSigilLoc(Loc);
}
};
-
/// \brief Wrapper for source info for block pointers.
class BlockPointerTypeLoc : public PointerLikeTypeLoc<BlockPointerTypeLoc,
BlockPointerType> {
@@ -1252,6 +1287,7 @@ public:
SourceLocation getCaretLoc() const {
return getSigilLoc();
}
+
void setCaretLoc(SourceLocation Loc) {
setSigilLoc(Loc);
}
@@ -1269,6 +1305,7 @@ public:
SourceLocation getStarLoc() const {
return getSigilLoc();
}
+
void setStarLoc(SourceLocation Loc) {
setSigilLoc(Loc);
}
@@ -1276,9 +1313,11 @@ public:
const Type *getClass() const {
return getTypePtr()->getClass();
}
+
TypeSourceInfo *getClassTInfo() const {
return getLocalData()->ClassTInfo;
}
+
void setClassTInfo(TypeSourceInfo* TI) {
getLocalData()->ClassTInfo = TI;
}
@@ -1310,7 +1349,6 @@ public:
}
};
-
class ReferenceTypeLoc : public PointerLikeTypeLoc<ReferenceTypeLoc,
ReferenceType> {
public:
@@ -1327,6 +1365,7 @@ public:
SourceLocation getAmpLoc() const {
return getSigilLoc();
}
+
void setAmpLoc(SourceLocation Loc) {
setSigilLoc(Loc);
}
@@ -1340,12 +1379,12 @@ public:
SourceLocation getAmpAmpLoc() const {
return getSigilLoc();
}
+
void setAmpAmpLoc(SourceLocation Loc) {
setSigilLoc(Loc);
}
};
-
struct FunctionLocInfo {
SourceLocation LocalRangeBegin;
SourceLocation LParenLoc;
@@ -1371,10 +1410,12 @@ class FunctionTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
// exception specification information.
return (SourceRange *)(getParmArray() + getNumParams());
}
+
public:
SourceLocation getLocalRangeBegin() const {
return getLocalData()->LocalRangeBegin;
}
+
void setLocalRangeBegin(SourceLocation L) {
getLocalData()->LocalRangeBegin = L;
}
@@ -1382,6 +1423,7 @@ public:
SourceLocation getLocalRangeEnd() const {
return getLocalData()->LocalRangeEnd;
}
+
void setLocalRangeEnd(SourceLocation L) {
getLocalData()->LocalRangeEnd = L;
}
@@ -1389,6 +1431,7 @@ public:
SourceLocation getLParenLoc() const {
return this->getLocalData()->LParenLoc;
}
+
void setLParenLoc(SourceLocation Loc) {
this->getLocalData()->LParenLoc = Loc;
}
@@ -1396,6 +1439,7 @@ public:
SourceLocation getRParenLoc() const {
return this->getLocalData()->RParenLoc;
}
+
void setRParenLoc(SourceLocation Loc) {
this->getLocalData()->RParenLoc = Loc;
}
@@ -1407,8 +1451,9 @@ public:
SourceRange getExceptionSpecRange() const {
if (hasExceptionSpec())
return *getExceptionSpecRangePtr();
- return SourceRange();
+ return {};
}
+
void setExceptionSpecRange(SourceRange R) {
if (hasExceptionSpec())
*getExceptionSpecRangePtr() = R;
@@ -1428,6 +1473,7 @@ public:
return 0;
return cast<FunctionProtoType>(getTypePtr())->getNumParams();
}
+
ParmVarDecl *getParam(unsigned i) const { return getParmArray()[i]; }
void setParam(unsigned i, ParmVarDecl *VD) { getParmArray()[i] = VD; }
@@ -1474,7 +1520,6 @@ class FunctionNoProtoTypeLoc :
FunctionNoProtoType> {
};
-
struct ArrayLocInfo {
SourceLocation LBracketLoc, RBracketLoc;
Expr *Size;
@@ -1489,6 +1534,7 @@ public:
SourceLocation getLBracketLoc() const {
return getLocalData()->LBracketLoc;
}
+
void setLBracketLoc(SourceLocation Loc) {
getLocalData()->LBracketLoc = Loc;
}
@@ -1496,6 +1542,7 @@ public:
SourceLocation getRBracketLoc() const {
return getLocalData()->RBracketLoc;
}
+
void setRBracketLoc(SourceLocation Loc) {
getLocalData()->RBracketLoc = Loc;
}
@@ -1507,6 +1554,7 @@ public:
Expr *getSizeExpr() const {
return getLocalData()->Size;
}
+
void setSizeExpr(Expr *Size) {
getLocalData()->Size = Size;
}
@@ -1557,7 +1605,6 @@ class VariableArrayTypeLoc :
VariableArrayType> {
};
-
// Location information for a TemplateName. Rudimentary for now.
struct TemplateNameLocInfo {
SourceLocation NameLoc;
@@ -1578,6 +1625,7 @@ public:
SourceLocation getTemplateKeywordLoc() const {
return getLocalData()->TemplateKWLoc;
}
+
void setTemplateKeywordLoc(SourceLocation Loc) {
getLocalData()->TemplateKWLoc = Loc;
}
@@ -1585,6 +1633,7 @@ public:
SourceLocation getLAngleLoc() const {
return getLocalData()->LAngleLoc;
}
+
void setLAngleLoc(SourceLocation Loc) {
getLocalData()->LAngleLoc = Loc;
}
@@ -1592,6 +1641,7 @@ public:
SourceLocation getRAngleLoc() const {
return getLocalData()->RAngleLoc;
}
+
void setRAngleLoc(SourceLocation Loc) {
getLocalData()->RAngleLoc = Loc;
}
@@ -1599,9 +1649,11 @@ public:
unsigned getNumArgs() const {
return getTypePtr()->getNumArgs();
}
+
void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) {
getArgInfos()[i] = AI;
}
+
TemplateArgumentLocInfo getArgLocInfo(unsigned i) const {
return getArgInfos()[i];
}
@@ -1613,6 +1665,7 @@ public:
SourceLocation getTemplateNameLoc() const {
return getLocalData()->NameLoc;
}
+
void setTemplateNameLoc(SourceLocation Loc) {
getLocalData()->NameLoc = Loc;
}
@@ -1664,6 +1717,74 @@ private:
}
};
+struct DependentAddressSpaceLocInfo {
+ Expr *ExprOperand;
+ SourceRange OperandParens;
+ SourceLocation AttrLoc;
+};
+
+class DependentAddressSpaceTypeLoc
+ : public ConcreteTypeLoc<UnqualTypeLoc,
+ DependentAddressSpaceTypeLoc,
+ DependentAddressSpaceType,
+ DependentAddressSpaceLocInfo> {
+public:
+ /// The location of the attribute name, i.e.
+ /// int * __attribute__((address_space(11)))
+ /// ^~~~~~~~~~~~~
+ SourceLocation getAttrNameLoc() const {
+ return getLocalData()->AttrLoc;
+ }
+ void setAttrNameLoc(SourceLocation loc) {
+ getLocalData()->AttrLoc = loc;
+ }
+
+ /// The attribute's expression operand, if it has one.
+ /// int * __attribute__((address_space(11)))
+ /// ^~
+ Expr *getAttrExprOperand() const {
+ return getLocalData()->ExprOperand;
+ }
+ void setAttrExprOperand(Expr *e) {
+ getLocalData()->ExprOperand = e;
+ }
+
+ /// The location of the parentheses around the operand, if there is
+ /// an operand.
+ /// int * __attribute__((address_space(11)))
+ /// ^ ^
+ SourceRange getAttrOperandParensRange() const {
+ return getLocalData()->OperandParens;
+ }
+ void setAttrOperandParensRange(SourceRange range) {
+ getLocalData()->OperandParens = range;
+ }
+
+ SourceRange getLocalSourceRange() const {
+ SourceRange range(getAttrNameLoc());
+ range.setEnd(getAttrOperandParensRange().getEnd());
+ return range;
+ }
+
+ /// Returns the type before the address space attribute application
+ /// area.
+ /// int * __attribute__((address_space(11))) *
+ /// ^ ^
+ QualType getInnerType() const {
+ return this->getTypePtr()->getPointeeType();
+ }
+
+ TypeLoc getPointeeTypeLoc() const {
+ return this->getInnerTypeLoc();
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation loc) {
+ setAttrNameLoc(loc);
+ setAttrOperandParensRange(SourceRange(loc));
+ setAttrExprOperand(getTypePtr()->getAddrSpaceExpr());
+ }
+};
+
//===----------------------------------------------------------------------===//
//
// All of these need proper implementations.
@@ -1717,6 +1838,7 @@ public:
SourceLocation getTypeofLoc() const {
return this->getLocalData()->TypeofLoc;
}
+
void setTypeofLoc(SourceLocation Loc) {
this->getLocalData()->TypeofLoc = Loc;
}
@@ -1724,6 +1846,7 @@ public:
SourceLocation getLParenLoc() const {
return this->getLocalData()->LParenLoc;
}
+
void setLParenLoc(SourceLocation Loc) {
this->getLocalData()->LParenLoc = Loc;
}
@@ -1731,6 +1854,7 @@ public:
SourceLocation getRParenLoc() const {
return this->getLocalData()->RParenLoc;
}
+
void setRParenLoc(SourceLocation Loc) {
this->getLocalData()->RParenLoc = Loc;
}
@@ -1738,6 +1862,7 @@ public:
SourceRange getParensRange() const {
return SourceRange(getLParenLoc(), getRParenLoc());
}
+
void setParensRange(SourceRange range) {
setLParenLoc(range.getBegin());
setRParenLoc(range.getEnd());
@@ -1761,6 +1886,7 @@ public:
Expr* getUnderlyingExpr() const {
return getTypePtr()->getUnderlyingExpr();
}
+
// Reimplemented to account for GNU/C++ extension
// typeof unary-expression
// where there are no parentheses.
@@ -1773,9 +1899,11 @@ public:
QualType getUnderlyingType() const {
return this->getTypePtr()->getUnderlyingType();
}
+
TypeSourceInfo* getUnderlyingTInfo() const {
return this->getLocalData()->UnderlyingTInfo;
}
+
void setUnderlyingTInfo(TypeSourceInfo* TI) const {
this->getLocalData()->UnderlyingTInfo = TI;
}
@@ -1815,6 +1943,7 @@ public:
TypeSourceInfo* getUnderlyingTInfo() const {
return getLocalData()->UnderlyingTInfo;
}
+
void setUnderlyingTInfo(TypeSourceInfo *TInfo) {
getLocalData()->UnderlyingTInfo = TInfo;
}
@@ -1826,16 +1955,13 @@ public:
SourceRange getParensRange() const {
return SourceRange(getLParenLoc(), getRParenLoc());
}
+
void setParensRange(SourceRange Range) {
setLParenLoc(Range.getBegin());
setRParenLoc(Range.getEnd());
}
- void initializeLocal(ASTContext &Context, SourceLocation Loc) {
- setKWLoc(Loc);
- setRParenLoc(Loc);
- setLParenLoc(Loc);
- }
+ void initializeLocal(ASTContext &Context, SourceLocation Loc);
};
class DeducedTypeLoc
@@ -1854,6 +1980,7 @@ public:
SourceLocation getTemplateNameLoc() const {
return getNameLoc();
}
+
void setTemplateNameLoc(SourceLocation Loc) {
setNameLoc(Loc);
}
@@ -1861,6 +1988,7 @@ public:
struct ElaboratedLocInfo {
SourceLocation ElaboratedKWLoc;
+
/// \brief Data associated with the nested-name-specifier location.
void *QualifierData;
};
@@ -1873,6 +2001,7 @@ public:
SourceLocation getElaboratedKeywordLoc() const {
return this->getLocalData()->ElaboratedKWLoc;
}
+
void setElaboratedKeywordLoc(SourceLocation Loc) {
this->getLocalData()->ElaboratedKWLoc = Loc;
}
@@ -1931,6 +2060,7 @@ public:
SourceLocation getElaboratedKeywordLoc() const {
return this->getLocalData()->ElaboratedKWLoc;
}
+
void setElaboratedKeywordLoc(SourceLocation Loc) {
this->getLocalData()->ElaboratedKWLoc = Loc;
}
@@ -1950,6 +2080,7 @@ public:
SourceLocation getNameLoc() const {
return this->getLocalData()->NameLoc;
}
+
void setNameLoc(SourceLocation Loc) {
this->getLocalData()->NameLoc = Loc;
}
@@ -1986,6 +2117,7 @@ public:
SourceLocation getElaboratedKeywordLoc() const {
return this->getLocalData()->ElaboratedKWLoc;
}
+
void setElaboratedKeywordLoc(SourceLocation Loc) {
this->getLocalData()->ElaboratedKWLoc = Loc;
}
@@ -2017,6 +2149,7 @@ public:
SourceLocation getTemplateKeywordLoc() const {
return getLocalData()->TemplateKWLoc;
}
+
void setTemplateKeywordLoc(SourceLocation Loc) {
getLocalData()->TemplateKWLoc = Loc;
}
@@ -2024,6 +2157,7 @@ public:
SourceLocation getTemplateNameLoc() const {
return this->getLocalData()->NameLoc;
}
+
void setTemplateNameLoc(SourceLocation Loc) {
this->getLocalData()->NameLoc = Loc;
}
@@ -2031,6 +2165,7 @@ public:
SourceLocation getLAngleLoc() const {
return this->getLocalData()->LAngleLoc;
}
+
void setLAngleLoc(SourceLocation Loc) {
this->getLocalData()->LAngleLoc = Loc;
}
@@ -2038,6 +2173,7 @@ public:
SourceLocation getRAngleLoc() const {
return this->getLocalData()->RAngleLoc;
}
+
void setRAngleLoc(SourceLocation Loc) {
this->getLocalData()->RAngleLoc = Loc;
}
@@ -2049,6 +2185,7 @@ public:
void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) {
getArgInfos()[i] = AI;
}
+
TemplateArgumentLocInfo getArgLocInfo(unsigned i) const {
return getArgInfos()[i];
}
@@ -2090,7 +2227,6 @@ private:
}
};
-
struct PackExpansionTypeLocInfo {
SourceLocation EllipsisLoc;
};
@@ -2142,6 +2278,7 @@ public:
SourceLocation getKWLoc() const {
return this->getLocalData()->KWLoc;
}
+
void setKWLoc(SourceLocation Loc) {
this->getLocalData()->KWLoc = Loc;
}
@@ -2149,6 +2286,7 @@ public:
SourceLocation getLParenLoc() const {
return this->getLocalData()->LParenLoc;
}
+
void setLParenLoc(SourceLocation Loc) {
this->getLocalData()->LParenLoc = Loc;
}
@@ -2156,6 +2294,7 @@ public:
SourceLocation getRParenLoc() const {
return this->getLocalData()->RParenLoc;
}
+
void setRParenLoc(SourceLocation Loc) {
this->getLocalData()->RParenLoc = Loc;
}
@@ -2163,6 +2302,7 @@ public:
SourceRange getParensRange() const {
return SourceRange(getLParenLoc(), getRParenLoc());
}
+
void setParensRange(SourceRange Range) {
setLParenLoc(Range.getBegin());
setRParenLoc(Range.getEnd());
@@ -2217,6 +2357,7 @@ inline T TypeLoc::getAsAdjusted() const {
}
return Cur.getAs<T>();
}
-}
-#endif
+} // namespace clang
+
+#endif // LLVM_CLANG_AST_TYPELOC_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/TypeNodes.def b/contrib/llvm/tools/clang/include/clang/AST/TypeNodes.def
index 9d1d09e2cc661..66697fa0d0faf 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/TypeNodes.def
+++ b/contrib/llvm/tools/clang/include/clang/AST/TypeNodes.def
@@ -23,7 +23,7 @@
// NON_CANONICAL_TYPE(Class, Base) - A type that can show up
// anywhere in the AST but will never be a part of a canonical
// type. Clients that only need to deal with canonical types
-// (ignoring, e.g., typedefs and other type alises used for
+// (ignoring, e.g., typedefs and other type aliases used for
// pretty-printing) can ignore these types.
//
// DEPENDENT_TYPE(Class, Base) - A type that will only show up
@@ -73,6 +73,7 @@ TYPE(IncompleteArray, ArrayType)
TYPE(VariableArray, ArrayType)
DEPENDENT_TYPE(DependentSizedArray, ArrayType)
DEPENDENT_TYPE(DependentSizedExtVector, Type)
+DEPENDENT_TYPE(DependentAddressSpace, Type)
TYPE(Vector, Type)
TYPE(ExtVector, VectorType)
ABSTRACT_TYPE(Function, Type)
diff --git a/contrib/llvm/tools/clang/include/clang/AST/UnresolvedSet.h b/contrib/llvm/tools/clang/include/clang/AST/UnresolvedSet.h
index b63c6eb217697..614ff9bf2efda 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/UnresolvedSet.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/UnresolvedSet.h
@@ -1,4 +1,4 @@
-//===-- UnresolvedSet.h - Unresolved sets of declarations ------*- C++ -*-===//
+//===- UnresolvedSet.h - Unresolved sets of declarations --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,20 +17,25 @@
#include "clang/AST/DeclAccessPair.h"
#include "clang/Basic/LLVM.h"
+#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/iterator.h"
+#include <cstddef>
+#include <iterator>
namespace clang {
+class NamedDecl;
+
/// The iterator over UnresolvedSets. Serves as both the const and
/// non-const iterator.
class UnresolvedSetIterator : public llvm::iterator_adaptor_base<
UnresolvedSetIterator, DeclAccessPair *,
std::random_access_iterator_tag, NamedDecl *,
std::ptrdiff_t, NamedDecl *, NamedDecl *> {
- friend class UnresolvedSetImpl;
friend class ASTUnresolvedSet;
friend class OverloadExpr;
+ friend class UnresolvedSetImpl;
explicit UnresolvedSetIterator(DeclAccessPair *Iter)
: iterator_adaptor_base(Iter) {}
@@ -54,12 +59,13 @@ public:
/// \brief A set of unresolved declarations.
class UnresolvedSetImpl {
- typedef SmallVectorImpl<DeclAccessPair> DeclsTy;
+ using DeclsTy = SmallVectorImpl<DeclAccessPair>;
// Don't allow direct construction, and only permit subclassing by
// UnresolvedSet.
private:
template <unsigned N> friend class UnresolvedSet;
+
UnresolvedSetImpl() = default;
UnresolvedSetImpl(const UnresolvedSetImpl &) = default;
UnresolvedSetImpl &operator=(const UnresolvedSetImpl &) = default;
@@ -71,8 +77,8 @@ private:
public:
// We don't currently support assignment through this iterator, so we might
// as well use the same implementation twice.
- typedef UnresolvedSetIterator iterator;
- typedef UnresolvedSetIterator const_iterator;
+ using iterator = UnresolvedSetIterator;
+ using const_iterator = UnresolvedSetIterator;
iterator begin() { return iterator(decls().begin()); }
iterator end() { return iterator(decls().end()); }
@@ -140,7 +146,7 @@ template <unsigned InlineCapacity> class UnresolvedSet :
SmallVector<DeclAccessPair, InlineCapacity> Decls;
};
-
+
} // namespace clang
-#endif
+#endif // LLVM_CLANG_AST_UNRESOLVEDSET_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/VTTBuilder.h b/contrib/llvm/tools/clang/include/clang/AST/VTTBuilder.h
index b4a6fe3bdb942..178139477d001 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/VTTBuilder.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/VTTBuilder.h
@@ -1,4 +1,4 @@
-//===--- VTTBuilder.h - C++ VTT layout builder --------------------*- C++ -*-=//
+//===- VTTBuilder.h - C++ VTT layout builder --------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,25 +16,31 @@
#define LLVM_CLANG_AST_VTTBUILDER_H
#include "clang/AST/BaseSubobject.h"
-#include "clang/AST/CXXInheritance.h"
-#include "clang/AST/GlobalDecl.h"
-#include "clang/AST/RecordLayout.h"
-#include "clang/Basic/ABI.h"
-#include <utility>
+#include "clang/AST/CharUnits.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include <cstdint>
namespace clang {
+class ASTContext;
+class ASTRecordLayout;
+class CXXRecordDecl;
+
class VTTVTable {
llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> BaseAndIsVirtual;
CharUnits BaseOffset;
public:
- VTTVTable() {}
+ VTTVTable() = default;
VTTVTable(const CXXRecordDecl *Base, CharUnits BaseOffset, bool BaseIsVirtual)
- : BaseAndIsVirtual(Base, BaseIsVirtual), BaseOffset(BaseOffset) {}
+ : BaseAndIsVirtual(Base, BaseIsVirtual), BaseOffset(BaseOffset) {}
VTTVTable(BaseSubobject Base, bool BaseIsVirtual)
- : BaseAndIsVirtual(Base.getBase(), BaseIsVirtual),
- BaseOffset(Base.getBaseOffset()) {}
+ : BaseAndIsVirtual(Base.getBase(), BaseIsVirtual),
+ BaseOffset(Base.getBaseOffset()) {}
const CXXRecordDecl *getBase() const {
return BaseAndIsVirtual.getPointer();
@@ -57,25 +63,24 @@ struct VTTComponent {
uint64_t VTableIndex;
BaseSubobject VTableBase;
- VTTComponent() {}
+ VTTComponent() = default;
VTTComponent(uint64_t VTableIndex, BaseSubobject VTableBase)
- : VTableIndex(VTableIndex), VTableBase(VTableBase) {}
+ : VTableIndex(VTableIndex), VTableBase(VTableBase) {}
};
/// \brief Class for building VTT layout information.
class VTTBuilder {
-
ASTContext &Ctx;
/// \brief The most derived class for which we're building this vtable.
const CXXRecordDecl *MostDerivedClass;
- typedef SmallVector<VTTVTable, 64> VTTVTablesVectorTy;
+ using VTTVTablesVectorTy = SmallVector<VTTVTable, 64>;
/// \brief The VTT vtables.
VTTVTablesVectorTy VTTVTables;
- typedef SmallVector<VTTComponent, 64> VTTComponentsVectorTy;
+ using VTTComponentsVectorTy = SmallVector<VTTComponent, 64>;
/// \brief The VTT components.
VTTComponentsVectorTy VTTComponents;
@@ -83,9 +88,9 @@ class VTTBuilder {
/// \brief The AST record layout of the most derived class.
const ASTRecordLayout &MostDerivedClassLayout;
- typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
+ using VisitedVirtualBasesSetTy = llvm::SmallPtrSet<const CXXRecordDecl *, 4>;
- typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy;
+ using AddressPointsMapTy = llvm::DenseMap<BaseSubobject, uint64_t>;
/// \brief The sub-VTT indices for the bases of the most derived class.
llvm::DenseMap<BaseSubobject, uint64_t> SubVTTIndicies;
@@ -153,9 +158,8 @@ public:
getSecondaryVirtualPointerIndices() const {
return SecondaryVirtualPointerIndices;
}
-
};
-}
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_AST_VTTBUILDER_H
diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchers.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchers.h
index c9b496df33f7c..64e7e908d51ed 100644
--- a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -1,4 +1,4 @@
-//===--- ASTMatchers.h - Structural query framework -------------*- C++ -*-===//
+//===- ASTMatchers.h - Structural query framework ---------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -25,7 +25,7 @@
//
// For example, when we're interested in child classes of a certain class, we
// would write:
-// cxxRecordDecl(hasName("MyClass"), hasChild(id("child", recordDecl())))
+// cxxRecordDecl(hasName("MyClass"), has(id("child", recordDecl())))
// When the match is found via the MatchFinder, a user provided callback will
// be called with a BoundNodes instance that contains a mapping from the
// strings that we provided for the id(...) calls to the nodes that were
@@ -46,13 +46,48 @@
#define LLVM_CLANG_ASTMATCHERS_ASTMATCHERS_H
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTTypeTraits.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/OperationKinds.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtObjC.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/TemplateName.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
#include "clang/ASTMatchers/ASTMatchersInternal.h"
#include "clang/ASTMatchers/ASTMatchersMacros.h"
+#include "clang/Basic/AttrKinds.h"
+#include "clang/Basic/ExceptionSpecificationType.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Basic/TypeTraits.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Regex.h"
+#include <cassert>
+#include <cstddef>
#include <iterator>
+#include <limits>
+#include <string>
+#include <utility>
+#include <vector>
namespace clang {
namespace ast_matchers {
@@ -78,7 +113,7 @@ public:
/// \brief Type of mapping from binding identifiers to bound nodes. This type
/// is an associative container with a key type of \c std::string and a value
/// type of \c clang::ast_type_traits::DynTypedNode
- typedef internal::BoundNodesMap::IDToNodeMap IDToNodeMap;
+ using IDToNodeMap = internal::BoundNodesMap::IDToNodeMap;
/// \brief Retrieve mapping from binding identifiers to bound nodes.
const IDToNodeMap &getMap() const {
@@ -86,13 +121,13 @@ public:
}
private:
+ friend class internal::BoundNodesTreeBuilder;
+
/// \brief Create BoundNodes from a pre-filled map of bindings.
BoundNodes(internal::BoundNodesMap &MyBoundNodes)
: MyBoundNodes(MyBoundNodes) {}
internal::BoundNodesMap MyBoundNodes;
-
- friend class internal::BoundNodesTreeBuilder;
};
/// \brief If the provided matcher matches a node, binds the node to \c ID.
@@ -107,13 +142,13 @@ internal::Matcher<T> id(StringRef ID,
/// \brief Types of matchers for the top-level classes in the AST class
/// hierarchy.
/// @{
-typedef internal::Matcher<Decl> DeclarationMatcher;
-typedef internal::Matcher<Stmt> StatementMatcher;
-typedef internal::Matcher<QualType> TypeMatcher;
-typedef internal::Matcher<TypeLoc> TypeLocMatcher;
-typedef internal::Matcher<NestedNameSpecifier> NestedNameSpecifierMatcher;
-typedef internal::Matcher<NestedNameSpecifierLoc> NestedNameSpecifierLocMatcher;
-typedef internal::Matcher<CXXCtorInitializer> CXXCtorInitializerMatcher;
+using DeclarationMatcher = internal::Matcher<Decl>;
+using StatementMatcher = internal::Matcher<Stmt>;
+using TypeMatcher = internal::Matcher<QualType>;
+using TypeLocMatcher = internal::Matcher<TypeLoc>;
+using NestedNameSpecifierMatcher = internal::Matcher<NestedNameSpecifier>;
+using NestedNameSpecifierLocMatcher = internal::Matcher<NestedNameSpecifierLoc>;
+using CXXCtorInitializerMatcher = internal::Matcher<CXXCtorInitializer>;
/// @}
/// \brief Matches any node.
@@ -143,7 +178,7 @@ inline internal::TrueMatcher anything() { return internal::TrueMatcher(); }
/// \endcode
/// decl(hasDeclContext(translationUnitDecl()))
/// matches "int X", but not "int Y".
-const internal::VariadicDynCastAllOfMatcher<Decl, TranslationUnitDecl>
+extern const internal::VariadicDynCastAllOfMatcher<Decl, TranslationUnitDecl>
translationUnitDecl;
/// \brief Matches typedef declarations.
@@ -155,7 +190,8 @@ const internal::VariadicDynCastAllOfMatcher<Decl, TranslationUnitDecl>
/// \endcode
/// typedefDecl()
/// matches "typedef int X", but not "using Y = int"
-const internal::VariadicDynCastAllOfMatcher<Decl, TypedefDecl> typedefDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, TypedefDecl>
+ typedefDecl;
/// \brief Matches typedef name declarations.
///
@@ -166,7 +202,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, TypedefDecl> typedefDecl;
/// \endcode
/// typedefNameDecl()
/// matches "typedef int X" and "using Y = int"
-const internal::VariadicDynCastAllOfMatcher<Decl, TypedefNameDecl>
+extern const internal::VariadicDynCastAllOfMatcher<Decl, TypedefNameDecl>
typedefNameDecl;
/// \brief Matches type alias declarations.
@@ -178,7 +214,8 @@ const internal::VariadicDynCastAllOfMatcher<Decl, TypedefNameDecl>
/// \endcode
/// typeAliasDecl()
/// matches "using Y = int", but not "typedef int X"
-const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasDecl> typeAliasDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasDecl>
+ typeAliasDecl;
/// \brief Matches type alias template declarations.
///
@@ -187,7 +224,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasDecl> typeAliasDecl;
/// template <typename T>
/// using Y = X<T>;
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasTemplateDecl>
+extern const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasTemplateDecl>
typeAliasTemplateDecl;
/// \brief Matches AST nodes that were expanded within the main-file.
@@ -278,7 +315,7 @@ AST_POLYMORPHIC_MATCHER_P(isExpansionInFileMatching,
/// friend X;
/// };
/// \endcode
-const internal::VariadicAllOfMatcher<Decl> decl;
+extern const internal::VariadicAllOfMatcher<Decl> decl;
/// \brief Matches a declaration of a linkage specification.
///
@@ -288,7 +325,7 @@ const internal::VariadicAllOfMatcher<Decl> decl;
/// \endcode
/// linkageSpecDecl()
/// matches "extern "C" {}"
-const internal::VariadicDynCastAllOfMatcher<Decl, LinkageSpecDecl>
+extern const internal::VariadicDynCastAllOfMatcher<Decl, LinkageSpecDecl>
linkageSpecDecl;
/// \brief Matches a declaration of anything that could have a name.
@@ -302,7 +339,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, LinkageSpecDecl>
/// } U;
/// };
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<Decl, NamedDecl> namedDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, NamedDecl> namedDecl;
/// \brief Matches a declaration of label.
///
@@ -313,7 +350,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, NamedDecl> namedDecl;
/// \endcode
/// labelDecl()
/// matches 'FOO:'
-const internal::VariadicDynCastAllOfMatcher<Decl, LabelDecl> labelDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, LabelDecl> labelDecl;
/// \brief Matches a declaration of a namespace.
///
@@ -324,7 +361,8 @@ const internal::VariadicDynCastAllOfMatcher<Decl, LabelDecl> labelDecl;
/// \endcode
/// namespaceDecl()
/// matches "namespace {}" and "namespace test {}"
-const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceDecl> namespaceDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceDecl>
+ namespaceDecl;
/// \brief Matches a declaration of a namespace alias.
///
@@ -335,7 +373,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceDecl> namespaceDecl;
/// \endcode
/// namespaceAliasDecl()
/// matches "namespace alias" but not "namespace test"
-const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceAliasDecl>
+extern const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceAliasDecl>
namespaceAliasDecl;
/// \brief Matches class, struct, and union declarations.
@@ -347,9 +385,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceAliasDecl>
/// struct S {};
/// union U {};
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Decl,
- RecordDecl> recordDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, RecordDecl> recordDecl;
/// \brief Matches C++ class declarations.
///
@@ -358,9 +394,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// class X;
/// template<class T> class Z {};
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Decl,
- CXXRecordDecl> cxxRecordDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXRecordDecl>
+ cxxRecordDecl;
/// \brief Matches C++ class template declarations.
///
@@ -368,9 +403,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// \code
/// template<class T> class Z {};
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Decl,
- ClassTemplateDecl> classTemplateDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, ClassTemplateDecl>
+ classTemplateDecl;
/// \brief Matches C++ class template specializations.
///
@@ -382,9 +416,9 @@ const internal::VariadicDynCastAllOfMatcher<
/// \endcode
/// classTemplateSpecializationDecl()
/// matches the specializations \c A<int> and \c A<double>
-const internal::VariadicDynCastAllOfMatcher<
- Decl,
- ClassTemplateSpecializationDecl> classTemplateSpecializationDecl;
+extern const internal::VariadicDynCastAllOfMatcher<
+ Decl, ClassTemplateSpecializationDecl>
+ classTemplateSpecializationDecl;
/// \brief Matches declarator declarations (field, variable, function
/// and non-type template parameter declarations).
@@ -395,7 +429,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// \endcode
/// declaratorDecl()
/// matches \c int y.
-const internal::VariadicDynCastAllOfMatcher<Decl, DeclaratorDecl>
+extern const internal::VariadicDynCastAllOfMatcher<Decl, DeclaratorDecl>
declaratorDecl;
/// \brief Matches parameter variable declarations.
@@ -406,7 +440,8 @@ const internal::VariadicDynCastAllOfMatcher<Decl, DeclaratorDecl>
/// \endcode
/// parmVarDecl()
/// matches \c int x.
-const internal::VariadicDynCastAllOfMatcher<Decl, ParmVarDecl> parmVarDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, ParmVarDecl>
+ parmVarDecl;
/// \brief Matches C++ access specifier declarations.
///
@@ -419,9 +454,8 @@ const internal::VariadicDynCastAllOfMatcher<Decl, ParmVarDecl> parmVarDecl;
/// \endcode
/// accessSpecDecl()
/// matches 'public:'
-const internal::VariadicDynCastAllOfMatcher<
- Decl,
- AccessSpecDecl> accessSpecDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, AccessSpecDecl>
+ accessSpecDecl;
/// \brief Matches constructor initializers.
///
@@ -432,7 +466,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// int i;
/// };
/// \endcode
-const internal::VariadicAllOfMatcher<CXXCtorInitializer> cxxCtorInitializer;
+extern const internal::VariadicAllOfMatcher<CXXCtorInitializer>
+ cxxCtorInitializer;
/// \brief Matches template arguments.
///
@@ -443,7 +478,7 @@ const internal::VariadicAllOfMatcher<CXXCtorInitializer> cxxCtorInitializer;
/// \endcode
/// templateArgument()
/// matches 'int' in C<int>.
-const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument;
+extern const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument;
/// \brief Matches template name.
///
@@ -454,7 +489,7 @@ const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument;
/// \endcode
/// templateName()
/// matches 'X' in X<int>.
-const internal::VariadicAllOfMatcher<TemplateName> templateName;
+extern const internal::VariadicAllOfMatcher<TemplateName> templateName;
/// \brief Matches non-type template parameter declarations.
///
@@ -464,9 +499,9 @@ const internal::VariadicAllOfMatcher<TemplateName> templateName;
/// \endcode
/// nonTypeTemplateParmDecl()
/// matches 'N', but not 'T'.
-const internal::VariadicDynCastAllOfMatcher<
- Decl,
- NonTypeTemplateParmDecl> nonTypeTemplateParmDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl,
+ NonTypeTemplateParmDecl>
+ nonTypeTemplateParmDecl;
/// \brief Matches template type parameter declarations.
///
@@ -476,9 +511,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// \endcode
/// templateTypeParmDecl()
/// matches 'T', but not 'N'.
-const internal::VariadicDynCastAllOfMatcher<
- Decl,
- TemplateTypeParmDecl> templateTypeParmDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, TemplateTypeParmDecl>
+ templateTypeParmDecl;
/// \brief Matches public C++ declarations.
///
@@ -582,6 +616,23 @@ AST_MATCHER_P(FieldDecl, hasInClassInitializer, internal::Matcher<Expr>,
InnerMatcher.matches(*Initializer, Finder, Builder));
}
+/// \brief Matches the specialized template of a specialization declaration.
+///
+/// Given
+/// \code
+/// tempalate<typename T> class A {};
+/// typedef A<int> B;
+/// \endcode
+/// classTemplateSpecializationDecl(hasSpecializedTemplate(classTemplateDecl()))
+/// matches 'B' with classTemplateDecl() matching the class template
+/// declaration of 'A'.
+AST_MATCHER_P(ClassTemplateSpecializationDecl, hasSpecializedTemplate,
+ internal::Matcher<ClassTemplateDecl>, InnerMatcher) {
+ const ClassTemplateDecl* Decl = Node.getSpecializedTemplate();
+ return (Decl != nullptr &&
+ InnerMatcher.matches(*Decl, Finder, Builder));
+}
+
/// \brief Matches a declaration that has been implicitly added
/// by the compiler (eg. implicit default/copy constructors).
AST_MATCHER(Decl, isImplicit) {
@@ -922,7 +973,7 @@ AST_MATCHER_P(TemplateArgument, equalsIntegralValue,
/// enum X { A, B, C };
/// void F();
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<Decl, ValueDecl> valueDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, ValueDecl> valueDecl;
/// \brief Matches C++ constructor declarations.
///
@@ -935,9 +986,8 @@ const internal::VariadicDynCastAllOfMatcher<Decl, ValueDecl> valueDecl;
/// int DoSomething();
/// };
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Decl,
- CXXConstructorDecl> cxxConstructorDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXConstructorDecl>
+ cxxConstructorDecl;
/// \brief Matches explicit C++ destructor declarations.
///
@@ -948,9 +998,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// virtual ~Foo();
/// };
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Decl,
- CXXDestructorDecl> cxxDestructorDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXDestructorDecl>
+ cxxDestructorDecl;
/// \brief Matches enum declarations.
///
@@ -960,7 +1009,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// A, B, C
/// };
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<Decl, EnumDecl> enumDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, EnumDecl> enumDecl;
/// \brief Matches enum constants.
///
@@ -970,9 +1019,8 @@ const internal::VariadicDynCastAllOfMatcher<Decl, EnumDecl> enumDecl;
/// A, B, C
/// };
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Decl,
- EnumConstantDecl> enumConstantDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, EnumConstantDecl>
+ enumConstantDecl;
/// \brief Matches method declarations.
///
@@ -980,7 +1028,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// \code
/// class X { void y(); };
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl> cxxMethodDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl>
+ cxxMethodDecl;
/// \brief Matches conversion operator declarations.
///
@@ -988,7 +1037,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl> cxxMethodDecl;
/// \code
/// class X { operator int() const; };
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<Decl, CXXConversionDecl>
+extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXConversionDecl>
cxxConversionDecl;
/// \brief Matches variable declarations.
@@ -1000,7 +1049,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, CXXConversionDecl>
/// \code
/// int a;
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<Decl, VarDecl> varDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, VarDecl> varDecl;
/// \brief Matches field declarations.
///
@@ -1010,7 +1059,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, VarDecl> varDecl;
/// \endcode
/// fieldDecl()
/// matches 'm'.
-const internal::VariadicDynCastAllOfMatcher<Decl, FieldDecl> fieldDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, FieldDecl> fieldDecl;
/// \brief Matches function declarations.
///
@@ -1018,7 +1067,8 @@ const internal::VariadicDynCastAllOfMatcher<Decl, FieldDecl> fieldDecl;
/// \code
/// void f();
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<Decl, FunctionDecl> functionDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, FunctionDecl>
+ functionDecl;
/// \brief Matches C++ function template declarations.
///
@@ -1026,9 +1076,8 @@ const internal::VariadicDynCastAllOfMatcher<Decl, FunctionDecl> functionDecl;
/// \code
/// template<class T> void f(T t) {}
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Decl,
- FunctionTemplateDecl> functionTemplateDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, FunctionTemplateDecl>
+ functionTemplateDecl;
/// \brief Matches friend declarations.
///
@@ -1038,7 +1087,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// \endcode
/// friendDecl()
/// matches 'friend void foo()'.
-const internal::VariadicDynCastAllOfMatcher<Decl, FriendDecl> friendDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, FriendDecl> friendDecl;
/// \brief Matches statements.
///
@@ -1048,7 +1097,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, FriendDecl> friendDecl;
/// \endcode
/// stmt()
/// matches both the compound statement '{ ++a; }' and '++a'.
-const internal::VariadicAllOfMatcher<Stmt> stmt;
+extern const internal::VariadicAllOfMatcher<Stmt> stmt;
/// \brief Matches declaration statements.
///
@@ -1058,9 +1107,7 @@ const internal::VariadicAllOfMatcher<Stmt> stmt;
/// \endcode
/// declStmt()
/// matches 'int a'.
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- DeclStmt> declStmt;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, DeclStmt> declStmt;
/// \brief Matches member expressions.
///
@@ -1073,7 +1120,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// \endcode
/// memberExpr()
/// matches this->x, x, y.x, a, this->b
-const internal::VariadicDynCastAllOfMatcher<Stmt, MemberExpr> memberExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, MemberExpr> memberExpr;
/// \brief Matches call expressions.
///
@@ -1083,7 +1130,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, MemberExpr> memberExpr;
/// x.y();
/// y();
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> callExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> callExpr;
/// \brief Matches lambda expressions.
///
@@ -1091,7 +1138,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> callExpr;
/// \code
/// [&](){return 5;}
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<Stmt, LambdaExpr> lambdaExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, LambdaExpr> lambdaExpr;
/// \brief Matches member call expressions.
///
@@ -1100,9 +1147,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, LambdaExpr> lambdaExpr;
/// X x;
/// x.y();
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- CXXMemberCallExpr> cxxMemberCallExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXMemberCallExpr>
+ cxxMemberCallExpr;
/// \brief Matches ObjectiveC Message invocation expressions.
///
@@ -1113,9 +1159,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// \code
/// [[NSString alloc] initWithString:@"Hello"]
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- ObjCMessageExpr> objcMessageExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCMessageExpr>
+ objcMessageExpr;
/// \brief Matches Objective-C interface declarations.
///
@@ -1124,9 +1169,18 @@ const internal::VariadicDynCastAllOfMatcher<
/// @interface Foo
/// @end
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Decl,
- ObjCInterfaceDecl> objcInterfaceDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCInterfaceDecl>
+ objcInterfaceDecl;
+
+/// \brief Matches Objective-C implementation declarations.
+///
+/// Example matches Foo
+/// \code
+/// @implementation Foo
+/// @end
+/// \endcode
+extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCImplementationDecl>
+ objcImplementationDecl;
/// \brief Matches Objective-C protocol declarations.
///
@@ -1135,9 +1189,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// @protocol FooDelegate
/// @end
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Decl,
- ObjCProtocolDecl> objcProtocolDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCProtocolDecl>
+ objcProtocolDecl;
/// \brief Matches Objective-C category declarations.
///
@@ -1146,9 +1199,18 @@ const internal::VariadicDynCastAllOfMatcher<
/// @interface Foo (Additions)
/// @end
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Decl,
- ObjCCategoryDecl> objcCategoryDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCCategoryDecl>
+ objcCategoryDecl;
+
+/// \brief Matches Objective-C category definitions.
+///
+/// Example matches Foo (Additions)
+/// \code
+/// @implementation Foo (Additions)
+/// @end
+/// \endcode
+extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCCategoryImplDecl>
+ objcCategoryImplDecl;
/// \brief Matches Objective-C method declarations.
///
@@ -1162,9 +1224,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// - (void)method {}
/// @end
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Decl,
- ObjCMethodDecl> objcMethodDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCMethodDecl>
+ objcMethodDecl;
/// \brief Matches Objective-C instance variable declarations.
///
@@ -1175,9 +1236,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// }
/// @end
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Decl,
- ObjCIvarDecl> objcIvarDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCIvarDecl>
+ objcIvarDecl;
/// \brief Matches Objective-C property declarations.
///
@@ -1187,9 +1247,47 @@ const internal::VariadicDynCastAllOfMatcher<
/// @property BOOL enabled;
/// @end
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Decl,
- ObjCPropertyDecl> objcPropertyDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCPropertyDecl>
+ objcPropertyDecl;
+
+/// \brief Matches Objective-C \@throw statements.
+///
+/// Example matches \@throw
+/// \code
+/// @throw obj;
+/// \endcode
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtThrowStmt>
+ objcThrowStmt;
+
+/// \brief Matches Objective-C @try statements.
+///
+/// Example matches @try
+/// \code
+/// @try {}
+/// @catch (...) {}
+/// \endcode
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtTryStmt>
+ objcTryStmt;
+
+/// \brief Matches Objective-C @catch statements.
+///
+/// Example matches @catch
+/// \code
+/// @try {}
+/// @catch (...) {}
+/// \endcode
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtCatchStmt>
+ objcCatchStmt;
+
+/// \brief Matches Objective-C @finally statements.
+///
+/// Example matches @finally
+/// \code
+/// @try {}
+/// @finally {}
+/// \endcode
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtFinallyStmt>
+ objcFinallyStmt;
/// \brief Matches expressions that introduce cleanups to be run at the end
/// of the sub-expression's evaluation.
@@ -1198,9 +1296,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// \code
/// const std::string str = std::string();
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- ExprWithCleanups> exprWithCleanups;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, ExprWithCleanups>
+ exprWithCleanups;
/// \brief Matches init list expressions.
///
@@ -1212,7 +1309,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// \endcode
/// initListExpr()
/// matches "{ 1, 2 }" and "{ 5, 6 }"
-const internal::VariadicDynCastAllOfMatcher<Stmt, InitListExpr> initListExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, InitListExpr>
+ initListExpr;
/// \brief Matches the syntactic form of init list expressions
/// (if expression have it).
@@ -1234,8 +1332,9 @@ AST_MATCHER_P(InitListExpr, hasSyntacticForm,
/// \endcode
/// cxxStdInitializerListExpr()
/// matches "{ 1, 2, 3 }" and "{ 4, 5 }"
-const internal::VariadicDynCastAllOfMatcher<Stmt,
- CXXStdInitializerListExpr> cxxStdInitializerListExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt,
+ CXXStdInitializerListExpr>
+ cxxStdInitializerListExpr;
/// \brief Matches implicit initializers of init list expressions.
///
@@ -1245,8 +1344,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt,
/// \endcode
/// implicitValueInitExpr()
/// matches "[0].y" (implicitly)
-const internal::VariadicDynCastAllOfMatcher<Stmt, ImplicitValueInitExpr>
-implicitValueInitExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, ImplicitValueInitExpr>
+ implicitValueInitExpr;
/// \brief Matches paren list expressions.
/// ParenListExprs don't have a predefined type and are used for late parsing.
@@ -1263,7 +1362,8 @@ implicitValueInitExpr;
/// \endcode
/// parenListExpr() matches "*this" but NOT matches (a, b) because (a, b)
/// has a predefined type and is a ParenExpr, not a ParenListExpr.
-const internal::VariadicDynCastAllOfMatcher<Stmt, ParenListExpr> parenListExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, ParenListExpr>
+ parenListExpr;
/// \brief Matches substitutions of non-type template parameters.
///
@@ -1275,9 +1375,9 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, ParenListExpr> parenListExpr;
/// \endcode
/// substNonTypeTemplateParmExpr()
/// matches "N" in the right-hand side of "static const int n = N;"
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- SubstNonTypeTemplateParmExpr> substNonTypeTemplateParmExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt,
+ SubstNonTypeTemplateParmExpr>
+ substNonTypeTemplateParmExpr;
/// \brief Matches using declarations.
///
@@ -1288,7 +1388,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// \endcode
/// usingDecl()
/// matches \code using X::x \endcode
-const internal::VariadicDynCastAllOfMatcher<Decl, UsingDecl> usingDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, UsingDecl> usingDecl;
/// \brief Matches using namespace declarations.
///
@@ -1299,9 +1399,8 @@ const internal::VariadicDynCastAllOfMatcher<Decl, UsingDecl> usingDecl;
/// \endcode
/// usingDirectiveDecl()
/// matches \code using namespace X \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Decl,
- UsingDirectiveDecl> usingDirectiveDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, UsingDirectiveDecl>
+ usingDirectiveDecl;
/// \brief Matches reference to a name that can be looked up during parsing
/// but could not be resolved to a specific declaration.
@@ -1317,9 +1416,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// \endcode
/// unresolvedLookupExpr()
/// matches \code foo<T>() \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- UnresolvedLookupExpr> unresolvedLookupExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, UnresolvedLookupExpr>
+ unresolvedLookupExpr;
/// \brief Matches unresolved using value declarations.
///
@@ -1332,9 +1430,9 @@ const internal::VariadicDynCastAllOfMatcher<
/// \endcode
/// unresolvedUsingValueDecl()
/// matches \code using X::x \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Decl,
- UnresolvedUsingValueDecl> unresolvedUsingValueDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl,
+ UnresolvedUsingValueDecl>
+ unresolvedUsingValueDecl;
/// \brief Matches unresolved using value declarations that involve the
/// typename.
@@ -1351,9 +1449,9 @@ const internal::VariadicDynCastAllOfMatcher<
/// \endcode
/// unresolvedUsingTypenameDecl()
/// matches \code using Base<T>::Foo \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Decl,
- UnresolvedUsingTypenameDecl> unresolvedUsingTypenameDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl,
+ UnresolvedUsingTypenameDecl>
+ unresolvedUsingTypenameDecl;
/// \brief Matches parentheses used in expressions.
///
@@ -1362,9 +1460,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// int foo() { return 1; }
/// int a = (foo() + 1);
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- ParenExpr> parenExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, ParenExpr> parenExpr;
/// \brief Matches constructor call expressions (including implicit ones).
///
@@ -1376,9 +1472,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// int n;
/// f(string(ptr, n), ptr);
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- CXXConstructExpr> cxxConstructExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXConstructExpr>
+ cxxConstructExpr;
/// \brief Matches unresolved constructor call expressions.
///
@@ -1388,9 +1483,9 @@ const internal::VariadicDynCastAllOfMatcher<
/// template <typename T>
/// void f(const T& t) { return T(t); }
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- CXXUnresolvedConstructExpr> cxxUnresolvedConstructExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt,
+ CXXUnresolvedConstructExpr>
+ cxxUnresolvedConstructExpr;
/// \brief Matches implicit and explicit this expressions.
///
@@ -1402,7 +1497,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// int f() { return i; }
/// };
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThisExpr> cxxThisExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThisExpr>
+ cxxThisExpr;
/// \brief Matches nodes where temporaries are created.
///
@@ -1412,9 +1508,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThisExpr> cxxThisExpr;
/// FunctionTakesString(GetStringByValue());
/// FunctionTakesStringByPointer(GetStringPointer());
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- CXXBindTemporaryExpr> cxxBindTemporaryExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXBindTemporaryExpr>
+ cxxBindTemporaryExpr;
/// \brief Matches nodes where temporaries are materialized.
///
@@ -1434,9 +1529,9 @@ const internal::VariadicDynCastAllOfMatcher<
/// f();
/// f().func();
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- MaterializeTemporaryExpr> materializeTemporaryExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt,
+ MaterializeTemporaryExpr>
+ materializeTemporaryExpr;
/// \brief Matches new expressions.
///
@@ -1446,7 +1541,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// \endcode
/// cxxNewExpr()
/// matches 'new X'.
-const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNewExpr> cxxNewExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNewExpr> cxxNewExpr;
/// \brief Matches delete expressions.
///
@@ -1456,7 +1551,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNewExpr> cxxNewExpr;
/// \endcode
/// cxxDeleteExpr()
/// matches 'delete X'.
-const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDeleteExpr> cxxDeleteExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDeleteExpr>
+ cxxDeleteExpr;
/// \brief Matches array subscript expressions.
///
@@ -1466,9 +1562,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDeleteExpr> cxxDeleteExpr;
/// \endcode
/// arraySubscriptExpr()
/// matches "a[1]"
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- ArraySubscriptExpr> arraySubscriptExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, ArraySubscriptExpr>
+ arraySubscriptExpr;
/// \brief Matches the value of a default argument at the call site.
///
@@ -1479,9 +1574,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// void f(int x, int y = 0);
/// f(42);
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- CXXDefaultArgExpr> cxxDefaultArgExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDefaultArgExpr>
+ cxxDefaultArgExpr;
/// \brief Matches overloaded operator calls.
///
@@ -1497,9 +1591,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// ostream &o; int b = 1, c = 1;
/// o << b << c;
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- CXXOperatorCallExpr> cxxOperatorCallExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXOperatorCallExpr>
+ cxxOperatorCallExpr;
/// \brief Matches expressions.
///
@@ -1507,7 +1600,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// \code
/// void f() { x(); }
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<Stmt, Expr> expr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, Expr> expr;
/// \brief Matches expressions that refer to declarations.
///
@@ -1516,7 +1609,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, Expr> expr;
/// bool x;
/// if (x) {}
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<Stmt, DeclRefExpr> declRefExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, DeclRefExpr>
+ declRefExpr;
/// \brief Matches if statements.
///
@@ -1524,7 +1618,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, DeclRefExpr> declRefExpr;
/// \code
/// if (x) {}
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<Stmt, IfStmt> ifStmt;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, IfStmt> ifStmt;
/// \brief Matches for statements.
///
@@ -1533,7 +1627,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, IfStmt> ifStmt;
/// for (;;) {}
/// int i[] = {1, 2, 3}; for (auto a : i);
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<Stmt, ForStmt> forStmt;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, ForStmt> forStmt;
/// \brief Matches the increment statement of a for loop.
///
@@ -1571,9 +1665,8 @@ AST_MATCHER_P(ForStmt, hasLoopInit, internal::Matcher<Stmt>,
/// int i[] = {1, 2, 3}; for (auto a : i);
/// for(int j = 0; j < 5; ++j);
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- CXXForRangeStmt> cxxForRangeStmt;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXForRangeStmt>
+ cxxForRangeStmt;
/// \brief Matches the initialization statement of a for loop.
///
@@ -1611,7 +1704,7 @@ AST_MATCHER_P(CXXForRangeStmt, hasRangeInit, internal::Matcher<Expr>,
/// \endcode
/// whileStmt()
/// matches 'while (true) {}'.
-const internal::VariadicDynCastAllOfMatcher<Stmt, WhileStmt> whileStmt;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, WhileStmt> whileStmt;
/// \brief Matches do statements.
///
@@ -1621,7 +1714,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, WhileStmt> whileStmt;
/// \endcode
/// doStmt()
/// matches 'do {} while(true)'
-const internal::VariadicDynCastAllOfMatcher<Stmt, DoStmt> doStmt;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, DoStmt> doStmt;
/// \brief Matches break statements.
///
@@ -1631,7 +1724,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, DoStmt> doStmt;
/// \endcode
/// breakStmt()
/// matches 'break'
-const internal::VariadicDynCastAllOfMatcher<Stmt, BreakStmt> breakStmt;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, BreakStmt> breakStmt;
/// \brief Matches continue statements.
///
@@ -1641,7 +1734,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, BreakStmt> breakStmt;
/// \endcode
/// continueStmt()
/// matches 'continue'
-const internal::VariadicDynCastAllOfMatcher<Stmt, ContinueStmt> continueStmt;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, ContinueStmt>
+ continueStmt;
/// \brief Matches return statements.
///
@@ -1651,7 +1745,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, ContinueStmt> continueStmt;
/// \endcode
/// returnStmt()
/// matches 'return 1'
-const internal::VariadicDynCastAllOfMatcher<Stmt, ReturnStmt> returnStmt;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, ReturnStmt> returnStmt;
/// \brief Matches goto statements.
///
@@ -1662,7 +1756,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, ReturnStmt> returnStmt;
/// \endcode
/// gotoStmt()
/// matches 'goto FOO'
-const internal::VariadicDynCastAllOfMatcher<Stmt, GotoStmt> gotoStmt;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, GotoStmt> gotoStmt;
/// \brief Matches label statements.
///
@@ -1673,7 +1767,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, GotoStmt> gotoStmt;
/// \endcode
/// labelStmt()
/// matches 'FOO:'
-const internal::VariadicDynCastAllOfMatcher<Stmt, LabelStmt> labelStmt;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, LabelStmt> labelStmt;
/// \brief Matches address of label statements (GNU extension).
///
@@ -1685,7 +1779,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, LabelStmt> labelStmt;
/// \endcode
/// addrLabelExpr()
/// matches '&&FOO'
-const internal::VariadicDynCastAllOfMatcher<Stmt, AddrLabelExpr> addrLabelExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, AddrLabelExpr>
+ addrLabelExpr;
/// \brief Matches switch statements.
///
@@ -1695,7 +1790,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, AddrLabelExpr> addrLabelExpr;
/// \endcode
/// switchStmt()
/// matches 'switch(a)'.
-const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchStmt> switchStmt;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchStmt> switchStmt;
/// \brief Matches case and default statements inside switch statements.
///
@@ -1705,7 +1800,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchStmt> switchStmt;
/// \endcode
/// switchCase()
/// matches 'case 42: break;' and 'default: break;'.
-const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchCase> switchCase;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchCase> switchCase;
/// \brief Matches case statements inside switch statements.
///
@@ -1715,7 +1810,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchCase> switchCase;
/// \endcode
/// caseStmt()
/// matches 'case 42: break;'.
-const internal::VariadicDynCastAllOfMatcher<Stmt, CaseStmt> caseStmt;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, CaseStmt> caseStmt;
/// \brief Matches default statements inside switch statements.
///
@@ -1725,7 +1820,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CaseStmt> caseStmt;
/// \endcode
/// defaultStmt()
/// matches 'default: break;'.
-const internal::VariadicDynCastAllOfMatcher<Stmt, DefaultStmt> defaultStmt;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, DefaultStmt>
+ defaultStmt;
/// \brief Matches compound statements.
///
@@ -1733,7 +1829,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, DefaultStmt> defaultStmt;
/// \code
/// for (;;) {{}}
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundStmt> compoundStmt;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundStmt>
+ compoundStmt;
/// \brief Matches catch statements.
///
@@ -1742,7 +1839,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundStmt> compoundStmt;
/// \endcode
/// cxxCatchStmt()
/// matches 'catch(int i)'
-const internal::VariadicDynCastAllOfMatcher<Stmt, CXXCatchStmt> cxxCatchStmt;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXCatchStmt>
+ cxxCatchStmt;
/// \brief Matches try statements.
///
@@ -1751,7 +1849,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CXXCatchStmt> cxxCatchStmt;
/// \endcode
/// cxxTryStmt()
/// matches 'try {}'
-const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTryStmt> cxxTryStmt;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTryStmt> cxxTryStmt;
/// \brief Matches throw expressions.
///
@@ -1760,7 +1858,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTryStmt> cxxTryStmt;
/// \endcode
/// cxxThrowExpr()
/// matches 'throw 5'
-const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThrowExpr> cxxThrowExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThrowExpr>
+ cxxThrowExpr;
/// \brief Matches null statements.
///
@@ -1769,7 +1868,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThrowExpr> cxxThrowExpr;
/// \endcode
/// nullStmt()
/// matches the second ';'
-const internal::VariadicDynCastAllOfMatcher<Stmt, NullStmt> nullStmt;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, NullStmt> nullStmt;
/// \brief Matches asm statements.
///
@@ -1779,7 +1878,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, NullStmt> nullStmt;
/// \endcode
/// asmStmt()
/// matches '__asm("mov al, 2")'
-const internal::VariadicDynCastAllOfMatcher<Stmt, AsmStmt> asmStmt;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, AsmStmt> asmStmt;
/// \brief Matches bool literals.
///
@@ -1787,9 +1886,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, AsmStmt> asmStmt;
/// \code
/// true
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- CXXBoolLiteralExpr> cxxBoolLiteral;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXBoolLiteralExpr>
+ cxxBoolLiteral;
/// \brief Matches string literals (also matches wide string literals).
///
@@ -1798,9 +1896,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// char *s = "abcd";
/// wchar_t *ws = L"abcd";
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- StringLiteral> stringLiteral;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, StringLiteral>
+ stringLiteral;
/// \brief Matches character literals (also matches wchar_t).
///
@@ -1812,17 +1909,15 @@ const internal::VariadicDynCastAllOfMatcher<
/// char ch = 'a';
/// wchar_t chw = L'a';
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- CharacterLiteral> characterLiteral;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, CharacterLiteral>
+ characterLiteral;
/// \brief Matches integer literals of all sizes / encodings, e.g.
/// 1, 1L, 0x1 and 1U.
///
/// Does not match character-encoded integers such as L'a'.
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- IntegerLiteral> integerLiteral;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, IntegerLiteral>
+ integerLiteral;
/// \brief Matches float literals of all sizes / encodings, e.g.
/// 1.0, 1.0f, 1.0L and 1e10.
@@ -1831,16 +1926,14 @@ const internal::VariadicDynCastAllOfMatcher<
/// \code
/// float a = 10;
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- FloatingLiteral> floatLiteral;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, FloatingLiteral>
+ floatLiteral;
/// \brief Matches user defined literal operator call.
///
/// Example match: "foo"_suffix
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- UserDefinedLiteral> userDefinedLiteral;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, UserDefinedLiteral>
+ userDefinedLiteral;
/// \brief Matches compound (i.e. non-scalar) literals
///
@@ -1849,24 +1942,23 @@ const internal::VariadicDynCastAllOfMatcher<
/// int array[4] = {1};
/// vector int myvec = (vector int)(1, 2);
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- CompoundLiteralExpr> compoundLiteralExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundLiteralExpr>
+ compoundLiteralExpr;
/// \brief Matches nullptr literal.
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- CXXNullPtrLiteralExpr> cxxNullPtrLiteralExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNullPtrLiteralExpr>
+ cxxNullPtrLiteralExpr;
/// \brief Matches GNU __null expression.
-const internal::VariadicDynCastAllOfMatcher<Stmt, GNUNullExpr> gnuNullExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, GNUNullExpr>
+ gnuNullExpr;
/// \brief Matches atomic builtins.
/// Example matches __atomic_load_n(ptr, 1)
/// \code
/// void foo() { int *ptr; __atomic_load_n(ptr, 1); }
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<Stmt, AtomicExpr> atomicExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, AtomicExpr> atomicExpr;
/// \brief Matches statement expression (GNU extension).
///
@@ -1874,7 +1966,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, AtomicExpr> atomicExpr;
/// \code
/// int C = ({ int X = 4; X; });
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<Stmt, StmtExpr> stmtExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, StmtExpr> stmtExpr;
/// \brief Matches binary operator expressions.
///
@@ -1882,9 +1974,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, StmtExpr> stmtExpr;
/// \code
/// !(a || b)
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- BinaryOperator> binaryOperator;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, BinaryOperator>
+ binaryOperator;
/// \brief Matches unary operator expressions.
///
@@ -1892,9 +1983,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// \code
/// !a || b
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- UnaryOperator> unaryOperator;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, UnaryOperator>
+ unaryOperator;
/// \brief Matches conditional operator expressions.
///
@@ -1902,9 +1992,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// \code
/// (a ? b : c) + 42
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- ConditionalOperator> conditionalOperator;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, ConditionalOperator>
+ conditionalOperator;
/// \brief Matches binary conditional operator expressions (GNU extension).
///
@@ -1912,9 +2001,9 @@ const internal::VariadicDynCastAllOfMatcher<
/// \code
/// (a ?: b) + 42;
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- BinaryConditionalOperator> binaryConditionalOperator;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt,
+ BinaryConditionalOperator>
+ binaryConditionalOperator;
/// \brief Matches opaque value expressions. They are used as helpers
/// to reference another expressions and can be met
@@ -1924,9 +2013,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// \code
/// (a ?: c) + 42;
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- OpaqueValueExpr> opaqueValueExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, OpaqueValueExpr>
+ opaqueValueExpr;
/// \brief Matches a C++ static_assert declaration.
///
@@ -1941,9 +2029,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// };
/// static_assert(sizeof(S) == sizeof(int));
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Decl,
- StaticAssertDecl> staticAssertDecl;
+extern const internal::VariadicDynCastAllOfMatcher<Decl, StaticAssertDecl>
+ staticAssertDecl;
/// \brief Matches a reinterpret_cast expression.
///
@@ -1955,9 +2042,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// \code
/// void* p = reinterpret_cast<char*>(&p);
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- CXXReinterpretCastExpr> cxxReinterpretCastExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXReinterpretCastExpr>
+ cxxReinterpretCastExpr;
/// \brief Matches a C++ static_cast expression.
///
@@ -1972,9 +2058,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// \code
/// long eight(static_cast<long>(8));
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- CXXStaticCastExpr> cxxStaticCastExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXStaticCastExpr>
+ cxxStaticCastExpr;
/// \brief Matches a dynamic_cast expression.
///
@@ -1988,9 +2073,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// B b;
/// D* p = dynamic_cast<D*>(&b);
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- CXXDynamicCastExpr> cxxDynamicCastExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDynamicCastExpr>
+ cxxDynamicCastExpr;
/// \brief Matches a const_cast expression.
///
@@ -2000,9 +2084,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// const int &r(n);
/// int* p = const_cast<int*>(&r);
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- CXXConstCastExpr> cxxConstCastExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXConstCastExpr>
+ cxxConstCastExpr;
/// \brief Matches a C-style cast expression.
///
@@ -2010,9 +2093,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// \code
/// int i = (int) 2.2f;
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- CStyleCastExpr> cStyleCastExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, CStyleCastExpr>
+ cStyleCastExpr;
/// \brief Matches explicit cast expressions.
///
@@ -2035,17 +2117,15 @@ const internal::VariadicDynCastAllOfMatcher<
/// \code
/// long ell = 42;
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- ExplicitCastExpr> explicitCastExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, ExplicitCastExpr>
+ explicitCastExpr;
/// \brief Matches the implicit cast nodes of Clang's AST.
///
/// This matches many different places, including function call return value
/// eliding, as well as any type conversions.
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- ImplicitCastExpr> implicitCastExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, ImplicitCastExpr>
+ implicitCastExpr;
/// \brief Matches any cast nodes of Clang's AST.
///
@@ -2060,7 +2140,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// int i = (0);
/// int k = 0;
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<Stmt, CastExpr> castExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, CastExpr> castExpr;
/// \brief Matches functional cast expressions
///
@@ -2070,9 +2150,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CastExpr> castExpr;
/// Foo g = (Foo) bar;
/// Foo h = Foo(bar);
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- CXXFunctionalCastExpr> cxxFunctionalCastExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXFunctionalCastExpr>
+ cxxFunctionalCastExpr;
/// \brief Matches functional cast expressions having N != 1 arguments
///
@@ -2080,9 +2159,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// \code
/// Foo h = Foo(bar, bar);
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- CXXTemporaryObjectExpr> cxxTemporaryObjectExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTemporaryObjectExpr>
+ cxxTemporaryObjectExpr;
/// \brief Matches predefined identifier expressions [C99 6.4.2.2].
///
@@ -2090,9 +2168,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// \code
/// printf("%s", __func__);
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- PredefinedExpr> predefinedExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, PredefinedExpr>
+ predefinedExpr;
/// \brief Matches C99 designated initializer expressions [C99 6.7.8].
///
@@ -2100,9 +2177,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// \code
/// point ptarray[10] = { [2].y = 1.0, [0].x = 1.0 };
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- DesignatedInitExpr> designatedInitExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, DesignatedInitExpr>
+ designatedInitExpr;
/// \brief Matches designated initializer expressions that contain
/// a specific number of designators.
@@ -2120,13 +2196,13 @@ AST_MATCHER_P(DesignatedInitExpr, designatorCountIs, unsigned, N) {
}
/// \brief Matches \c QualTypes in the clang AST.
-const internal::VariadicAllOfMatcher<QualType> qualType;
+extern const internal::VariadicAllOfMatcher<QualType> qualType;
/// \brief Matches \c Types in the clang AST.
-const internal::VariadicAllOfMatcher<Type> type;
+extern const internal::VariadicAllOfMatcher<Type> type;
/// \brief Matches \c TypeLocs in the clang AST.
-const internal::VariadicAllOfMatcher<TypeLoc> typeLoc;
+extern const internal::VariadicAllOfMatcher<TypeLoc> typeLoc;
/// \brief Matches if any of the given matchers matches.
///
@@ -2147,23 +2223,23 @@ const internal::VariadicAllOfMatcher<TypeLoc> typeLoc;
/// \c b.
///
/// Usable as: Any Matcher
-const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> eachOf = {
- internal::DynTypedMatcher::VO_EachOf
-};
+extern const internal::VariadicOperatorMatcherFunc<
+ 2, std::numeric_limits<unsigned>::max()>
+ eachOf;
/// \brief Matches if any of the given matchers matches.
///
/// Usable as: Any Matcher
-const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> anyOf = {
- internal::DynTypedMatcher::VO_AnyOf
-};
+extern const internal::VariadicOperatorMatcherFunc<
+ 2, std::numeric_limits<unsigned>::max()>
+ anyOf;
/// \brief Matches if all given matchers match.
///
/// Usable as: Any Matcher
-const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> allOf = {
- internal::DynTypedMatcher::VO_AllOf
-};
+extern const internal::VariadicOperatorMatcherFunc<
+ 2, std::numeric_limits<unsigned>::max()>
+ allOf;
/// \brief Matches sizeof (C99), alignof (C++11) and vec_step (OpenCL)
///
@@ -2174,9 +2250,9 @@ const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> allOf = {
/// \endcode
/// unaryExprOrTypeTraitExpr()
/// matches \c sizeof(x) and \c alignof(x)
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- UnaryExprOrTypeTraitExpr> unaryExprOrTypeTraitExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt,
+ UnaryExprOrTypeTraitExpr>
+ unaryExprOrTypeTraitExpr;
/// \brief Matches unary expressions that have a specific type of argument.
///
@@ -2252,9 +2328,9 @@ inline internal::Matcher<NamedDecl> hasName(const std::string &Name) {
/// \code
/// anyOf(hasName(a), hasName(b), hasName(c))
/// \endcode
-const internal::VariadicFunction<internal::Matcher<NamedDecl>, StringRef,
- internal::hasAnyNameFunc>
- hasAnyName = {};
+extern const internal::VariadicFunction<internal::Matcher<NamedDecl>, StringRef,
+ internal::hasAnyNameFunc>
+ hasAnyName;
/// \brief Matches NamedDecl nodes whose fully qualified names contain
/// a substring matched by the given RegExp.
@@ -2403,8 +2479,7 @@ AST_MATCHER(CXXRecordDecl, isLambda) {
/// casts and paren casts. If you are matching with expr then you should
/// probably consider using ignoringParenImpCasts like:
/// has(ignoringParenImpCasts(expr())).
-const internal::ArgumentAdaptingMatcherFunc<internal::HasMatcher>
-LLVM_ATTRIBUTE_UNUSED has = {};
+extern const internal::ArgumentAdaptingMatcherFunc<internal::HasMatcher> has;
/// \brief Matches AST nodes that have descendant AST nodes that match the
/// provided matcher.
@@ -2420,8 +2495,9 @@ LLVM_ATTRIBUTE_UNUSED has = {};
/// DescendantT must be an AST base type.
///
/// Usable as: Any Matcher
-const internal::ArgumentAdaptingMatcherFunc<internal::HasDescendantMatcher>
-LLVM_ATTRIBUTE_UNUSED hasDescendant = {};
+extern const internal::ArgumentAdaptingMatcherFunc<
+ internal::HasDescendantMatcher>
+ hasDescendant;
/// \brief Matches AST nodes that have child AST nodes that match the
/// provided matcher.
@@ -2440,8 +2516,8 @@ LLVM_ATTRIBUTE_UNUSED hasDescendant = {};
/// matches instead of only on the first one.
///
/// Usable as: Any Matcher
-const internal::ArgumentAdaptingMatcherFunc<internal::ForEachMatcher>
-LLVM_ATTRIBUTE_UNUSED forEach = {};
+extern const internal::ArgumentAdaptingMatcherFunc<internal::ForEachMatcher>
+ forEach;
/// \brief Matches AST nodes that have descendant AST nodes that match the
/// provided matcher.
@@ -2469,8 +2545,9 @@ LLVM_ATTRIBUTE_UNUSED forEach = {};
/// \endcode
///
/// Usable as: Any Matcher
-const internal::ArgumentAdaptingMatcherFunc<internal::ForEachDescendantMatcher>
-LLVM_ATTRIBUTE_UNUSED forEachDescendant = {};
+extern const internal::ArgumentAdaptingMatcherFunc<
+ internal::ForEachDescendantMatcher>
+ forEachDescendant;
/// \brief Matches if the node or any descendant matches.
///
@@ -2503,11 +2580,11 @@ internal::Matcher<T> findAll(const internal::Matcher<T> &Matcher) {
/// \c compoundStmt(hasParent(ifStmt())) matches "{ int x = 43; }".
///
/// Usable as: Any Matcher
-const internal::ArgumentAdaptingMatcherFunc<
+extern const internal::ArgumentAdaptingMatcherFunc<
internal::HasParentMatcher,
internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>,
internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>>
- LLVM_ATTRIBUTE_UNUSED hasParent = {};
+ hasParent;
/// \brief Matches AST nodes that have an ancestor that matches the provided
/// matcher.
@@ -2520,11 +2597,11 @@ const internal::ArgumentAdaptingMatcherFunc<
/// \c expr(integerLiteral(hasAncestor(ifStmt()))) matches \c 42, but not 43.
///
/// Usable as: Any Matcher
-const internal::ArgumentAdaptingMatcherFunc<
+extern const internal::ArgumentAdaptingMatcherFunc<
internal::HasAncestorMatcher,
internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>,
internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>>
- LLVM_ATTRIBUTE_UNUSED hasAncestor = {};
+ hasAncestor;
/// \brief Matches if the provided matcher does not match.
///
@@ -2535,9 +2612,7 @@ const internal::ArgumentAdaptingMatcherFunc<
/// \endcode
///
/// Usable as: Any Matcher
-const internal::VariadicOperatorMatcherFunc<1, 1> unless = {
- internal::DynTypedMatcher::VO_UnaryNot
-};
+extern const internal::VariadicOperatorMatcherFunc<1, 1> unless;
/// \brief Matches a node if the declaration associated with that node
/// matches the given matcher.
@@ -2549,8 +2624,21 @@ const internal::VariadicOperatorMatcherFunc<1, 1> unless = {
/// - for CXXConstructExpr, the declaration of the constructor
/// - for CXXNewExpr, the declaration of the operator new
///
-/// Also usable as Matcher<T> for any T supporting the getDecl() member
-/// function. e.g. various subtypes of clang::Type and various expressions.
+/// For type nodes, hasDeclaration will generally match the declaration of the
+/// sugared type. Given
+/// \code
+/// class X {};
+/// typedef X Y;
+/// Y y;
+/// \endcode
+/// in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+/// typedefDecl. A common use case is to match the underlying, desugared type.
+/// This can be achieved by using the hasUnqualifiedDesugaredType matcher:
+/// \code
+/// varDecl(hasType(hasUnqualifiedDesugaredType(
+/// recordType(hasDeclaration(decl())))))
+/// \endcode
+/// In this matcher, the decl will match the CXXRecordDecl of class X.
///
/// Usable as: Matcher<AddrLabelExpr>, Matcher<CallExpr>,
/// Matcher<CXXConstructExpr>, Matcher<CXXNewExpr>, Matcher<DeclRefExpr>,
@@ -2843,7 +2931,7 @@ AST_MATCHER_P_OVERLOAD(QualType, pointsTo, internal::Matcher<Decl>,
/// class A {};
/// using B = A;
/// \endcode
-/// The matcher type(hasUniqualifeidDesugaredType(recordType())) matches
+/// The matcher type(hasUnqualifeidDesugaredType(recordType())) matches
/// both B and A.
AST_MATCHER_P(Type, hasUnqualifiedDesugaredType, internal::Matcher<Type>,
InnerMatcher) {
@@ -3237,7 +3325,7 @@ AST_MATCHER_P(CXXConstructorDecl, hasAnyConstructorInitializer,
/// with forField matching foo_
AST_MATCHER_P(CXXCtorInitializer, forField,
internal::Matcher<FieldDecl>, InnerMatcher) {
- const FieldDecl *NodeAsDecl = Node.getMember();
+ const FieldDecl *NodeAsDecl = Node.getAnyMember();
return (NodeAsDecl != nullptr &&
InnerMatcher.matches(*NodeAsDecl, Finder, Builder));
}
@@ -3492,16 +3580,21 @@ AST_MATCHER_P(FunctionDecl, returns,
return InnerMatcher.matches(Node.getReturnType(), Finder, Builder);
}
-/// \brief Matches extern "C" function declarations.
+/// \brief Matches extern "C" function or variable declarations.
///
/// Given:
/// \code
/// extern "C" void f() {}
/// extern "C" { void g() {} }
/// void h() {}
+/// extern "C" int x = 1;
+/// extern "C" int y = 2;
+/// int z = 3;
/// \endcode
/// functionDecl(isExternC())
-/// matches the declaration of f and g, but not the declaration h
+/// matches the declaration of f and g, but not the declaration of h.
+/// varDecl(isExternC())
+/// matches the declaration of x and y, but not the declaration of z.
AST_POLYMORPHIC_MATCHER(isExternC, AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
VarDecl)) {
return Node.isExternC();
@@ -3947,7 +4040,6 @@ AST_MATCHER_P(UnaryOperator, hasUnaryOperand,
/// \code
/// int a = b ?: 1;
/// \endcode
-
AST_POLYMORPHIC_MATCHER_P(hasSourceExpression,
AST_POLYMORPHIC_SUPPORTED_TYPES(CastExpr,
OpaqueValueExpr),
@@ -4067,11 +4159,19 @@ AST_MATCHER_P(AbstractConditionalOperator, hasFalseExpression,
/// extern int vb; // Doesn't match, as it doesn't define the variable.
/// void fa() {}
/// void fb(); // Doesn't match, as it has no body.
+/// @interface X
+/// - (void)ma; // Doesn't match, interface is declaration.
+/// @end
+/// @implementation X
+/// - (void)ma {}
+/// @end
/// \endcode
///
-/// Usable as: Matcher<TagDecl>, Matcher<VarDecl>, Matcher<FunctionDecl>
+/// Usable as: Matcher<TagDecl>, Matcher<VarDecl>, Matcher<FunctionDecl>,
+/// Matcher<ObjCMethodDecl>
AST_POLYMORPHIC_MATCHER(isDefinition,
AST_POLYMORPHIC_SUPPORTED_TYPES(TagDecl, VarDecl,
+ ObjCMethodDecl,
FunctionDecl)) {
return Node.isThisDeclarationADefinition();
}
@@ -4638,6 +4738,9 @@ AST_MATCHER(Type, voidType) {
return Node.isVoidType();
}
+template <typename NodeType>
+using AstTypeMatcher = internal::VariadicDynCastAllOfMatcher<Type, NodeType>;
+
/// \brief Matches builtin Types.
///
/// Given
@@ -4650,7 +4753,7 @@ AST_MATCHER(Type, voidType) {
/// \endcode
/// builtinType()
/// matches "int b", "float c" and "bool d"
-AST_TYPE_MATCHER(BuiltinType, builtinType);
+extern const AstTypeMatcher<BuiltinType> builtinType;
/// \brief Matches all kinds of arrays.
///
@@ -4662,7 +4765,7 @@ AST_TYPE_MATCHER(BuiltinType, builtinType);
/// \endcode
/// arrayType()
/// matches "int a[]", "int b[4]" and "int c[a[0]]";
-AST_TYPE_MATCHER(ArrayType, arrayType);
+extern const AstTypeMatcher<ArrayType> arrayType;
/// \brief Matches C99 complex types.
///
@@ -4672,7 +4775,7 @@ AST_TYPE_MATCHER(ArrayType, arrayType);
/// \endcode
/// complexType()
/// matches "_Complex float f"
-AST_TYPE_MATCHER(ComplexType, complexType);
+extern const AstTypeMatcher<ComplexType> complexType;
/// \brief Matches any real floating-point type (float, double, long double).
///
@@ -4700,9 +4803,9 @@ AST_MATCHER(Type, realFloatingPointType) {
/// matches "int b[7]"
///
/// Usable as: Matcher<ArrayType>, Matcher<ComplexType>
-AST_TYPELOC_TRAVERSE_MATCHER(hasElementType, getElement,
- AST_POLYMORPHIC_SUPPORTED_TYPES(ArrayType,
- ComplexType));
+AST_TYPELOC_TRAVERSE_MATCHER_DECL(hasElementType, getElement,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(ArrayType,
+ ComplexType));
/// \brief Matches C arrays with a specified constant size.
///
@@ -4716,7 +4819,7 @@ AST_TYPELOC_TRAVERSE_MATCHER(hasElementType, getElement,
/// \endcode
/// constantArrayType()
/// matches "int a[2]"
-AST_TYPE_MATCHER(ConstantArrayType, constantArrayType);
+extern const AstTypeMatcher<ConstantArrayType> constantArrayType;
/// \brief Matches nodes that have the specified size.
///
@@ -4751,7 +4854,7 @@ AST_POLYMORPHIC_MATCHER_P(hasSize,
/// \endcode
/// dependentSizedArrayType
/// matches "T data[Size]"
-AST_TYPE_MATCHER(DependentSizedArrayType, dependentSizedArrayType);
+extern const AstTypeMatcher<DependentSizedArrayType> dependentSizedArrayType;
/// \brief Matches C arrays with unspecified size.
///
@@ -4763,7 +4866,7 @@ AST_TYPE_MATCHER(DependentSizedArrayType, dependentSizedArrayType);
/// \endcode
/// incompleteArrayType()
/// matches "int a[]" and "int c[]"
-AST_TYPE_MATCHER(IncompleteArrayType, incompleteArrayType);
+extern const AstTypeMatcher<IncompleteArrayType> incompleteArrayType;
/// \brief Matches C arrays with a specified size that is not an
/// integer-constant-expression.
@@ -4778,7 +4881,7 @@ AST_TYPE_MATCHER(IncompleteArrayType, incompleteArrayType);
/// \endcode
/// variableArrayType()
/// matches "int c[a[0]]"
-AST_TYPE_MATCHER(VariableArrayType, variableArrayType);
+extern const AstTypeMatcher<VariableArrayType> variableArrayType;
/// \brief Matches \c VariableArrayType nodes that have a specific size
/// expression.
@@ -4805,7 +4908,7 @@ AST_MATCHER_P(VariableArrayType, hasSizeExpr,
/// \endcode
/// atomicType()
/// matches "_Atomic(int) i"
-AST_TYPE_MATCHER(AtomicType, atomicType);
+extern const AstTypeMatcher<AtomicType> atomicType;
/// \brief Matches atomic types with a specific value type.
///
@@ -4818,8 +4921,8 @@ AST_TYPE_MATCHER(AtomicType, atomicType);
/// matches "_Atomic(int) i"
///
/// Usable as: Matcher<AtomicType>
-AST_TYPELOC_TRAVERSE_MATCHER(hasValueType, getValue,
- AST_POLYMORPHIC_SUPPORTED_TYPES(AtomicType));
+AST_TYPELOC_TRAVERSE_MATCHER_DECL(hasValueType, getValue,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(AtomicType));
/// \brief Matches types nodes representing C++11 auto types.
///
@@ -4831,7 +4934,7 @@ AST_TYPELOC_TRAVERSE_MATCHER(hasValueType, getValue,
/// \endcode
/// autoType()
/// matches "auto n" and "auto i"
-AST_TYPE_MATCHER(AutoType, autoType);
+extern const AstTypeMatcher<AutoType> autoType;
/// \brief Matches \c AutoType nodes where the deduced type is a specific type.
///
@@ -4859,7 +4962,7 @@ AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType,
/// \endcode
/// functionType()
/// matches "int (*f)(int)" and the type of "g".
-AST_TYPE_MATCHER(FunctionType, functionType);
+extern const AstTypeMatcher<FunctionType> functionType;
/// \brief Matches \c FunctionProtoType nodes.
///
@@ -4871,7 +4974,7 @@ AST_TYPE_MATCHER(FunctionType, functionType);
/// functionProtoType()
/// matches "int (*f)(int)" and the type of "g" in C++ mode.
/// In C mode, "g" is not matched because it does not contain a prototype.
-AST_TYPE_MATCHER(FunctionProtoType, functionProtoType);
+extern const AstTypeMatcher<FunctionProtoType> functionProtoType;
/// \brief Matches \c ParenType nodes.
///
@@ -4883,7 +4986,7 @@ AST_TYPE_MATCHER(FunctionProtoType, functionProtoType);
///
/// \c varDecl(hasType(pointsTo(parenType()))) matches \c ptr_to_array but not
/// \c array_of_ptrs.
-AST_TYPE_MATCHER(ParenType, parenType);
+extern const AstTypeMatcher<ParenType> parenType;
/// \brief Matches \c ParenType nodes where the inner type is a specific type.
///
@@ -4904,7 +5007,7 @@ AST_TYPE_TRAVERSE_MATCHER(innerType, getInnerType,
/// "void (^)(int)".
///
/// The \c pointee is always required to be a \c FunctionType.
-AST_TYPE_MATCHER(BlockPointerType, blockPointerType);
+extern const AstTypeMatcher<BlockPointerType> blockPointerType;
/// \brief Matches member pointer types.
/// Given
@@ -4914,7 +5017,7 @@ AST_TYPE_MATCHER(BlockPointerType, blockPointerType);
/// \endcode
/// memberPointerType()
/// matches "A::* ptr"
-AST_TYPE_MATCHER(MemberPointerType, memberPointerType);
+extern const AstTypeMatcher<MemberPointerType> memberPointerType;
/// \brief Matches pointer types, but does not match Objective-C object pointer
/// types.
@@ -4931,7 +5034,7 @@ AST_TYPE_MATCHER(MemberPointerType, memberPointerType);
/// \endcode
/// pointerType()
/// matches "int *a", but does not match "Foo *f".
-AST_TYPE_MATCHER(PointerType, pointerType);
+extern const AstTypeMatcher<PointerType> pointerType;
/// \brief Matches an Objective-C object pointer type, which is different from
/// a pointer type, despite being syntactically similar.
@@ -4946,7 +5049,7 @@ AST_TYPE_MATCHER(PointerType, pointerType);
/// \endcode
/// pointerType()
/// matches "Foo *f", but does not match "int *a".
-AST_TYPE_MATCHER(ObjCObjectPointerType, objcObjectPointerType);
+extern const AstTypeMatcher<ObjCObjectPointerType> objcObjectPointerType;
/// \brief Matches both lvalue and rvalue reference types.
///
@@ -4962,7 +5065,7 @@ AST_TYPE_MATCHER(ObjCObjectPointerType, objcObjectPointerType);
/// \endcode
///
/// \c referenceType() matches the types of \c b, \c c, \c d, \c e, and \c f.
-AST_TYPE_MATCHER(ReferenceType, referenceType);
+extern const AstTypeMatcher<ReferenceType> referenceType;
/// \brief Matches lvalue reference types.
///
@@ -4979,7 +5082,7 @@ AST_TYPE_MATCHER(ReferenceType, referenceType);
///
/// \c lValueReferenceType() matches the types of \c b, \c d, and \c e. \c e is
/// matched since the type is deduced as int& by reference collapsing rules.
-AST_TYPE_MATCHER(LValueReferenceType, lValueReferenceType);
+extern const AstTypeMatcher<LValueReferenceType> lValueReferenceType;
/// \brief Matches rvalue reference types.
///
@@ -4996,7 +5099,7 @@ AST_TYPE_MATCHER(LValueReferenceType, lValueReferenceType);
///
/// \c rValueReferenceType() matches the types of \c c and \c f. \c e is not
/// matched as it is deduced to int& by reference collapsing rules.
-AST_TYPE_MATCHER(RValueReferenceType, rValueReferenceType);
+extern const AstTypeMatcher<RValueReferenceType> rValueReferenceType;
/// \brief Narrows PointerType (and similar) matchers to those where the
/// \c pointee matches a given matcher.
@@ -5012,11 +5115,10 @@ AST_TYPE_MATCHER(RValueReferenceType, rValueReferenceType);
///
/// Usable as: Matcher<BlockPointerType>, Matcher<MemberPointerType>,
/// Matcher<PointerType>, Matcher<ReferenceType>
-AST_TYPELOC_TRAVERSE_MATCHER(pointee, getPointee,
- AST_POLYMORPHIC_SUPPORTED_TYPES(BlockPointerType,
- MemberPointerType,
- PointerType,
- ReferenceType));
+AST_TYPELOC_TRAVERSE_MATCHER_DECL(
+ pointee, getPointee,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(BlockPointerType, MemberPointerType,
+ PointerType, ReferenceType));
/// \brief Matches typedef types.
///
@@ -5026,7 +5128,7 @@ AST_TYPELOC_TRAVERSE_MATCHER(pointee, getPointee,
/// \endcode
/// typedefType()
/// matches "typedef int X"
-AST_TYPE_MATCHER(TypedefType, typedefType);
+extern const AstTypeMatcher<TypedefType> typedefType;
/// \brief Matches enum types.
///
@@ -5041,7 +5143,7 @@ AST_TYPE_MATCHER(TypedefType, typedefType);
//
/// \c enumType() matches the type of the variable declarations of both \c c and
/// \c s.
-AST_TYPE_MATCHER(EnumType, enumType);
+extern const AstTypeMatcher<EnumType> enumType;
/// \brief Matches template specialization types.
///
@@ -5056,7 +5158,8 @@ AST_TYPE_MATCHER(EnumType, enumType);
///
/// \c templateSpecializationType() matches the type of the explicit
/// instantiation in \c A and the type of the variable declaration in \c B.
-AST_TYPE_MATCHER(TemplateSpecializationType, templateSpecializationType);
+extern const AstTypeMatcher<TemplateSpecializationType>
+ templateSpecializationType;
/// \brief Matches types nodes representing unary type transformations.
///
@@ -5066,7 +5169,7 @@ AST_TYPE_MATCHER(TemplateSpecializationType, templateSpecializationType);
/// \endcode
/// unaryTransformType()
/// matches "__underlying_type(T)"
-AST_TYPE_MATCHER(UnaryTransformType, unaryTransformType);
+extern const AstTypeMatcher<UnaryTransformType> unaryTransformType;
/// \brief Matches record types (e.g. structs, classes).
///
@@ -5081,7 +5184,22 @@ AST_TYPE_MATCHER(UnaryTransformType, unaryTransformType);
///
/// \c recordType() matches the type of the variable declarations of both \c c
/// and \c s.
-AST_TYPE_MATCHER(RecordType, recordType);
+extern const AstTypeMatcher<RecordType> recordType;
+
+/// \brief Matches tag types (record and enum types).
+///
+/// Given
+/// \code
+/// enum E {};
+/// class C {};
+///
+/// E e;
+/// C c;
+/// \endcode
+///
+/// \c tagType() matches the type of the variable declarations of both \c e
+/// and \c c.
+extern const AstTypeMatcher<TagType> tagType;
/// \brief Matches types specified with an elaborated type keyword or with a
/// qualified name.
@@ -5101,7 +5219,7 @@ AST_TYPE_MATCHER(RecordType, recordType);
///
/// \c elaboratedType() matches the type of the variable declarations of both
/// \c c and \c d.
-AST_TYPE_MATCHER(ElaboratedType, elaboratedType);
+extern const AstTypeMatcher<ElaboratedType> elaboratedType;
/// \brief Matches ElaboratedTypes whose qualifier, a NestedNameSpecifier,
/// matches \c InnerMatcher if the qualifier exists.
@@ -5158,7 +5276,8 @@ AST_MATCHER_P(ElaboratedType, namesType, internal::Matcher<QualType>,
/// \endcode
///
/// \c substTemplateTypeParmType() matches the type of 't' but not '1'
-AST_TYPE_MATCHER(SubstTemplateTypeParmType, substTemplateTypeParmType);
+extern const AstTypeMatcher<SubstTemplateTypeParmType>
+ substTemplateTypeParmType;
/// \brief Matches template type parameter substitutions that have a replacement
/// type that matches the provided matcher.
@@ -5183,7 +5302,7 @@ AST_TYPE_TRAVERSE_MATCHER(
/// \code
/// template <typename T> void f(int i);
/// \endcode
-AST_TYPE_MATCHER(TemplateTypeParmType, templateTypeParmType);
+extern const AstTypeMatcher<TemplateTypeParmType> templateTypeParmType;
/// \brief Matches injected class name types.
///
@@ -5195,7 +5314,7 @@ AST_TYPE_MATCHER(TemplateTypeParmType, templateTypeParmType);
/// void g(S<T> s);
/// };
/// \endcode
-AST_TYPE_MATCHER(InjectedClassNameType, injectedClassNameType);
+extern const AstTypeMatcher<InjectedClassNameType> injectedClassNameType;
/// \brief Matches decayed type
/// Example matches i[] in declaration of f.
@@ -5207,7 +5326,7 @@ AST_TYPE_MATCHER(InjectedClassNameType, injectedClassNameType);
/// i[1] = 0;
/// }
/// \endcode
-AST_TYPE_MATCHER(DecayedType, decayedType);
+extern const AstTypeMatcher<DecayedType> decayedType;
/// \brief Matches the decayed type, whos decayed type matches \c InnerMatcher
AST_MATCHER_P(DecayedType, hasDecayedType, internal::Matcher<QualType>,
@@ -5248,11 +5367,12 @@ AST_MATCHER_P(Decl, hasDeclContext, internal::Matcher<Decl>, InnerMatcher) {
/// \endcode
/// nestedNameSpecifier()
/// matches "ns::" and both "A::"
-const internal::VariadicAllOfMatcher<NestedNameSpecifier> nestedNameSpecifier;
+extern const internal::VariadicAllOfMatcher<NestedNameSpecifier>
+ nestedNameSpecifier;
/// \brief Same as \c nestedNameSpecifier but matches \c NestedNameSpecifierLoc.
-const internal::VariadicAllOfMatcher<
- NestedNameSpecifierLoc> nestedNameSpecifierLoc;
+extern const internal::VariadicAllOfMatcher<NestedNameSpecifierLoc>
+ nestedNameSpecifierLoc;
/// \brief Matches \c NestedNameSpecifierLocs for which the given inner
/// NestedNameSpecifier-matcher matches.
@@ -5605,17 +5725,14 @@ AST_MATCHER_P(ReturnStmt, hasReturnValue, internal::Matcher<Expr>,
return false;
}
-
/// \brief Matches CUDA kernel call expression.
///
/// Example matches,
/// \code
/// kernel<<<i,j>>>();
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<
- Stmt,
- CUDAKernelCallExpr> cudaKernelCallExpr;
-
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, CUDAKernelCallExpr>
+ cudaKernelCallExpr;
/// \brief Matches expressions that resolve to a null pointer constant, such as
/// GNU's __null, C++11's nullptr, or C's NULL macro.
@@ -5700,7 +5817,54 @@ AST_MATCHER(NamedDecl, hasExternalFormalLinkage) {
return Node.hasExternalFormalLinkage();
}
-} // end namespace ast_matchers
-} // end namespace clang
+/// \brief Matches a declaration that has default arguments.
+///
+/// Example matches y (matcher = parmVarDecl(hasDefaultArgument()))
+/// \code
+/// void x(int val) {}
+/// void y(int val = 0) {}
+/// \endcode
+AST_MATCHER(ParmVarDecl, hasDefaultArgument) {
+ return Node.hasDefaultArg();
+}
+
+/// \brief Matches array new expressions.
+///
+/// Given:
+/// \code
+/// MyClass *p1 = new MyClass[10];
+/// \endcode
+/// cxxNewExpr(isArray())
+/// matches the expression 'new MyClass[10]'.
+AST_MATCHER(CXXNewExpr, isArray) {
+ return Node.isArray();
+}
+
+/// \brief Matches array new expressions with a given array size.
+///
+/// Given:
+/// \code
+/// MyClass *p1 = new MyClass[10];
+/// \endcode
+/// cxxNewExpr(hasArraySize(intgerLiteral(equals(10))))
+/// matches the expression 'new MyClass[10]'.
+AST_MATCHER_P(CXXNewExpr, hasArraySize, internal::Matcher<Expr>, InnerMatcher) {
+ return Node.isArray() &&
+ InnerMatcher.matches(*Node.getArraySize(), Finder, Builder);
+}
+
+/// \brief Matches a class declaration that is defined.
+///
+/// Example matches x (matcher = cxxRecordDecl(hasDefinition()))
+/// \code
+/// class x {};
+/// class y;
+/// \endcode
+AST_MATCHER(CXXRecordDecl, hasDefinition) {
+ return Node.hasDefinition();
+}
+
+} // namespace ast_matchers
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_ASTMATCHERS_ASTMATCHERS_H
diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
index bc75e807ced98..8bd61a76e1852 100644
--- a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -1,4 +1,4 @@
-//===--- ASTMatchersInternal.h - Structural query framework -----*- C++ -*-===//
+//===- ASTMatchersInternal.h - Structural query framework -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -38,23 +38,42 @@
#include "clang/AST/ASTTypeTraits.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
-#include "clang/AST/ExprObjC.h"
+#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/Stmt.h"
-#include "clang/AST/StmtCXX.h"
-#include "clang/AST/StmtObjC.h"
+#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/OperatorKinds.h"
+#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/ManagedStatic.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
#include <map>
#include <string>
+#include <tuple>
+#include <type_traits>
+#include <utility>
#include <vector>
namespace clang {
+
+class ASTContext;
+
namespace ast_matchers {
class BoundNodes;
@@ -158,7 +177,7 @@ public:
/// Note that we're using std::map here, as for memoization:
/// - we need a comparison operator
/// - we need an assignment operator
- typedef std::map<std::string, ast_type_traits::DynTypedNode> IDToNodeMap;
+ using IDToNodeMap = std::map<std::string, ast_type_traits::DynTypedNode>;
const IDToNodeMap &getMap() const {
return NodeMap;
@@ -188,7 +207,7 @@ public:
/// BoundNodesTree.
class Visitor {
public:
- virtual ~Visitor() {}
+ virtual ~Visitor() = default;
/// \brief Called multiple times during a single call to VisitMatches(...).
///
@@ -248,7 +267,7 @@ class ASTMatchFinder;
class DynMatcherInterface
: public llvm::ThreadSafeRefCountedBase<DynMatcherInterface> {
public:
- virtual ~DynMatcherInterface() {}
+ virtual ~DynMatcherInterface() = default;
/// \brief Returns true if \p DynNode can be matched.
///
@@ -317,26 +336,29 @@ 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>()),
+ : SupportedKind(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()),
RestrictKind(SupportedKind), Implementation(Implementation) {}
/// \brief Construct from a variadic function.
enum VariadicOperator {
/// \brief Matches nodes for which all provided matchers match.
VO_AllOf,
+
/// \brief Matches nodes for which at least one of the provided matchers
/// matches.
VO_AnyOf,
+
/// \brief Matches nodes for which at least one of the provided matchers
/// matches, but doesn't stop at the first match.
VO_EachOf,
+
/// \brief Matches nodes that do not match the provided matcher.
///
/// Uses the variadic matcher interface, but fails if
/// InnerMatchers.size() != 1.
VO_UnaryNot
};
+
static DynTypedMatcher
constructVariadic(VariadicOperator Op,
ast_type_traits::ASTNodeKind SupportedKind,
@@ -382,7 +404,7 @@ public:
/// 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;
+ using MatcherIDType = std::pair<ast_type_traits::ASTNodeKind, uint64_t>;
MatcherIDType getID() const {
/// FIXME: Document the requirements this imposes on matcher
/// implementations (no new() implementation_ during a Matches()).
@@ -428,13 +450,12 @@ private:
DynTypedMatcher(ast_type_traits::ASTNodeKind SupportedKind,
ast_type_traits::ASTNodeKind RestrictKind,
IntrusiveRefCntPtr<DynMatcherInterface> Implementation)
- : AllowBind(false),
- SupportedKind(SupportedKind),
- RestrictKind(RestrictKind),
+ : SupportedKind(SupportedKind), RestrictKind(RestrictKind),
Implementation(std::move(Implementation)) {}
- bool AllowBind;
+ bool AllowBind = false;
ast_type_traits::ASTNodeKind SupportedKind;
+
/// \brief A potentially stricter node kind.
///
/// It allows to perform implicit and dynamic cast of matchers without
@@ -545,6 +566,7 @@ public:
private:
// For Matcher<T> <=> Matcher<U> conversions.
template <typename U> friend class Matcher;
+
// For DynTypedMatcher::unconditionalConvertTo<T>.
friend class DynTypedMatcher;
@@ -618,8 +640,8 @@ bool matchesFirstInPointerRange(const MatcherT &Matcher, IteratorT Start,
// Metafunction to determine if type T has a member called getDecl.
template <typename Ty>
class has_getDecl {
- typedef char yes[1];
- typedef char no[2];
+ using yes = char[1];
+ using no = char[2];
template <typename Inner>
static yes& test(Inner *I, decltype(I->getDecl()) * = nullptr);
@@ -728,48 +750,94 @@ public:
}
private:
- /// \brief If getDecl exists as a member of U, returns whether the inner
- /// matcher matches Node.getDecl().
- template <typename U>
- bool matchesSpecialized(
- const U &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
- typename std::enable_if<has_getDecl<U>::value, int>::type = 0) const {
- return matchesDecl(Node.getDecl(), Finder, Builder);
- }
-
- /// \brief Extracts the TagDecl of a QualType and returns whether the inner
- /// matcher matches on it.
+ /// \brief Forwards to matching on the underlying type of the QualType.
bool matchesSpecialized(const QualType &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const {
if (Node.isNull())
return false;
- if (auto *TD = Node->getAsTagDecl())
- return matchesDecl(TD, Finder, Builder);
- else if (auto *TT = Node->getAs<TypedefType>())
- return matchesDecl(TT->getDecl(), Finder, Builder);
- // Do not use getAs<TemplateTypeParmType> instead of the direct dyn_cast.
- // Calling getAs will return the canonical type, but that type does not
- // store a TemplateTypeParmDecl. We *need* the uncanonical type, if it is
- // available, and using dyn_cast ensures that.
- else if (auto *TTP = dyn_cast<TemplateTypeParmType>(Node.getTypePtr()))
- return matchesDecl(TTP->getDecl(), Finder, Builder);
- else if (auto *OCIT = Node->getAs<ObjCInterfaceType>())
- return matchesDecl(OCIT->getDecl(), Finder, Builder);
- else if (auto *UUT = Node->getAs<UnresolvedUsingType>())
- return matchesDecl(UUT->getDecl(), Finder, Builder);
- else if (auto *ICNT = Node->getAs<InjectedClassNameType>())
- return matchesDecl(ICNT->getDecl(), Finder, Builder);
+ return matchesSpecialized(*Node, Finder, Builder);
+ }
+
+ /// \brief Finds the best declaration for a type and returns whether the inner
+ /// matcher matches on it.
+ bool matchesSpecialized(const Type &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ // DeducedType does not have declarations of its own, so
+ // match the deduced type instead.
+ const Type *EffectiveType = &Node;
+ if (const auto *S = dyn_cast<DeducedType>(&Node)) {
+ EffectiveType = S->getDeducedType().getTypePtrOrNull();
+ if (!EffectiveType)
+ return false;
+ }
+
+ // First, for any types that have a declaration, extract the declaration and
+ // match on it.
+ if (const auto *S = dyn_cast<TagType>(EffectiveType)) {
+ return matchesDecl(S->getDecl(), Finder, Builder);
+ }
+ if (const auto *S = dyn_cast<InjectedClassNameType>(EffectiveType)) {
+ return matchesDecl(S->getDecl(), Finder, Builder);
+ }
+ if (const auto *S = dyn_cast<TemplateTypeParmType>(EffectiveType)) {
+ return matchesDecl(S->getDecl(), Finder, Builder);
+ }
+ if (const auto *S = dyn_cast<TypedefType>(EffectiveType)) {
+ return matchesDecl(S->getDecl(), Finder, Builder);
+ }
+ if (const auto *S = dyn_cast<UnresolvedUsingType>(EffectiveType)) {
+ return matchesDecl(S->getDecl(), Finder, Builder);
+ }
+ if (const auto *S = dyn_cast<ObjCObjectType>(EffectiveType)) {
+ return matchesDecl(S->getInterface(), Finder, Builder);
+ }
+
+ // A SubstTemplateTypeParmType exists solely to mark a type substitution
+ // on the instantiated template. As users usually want to match the
+ // template parameter on the uninitialized template, we can always desugar
+ // one level without loss of expressivness.
+ // For example, given:
+ // template<typename T> struct X { T t; } class A {}; X<A> a;
+ // The following matcher will match, which otherwise would not:
+ // fieldDecl(hasType(pointerType())).
+ if (const auto *S = dyn_cast<SubstTemplateTypeParmType>(EffectiveType)) {
+ return matchesSpecialized(S->getReplacementType(), Finder, Builder);
+ }
+
+ // For template specialization types, we want to match the template
+ // declaration, as long as the type is still dependent, and otherwise the
+ // declaration of the instantiated tag type.
+ if (const auto *S = dyn_cast<TemplateSpecializationType>(EffectiveType)) {
+ if (!S->isTypeAlias() && S->isSugared()) {
+ // If the template is non-dependent, we want to match the instantiated
+ // tag type.
+ // For example, given:
+ // template<typename T> struct X {}; X<int> a;
+ // The following matcher will match, which otherwise would not:
+ // templateSpecializationType(hasDeclaration(cxxRecordDecl())).
+ return matchesSpecialized(*S->desugar(), Finder, Builder);
+ }
+ // If the template is dependent or an alias, match the template
+ // declaration.
+ return matchesDecl(S->getTemplateName().getAsTemplateDecl(), Finder,
+ Builder);
+ }
+
+ // FIXME: We desugar elaborated types. This makes the assumption that users
+ // do never want to match on whether a type is elaborated - there are
+ // arguments for both sides; for now, continue desugaring.
+ if (const auto *S = dyn_cast<ElaboratedType>(EffectiveType)) {
+ return matchesSpecialized(S->desugar(), Finder, Builder);
+ }
return false;
}
- /// \brief Gets the TemplateDecl from a TemplateSpecializationType
- /// and returns whether the inner matches on it.
- bool matchesSpecialized(const TemplateSpecializationType &Node,
- ASTMatchFinder *Finder,
+ /// \brief Extracts the Decl the DeclRefExpr references and returns whether
+ /// the inner matcher matches on it.
+ bool matchesSpecialized(const DeclRefExpr &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const {
- return matchesDecl(Node.getTemplateName().getAsTemplateDecl(),
- Finder, Builder);
+ return matchesDecl(Node.getDecl(), Finder, Builder);
}
/// \brief Extracts the Decl of the callee of a CallExpr and returns whether
@@ -811,6 +879,13 @@ private:
return matchesDecl(Node.getLabel(), Finder, Builder);
}
+ /// \brief Extracts the declaration of a LabelStmt and returns whether the
+ /// inner matcher matches on it.
+ bool matchesSpecialized(const LabelStmt &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ return matchesDecl(Node.getDecl(), Finder, Builder);
+ }
+
/// \brief Returns whether the inner matcher \c Node. Returns false if \c Node
/// is \c NULL.
bool matchesDecl(const Decl *Node, ASTMatchFinder *Finder,
@@ -863,6 +938,7 @@ public:
enum TraversalKind {
/// Will traverse any child nodes.
TK_AsIs,
+
/// Will not traverse implicit casts and parentheses.
TK_IgnoreImplicitCastsAndParentheses
};
@@ -871,6 +947,7 @@ public:
enum BindKind {
/// Stop at the first match and only bind the first match.
BK_First,
+
/// Create results for all combinations of bindings that match.
BK_All
};
@@ -879,11 +956,12 @@ public:
enum AncestorMatchMode {
/// All ancestors.
AMM_All,
+
/// Direct parent only.
AMM_ParentOnly
};
- virtual ~ASTMatchFinder() {}
+ virtual ~ASTMatchFinder() = default;
/// \brief Returns true if the given class is directly or indirectly derived
/// from a base type matching \c base.
@@ -906,7 +984,7 @@ public:
std::is_base_of<TypeLoc, T>::value ||
std::is_base_of<QualType, T>::value,
"unsupported type for recursive matching");
- return matchesChildOf(ast_type_traits::DynTypedNode::create(Node),
+ return matchesChildOf(ast_type_traits::DynTypedNode::create(Node),
Matcher, Builder, Traverse, Bind);
}
@@ -969,17 +1047,17 @@ template <typename... Ts> struct TypeList {}; // Empty sentinel type list.
template <typename T1, typename... Ts> struct TypeList<T1, Ts...> {
/// \brief The first type on the list.
- typedef T1 head;
+ using head = T1;
/// \brief A sublist with the tail. ie everything but the head.
///
/// This type is used to do recursion. TypeList<>/EmptyTypeList indicates the
/// end of the list.
- typedef TypeList<Ts...> tail;
+ using tail = TypeList<Ts...>;
};
/// \brief The empty type list.
-typedef TypeList<> EmptyTypeList;
+using EmptyTypeList = TypeList<>;
/// \brief Helper meta-function to determine if some type \c T is present or
/// a parent type in the list.
@@ -997,8 +1075,9 @@ struct TypeListContainsSuperOf<EmptyTypeList, T> {
/// \brief A "type list" that contains all types.
///
/// Useful for matchers like \c anything and \c unless.
-typedef TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc,
- QualType, Type, TypeLoc, CXXCtorInitializer> AllNodeBaseTypes;
+using AllNodeBaseTypes =
+ TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc, QualType,
+ Type, TypeLoc, CXXCtorInitializer>;
/// \brief Helper meta-function to extract the argument out of a function of
/// type void(Arg).
@@ -1006,20 +1085,22 @@ typedef TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc,
/// See AST_POLYMORPHIC_SUPPORTED_TYPES for details.
template <class T> struct ExtractFunctionArgMeta;
template <class T> struct ExtractFunctionArgMeta<void(T)> {
- typedef T type;
+ using type = T;
};
/// \brief Default type lists for ArgumentAdaptingMatcher matchers.
-typedef AllNodeBaseTypes AdaptativeDefaultFromTypes;
-typedef TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc,
- TypeLoc, QualType> AdaptativeDefaultToTypes;
+using AdaptativeDefaultFromTypes = AllNodeBaseTypes;
+using AdaptativeDefaultToTypes =
+ TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc, TypeLoc,
+ QualType>;
/// \brief All types that are supported by HasDeclarationMatcher above.
-typedef TypeList<CallExpr, CXXConstructExpr, CXXNewExpr, DeclRefExpr, EnumType,
- InjectedClassNameType, LabelStmt, AddrLabelExpr, MemberExpr,
- QualType, RecordType, TagType, TemplateSpecializationType,
- TemplateTypeParmType, TypedefType, UnresolvedUsingType>
- HasDeclarationSupportedTypes;
+using HasDeclarationSupportedTypes =
+ TypeList<CallExpr, CXXConstructExpr, CXXNewExpr, DeclRefExpr, EnumType,
+ ElaboratedType, InjectedClassNameType, LabelStmt, AddrLabelExpr,
+ MemberExpr, QualType, RecordType, TagType,
+ TemplateSpecializationType, TemplateTypeParmType, TypedefType,
+ UnresolvedUsingType>;
/// \brief Converts a \c Matcher<T> to a matcher of desired type \c To by
/// "adapting" a \c To into a \c T.
@@ -1043,7 +1124,7 @@ struct ArgumentAdaptingMatcherFunc {
explicit Adaptor(const Matcher<T> &InnerMatcher)
: InnerMatcher(InnerMatcher) {}
- typedef ToTypes ReturnTypes;
+ using ReturnTypes = ToTypes;
template <typename To> operator Matcher<To>() const {
return Matcher<To>(new ArgumentAdapterT<To, T>(InnerMatcher));
@@ -1080,7 +1161,8 @@ template <template <typename T> class MatcherT,
typename ReturnTypesF = void(AllNodeBaseTypes)>
class PolymorphicMatcherWithParam0 {
public:
- typedef typename ExtractFunctionArgMeta<ReturnTypesF>::type ReturnTypes;
+ using ReturnTypes = typename ExtractFunctionArgMeta<ReturnTypesF>::type;
+
template <typename T>
operator Matcher<T>() const {
static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value,
@@ -1097,7 +1179,7 @@ public:
explicit PolymorphicMatcherWithParam1(const P1 &Param1)
: Param1(Param1) {}
- typedef typename ExtractFunctionArgMeta<ReturnTypesF>::type ReturnTypes;
+ using ReturnTypes = typename ExtractFunctionArgMeta<ReturnTypesF>::type;
template <typename T>
operator Matcher<T>() const {
@@ -1118,7 +1200,7 @@ public:
PolymorphicMatcherWithParam2(const P1 &Param1, const P2 &Param2)
: Param1(Param1), Param2(Param2) {}
- typedef typename ExtractFunctionArgMeta<ReturnTypesF>::type ReturnTypes;
+ using ReturnTypes = typename ExtractFunctionArgMeta<ReturnTypesF>::type;
template <typename T>
operator Matcher<T>() const {
@@ -1137,8 +1219,8 @@ private:
/// This is useful when a matcher syntactically requires a child matcher,
/// but the context doesn't care. See for example: anything().
class TrueMatcher {
- public:
- typedef AllNodeBaseTypes ReturnTypes;
+public:
+ using ReturnTypes = AllNodeBaseTypes;
template <typename T>
operator Matcher<T>() const {
@@ -1184,7 +1266,6 @@ public:
/// ChildT must be an AST base type.
template <typename T, typename ChildT>
class HasMatcher : public WrapperMatcherInterface<T> {
-
public:
explicit HasMatcher(const Matcher<ChildT> &ChildMatcher)
: HasMatcher::WrapperMatcherInterface(ChildMatcher) {}
@@ -1278,7 +1359,7 @@ template<typename T>
BindableMatcher<T> makeAllOfComposite(
ArrayRef<const Matcher<T> *> InnerMatchers) {
// For the size() == 0 case, we return a "true" matcher.
- if (InnerMatchers.size() == 0) {
+ if (InnerMatchers.empty()) {
return BindableMatcher<T>(TrueMatcher());
}
// For the size() == 1 case, we simply return that one matcher.
@@ -1287,7 +1368,8 @@ BindableMatcher<T> makeAllOfComposite(
return BindableMatcher<T>(*InnerMatchers[0]);
}
- typedef llvm::pointee_iterator<const Matcher<T> *const *> PI;
+ using PI = llvm::pointee_iterator<const Matcher<T> *const *>;
+
std::vector<DynTypedMatcher> DynMatchers(PI(InnerMatchers.begin()),
PI(InnerMatchers.end()));
return BindableMatcher<T>(
@@ -1580,12 +1662,13 @@ template <typename InnerTBase,
typename ReturnTypesF>
class TypeTraversePolymorphicMatcher {
private:
- typedef TypeTraversePolymorphicMatcher<InnerTBase, Getter, MatcherImpl,
- ReturnTypesF> Self;
+ using Self = TypeTraversePolymorphicMatcher<InnerTBase, Getter, MatcherImpl,
+ ReturnTypesF>;
+
static Self create(ArrayRef<const Matcher<InnerTBase> *> InnerMatchers);
public:
- typedef typename ExtractFunctionArgMeta<ReturnTypesF>::type ReturnTypes;
+ using ReturnTypes = typename ExtractFunctionArgMeta<ReturnTypesF>::type;
explicit TypeTraversePolymorphicMatcher(
ArrayRef<const Matcher<InnerTBase> *> InnerMatchers)
@@ -1612,6 +1695,7 @@ private:
template <typename Matcher, Matcher (*Func)()> class MemoizedMatcher {
struct Wrapper {
Wrapper() : M(Func()) {}
+
Matcher M;
};
@@ -1657,6 +1741,7 @@ struct NotEqualsBoundNodePredicate {
bool operator()(const internal::BoundNodesMap &Nodes) const {
return Nodes.getNode(ID) != Node;
}
+
std::string ID;
ast_type_traits::DynTypedNode Node;
};
@@ -1712,9 +1797,10 @@ CompoundStmtMatcher<StmtExpr>::get(const StmtExpr &Node) {
return Node.getSubStmt();
}
+} // namespace internal
+
+} // namespace ast_matchers
-} // end namespace internal
-} // end namespace ast_matchers
-} // end namespace clang
+} // namespace clang
#endif // LLVM_CLANG_ASTMATCHERS_ASTMATCHERSINTERNAL_H
diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersMacros.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersMacros.h
index ddc48378e714a..6a48da821a53e 100644
--- a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersMacros.h
+++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersMacros.h
@@ -367,6 +367,27 @@
// FIXME: add a matcher for TypeLoc derived classes using its custom casting
// API (no longer dyn_cast) if/when we need such matching
+#define AST_TYPE_TRAVERSE_MATCHER_DECL(MatcherName, FunctionName, \
+ ReturnTypesF) \
+ namespace internal { \
+ template <typename T> struct TypeMatcher##MatcherName##Getter { \
+ static QualType (T::*value())() const { return &T::FunctionName; } \
+ }; \
+ } \
+ extern const ::clang::ast_matchers::internal:: \
+ TypeTraversePolymorphicMatcher< \
+ QualType, \
+ ::clang::ast_matchers::internal::TypeMatcher##MatcherName##Getter, \
+ ::clang::ast_matchers::internal::TypeTraverseMatcher, \
+ ReturnTypesF>::Func MatcherName
+
+#define AST_TYPE_TRAVERSE_MATCHER_DEF(MatcherName, ReturnTypesF) \
+ const ::clang::ast_matchers::internal::TypeTraversePolymorphicMatcher< \
+ QualType, \
+ ::clang::ast_matchers::internal::TypeMatcher##MatcherName##Getter, \
+ ::clang::ast_matchers::internal::TypeTraverseMatcher, \
+ ReturnTypesF>::Func MatcherName
+
/// \brief AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName) defines
/// the matcher \c MatcherName that can be used to traverse from one \c Type
/// to another.
@@ -386,6 +407,30 @@
::clang::ast_matchers::internal::TypeTraverseMatcher, \
ReturnTypesF>::Func MatcherName
+#define AST_TYPELOC_TRAVERSE_MATCHER_DECL(MatcherName, FunctionName, \
+ ReturnTypesF) \
+ namespace internal { \
+ template <typename T> struct TypeLocMatcher##MatcherName##Getter { \
+ static TypeLoc (T::*value())() const { return &T::FunctionName##Loc; } \
+ }; \
+ } \
+ extern const ::clang::ast_matchers::internal:: \
+ TypeTraversePolymorphicMatcher< \
+ TypeLoc, \
+ ::clang::ast_matchers::internal:: \
+ TypeLocMatcher##MatcherName##Getter, \
+ ::clang::ast_matchers::internal::TypeLocTraverseMatcher, \
+ ReturnTypesF>::Func MatcherName##Loc; \
+ AST_TYPE_TRAVERSE_MATCHER_DECL(MatcherName, FunctionName##Type, ReturnTypesF)
+
+#define AST_TYPELOC_TRAVERSE_MATCHER_DEF(MatcherName, ReturnTypesF) \
+ const ::clang::ast_matchers::internal::TypeTraversePolymorphicMatcher< \
+ TypeLoc, \
+ ::clang::ast_matchers::internal::TypeLocMatcher##MatcherName##Getter, \
+ ::clang::ast_matchers::internal::TypeLocTraverseMatcher, \
+ ReturnTypesF>::Func MatcherName##Loc; \
+ AST_TYPE_TRAVERSE_MATCHER_DEF(MatcherName, ReturnTypesF)
+
/// \brief AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName) works
/// identical to \c AST_TYPE_TRAVERSE_MATCHER but operates on \c TypeLocs.
#define AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName, ReturnTypesF) \
diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Parser.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Parser.h
index 5ec4a9abf4bff..e8fcf0a9d6ccd 100644
--- a/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Parser.h
+++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Parser.h
@@ -1,4 +1,4 @@
-//===--- Parser.h - Matcher expression parser -----*- C++ -*-===//
+//===- Parser.h - Matcher expression parser ---------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,7 +6,7 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
/// \brief Simple matcher expression parser.
///
@@ -30,24 +30,28 @@
/// <Identifier> := [a-zA-Z]+
/// <ArgumentList> := <Expression> | <Expression>,<ArgumentList>
/// \endcode
-///
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_PARSER_H
#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_PARSER_H
-#include "clang/ASTMatchers/Dynamic/Diagnostics.h"
+#include "clang/ASTMatchers/ASTMatchersInternal.h"
#include "clang/ASTMatchers/Dynamic/Registry.h"
#include "clang/ASTMatchers/Dynamic/VariantValue.h"
-#include "clang/Basic/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
+#include <utility>
+#include <vector>
namespace clang {
namespace ast_matchers {
namespace dynamic {
+class Diagnostics;
+
/// \brief Matcher expression parser.
class Parser {
public:
@@ -124,8 +128,8 @@ public:
/// \brief Sema implementation that uses the matcher registry to process the
/// tokens.
class RegistrySema : public Parser::Sema {
- public:
- ~RegistrySema() override;
+ public:
+ ~RegistrySema() override;
llvm::Optional<MatcherCtor>
lookupMatcherCtor(StringRef MatcherName) override;
@@ -143,7 +147,7 @@ public:
getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes) override;
};
- typedef llvm::StringMap<VariantValue> NamedValueMap;
+ using NamedValueMap = llvm::StringMap<VariantValue>;
/// \brief Parse a matcher expression.
///
@@ -247,13 +251,14 @@ private:
const NamedValueMap *const NamedValues;
Diagnostics *const Error;
- typedef std::vector<std::pair<MatcherCtor, unsigned> > ContextStackTy;
+ using ContextStackTy = std::vector<std::pair<MatcherCtor, unsigned>>;
+
ContextStackTy ContextStack;
std::vector<MatcherCompletion> Completions;
};
-} // namespace dynamic
-} // namespace ast_matchers
-} // namespace clang
+} // namespace dynamic
+} // namespace ast_matchers
+} // namespace clang
-#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H
+#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H
diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Registry.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Registry.h
index 7bba95dbffeab..277491250db8f 100644
--- a/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Registry.h
+++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Registry.h
@@ -1,4 +1,4 @@
-//===--- Registry.h - Matcher registry --------------------------*- C++ -*-===//
+//===- Registry.h - Matcher registry ----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,12 +6,12 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
/// \brief Registry of all known matchers.
///
/// The registry provides a generic interface to construct any matcher by name.
-///
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_REGISTRY_H
@@ -34,9 +34,9 @@ namespace internal {
class MatcherDescriptor;
-} // end namespace internal
+} // namespace internal
-typedef const internal::MatcherDescriptor *MatcherCtor;
+using MatcherCtor = const internal::MatcherDescriptor *;
struct MatcherCompletion {
MatcherCompletion() = default;
@@ -129,8 +129,8 @@ public:
Diagnostics *Error);
};
-} // end namespace dynamic
-} // end namespace ast_matchers
-} // end namespace clang
+} // namespace dynamic
+} // namespace ast_matchers
+} // namespace clang
#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Consumed.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Consumed.h
index c0fc02724f099..5ba42b475c830 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Consumed.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Consumed.h
@@ -19,7 +19,7 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtCXX.h"
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
-#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Basic/SourceLocation.h"
namespace clang {
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Dominators.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Dominators.h
index 38010e1ee1d8e..6cb161ab37c8a 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Dominators.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Dominators.h
@@ -14,7 +14,7 @@
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_DOMINATORS_H
#define LLVM_CLANG_ANALYSIS_ANALYSES_DOMINATORS_H
-#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/Support/GenericDomTree.h"
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/LiveVariables.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/LiveVariables.h
index 8db4b0a58f86e..6a1222386bae1 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/LiveVariables.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/LiveVariables.h
@@ -15,7 +15,7 @@
#define LLVM_CLANG_ANALYSIS_ANALYSES_LIVEVARIABLES_H
#include "clang/AST/Decl.h"
-#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
#include "llvm/ADT/ImmutableSet.h"
namespace clang {
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/PostOrderCFGView.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/PostOrderCFGView.h
index a1c6504275889..c0a93528373e2 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/PostOrderCFGView.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/PostOrderCFGView.h
@@ -21,7 +21,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/BitVector.h"
-#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
namespace clang {
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafety.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafety.h
index 22694a7a225ab..7e403b1f40906 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafety.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafety.h
@@ -19,7 +19,7 @@
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETY_H
#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETY_H
-#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/StringRef.h"
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
index 8c1d1da554bd7..414645b7231bd 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
@@ -25,7 +25,7 @@
#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/Analysis/AnalysisDeclContext.h"
#include "clang/Basic/OperatorKinds.h"
#include <memory>
#include <ostream>
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
index be8a7105d7835..0a58d2a80250a 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
@@ -92,6 +92,7 @@ enum TIL_BinaryOpcode : unsigned char {
BOP_Neq, // !=
BOP_Lt, // <
BOP_Leq, // <=
+ BOP_Cmp, // <=>
BOP_LogicAnd, // && (no short-circuit)
BOP_LogicOr // || (no short-circuit)
};
@@ -909,15 +910,10 @@ class Project : public SExpr {
public:
static bool classof(const SExpr *E) { return E->opcode() == COP_Project; }
- Project(SExpr *R, StringRef SName)
- : SExpr(COP_Project), Rec(R), SlotName(SName), Cvdecl(nullptr)
- { }
Project(SExpr *R, const clang::ValueDecl *Cvd)
- : SExpr(COP_Project), Rec(R), SlotName(Cvd->getName()), Cvdecl(Cvd)
- { }
- Project(const Project &P, SExpr *R)
- : SExpr(P), Rec(R), SlotName(P.SlotName), Cvdecl(P.Cvdecl)
- { }
+ : SExpr(COP_Project), Rec(R), Cvdecl(Cvd) {
+ assert(Cvd && "ValueDecl must not be null");
+ }
SExpr *record() { return Rec; }
const SExpr *record() const { return Rec; }
@@ -931,10 +927,14 @@ public:
}
StringRef slotName() const {
- if (Cvdecl)
+ if (Cvdecl->getDeclName().isIdentifier())
return Cvdecl->getName();
- else
- return SlotName;
+ if (!SlotName) {
+ SlotName = "";
+ llvm::raw_string_ostream OS(*SlotName);
+ Cvdecl->printName(OS);
+ }
+ return *SlotName;
}
template <class V>
@@ -953,7 +953,7 @@ public:
private:
SExpr* Rec;
- StringRef SlotName;
+ mutable llvm::Optional<std::string> SlotName;
const clang::ValueDecl *Cvdecl;
};
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h b/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisDeclContext.h
index ec7549d4535cc..03ff4a9516da0 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisDeclContext.h
@@ -1,4 +1,4 @@
-//=== AnalysisContext.h - Analysis context for Path Sens analysis --*- C++ -*-//
+//=== AnalysisDeclContext.h - Analysis context for Path Sens analysis --*- C++ -*-//
//
// The LLVM Compiler Infrastructure
//
@@ -12,10 +12,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H
-#define LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H
+#define LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H
#include "clang/AST/Decl.h"
+#include "clang/Analysis/BodyFarm.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/CodeInjector.h"
#include "llvm/ADT/DenseMap.h"
@@ -416,23 +417,25 @@ class AnalysisDeclContextManager {
/// Pointer to an interface that can provide function bodies for
/// declarations from external source.
std::unique_ptr<CodeInjector> Injector;
-
+
+ /// A factory for creating and caching implementations for common
+ /// methods during the analysis.
+ BodyFarm FunctionBodyFarm;
+
/// Flag to indicate whether or not bodies should be synthesized
/// for well-known functions.
bool SynthesizeBodies;
public:
- AnalysisDeclContextManager(bool useUnoptimizedCFG = false,
+ AnalysisDeclContextManager(ASTContext &ASTCtx, bool useUnoptimizedCFG = false,
bool addImplicitDtors = false,
bool addInitializers = false,
bool addTemporaryDtors = false,
- bool addLifetime = false,
+ bool addLifetime = false, bool addLoopExit = false,
bool synthesizeBodies = false,
bool addStaticInitBranches = false,
bool addCXXNewAllocator = true,
- CodeInjector* injector = nullptr);
-
- ~AnalysisDeclContextManager();
+ CodeInjector *injector = nullptr);
AnalysisDeclContext *getContext(const Decl *D);
@@ -471,6 +474,9 @@ public:
return LocContexts.getStackFrame(getContext(D), Parent, S, Blk, Idx);
}
+ /// Get a reference to {@code BodyFarm} instance.
+ BodyFarm &getBodyFarm();
+
/// Discard all previously created AnalysisDeclContexts.
void clear();
diff --git a/contrib/llvm/tools/clang/lib/Analysis/BodyFarm.h b/contrib/llvm/tools/clang/include/clang/Analysis/BodyFarm.h
index edbe996246515..ff0859bc662da 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/BodyFarm.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/BodyFarm.h
@@ -28,24 +28,27 @@ class ObjCMethodDecl;
class ObjCPropertyDecl;
class Stmt;
class CodeInjector;
-
+
class BodyFarm {
public:
BodyFarm(ASTContext &C, CodeInjector *injector) : C(C), Injector(injector) {}
-
+
/// Factory method for creating bodies for ordinary functions.
Stmt *getBody(const FunctionDecl *D);
/// Factory method for creating bodies for Objective-C properties.
Stmt *getBody(const ObjCMethodDecl *D);
+ /// Remove copy constructor to avoid accidental copying.
+ BodyFarm(const BodyFarm &other) = delete;
+
private:
- typedef llvm::DenseMap<const Decl *, Optional<Stmt *> > BodyMap;
+ typedef llvm::DenseMap<const Decl *, Optional<Stmt *>> BodyMap;
ASTContext &C;
BodyMap Bodies;
CodeInjector *Injector;
};
-}
+} // namespace clang
#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h b/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h
index 97639bbfade20..cfedb2aa8ed5d 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h
@@ -1,4 +1,4 @@
-//===--- CFG.h - Classes for representing and building CFGs------*- C++ -*-===//
+//===- CFG.h - Classes for representing and building CFGs -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,38 +17,38 @@
#include "clang/AST/Stmt.h"
#include "clang/Analysis/Support/BumpVector.h"
-#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/LLVM.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
#include <bitset>
#include <cassert>
+#include <cstddef>
#include <iterator>
#include <memory>
+#include <vector>
namespace clang {
- class CXXDestructorDecl;
- class Decl;
- class Stmt;
- class Expr;
- class FieldDecl;
- class VarDecl;
- class CXXCtorInitializer;
- class CXXBaseSpecifier;
- class CXXBindTemporaryExpr;
- class CFG;
- class PrinterHelper;
- class LangOptions;
- class ASTContext;
- class CXXRecordDecl;
- class CXXDeleteExpr;
- class CXXNewExpr;
- class BinaryOperator;
+
+class ASTContext;
+class BinaryOperator;
+class CFG;
+class CXXBaseSpecifier;
+class CXXBindTemporaryExpr;
+class CXXCtorInitializer;
+class CXXDeleteExpr;
+class CXXDestructorDecl;
+class CXXNewExpr;
+class CXXRecordDecl;
+class Decl;
+class FieldDecl;
+class LangOptions;
+class VarDecl;
/// CFGElement - Represents a top-level expression in a basic block.
class CFGElement {
@@ -59,6 +59,7 @@ public:
Initializer,
NewAllocator,
LifetimeEnds,
+ LoopExit,
// dtor kind
AutomaticObjectDtor,
DeleteDtor,
@@ -75,14 +76,14 @@ protected:
llvm::PointerIntPair<void *, 2> Data2;
CFGElement(Kind kind, const void *Ptr1, const void *Ptr2 = nullptr)
- : Data1(const_cast<void*>(Ptr1), ((unsigned) kind) & 0x3),
- Data2(const_cast<void*>(Ptr2), (((unsigned) kind) >> 2) & 0x3) {
+ : Data1(const_cast<void*>(Ptr1), ((unsigned) kind) & 0x3),
+ Data2(const_cast<void*>(Ptr2), (((unsigned) kind) >> 2) & 0x3) {
assert(getKind() == kind);
}
- CFGElement() {}
-public:
+ CFGElement() = default;
+public:
/// \brief Convert to the specified CFGElement type, asserting that this
/// CFGElement is of the desired type.
template<typename T>
@@ -124,7 +125,9 @@ public:
private:
friend class CFGElement;
- CFGStmt() {}
+
+ CFGStmt() = default;
+
static bool isKind(const CFGElement &E) {
return E.getKind() == Statement;
}
@@ -143,7 +146,9 @@ public:
private:
friend class CFGElement;
- CFGInitializer() {}
+
+ CFGInitializer() = default;
+
static bool isKind(const CFGElement &E) {
return E.getKind() == Initializer;
}
@@ -162,12 +167,38 @@ public:
private:
friend class CFGElement;
- CFGNewAllocator() {}
+
+ CFGNewAllocator() = default;
+
static bool isKind(const CFGElement &elem) {
return elem.getKind() == NewAllocator;
}
};
+/// Represents the point where a loop ends.
+/// This element is is only produced when building the CFG for the static
+/// analyzer and hidden behind the 'cfg-loopexit' analyzer config flag.
+///
+/// Note: a loop exit element can be reached even when the loop body was never
+/// entered.
+class CFGLoopExit : public CFGElement {
+public:
+ explicit CFGLoopExit(const Stmt *stmt) : CFGElement(LoopExit, stmt) {}
+
+ const Stmt *getLoopStmt() const {
+ return static_cast<Stmt *>(Data1.getPointer());
+ }
+
+private:
+ friend class CFGElement;
+
+ CFGLoopExit() = default;
+
+ static bool isKind(const CFGElement &elem) {
+ return elem.getKind() == LoopExit;
+ }
+};
+
/// Represents the point where the lifetime of an automatic object ends
class CFGLifetimeEnds : public CFGElement {
public:
@@ -184,7 +215,9 @@ public:
private:
friend class CFGElement;
- CFGLifetimeEnds() {}
+
+ CFGLifetimeEnds() = default;
+
static bool isKind(const CFGElement &elem) {
return elem.getKind() == LifetimeEnds;
}
@@ -194,7 +227,8 @@ private:
/// by compiler on various occasions.
class CFGImplicitDtor : public CFGElement {
protected:
- CFGImplicitDtor() {}
+ CFGImplicitDtor() = default;
+
CFGImplicitDtor(Kind kind, const void *data1, const void *data2 = nullptr)
: CFGElement(kind, data1, data2) {
assert(kind >= DTOR_BEGIN && kind <= DTOR_END);
@@ -206,6 +240,7 @@ public:
private:
friend class CFGElement;
+
static bool isKind(const CFGElement &E) {
Kind kind = E.getKind();
return kind >= DTOR_BEGIN && kind <= DTOR_END;
@@ -231,7 +266,9 @@ public:
private:
friend class CFGElement;
- CFGAutomaticObjDtor() {}
+
+ CFGAutomaticObjDtor() = default;
+
static bool isKind(const CFGElement &elem) {
return elem.getKind() == AutomaticObjectDtor;
}
@@ -255,7 +292,9 @@ public:
private:
friend class CFGElement;
- CFGDeleteDtor() {}
+
+ CFGDeleteDtor() = default;
+
static bool isKind(const CFGElement &elem) {
return elem.getKind() == DeleteDtor;
}
@@ -274,7 +313,9 @@ public:
private:
friend class CFGElement;
- CFGBaseDtor() {}
+
+ CFGBaseDtor() = default;
+
static bool isKind(const CFGElement &E) {
return E.getKind() == BaseDtor;
}
@@ -293,7 +334,9 @@ public:
private:
friend class CFGElement;
- CFGMemberDtor() {}
+
+ CFGMemberDtor() = default;
+
static bool isKind(const CFGElement &E) {
return E.getKind() == MemberDtor;
}
@@ -312,7 +355,9 @@ public:
private:
friend class CFGElement;
- CFGTemporaryDtor() {}
+
+ CFGTemporaryDtor() = default;
+
static bool isKind(const CFGElement &E) {
return E.getKind() == TemporaryDtor;
}
@@ -326,8 +371,9 @@ private:
/// of matching full expression.
class CFGTerminator {
llvm::PointerIntPair<Stmt *, 1> Data;
+
public:
- CFGTerminator() {}
+ CFGTerminator() = default;
CFGTerminator(Stmt *S, bool TemporaryDtorsBranch = false)
: Data(S, TemporaryDtorsBranch) {}
@@ -373,21 +419,23 @@ public:
/// &&, || expression that uses result of && or ||, RHS
///
/// But note that any of that may be NULL in case of optimized-out edges.
-///
class CFGBlock {
class ElementList {
- typedef BumpVector<CFGElement> ImplTy;
+ using ImplTy = BumpVector<CFGElement>;
+
ImplTy Impl;
+
public:
ElementList(BumpVectorContext &C) : Impl(C, 4) {}
- typedef std::reverse_iterator<ImplTy::iterator> iterator;
- typedef std::reverse_iterator<ImplTy::const_iterator> const_iterator;
- typedef ImplTy::iterator reverse_iterator;
- typedef ImplTy::const_iterator const_reverse_iterator;
- typedef ImplTy::const_reference const_reference;
+ using iterator = std::reverse_iterator<ImplTy::iterator>;
+ using const_iterator = std::reverse_iterator<ImplTy::const_iterator>;
+ using reverse_iterator = ImplTy::iterator;
+ using const_reverse_iterator = ImplTy::const_iterator;
+ using const_reference = ImplTy::const_reference;
void push_back(CFGElement e, BumpVectorContext &C) { Impl.push_back(e, C); }
+
reverse_iterator insert(reverse_iterator I, size_t Cnt, CFGElement E,
BumpVectorContext &C) {
return Impl.insert(I, Cnt, E, C);
@@ -405,10 +453,10 @@ class CFGBlock {
const_reverse_iterator rbegin() const { return Impl.begin(); }
const_reverse_iterator rend() const { return Impl.end(); }
- CFGElement operator[](size_t i) const {
- assert(i < Impl.size());
- return Impl[Impl.size() - 1 - i];
- }
+ CFGElement operator[](size_t i) const {
+ assert(i < Impl.size());
+ return Impl[Impl.size() - 1 - i];
+ }
size_t size() const { return Impl.size(); }
bool empty() const { return Impl.empty(); }
@@ -420,7 +468,7 @@ class CFGBlock {
/// Label - An (optional) label that prefixes the executable
/// statements in the block. When this variable is non-NULL, it is
/// either an instance of LabelStmt, SwitchCase or CXXCatchStmt.
- Stmt *Label;
+ Stmt *Label = nullptr;
/// Terminator - The terminator for a basic block that
/// indicates the type of control-flow that occurs between a block
@@ -430,7 +478,7 @@ class CFGBlock {
/// LoopTarget - Some blocks are used to represent the "loop edge" to
/// the start of a loop from within the loop body. This Stmt* will be
/// refer to the loop statement for such blocks (and be null otherwise).
- const Stmt *LoopTarget;
+ const Stmt *LoopTarget = nullptr;
/// BlockID - A numerical ID assigned to a CFGBlock during construction
/// of the CFG.
@@ -450,7 +498,7 @@ public:
};
CFGBlock *ReachableBlock;
- llvm::PointerIntPair<CFGBlock*, 2> UnreachableBlock;
+ llvm::PointerIntPair<CFGBlock *, 2> UnreachableBlock;
public:
/// Construct an AdjacentBlock with a possibly unreachable block.
@@ -493,7 +541,7 @@ public:
private:
/// Predecessors/Successors - Keep track of the predecessor / successor
/// CFG blocks.
- typedef BumpVector<AdjacentBlock> AdjacentBlocks;
+ using AdjacentBlocks = BumpVector<AdjacentBlock>;
AdjacentBlocks Preds;
AdjacentBlocks Succs;
@@ -513,15 +561,14 @@ private:
public:
explicit CFGBlock(unsigned blockid, BumpVectorContext &C, CFG *parent)
- : Elements(C), Label(nullptr), Terminator(nullptr), LoopTarget(nullptr),
- BlockID(blockid), Preds(C, 1), Succs(C, 1), HasNoReturnElement(false),
- Parent(parent) {}
+ : Elements(C), Terminator(nullptr), BlockID(blockid), Preds(C, 1),
+ Succs(C, 1), HasNoReturnElement(false), Parent(parent) {}
// Statement iterators
- typedef ElementList::iterator iterator;
- typedef ElementList::const_iterator const_iterator;
- typedef ElementList::reverse_iterator reverse_iterator;
- typedef ElementList::const_reverse_iterator const_reverse_iterator;
+ using iterator = ElementList::iterator;
+ using const_iterator = ElementList::const_iterator;
+ using reverse_iterator = ElementList::reverse_iterator;
+ using const_reverse_iterator = ElementList::const_reverse_iterator;
CFGElement front() const { return Elements.front(); }
CFGElement back() const { return Elements.back(); }
@@ -542,19 +589,19 @@ public:
CFGElement operator[](size_t i) const { return Elements[i]; }
// CFG iterators
- typedef AdjacentBlocks::iterator pred_iterator;
- typedef AdjacentBlocks::const_iterator const_pred_iterator;
- typedef AdjacentBlocks::reverse_iterator pred_reverse_iterator;
- typedef AdjacentBlocks::const_reverse_iterator const_pred_reverse_iterator;
- typedef llvm::iterator_range<pred_iterator> pred_range;
- typedef llvm::iterator_range<const_pred_iterator> pred_const_range;
+ using pred_iterator = AdjacentBlocks::iterator;
+ using const_pred_iterator = AdjacentBlocks::const_iterator;
+ using pred_reverse_iterator = AdjacentBlocks::reverse_iterator;
+ using const_pred_reverse_iterator = AdjacentBlocks::const_reverse_iterator;
+ using pred_range = llvm::iterator_range<pred_iterator>;
+ using pred_const_range = llvm::iterator_range<const_pred_iterator>;
- typedef AdjacentBlocks::iterator succ_iterator;
- typedef AdjacentBlocks::const_iterator const_succ_iterator;
- typedef AdjacentBlocks::reverse_iterator succ_reverse_iterator;
- typedef AdjacentBlocks::const_reverse_iterator const_succ_reverse_iterator;
- typedef llvm::iterator_range<succ_iterator> succ_range;
- typedef llvm::iterator_range<const_succ_iterator> succ_const_range;
+ using succ_iterator = AdjacentBlocks::iterator;
+ using const_succ_iterator = AdjacentBlocks::const_iterator;
+ using succ_reverse_iterator = AdjacentBlocks::reverse_iterator;
+ using const_succ_reverse_iterator = AdjacentBlocks::const_reverse_iterator;
+ using succ_range = llvm::iterator_range<succ_iterator>;
+ using succ_const_range = llvm::iterator_range<const_succ_iterator>;
pred_iterator pred_begin() { return Preds.begin(); }
pred_iterator pred_end() { return Preds.end(); }
@@ -566,10 +613,11 @@ public:
const_pred_reverse_iterator pred_rbegin() const { return Preds.rbegin(); }
const_pred_reverse_iterator pred_rend() const { return Preds.rend(); }
- pred_range preds() {
+ pred_range preds() {
return pred_range(pred_begin(), pred_end());
}
- pred_const_range preds() const {
+
+ pred_const_range preds() const {
return pred_const_range(pred_begin(), pred_end());
}
@@ -583,10 +631,11 @@ public:
const_succ_reverse_iterator succ_rbegin() const { return Succs.rbegin(); }
const_succ_reverse_iterator succ_rend() const { return Succs.rend(); }
- succ_range succs() {
+ succ_range succs() {
return succ_range(succ_begin(), succ_end());
}
- succ_const_range succs() const {
+
+ succ_const_range succs() const {
return succ_const_range(succ_begin(), succ_end());
}
@@ -599,13 +648,11 @@ public:
class FilterOptions {
public:
- FilterOptions() {
- IgnoreNullPredecessors = 1;
- IgnoreDefaultsWithCoveredEnums = 0;
- }
-
unsigned IgnoreNullPredecessors : 1;
unsigned IgnoreDefaultsWithCoveredEnums : 1;
+
+ FilterOptions()
+ : IgnoreNullPredecessors(1), IgnoreDefaultsWithCoveredEnums(0) {}
};
static bool FilterEdge(const FilterOptions &F, const CFGBlock *Src,
@@ -617,6 +664,7 @@ public:
IMPL I, E;
const FilterOptions F;
const CFGBlock *From;
+
public:
explicit FilteredCFGBlockIterator(const IMPL &i, const IMPL &e,
const CFGBlock *from,
@@ -634,17 +682,18 @@ public:
}
const CFGBlock *operator*() const { return *I; }
+
private:
bool Filter(const CFGBlock *To) {
return IsPred ? FilterEdge(F, To, From) : FilterEdge(F, From, To);
}
};
- typedef FilteredCFGBlockIterator<const_pred_iterator, true>
- filtered_pred_iterator;
+ using filtered_pred_iterator =
+ FilteredCFGBlockIterator<const_pred_iterator, true>;
- typedef FilteredCFGBlockIterator<const_succ_iterator, false>
- filtered_succ_iterator;
+ using filtered_succ_iterator =
+ FilteredCFGBlockIterator<const_succ_iterator, false>;
filtered_pred_iterator filtered_pred_start_end(const FilterOptions &f) const {
return filtered_pred_iterator(pred_begin(), pred_end(), this, f);
@@ -728,6 +777,10 @@ public:
Elements.push_back(CFGLifetimeEnds(VD, S), C);
}
+ void appendLoopExit(const Stmt *LoopStmt, BumpVectorContext &C) {
+ Elements.push_back(CFGLoopExit(LoopStmt), C);
+ }
+
void appendDeleteDtor(CXXRecordDecl *RD, CXXDeleteExpr *DE, BumpVectorContext &C) {
Elements.push_back(CFGDeleteDtor(RD, DE), C);
}
@@ -763,11 +816,12 @@ public:
/// operator error is found when building the CFG.
class CFGCallback {
public:
- CFGCallback() {}
+ CFGCallback() = default;
+ virtual ~CFGCallback() = default;
+
virtual void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) {}
virtual void compareBitwiseEquality(const BinaryOperator *B,
bool isAlwaysTrue) {}
- virtual ~CFGCallback() {}
};
/// CFG - Represents a source-level, intra-procedural CFG that represents the
@@ -785,19 +839,24 @@ public:
class BuildOptions {
std::bitset<Stmt::lastStmtConstant> alwaysAddMask;
+
public:
- typedef llvm::DenseMap<const Stmt *, const CFGBlock*> ForcedBlkExprs;
- ForcedBlkExprs **forcedBlkExprs;
- CFGCallback *Observer;
- bool PruneTriviallyFalseEdges;
- bool AddEHEdges;
- bool AddInitializers;
- bool AddImplicitDtors;
- bool AddLifetime;
- bool AddTemporaryDtors;
- bool AddStaticInitBranches;
- bool AddCXXNewAllocator;
- bool AddCXXDefaultInitExprInCtors;
+ using ForcedBlkExprs = llvm::DenseMap<const Stmt *, const CFGBlock *>;
+
+ ForcedBlkExprs **forcedBlkExprs = nullptr;
+ CFGCallback *Observer = nullptr;
+ bool PruneTriviallyFalseEdges = true;
+ bool AddEHEdges = false;
+ bool AddInitializers = false;
+ bool AddImplicitDtors = false;
+ bool AddLifetime = false;
+ bool AddLoopExit = false;
+ bool AddTemporaryDtors = false;
+ bool AddStaticInitBranches = false;
+ bool AddCXXNewAllocator = false;
+ bool AddCXXDefaultInitExprInCtors = false;
+
+ BuildOptions() = default;
bool alwaysAdd(const Stmt *stmt) const {
return alwaysAddMask[stmt->getStmtClass()];
@@ -812,15 +871,6 @@ public:
alwaysAddMask.set();
return *this;
}
-
- BuildOptions()
- : forcedBlkExprs(nullptr), Observer(nullptr),
- PruneTriviallyFalseEdges(true),
- AddEHEdges(false),
- AddInitializers(false), AddImplicitDtors(false),
- AddLifetime(false),
- AddTemporaryDtors(false), AddStaticInitBranches(false),
- AddCXXNewAllocator(false), AddCXXDefaultInitExprInCtors(false) {}
};
/// buildCFG - Builds a CFG from an AST.
@@ -844,11 +894,11 @@ public:
// Block Iterators
//===--------------------------------------------------------------------===//
- typedef BumpVector<CFGBlock*> CFGBlockListTy;
- typedef CFGBlockListTy::iterator iterator;
- typedef CFGBlockListTy::const_iterator const_iterator;
- typedef std::reverse_iterator<iterator> reverse_iterator;
- typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+ using CFGBlockListTy = BumpVector<CFGBlock *>;
+ using iterator = CFGBlockListTy::iterator;
+ using const_iterator = CFGBlockListTy::const_iterator;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
CFGBlock & front() { return *Blocks.front(); }
CFGBlock & back() { return *Blocks.back(); }
@@ -876,10 +926,12 @@ public:
CFGBlock * getIndirectGotoBlock() { return IndirectGotoBlock; }
const CFGBlock * getIndirectGotoBlock() const { return IndirectGotoBlock; }
- typedef std::vector<const CFGBlock*>::const_iterator try_block_iterator;
+ using try_block_iterator = std::vector<const CFGBlock *>::const_iterator;
+
try_block_iterator try_blocks_begin() const {
return TryDispatchBlocks.begin();
}
+
try_block_iterator try_blocks_end() const {
return TryDispatchBlocks.end();
}
@@ -900,9 +952,9 @@ public:
SyntheticDeclStmts[Synthetic] = Source;
}
- typedef llvm::DenseMap<const DeclStmt *, const DeclStmt *>::const_iterator
- synthetic_stmt_iterator;
- typedef llvm::iterator_range<synthetic_stmt_iterator> synthetic_stmt_range;
+ using synthetic_stmt_iterator =
+ llvm::DenseMap<const DeclStmt *, const DeclStmt *>::const_iterator;
+ using synthetic_stmt_range = llvm::iterator_range<synthetic_stmt_iterator>;
/// Iterates over synthetic DeclStmts in the CFG.
///
@@ -962,9 +1014,7 @@ public:
// Internal: constructors and data.
//===--------------------------------------------------------------------===//
- CFG()
- : Entry(nullptr), Exit(nullptr), IndirectGotoBlock(nullptr), NumBlockIDs(0),
- Blocks(BlkBVC, 10) {}
+ CFG() : Blocks(BlkBVC, 10) {}
llvm::BumpPtrAllocator& getAllocator() {
return BlkBVC.getAllocator();
@@ -975,11 +1025,13 @@ public:
}
private:
- CFGBlock *Entry;
- CFGBlock *Exit;
- CFGBlock* IndirectGotoBlock; // Special block to contain collective dispatch
- // for indirect gotos
- unsigned NumBlockIDs;
+ CFGBlock *Entry = nullptr;
+ CFGBlock *Exit = nullptr;
+
+ // Special block to contain collective dispatch for indirect gotos
+ CFGBlock* IndirectGotoBlock = nullptr;
+
+ unsigned NumBlockIDs = 0;
BumpVectorContext BlkBVC;
@@ -993,7 +1045,8 @@ private:
/// source DeclStmt.
llvm::DenseMap<const DeclStmt *, const DeclStmt *> SyntheticDeclStmts;
};
-} // end namespace clang
+
+} // namespace clang
//===----------------------------------------------------------------------===//
// GraphTraits specializations for CFG basic block graphs (source-level CFGs)
@@ -1004,7 +1057,8 @@ namespace llvm {
/// Implement simplify_type for CFGTerminator, so that we can dyn_cast from
/// CFGTerminator to a specific Stmt class.
template <> struct simplify_type< ::clang::CFGTerminator> {
- typedef ::clang::Stmt *SimpleType;
+ using SimpleType = ::clang::Stmt *;
+
static SimpleType getSimplifiedValue(::clang::CFGTerminator Val) {
return Val.getStmt();
}
@@ -1013,50 +1067,44 @@ template <> struct simplify_type< ::clang::CFGTerminator> {
// Traits for: CFGBlock
template <> struct GraphTraits< ::clang::CFGBlock *> {
- typedef ::clang::CFGBlock *NodeRef;
- typedef ::clang::CFGBlock::succ_iterator ChildIteratorType;
+ using NodeRef = ::clang::CFGBlock *;
+ using ChildIteratorType = ::clang::CFGBlock::succ_iterator;
static NodeRef getEntryNode(::clang::CFGBlock *BB) { return BB; }
-
static ChildIteratorType child_begin(NodeRef N) { return N->succ_begin(); }
-
static ChildIteratorType child_end(NodeRef N) { return N->succ_end(); }
};
template <> struct GraphTraits< const ::clang::CFGBlock *> {
- typedef const ::clang::CFGBlock *NodeRef;
- typedef ::clang::CFGBlock::const_succ_iterator ChildIteratorType;
+ using NodeRef = const ::clang::CFGBlock *;
+ using ChildIteratorType = ::clang::CFGBlock::const_succ_iterator;
static NodeRef getEntryNode(const clang::CFGBlock *BB) { return BB; }
-
static ChildIteratorType child_begin(NodeRef N) { return N->succ_begin(); }
-
static ChildIteratorType child_end(NodeRef N) { return N->succ_end(); }
};
-template <> struct GraphTraits<Inverse< ::clang::CFGBlock*> > {
- typedef ::clang::CFGBlock *NodeRef;
- typedef ::clang::CFGBlock::const_pred_iterator ChildIteratorType;
+template <> struct GraphTraits<Inverse< ::clang::CFGBlock *>> {
+ using NodeRef = ::clang::CFGBlock *;
+ using ChildIteratorType = ::clang::CFGBlock::const_pred_iterator;
static NodeRef getEntryNode(Inverse<::clang::CFGBlock *> G) {
return G.Graph;
}
static ChildIteratorType child_begin(NodeRef N) { return N->pred_begin(); }
-
static ChildIteratorType child_end(NodeRef N) { return N->pred_end(); }
};
-template <> struct GraphTraits<Inverse<const ::clang::CFGBlock*> > {
- typedef const ::clang::CFGBlock *NodeRef;
- typedef ::clang::CFGBlock::const_pred_iterator ChildIteratorType;
+template <> struct GraphTraits<Inverse<const ::clang::CFGBlock *>> {
+ using NodeRef = const ::clang::CFGBlock *;
+ using ChildIteratorType = ::clang::CFGBlock::const_pred_iterator;
static NodeRef getEntryNode(Inverse<const ::clang::CFGBlock *> G) {
return G.Graph;
}
static ChildIteratorType child_begin(NodeRef N) { return N->pred_begin(); }
-
static ChildIteratorType child_end(NodeRef N) { return N->pred_end(); }
};
@@ -1064,8 +1112,7 @@ template <> struct GraphTraits<Inverse<const ::clang::CFGBlock*> > {
template <> struct GraphTraits< ::clang::CFG* >
: public GraphTraits< ::clang::CFGBlock *> {
-
- typedef ::clang::CFG::iterator nodes_iterator;
+ using nodes_iterator = ::clang::CFG::iterator;
static NodeRef getEntryNode(::clang::CFG *F) { return &F->getEntry(); }
static nodes_iterator nodes_begin(::clang::CFG* F) { return F->nodes_begin();}
@@ -1075,44 +1122,47 @@ template <> struct GraphTraits< ::clang::CFG* >
template <> struct GraphTraits<const ::clang::CFG* >
: public GraphTraits<const ::clang::CFGBlock *> {
-
- typedef ::clang::CFG::const_iterator nodes_iterator;
+ using nodes_iterator = ::clang::CFG::const_iterator;
static NodeRef getEntryNode(const ::clang::CFG *F) { return &F->getEntry(); }
+
static nodes_iterator nodes_begin( const ::clang::CFG* F) {
return F->nodes_begin();
}
+
static nodes_iterator nodes_end( const ::clang::CFG* F) {
return F->nodes_end();
}
+
static unsigned size(const ::clang::CFG* F) {
return F->size();
}
};
-template <> struct GraphTraits<Inverse< ::clang::CFG*> >
- : public GraphTraits<Inverse< ::clang::CFGBlock*> > {
-
- typedef ::clang::CFG::iterator nodes_iterator;
+template <> struct GraphTraits<Inverse< ::clang::CFG *>>
+ : public GraphTraits<Inverse< ::clang::CFGBlock *>> {
+ using nodes_iterator = ::clang::CFG::iterator;
static NodeRef getEntryNode(::clang::CFG *F) { return &F->getExit(); }
static nodes_iterator nodes_begin( ::clang::CFG* F) {return F->nodes_begin();}
static nodes_iterator nodes_end( ::clang::CFG* F) { return F->nodes_end(); }
};
-template <> struct GraphTraits<Inverse<const ::clang::CFG*> >
- : public GraphTraits<Inverse<const ::clang::CFGBlock*> > {
-
- typedef ::clang::CFG::const_iterator nodes_iterator;
+template <> struct GraphTraits<Inverse<const ::clang::CFG *>>
+ : public GraphTraits<Inverse<const ::clang::CFGBlock *>> {
+ using nodes_iterator = ::clang::CFG::const_iterator;
static NodeRef getEntryNode(const ::clang::CFG *F) { return &F->getExit(); }
+
static nodes_iterator nodes_begin(const ::clang::CFG* F) {
return F->nodes_begin();
}
+
static nodes_iterator nodes_end(const ::clang::CFG* F) {
return F->nodes_end();
}
};
-} // end llvm namespace
+
+} // namespace llvm
#endif // LLVM_CLANG_ANALYSIS_CFG_H
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/CallGraph.h b/contrib/llvm/tools/clang/include/clang/Analysis/CallGraph.h
index a2a27a8e47c75..bdcdfecddc3eb 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/CallGraph.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/CallGraph.h
@@ -1,4 +1,4 @@
-//== CallGraph.h - AST-based Call graph ------------------------*- C++ -*--==//
+//===- CallGraph.h - AST-based Call graph -----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,19 +12,27 @@
// A call graph for functions whose definitions/bodies are available in the
// current translation unit. The graph has a "virtual" root node that contains
// edges to all externally available functions.
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_CALLGRAPH_H
#define LLVM_CLANG_ANALYSIS_CALLGRAPH_H
-#include "clang/AST/DeclBase.h"
+#include "clang/AST/Decl.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallVector.h"
+#include <memory>
namespace clang {
+
class CallGraphNode;
+class Decl;
+class DeclContext;
+class Stmt;
/// \brief The AST-based call graph.
///
@@ -34,8 +42,8 @@ class CallGraphNode;
class CallGraph : public RecursiveASTVisitor<CallGraph> {
friend class CallGraphNode;
- typedef llvm::DenseMap<const Decl *, std::unique_ptr<CallGraphNode>>
- FunctionMapTy;
+ using FunctionMapTy =
+ llvm::DenseMap<const Decl *, std::unique_ptr<CallGraphNode>>;
/// FunctionMap owns all CallGraphNodes.
FunctionMapTy FunctionMap;
@@ -65,10 +73,11 @@ public:
/// one into the graph.
CallGraphNode *getOrInsertNode(Decl *);
+ using iterator = FunctionMapTy::iterator;
+ using const_iterator = FunctionMapTy::const_iterator;
+
/// Iterators through all the elements in the graph. Note, this gives
/// non-deterministic order.
- typedef FunctionMapTy::iterator iterator;
- typedef FunctionMapTy::const_iterator const_iterator;
iterator begin() { return FunctionMap.begin(); }
iterator end() { return FunctionMap.end(); }
const_iterator begin() const { return FunctionMap.begin(); }
@@ -84,8 +93,8 @@ public:
/// Iterators through all the nodes of the graph that have no parent. These
/// are the unreachable nodes, which are either unused or are due to us
/// failing to add a call edge due to the analysis imprecision.
- typedef llvm::SetVector<CallGraphNode *>::iterator nodes_iterator;
- typedef llvm::SetVector<CallGraphNode *>::const_iterator const_nodes_iterator;
+ using nodes_iterator = llvm::SetVector<CallGraphNode *>::iterator;
+ using const_nodes_iterator = llvm::SetVector<CallGraphNode *>::const_iterator;
void print(raw_ostream &os) const;
void dump() const;
@@ -133,7 +142,7 @@ private:
class CallGraphNode {
public:
- typedef CallGraphNode* CallRecord;
+ using CallRecord = CallGraphNode *;
private:
/// \brief The function/method declaration.
@@ -145,17 +154,17 @@ private:
public:
CallGraphNode(Decl *D) : FD(D) {}
- typedef SmallVectorImpl<CallRecord>::iterator iterator;
- typedef SmallVectorImpl<CallRecord>::const_iterator const_iterator;
+ using iterator = SmallVectorImpl<CallRecord>::iterator;
+ using const_iterator = SmallVectorImpl<CallRecord>::const_iterator;
/// Iterators through all the callees/children of the node.
- inline iterator begin() { return CalledFunctions.begin(); }
- inline iterator end() { return CalledFunctions.end(); }
- inline const_iterator begin() const { return CalledFunctions.begin(); }
- inline const_iterator end() const { return CalledFunctions.end(); }
+ iterator begin() { return CalledFunctions.begin(); }
+ iterator end() { return CalledFunctions.end(); }
+ const_iterator begin() const { return CalledFunctions.begin(); }
+ const_iterator end() const { return CalledFunctions.end(); }
- inline bool empty() const {return CalledFunctions.empty(); }
- inline unsigned size() const {return CalledFunctions.size(); }
+ bool empty() const { return CalledFunctions.empty(); }
+ unsigned size() const { return CalledFunctions.size(); }
void addCallee(CallGraphNode *N) {
CalledFunctions.push_back(N);
@@ -167,35 +176,33 @@ public:
void dump() const;
};
-} // end clang namespace
+} // namespace clang
// Graph traits for iteration, viewing.
namespace llvm {
+
template <> struct GraphTraits<clang::CallGraphNode*> {
- typedef clang::CallGraphNode NodeType;
- typedef clang::CallGraphNode *NodeRef;
- typedef NodeType::iterator ChildIteratorType;
+ using NodeType = clang::CallGraphNode;
+ using NodeRef = clang::CallGraphNode *;
+ using ChildIteratorType = NodeType::iterator;
static NodeType *getEntryNode(clang::CallGraphNode *CGN) { return CGN; }
- static inline ChildIteratorType child_begin(NodeType *N) {
- return N->begin();
- }
- static inline ChildIteratorType child_end(NodeType *N) { return N->end(); }
+ static ChildIteratorType child_begin(NodeType *N) { return N->begin(); }
+ static ChildIteratorType child_end(NodeType *N) { return N->end(); }
};
template <> struct GraphTraits<const clang::CallGraphNode*> {
- typedef const clang::CallGraphNode NodeType;
- typedef const clang::CallGraphNode *NodeRef;
- typedef NodeType::const_iterator ChildIteratorType;
+ using NodeType = const clang::CallGraphNode;
+ using NodeRef = const clang::CallGraphNode *;
+ using ChildIteratorType = NodeType::const_iterator;
static NodeType *getEntryNode(const clang::CallGraphNode *CGN) { return CGN; }
- static inline ChildIteratorType child_begin(NodeType *N) { return N->begin();}
- static inline ChildIteratorType child_end(NodeType *N) { return N->end(); }
+ static ChildIteratorType child_begin(NodeType *N) { return N->begin();}
+ static ChildIteratorType child_end(NodeType *N) { return N->end(); }
};
template <> struct GraphTraits<clang::CallGraph*>
: public GraphTraits<clang::CallGraphNode*> {
-
static NodeType *getEntryNode(clang::CallGraph *CGN) {
return CGN->getRoot(); // Start at the external node!
}
@@ -206,19 +213,18 @@ template <> struct GraphTraits<clang::CallGraph*>
}
// nodes_iterator/begin/end - Allow iteration over all nodes in the graph
- typedef mapped_iterator<clang::CallGraph::iterator, decltype(&CGGetValue)>
- nodes_iterator;
+ using nodes_iterator =
+ mapped_iterator<clang::CallGraph::iterator, decltype(&CGGetValue)>;
static nodes_iterator nodes_begin(clang::CallGraph *CG) {
return nodes_iterator(CG->begin(), &CGGetValue);
}
+
static nodes_iterator nodes_end (clang::CallGraph *CG) {
return nodes_iterator(CG->end(), &CGGetValue);
}
- static unsigned size(clang::CallGraph *CG) {
- return CG->size();
- }
+ static unsigned size(clang::CallGraph *CG) { return CG->size(); }
};
template <> struct GraphTraits<const clang::CallGraph*> :
@@ -233,21 +239,20 @@ template <> struct GraphTraits<const clang::CallGraph*> :
}
// nodes_iterator/begin/end - Allow iteration over all nodes in the graph
- typedef mapped_iterator<clang::CallGraph::const_iterator,
- decltype(&CGGetValue)>
- nodes_iterator;
+ using nodes_iterator =
+ mapped_iterator<clang::CallGraph::const_iterator, decltype(&CGGetValue)>;
static nodes_iterator nodes_begin(const clang::CallGraph *CG) {
return nodes_iterator(CG->begin(), &CGGetValue);
}
+
static nodes_iterator nodes_end(const clang::CallGraph *CG) {
return nodes_iterator(CG->end(), &CGGetValue);
}
- static unsigned size(const clang::CallGraph *CG) {
- return CG->size();
- }
+
+ static unsigned size(const clang::CallGraph *CG) { return CG->size(); }
};
-} // end llvm namespace
+} // namespace llvm
-#endif
+#endif // LLVM_CLANG_ANALYSIS_CALLGRAPH_H
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/CloneDetection.h b/contrib/llvm/tools/clang/include/clang/Analysis/CloneDetection.h
index 6339deef41bde..051b9236658cf 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/CloneDetection.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/CloneDetection.h
@@ -7,19 +7,15 @@
//
//===----------------------------------------------------------------------===//
///
-/// /file
-/// This file defines classes for searching and anlyzing source code clones.
+/// \file
+/// This file defines classes for searching and analyzing source code clones.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_CLONEDETECTION_H
#define LLVM_CLANG_AST_CLONEDETECTION_H
-#include "clang/AST/DeclTemplate.h"
#include "clang/AST/StmtVisitor.h"
-#include "clang/Basic/SourceLocation.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Regex.h"
#include <vector>
@@ -31,192 +27,6 @@ class VarDecl;
class ASTContext;
class CompoundStmt;
-namespace clone_detection {
-
-/// Returns a string that represents all macro expansions that expanded into the
-/// given SourceLocation.
-///
-/// If 'getMacroStack(A) == getMacroStack(B)' is true, then the SourceLocations
-/// A and B are expanded from the same macros in the same order.
-std::string getMacroStack(SourceLocation Loc, ASTContext &Context);
-
-/// Collects the data of a single Stmt.
-///
-/// This class defines what a code clone is: If it collects for two statements
-/// the same data, then those two statements are considered to be clones of each
-/// other.
-///
-/// All collected data is forwarded to the given data consumer of the type T.
-/// The data consumer class needs to provide a member method with the signature:
-/// update(StringRef Str)
-template <typename T>
-class StmtDataCollector : public ConstStmtVisitor<StmtDataCollector<T>> {
-
- ASTContext &Context;
- /// The data sink to which all data is forwarded.
- T &DataConsumer;
-
-public:
- /// Collects data of the given Stmt.
- /// \param S The given statement.
- /// \param Context The ASTContext of S.
- /// \param DataConsumer The data sink to which all data is forwarded.
- StmtDataCollector(const Stmt *S, ASTContext &Context, T &DataConsumer)
- : Context(Context), DataConsumer(DataConsumer) {
- this->Visit(S);
- }
-
- typedef unsigned DataPiece;
-
- // Below are utility methods for appending different data to the vector.
-
- void addData(DataPiece Integer) {
- DataConsumer.update(
- StringRef(reinterpret_cast<char *>(&Integer), sizeof(Integer)));
- }
-
- void addData(llvm::StringRef Str) { DataConsumer.update(Str); }
-
- void addData(const QualType &QT) { addData(QT.getAsString()); }
-
-// The functions below collect the class specific data of each Stmt subclass.
-
-// Utility macro for defining a visit method for a given class. This method
-// calls back to the ConstStmtVisitor to visit all parent classes.
-#define DEF_ADD_DATA(CLASS, CODE) \
- void Visit##CLASS(const CLASS *S) { \
- CODE; \
- ConstStmtVisitor<StmtDataCollector>::Visit##CLASS(S); \
- }
-
- DEF_ADD_DATA(Stmt, {
- addData(S->getStmtClass());
- // This ensures that macro generated code isn't identical to macro-generated
- // code.
- addData(getMacroStack(S->getLocStart(), Context));
- addData(getMacroStack(S->getLocEnd(), Context));
- })
- DEF_ADD_DATA(Expr, { addData(S->getType()); })
-
- //--- Builtin functionality ----------------------------------------------//
- DEF_ADD_DATA(ArrayTypeTraitExpr, { addData(S->getTrait()); })
- DEF_ADD_DATA(ExpressionTraitExpr, { addData(S->getTrait()); })
- DEF_ADD_DATA(PredefinedExpr, { addData(S->getIdentType()); })
- DEF_ADD_DATA(TypeTraitExpr, {
- addData(S->getTrait());
- for (unsigned i = 0; i < S->getNumArgs(); ++i)
- addData(S->getArg(i)->getType());
- })
-
- //--- Calls --------------------------------------------------------------//
- DEF_ADD_DATA(CallExpr, {
- // Function pointers don't have a callee and we just skip hashing it.
- if (const FunctionDecl *D = S->getDirectCallee()) {
- // If the function is a template specialization, we also need to handle
- // the template arguments as they are not included in the qualified name.
- if (auto Args = D->getTemplateSpecializationArgs()) {
- std::string ArgString;
-
- // Print all template arguments into ArgString
- llvm::raw_string_ostream OS(ArgString);
- for (unsigned i = 0; i < Args->size(); ++i) {
- Args->get(i).print(Context.getLangOpts(), OS);
- // Add a padding character so that 'foo<X, XX>()' != 'foo<XX, X>()'.
- OS << '\n';
- }
- OS.flush();
-
- addData(ArgString);
- }
- addData(D->getQualifiedNameAsString());
- }
- })
-
- //--- Exceptions ---------------------------------------------------------//
- DEF_ADD_DATA(CXXCatchStmt, { addData(S->getCaughtType()); })
-
- //--- C++ OOP Stmts ------------------------------------------------------//
- DEF_ADD_DATA(CXXDeleteExpr, {
- addData(S->isArrayFormAsWritten());
- addData(S->isGlobalDelete());
- })
-
- //--- Casts --------------------------------------------------------------//
- DEF_ADD_DATA(ObjCBridgedCastExpr, { addData(S->getBridgeKind()); })
-
- //--- Miscellaneous Exprs ------------------------------------------------//
- DEF_ADD_DATA(BinaryOperator, { addData(S->getOpcode()); })
- DEF_ADD_DATA(UnaryOperator, { addData(S->getOpcode()); })
-
- //--- Control flow -------------------------------------------------------//
- DEF_ADD_DATA(GotoStmt, { addData(S->getLabel()->getName()); })
- DEF_ADD_DATA(IndirectGotoStmt, {
- if (S->getConstantTarget())
- addData(S->getConstantTarget()->getName());
- })
- DEF_ADD_DATA(LabelStmt, { addData(S->getDecl()->getName()); })
- DEF_ADD_DATA(MSDependentExistsStmt, { addData(S->isIfExists()); })
- DEF_ADD_DATA(AddrLabelExpr, { addData(S->getLabel()->getName()); })
-
- //--- Objective-C --------------------------------------------------------//
- DEF_ADD_DATA(ObjCIndirectCopyRestoreExpr, { addData(S->shouldCopy()); })
- DEF_ADD_DATA(ObjCPropertyRefExpr, {
- addData(S->isSuperReceiver());
- addData(S->isImplicitProperty());
- })
- DEF_ADD_DATA(ObjCAtCatchStmt, { addData(S->hasEllipsis()); })
-
- //--- Miscellaneous Stmts ------------------------------------------------//
- DEF_ADD_DATA(CXXFoldExpr, {
- addData(S->isRightFold());
- addData(S->getOperator());
- })
- DEF_ADD_DATA(GenericSelectionExpr, {
- for (unsigned i = 0; i < S->getNumAssocs(); ++i) {
- addData(S->getAssocType(i));
- }
- })
- DEF_ADD_DATA(LambdaExpr, {
- for (const LambdaCapture &C : S->captures()) {
- addData(C.isPackExpansion());
- addData(C.getCaptureKind());
- if (C.capturesVariable())
- addData(C.getCapturedVar()->getType());
- }
- addData(S->isGenericLambda());
- addData(S->isMutable());
- })
- DEF_ADD_DATA(DeclStmt, {
- auto numDecls = std::distance(S->decl_begin(), S->decl_end());
- addData(static_cast<DataPiece>(numDecls));
- for (const Decl *D : S->decls()) {
- if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
- addData(VD->getType());
- }
- }
- })
- DEF_ADD_DATA(AsmStmt, {
- addData(S->isSimple());
- addData(S->isVolatile());
- addData(S->generateAsmString(Context));
- for (unsigned i = 0; i < S->getNumInputs(); ++i) {
- addData(S->getInputConstraint(i));
- }
- for (unsigned i = 0; i < S->getNumOutputs(); ++i) {
- addData(S->getOutputConstraint(i));
- }
- for (unsigned i = 0; i < S->getNumClobbers(); ++i) {
- addData(S->getClobber(i));
- }
- })
- DEF_ADD_DATA(AttributedStmt, {
- for (const Attr *A : S->getAttrs()) {
- addData(std::string(A->getSpelling()));
- }
- })
-};
-} // namespace clone_detection
-
/// Identifies a list of statements.
///
/// Can either identify a single arbitrary Stmt object, a continuous sequence of
@@ -423,9 +233,9 @@ public:
/// filtered.
/// \param Filter The filter function that should return true for all groups
/// that should be removed from the list.
- static void
- filterGroups(std::vector<CloneDetector::CloneGroup> &CloneGroups,
- std::function<bool(const CloneDetector::CloneGroup &)> Filter) {
+ static void filterGroups(
+ std::vector<CloneDetector::CloneGroup> &CloneGroups,
+ llvm::function_ref<bool(const CloneDetector::CloneGroup &)> Filter) {
CloneGroups.erase(
std::remove_if(CloneGroups.begin(), CloneGroups.end(), Filter),
CloneGroups.end());
@@ -439,25 +249,29 @@ public:
/// to the same CloneGroup.
static void splitCloneGroups(
std::vector<CloneDetector::CloneGroup> &CloneGroups,
- std::function<bool(const StmtSequence &, const StmtSequence &)> Compare);
+ llvm::function_ref<bool(const StmtSequence &, const StmtSequence &)>
+ Compare);
};
-/// Searches all children of the given clones for type II clones (i.e. they are
-/// identical in every aspect beside the used variable names).
-class RecursiveCloneTypeIIConstraint {
-
- /// Generates and saves a hash code for the given Stmt.
- /// \param S The given Stmt.
- /// \param D The Decl containing S.
- /// \param StmtsByHash Output parameter that will contain the hash codes for
- /// each StmtSequence in the given Stmt.
- /// \return The hash code of the given Stmt.
- ///
- /// If the given Stmt is a CompoundStmt, this method will also generate
- /// hashes for all possible StmtSequences in the children of this Stmt.
- size_t saveHash(const Stmt *S, const Decl *D,
- std::vector<std::pair<size_t, StmtSequence>> &StmtsByHash);
+/// This constraint moves clones into clone groups of type II via hashing.
+///
+/// Clones with different hash values are moved into separate clone groups.
+/// Collisions are possible, and this constraint does nothing to address this
+/// them. Add the slower RecursiveCloneTypeIIVerifyConstraint later in the
+/// constraint chain, not necessarily immediately, to eliminate hash collisions
+/// through a more detailed analysis.
+class RecursiveCloneTypeIIHashConstraint {
+public:
+ void constrain(std::vector<CloneDetector::CloneGroup> &Sequences);
+};
+/// This constraint moves clones into clone groups of type II by comparing them.
+///
+/// Clones that aren't type II clones are moved into separate clone groups.
+/// In contrast to the RecursiveCloneTypeIIHashConstraint, all clones in a clone
+/// group are guaranteed to be be type II clones of each other, but it is too
+/// slow to efficiently handle large amounts of clones.
+class RecursiveCloneTypeIIVerifyConstraint {
public:
void constrain(std::vector<CloneDetector::CloneGroup> &Sequences);
};
@@ -474,14 +288,19 @@ public:
MinComplexityConstraint(unsigned MinComplexity)
: MinComplexity(MinComplexity) {}
- size_t calculateStmtComplexity(const StmtSequence &Seq,
+ /// Calculates the complexity of the given StmtSequence.
+ /// \param Limit The limit of complexity we probe for. After reaching
+ /// this limit during calculation, this method is exiting
+ /// early to improve performance and returns this limit.
+ size_t calculateStmtComplexity(const StmtSequence &Seq, std::size_t Limit,
const std::string &ParentMacroStack = "");
void constrain(std::vector<CloneDetector::CloneGroup> &CloneGroups) {
CloneConstraint::filterGroups(
CloneGroups, [this](const CloneDetector::CloneGroup &A) {
if (!A.empty())
- return calculateStmtComplexity(A.front()) < MinComplexity;
+ return calculateStmtComplexity(A.front(), MinComplexity) <
+ MinComplexity;
else
return false;
});
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h b/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h
index be5adfb29423c..2d59dec48a880 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h
@@ -15,7 +15,7 @@
#ifndef LLVM_CLANG_ANALYSIS_PROGRAMPOINT_H
#define LLVM_CLANG_ANALYSIS_PROGRAMPOINT_H
-#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
@@ -83,6 +83,7 @@ public:
PostImplicitCallKind,
MinImplicitCallKind = PreImplicitCallKind,
MaxImplicitCallKind = PostImplicitCallKind,
+ LoopExitKind,
EpsilonKind};
private:
@@ -654,6 +655,29 @@ private:
}
};
+/// Represents a point when we exit a loop.
+/// When this ProgramPoint is encountered we can be sure that the symbolic
+/// execution of the corresponding LoopStmt is finished on the given path.
+/// Note: It is possible to encounter a LoopExit element when we haven't even
+/// encountered the loop itself. At the current state not all loop exits will
+/// result in a LoopExit program point.
+class LoopExit : public ProgramPoint {
+public:
+ LoopExit(const Stmt *LoopStmt, const LocationContext *LC)
+ : ProgramPoint(LoopStmt, nullptr, LoopExitKind, LC) {}
+
+ const Stmt *getLoopStmt() const {
+ return static_cast<const Stmt *>(getData1());
+ }
+
+private:
+ friend class ProgramPoint;
+ LoopExit() {}
+ static bool isKind(const ProgramPoint &Location) {
+ return Location.getKind() == LoopExitKind;
+ }
+};
+
/// This is a meta program point, which should be skipped by all the diagnostic
/// reasoning etc.
class EpsilonPoint : public ProgramPoint {
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Support/BumpVector.h b/contrib/llvm/tools/clang/include/clang/Analysis/Support/BumpVector.h
index 591d17b9bc03c..5940520855ef2 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/Support/BumpVector.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Support/BumpVector.h
@@ -1,4 +1,4 @@
-//===-- BumpVector.h - Vector-like ADT that uses bump allocation --*- C++ -*-=//
+//===- BumpVector.h - Vector-like ADT that uses bump allocation -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -21,16 +21,18 @@
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/Support/Allocator.h"
-#include "llvm/Support/type_traits.h"
-#include <algorithm>
+#include <cassert>
+#include <cstddef>
#include <cstring>
#include <iterator>
#include <memory>
+#include <type_traits>
namespace clang {
class BumpVectorContext {
llvm::PointerIntPair<llvm::BumpPtrAllocator*, 1> Alloc;
+
public:
/// Construct a new BumpVectorContext that creates a new BumpPtrAllocator
/// and destroys it when the BumpVectorContext object is destroyed.
@@ -56,11 +58,13 @@ public:
template<typename T>
class BumpVector {
- T *Begin, *End, *Capacity;
+ T *Begin = nullptr;
+ T *End = nullptr;
+ T *Capacity = nullptr;
+
public:
// Default ctor - Initialize to empty.
- explicit BumpVector(BumpVectorContext &C, unsigned N)
- : Begin(nullptr), End(nullptr), Capacity(nullptr) {
+ explicit BumpVector(BumpVectorContext &C, unsigned N) {
reserve(C, N);
}
@@ -71,19 +75,19 @@ public:
}
}
- typedef size_t size_type;
- typedef ptrdiff_t difference_type;
- typedef T value_type;
- typedef T* iterator;
- typedef const T* const_iterator;
+ using size_type = size_t;
+ using difference_type = ptrdiff_t;
+ using value_type = T;
+ using iterator = T *;
+ using const_iterator = const T *;
- typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
- typedef std::reverse_iterator<iterator> reverse_iterator;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+ using reverse_iterator = std::reverse_iterator<iterator>;
- typedef T& reference;
- typedef const T& const_reference;
- typedef T* pointer;
- typedef const T* const_pointer;
+ using reference = T &;
+ using const_reference = const T &;
+ using pointer = T *;
+ using const_pointer = const T *;
// forward iterator creation methods.
iterator begin() { return Begin; }
@@ -92,10 +96,12 @@ public:
const_iterator end() const { return End; }
// reverse iterator creation methods.
- reverse_iterator rbegin() { return reverse_iterator(end()); }
+ reverse_iterator rbegin() { return reverse_iterator(end()); }
const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); }
- reverse_iterator rend() { return reverse_iterator(begin()); }
- const_reverse_iterator rend() const { return const_reverse_iterator(begin());}
+ reverse_iterator rend() { return reverse_iterator(begin()); }
+ const_reverse_iterator rend() const {
+ return const_reverse_iterator(begin());
+ }
bool empty() const { return Begin == End; }
size_type size() const { return End-Begin; }
@@ -166,7 +172,7 @@ public:
/// iterator to position after last inserted copy.
iterator insert(iterator I, size_t Cnt, const_reference E,
BumpVectorContext &C) {
- assert (I >= Begin && I <= End && "Iterator out of bounds.");
+ assert(I >= Begin && I <= End && "Iterator out of bounds.");
if (End + Cnt <= Capacity) {
Retry:
move_range_right(I, End, Cnt);
@@ -246,5 +252,6 @@ void BumpVector<T>::grow(BumpVectorContext &C, size_t MinSize) {
Capacity = Begin+NewCapacity;
}
-} // end: clang namespace
-#endif
+} // namespace clang
+
+#endif // LLVM_CLANG_ANALYSIS_SUPPORT_BUMPVECTOR_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/AddressSpaces.h b/contrib/llvm/tools/clang/include/clang/Basic/AddressSpaces.h
index 95b9b9c7d0b31..6b0090813e9b4 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/AddressSpaces.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/AddressSpaces.h
@@ -16,25 +16,26 @@
#ifndef LLVM_CLANG_BASIC_ADDRESSSPACES_H
#define LLVM_CLANG_BASIC_ADDRESSSPACES_H
-namespace clang {
+#include <assert.h>
-namespace LangAS {
+namespace clang {
/// \brief Defines the address space values used by the address space qualifier
/// of QualType.
///
-enum ID {
+enum class LangAS : unsigned {
// The default value 0 is the value used in QualType for the the situation
- // where there is no address space qualifier. For most languages, this also
- // corresponds to the situation where there is no address space qualifier in
- // the source code, except for OpenCL, where the address space value 0 in
- // QualType represents private address space in OpenCL source code.
+ // where there is no address space qualifier.
Default = 0,
// OpenCL specific address spaces.
+ // In OpenCL each l-value must have certain non-default address space, each
+ // r-value must have no address space (i.e. the default address space). The
+ // pointee of a pointer must have non-default address space.
opencl_global,
opencl_local,
opencl_constant,
+ opencl_private,
opencl_generic,
// CUDA specific address spaces.
@@ -50,9 +51,24 @@ enum ID {
/// The type of a lookup table which maps from language-specific address spaces
/// to target-specific ones.
-typedef unsigned Map[FirstTargetAddressSpace];
+typedef unsigned LangASMap[(unsigned)LangAS::FirstTargetAddressSpace];
+
+/// \return whether \p AS is a target-specific address space rather than a
+/// clang AST address space
+inline bool isTargetAddressSpace(LangAS AS) {
+ return (unsigned)AS >= (unsigned)LangAS::FirstTargetAddressSpace;
}
+inline unsigned toTargetAddressSpace(LangAS AS) {
+ assert(isTargetAddressSpace(AS));
+ return (unsigned)AS - (unsigned)LangAS::FirstTargetAddressSpace;
}
+inline LangAS getLangASFromTargetAS(unsigned TargetAS) {
+ return static_cast<LangAS>((TargetAS) +
+ (unsigned)LangAS::FirstTargetAddressSpace);
+}
+
+} // namespace clang
+
#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/AlignedAllocation.h b/contrib/llvm/tools/clang/include/clang/Basic/AlignedAllocation.h
new file mode 100644
index 0000000000000..b3496949f39ac
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/AlignedAllocation.h
@@ -0,0 +1,44 @@
+//===--- AlignedAllocation.h - Aligned Allocation ---------------*- 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 a function that returns the minimum OS versions supporting
+/// C++17's aligned allocation functions.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_ALIGNED_ALLOCATION_H
+#define LLVM_CLANG_BASIC_ALIGNED_ALLOCATION_H
+
+#include "clang/Basic/VersionTuple.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/ErrorHandling.h"
+
+namespace clang {
+
+inline VersionTuple alignedAllocMinVersion(llvm::Triple::OSType OS) {
+ switch (OS) {
+ default:
+ break;
+ case llvm::Triple::Darwin:
+ case llvm::Triple::MacOSX: // Earliest supporting version is 10.13.
+ return VersionTuple(10U, 13U);
+ case llvm::Triple::IOS:
+ case llvm::Triple::TvOS: // Earliest supporting version is 11.0.0.
+ return VersionTuple(11U);
+ case llvm::Triple::WatchOS: // Earliest supporting version is 4.0.0.
+ return VersionTuple(4U);
+ }
+
+ llvm_unreachable("Unexpected OS");
+}
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_BASIC_ALIGNED_ALLOCATION_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/AllDiagnostics.h b/contrib/llvm/tools/clang/include/clang/Basic/AllDiagnostics.h
index fc861a1952a51..1c83e2d0f8a0b 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/AllDiagnostics.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/AllDiagnostics.h
@@ -18,12 +18,14 @@
#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/CommentDiagnostic.h"
#include "clang/Analysis/AnalysisDiagnostic.h"
+#include "clang/CrossTU/CrossTUDiagnostic.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "clang/Serialization/SerializationDiagnostic.h"
+#include "clang/Tooling/Refactoring/RefactoringDiagnostic.h"
namespace clang {
template <size_t SizeOfStr, typename FieldType>
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Attr.td b/contrib/llvm/tools/clang/include/clang/Basic/Attr.td
index 5c69635b94924..d926fdde4eeed 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Attr.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Attr.td
@@ -69,44 +69,47 @@ include "clang/Basic/StmtNodes.td"
//
// The code fragment is a boolean expression that will confirm that the subject
// meets the requirements; the subject will have the name S, and will have the
-// type specified by the base. It should be a simple boolean expression.
-class SubsetSubject<AttrSubject base, code check> : AttrSubject {
+// type specified by the base. It should be a simple boolean expression. The
+// diagnostic string should be a comma-separated list of subject names.
+class SubsetSubject<AttrSubject base, code check, string diag> : AttrSubject {
AttrSubject Base = base;
code CheckCode = check;
+ string DiagSpelling = diag;
}
-// This is the type of a variable which C++11 allows alignas(...) to appertain
-// to.
-def NormalVar : SubsetSubject<Var,
- [{S->getStorageClass() != VarDecl::Register &&
- S->getKind() != Decl::ImplicitParam &&
- S->getKind() != Decl::ParmVar &&
- S->getKind() != Decl::NonTypeTemplateParm}]>;
+def LocalVar : SubsetSubject<Var,
+ [{S->hasLocalStorage() && !isa<ParmVarDecl>(S)}],
+ "local variables">;
def NonParmVar : SubsetSubject<Var,
- [{S->getKind() != Decl::ParmVar}]>;
+ [{S->getKind() != Decl::ParmVar}],
+ "variables">;
def NonBitField : SubsetSubject<Field,
- [{!S->isBitField()}]>;
+ [{!S->isBitField()}],
+ "non-bit-field non-static data members">;
def ObjCInstanceMethod : SubsetSubject<ObjCMethod,
- [{S->isInstanceMethod()}]>;
+ [{S->isInstanceMethod()}],
+ "Objective-C instance methods">;
def ObjCInterfaceDeclInitMethod : SubsetSubject<ObjCMethod,
[{S->getMethodFamily() == OMF_init &&
(isa<ObjCInterfaceDecl>(S->getDeclContext()) ||
(isa<ObjCCategoryDecl>(S->getDeclContext()) &&
- cast<ObjCCategoryDecl>(S->getDeclContext())->IsClassExtension()))}]>;
+ cast<ObjCCategoryDecl>(S->getDeclContext())->IsClassExtension()))}],
+ "init methods of interface or class extension declarations">;
def Struct : SubsetSubject<Record,
- [{!S->isUnion()}]>;
+ [{!S->isUnion()}], "structs">;
def TLSVar : SubsetSubject<Var,
- [{S->getTLSKind() != 0}]>;
+ [{S->getTLSKind() != 0}], "thread-local variables">;
def SharedVar : SubsetSubject<Var,
- [{S->hasGlobalStorage() && !S->getTLSKind()}]>;
+ [{S->hasGlobalStorage() && !S->getTLSKind()}],
+ "global variables">;
def GlobalVar : SubsetSubject<Var,
- [{S->hasGlobalStorage()}]>;
+ [{S->hasGlobalStorage()}], "global variables">;
// FIXME: this hack is needed because DeclNodes.td defines the base Decl node
// type to be a class, not a definition. This makes it impossible to create an
@@ -115,11 +118,12 @@ def GlobalVar : SubsetSubject<Var,
// the case of a SubsetSubject, there's no way to express it without this hack.
def DeclBase : AttrSubject;
def FunctionLike : SubsetSubject<DeclBase,
- [{S->getFunctionType(false) != nullptr}]>;
+ [{S->getFunctionType(false) != nullptr}],
+ "functions, function pointers">;
-def OpenCLKernelFunction : SubsetSubject<Function, [{
- S->hasAttr<OpenCLKernelAttr>()
-}]>;
+def OpenCLKernelFunction
+ : SubsetSubject<Function, [{S->hasAttr<OpenCLKernelAttr>()}],
+ "kernel functions">;
// HasFunctionProto is a more strict version of FunctionLike, so it should
// never be specified in a Subjects list along with FunctionLike (due to the
@@ -128,7 +132,8 @@ def HasFunctionProto : SubsetSubject<DeclBase,
[{(S->getFunctionType(true) != nullptr &&
isa<FunctionProtoType>(S->getFunctionType())) ||
isa<ObjCMethodDecl>(S) ||
- isa<BlockDecl>(S)}]>;
+ isa<BlockDecl>(S)}],
+ "non-K&R-style functions">;
// A single argument to an attribute
class Argument<string name, bit optional, bit fake = 0> {
@@ -210,18 +215,26 @@ class CXX11<string namespace, string name, int version = 1>
string Namespace = namespace;
int Version = version;
}
+class C2x<string namespace, string name> : Spelling<name, "C2x"> {
+ string Namespace = namespace;
+}
+
class Keyword<string name> : Spelling<name, "Keyword">;
class Pragma<string namespace, string name> : Spelling<name, "Pragma"> {
string Namespace = namespace;
}
-// The GCC spelling implies GNU<name, "GNU"> and CXX11<"gnu", name> and also
-// sets KnownToGCC to 1. This spelling should be used for any GCC-compatible
+// The GCC spelling implies GNU<name> and CXX11<"gnu", name> and also sets
+// KnownToGCC to 1. This spelling should be used for any GCC-compatible
// attributes.
class GCC<string name> : Spelling<name, "GCC"> {
let KnownToGCC = 1;
}
+// The Clang spelling implies GNU<name> and CXX11<"clang", name>. This spelling
+// should be used for any Clang-specific attributes.
+class Clang<string name> : Spelling<name, "Clang">;
+
class Accessor<string name, list<Spelling> spellings> {
string Name = name;
list<Spelling> Spellings = spellings;
@@ -264,14 +277,15 @@ class TargetArch<list<string> arches> {
}
def TargetARM : TargetArch<["arm", "thumb", "armeb", "thumbeb"]>;
def TargetAVR : TargetArch<["avr"]>;
-def TargetMips : TargetArch<["mips", "mipsel"]>;
+def TargetMips32 : TargetArch<["mips", "mipsel"]>;
+def TargetAnyMips : TargetArch<["mips", "mipsel", "mips64", "mips64el"]>;
def TargetMSP430 : TargetArch<["msp430"]>;
def TargetX86 : TargetArch<["x86"]>;
def TargetAnyX86 : TargetArch<["x86", "x86_64"]>;
-def TargetWindows : TargetArch<["x86", "x86_64", "arm", "thumb"]> {
+def TargetWindows : TargetArch<["x86", "x86_64", "arm", "thumb", "aarch64"]> {
let OSes = ["Win32"];
}
-def TargetMicrosoftCXXABI : TargetArch<["x86", "x86_64", "arm", "thumb"]> {
+def TargetMicrosoftCXXABI : TargetArch<["x86", "x86_64", "arm", "thumb", "aarch64"]> {
let CXXABIs = ["Microsoft"];
}
@@ -493,14 +507,13 @@ class IgnoredAttr : Attr {
def AbiTag : Attr {
let Spellings = [GCC<"abi_tag">];
let Args = [VariadicStringArgument<"Tags">];
- let Subjects = SubjectList<[Struct, Var, Function, Namespace], ErrorDiag,
- "ExpectedStructClassVariableFunctionOrInlineNamespace">;
+ let Subjects = SubjectList<[Struct, Var, Function, Namespace], ErrorDiag>;
let MeaningfulToClassTemplateDefinition = 1;
let Documentation = [AbiTagsDocs];
}
def AddressSpace : TypeAttr {
- let Spellings = [GNU<"address_space">];
+ let Spellings = [Clang<"address_space">];
let Args = [IntArgument<"AddressSpace">];
let Documentation = [Undocumented];
}
@@ -508,15 +521,13 @@ def AddressSpace : TypeAttr {
def Alias : Attr {
let Spellings = [GCC<"alias">];
let Args = [StringArgument<"Aliasee">];
- let Subjects = SubjectList<[Function, GlobalVar], ErrorDiag,
- "ExpectedFunctionOrGlobalVar">;
+ let Subjects = SubjectList<[Function, GlobalVar], ErrorDiag>;
let Documentation = [Undocumented];
}
def Aligned : InheritableAttr {
let Spellings = [GCC<"aligned">, Declspec<"align">, Keyword<"alignas">,
Keyword<"_Alignas">];
-// let Subjects = SubjectList<[NonBitField, NormalVar, Tag]>;
let Args = [AlignedArgument<"Alignment", 1>];
let Accessors = [Accessor<"isGNU", [GCC<"aligned">]>,
Accessor<"isC11", [Keyword<"_Alignas">]>,
@@ -534,13 +545,15 @@ def AlignValue : Attr {
// 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.
+ //
+ // Does not get a [[]] spelling because the attribute is not exposed as such
+ // by Intel.
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 Subjects = SubjectList<[Var, TypedefName]>;
let Documentation = [AlignValueDocs];
}
@@ -558,44 +571,40 @@ def AlwaysInline : InheritableAttr {
}
def XRayInstrument : InheritableAttr {
- let Spellings = [GNU<"xray_always_instrument">,
- CXX11<"clang", "xray_always_instrument">,
- GNU<"xray_never_instrument">,
- CXX11<"clang", "xray_never_instrument">];
- let Subjects = SubjectList<[CXXMethod, ObjCMethod, Function], WarnDiag,
- "ExpectedFunctionOrMethod">;
+ let Spellings = [Clang<"xray_always_instrument">,
+ Clang<"xray_never_instrument">];
+ let Subjects = SubjectList<[Function, ObjCMethod]>;
let Accessors = [Accessor<"alwaysXRayInstrument",
- [GNU<"xray_always_instrument">,
- CXX11<"clang", "xray_always_instrument">]>,
+ [Clang<"xray_always_instrument">]>,
Accessor<"neverXRayInstrument",
- [GNU<"xray_never_instrument">,
- CXX11<"clang", "xray_never_instrument">]>];
+ [Clang<"xray_never_instrument">]>];
let Documentation = [XRayDocs];
}
def XRayLogArgs : InheritableAttr {
- let Spellings = [GNU<"xray_log_args">, CXX11<"clang", "xray_log_args">];
- let Subjects = SubjectList<
- [CXXMethod, ObjCMethod, Function], WarnDiag, "ExpectedFunctionOrMethod"
- >;
+ let Spellings = [Clang<"xray_log_args">];
+ let Subjects = SubjectList<[Function, ObjCMethod]>;
let Args = [UnsignedArgument<"ArgumentCount">];
let Documentation = [XRayDocs];
}
def TLSModel : InheritableAttr {
let Spellings = [GCC<"tls_model">];
- let Subjects = SubjectList<[TLSVar], ErrorDiag, "ExpectedTLSVar">;
+ let Subjects = SubjectList<[TLSVar], ErrorDiag>;
let Args = [StringArgument<"Model">];
let Documentation = [TLSModelDocs];
}
def AnalyzerNoReturn : InheritableAttr {
+ // TODO: should this attribute be exposed with a [[]] spelling under the clang
+ // vendor namespace, or should it use a vendor namespace specific to the
+ // analyzer?
let Spellings = [GNU<"analyzer_noreturn">];
let Documentation = [Undocumented];
}
def Annotate : InheritableParamAttr {
- let Spellings = [GNU<"annotate">];
+ let Spellings = [Clang<"annotate">];
let Args = [StringArgument<"Annotation">];
// Ensure that the annotate attribute can be used with
// '#pragma clang attribute' even though it has no subject list.
@@ -606,7 +615,7 @@ def Annotate : InheritableParamAttr {
def ARMInterrupt : InheritableAttr, TargetSpecificAttr<TargetARM> {
// NOTE: If you add any additional spellings, MSP430Interrupt's,
// MipsInterrupt's and AnyX86Interrupt's spellings must match.
- let Spellings = [GNU<"interrupt">];
+ let Spellings = [GCC<"interrupt">];
let Args = [EnumArgument<"Interrupt", "InterruptType",
["IRQ", "FIQ", "SWI", "ABORT", "UNDEF", ""],
["IRQ", "FIQ", "SWI", "ABORT", "UNDEF", "Generic"],
@@ -617,14 +626,14 @@ def ARMInterrupt : InheritableAttr, TargetSpecificAttr<TargetARM> {
}
def AVRInterrupt : InheritableAttr, TargetSpecificAttr<TargetAVR> {
- let Spellings = [GNU<"interrupt">];
+ let Spellings = [GCC<"interrupt">];
let Subjects = SubjectList<[Function]>;
let ParseKind = "Interrupt";
let Documentation = [AVRInterruptDocs];
}
def AVRSignal : InheritableAttr, TargetSpecificAttr<TargetAVR> {
- let Spellings = [GNU<"signal">];
+ let Spellings = [GCC<"signal">];
let Subjects = SubjectList<[Function]>;
let Documentation = [AVRSignalDocs];
}
@@ -637,6 +646,8 @@ def AsmLabel : InheritableAttr {
}
def Availability : InheritableAttr {
+ // TODO: does not have a [[]] spelling because it requires custom parsing
+ // support.
let Spellings = [GNU<"availability">];
let Args = [IdentifierArgument<"platform">, VersionArgument<"introduced">,
VersionArgument<"deprecated">, VersionArgument<"obsoleted">,
@@ -687,8 +698,7 @@ static llvm::StringRef canonicalizePlatformName(llvm::StringRef Platform) {
}
def ExternalSourceSymbol : InheritableAttr {
- let Spellings = [GNU<"external_source_symbol">,
- CXX11<"clang", "external_source_symbol">];
+ let Spellings = [Clang<"external_source_symbol">];
let Args = [StringArgument<"language", 1>,
StringArgument<"definedIn", 1>,
BoolArgument<"generatedDeclaration", 1>];
@@ -698,12 +708,13 @@ def ExternalSourceSymbol : InheritableAttr {
}
def Blocks : InheritableAttr {
- let Spellings = [GNU<"blocks">];
+ let Spellings = [Clang<"blocks">];
let Args = [EnumArgument<"Type", "BlockType", ["byref"], ["ByRef"]>];
let Documentation = [Undocumented];
}
def Bounded : IgnoredAttr {
+ // Does not have a [[]] spelling because the attribute is ignored.
let Spellings = [GNU<"bounded">];
}
@@ -725,7 +736,7 @@ def CDecl : InheritableAttr {
// cf_returns_retained attributes. It is generally applied by
// '#pragma clang arc_cf_code_audited' rather than explicitly.
def CFAuditedTransfer : InheritableAttr {
- let Spellings = [GNU<"cf_audited_transfer">];
+ let Spellings = [Clang<"cf_audited_transfer">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [Undocumented];
}
@@ -734,25 +745,25 @@ def CFAuditedTransfer : InheritableAttr {
// It indicates that the function has unknown or unautomatable
// transfer semantics.
def CFUnknownTransfer : InheritableAttr {
- let Spellings = [GNU<"cf_unknown_transfer">];
+ let Spellings = [Clang<"cf_unknown_transfer">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [Undocumented];
}
def CFReturnsRetained : InheritableAttr {
- let Spellings = [GNU<"cf_returns_retained">];
+ let Spellings = [Clang<"cf_returns_retained">];
// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;
let Documentation = [Undocumented];
}
def CFReturnsNotRetained : InheritableAttr {
- let Spellings = [GNU<"cf_returns_not_retained">];
+ let Spellings = [Clang<"cf_returns_not_retained">];
// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;
let Documentation = [Undocumented];
}
def CFConsumed : InheritableParamAttr {
- let Spellings = [GNU<"cf_consumed">];
+ let Spellings = [Clang<"cf_consumed">];
let Subjects = SubjectList<[ParmVar]>;
let Documentation = [Undocumented];
}
@@ -760,7 +771,7 @@ def CFConsumed : InheritableParamAttr {
def Cleanup : InheritableAttr {
let Spellings = [GCC<"cleanup">];
let Args = [FunctionArgument<"FunctionDecl">];
- let Subjects = SubjectList<[Var]>;
+ let Subjects = SubjectList<[LocalVar]>;
let Documentation = [Undocumented];
}
@@ -788,8 +799,8 @@ def Constructor : InheritableAttr {
let Documentation = [Undocumented];
}
-// CUDA attributes are spelled __attribute__((attr)) or __declspec(__attr__).
-
+// CUDA attributes are spelled __attribute__((attr)) or __declspec(__attr__),
+// and they do not receive a [[]] spelling.
def CUDAConstant : InheritableAttr {
let Spellings = [GNU<"constant">, Declspec<"__constant__">];
let Subjects = SubjectList<[Var]>;
@@ -851,8 +862,7 @@ def CUDALaunchBounds : InheritableAttr {
let Spellings = [GNU<"launch_bounds">, Declspec<"__launch_bounds__">];
let Args = [ExprArgument<"MaxThreads">, ExprArgument<"MinBlocks", 1>];
let LangOpts = [CUDA];
- let Subjects = SubjectList<[ObjCMethod, FunctionLike], WarnDiag,
- "ExpectedFunctionOrMethod">;
+ let Subjects = SubjectList<[ObjCMethod, FunctionLike]>;
// An AST node is created for this attribute, but is not used by other parts
// of the compiler. However, this node needs to exist in the AST because
// non-LLVM backends may be relying on the attribute's presence.
@@ -874,11 +884,13 @@ def C11NoReturn : InheritableAttr {
}
def CXX11NoReturn : InheritableAttr {
- let Spellings = [CXX11<"","noreturn", 200809>];
+ let Spellings = [CXX11<"", "noreturn", 200809>];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [CXX11NoReturnDocs];
}
+// Similar to CUDA, OpenCL attributes do not receive a [[]] spelling because
+// the specification does not expose them with one currently.
def OpenCLKernel : InheritableAttr {
let Spellings = [Keyword<"__kernel">, Keyword<"kernel">];
let Subjects = SubjectList<[Function], ErrorDiag>;
@@ -904,8 +916,7 @@ def OpenCLAccess : Attr {
let Spellings = [Keyword<"__read_only">, Keyword<"read_only">,
Keyword<"__write_only">, Keyword<"write_only">,
Keyword<"__read_write">, Keyword<"read_write">];
- let Subjects = SubjectList<[ParmVar, TypedefName], ErrorDiag,
- "ExpectedParameterOrTypedef">;
+ let Subjects = SubjectList<[ParmVar, TypedefName], ErrorDiag>;
let Accessors = [Accessor<"isReadOnly", [Keyword<"__read_only">,
Keyword<"read_only">]>,
Accessor<"isReadWrite", [Keyword<"__read_write">,
@@ -957,7 +968,7 @@ def RenderScriptKernel : Attr {
def Deprecated : InheritableAttr {
let Spellings = [GCC<"deprecated">, Declspec<"deprecated">,
- CXX11<"","deprecated", 201309>];
+ CXX11<"","deprecated", 201309>, C2x<"", "deprecated">];
let Args = [StringArgument<"Message", 1>,
// An optional string argument that enables us to provide a
// Fix-It.
@@ -988,6 +999,9 @@ def AllocSize : InheritableAttr {
}
def EnableIf : InheritableAttr {
+ // Does not have a [[]] spelling because this attribute requires the ability
+ // to parse function arguments but the attribute is not written in the type
+ // position.
let Spellings = [GNU<"enable_if">];
let Subjects = SubjectList<[Function]>;
let Args = [ExprArgument<"Cond">, StringArgument<"Message">];
@@ -996,6 +1010,7 @@ def EnableIf : InheritableAttr {
}
def ExtVectorType : Attr {
+ // This is an OpenCL-related attribute and does not receive a [[]] spelling.
let Spellings = [GNU<"ext_vector_type">];
let Subjects = SubjectList<[TypedefName], ErrorDiag>;
let Args = [ExprArgument<"NumElements">];
@@ -1004,7 +1019,7 @@ def ExtVectorType : Attr {
}
def FallThrough : StmtAttr {
- let Spellings = [CXX11<"", "fallthrough", 201603>,
+ let Spellings = [CXX11<"", "fallthrough", 201603>, C2x<"", "fallthrough">,
CXX11<"clang", "fallthrough">];
// let Subjects = [NullStmt];
let Documentation = [FallthroughDocs];
@@ -1030,20 +1045,19 @@ def Final : InheritableAttr {
}
def MinSize : InheritableAttr {
- let Spellings = [GNU<"minsize">];
+ let Spellings = [Clang<"minsize">];
let Subjects = SubjectList<[Function, ObjCMethod], ErrorDiag>;
let Documentation = [Undocumented];
}
def FlagEnum : InheritableAttr {
- let Spellings = [GNU<"flag_enum">];
+ let Spellings = [Clang<"flag_enum">];
let Subjects = SubjectList<[Enum]>;
let Documentation = [FlagEnumDocs];
}
def EnumExtensibility : InheritableAttr {
- let Spellings = [GNU<"enum_extensibility">,
- CXX11<"clang", "enum_extensibility">];
+ let Spellings = [Clang<"enum_extensibility">];
let Subjects = SubjectList<[Enum]>;
let Args = [EnumArgument<"Extensibility", "Kind",
["closed", "open"], ["Closed", "Open"]>];
@@ -1060,16 +1074,14 @@ def Format : InheritableAttr {
let Spellings = [GCC<"format">];
let Args = [IdentifierArgument<"Type">, IntArgument<"FormatIdx">,
IntArgument<"FirstArg">];
- let Subjects = SubjectList<[ObjCMethod, Block, HasFunctionProto], WarnDiag,
- "ExpectedFunctionWithProtoType">;
+ let Subjects = SubjectList<[ObjCMethod, Block, HasFunctionProto]>;
let Documentation = [FormatDocs];
}
def FormatArg : InheritableAttr {
let Spellings = [GCC<"format_arg">];
let Args = [IntArgument<"FormatIdx">];
- let Subjects = SubjectList<[ObjCMethod, HasFunctionProto], WarnDiag,
- "ExpectedFunctionWithProtoType">;
+ let Subjects = SubjectList<[ObjCMethod, HasFunctionProto]>;
let Documentation = [Undocumented];
}
@@ -1088,9 +1100,8 @@ def Hot : InheritableAttr {
}
def IBAction : InheritableAttr {
- let Spellings = [GNU<"ibaction">];
- let Subjects = SubjectList<[ObjCInstanceMethod], WarnDiag,
- "ExpectedObjCInstanceMethod">;
+ let Spellings = [Clang<"ibaction">];
+ let Subjects = SubjectList<[ObjCInstanceMethod]>;
// An AST node is created for this attribute, but is not used by other parts
// of the compiler. However, this node needs to exist in the AST because
// external tools rely on it.
@@ -1098,13 +1109,13 @@ def IBAction : InheritableAttr {
}
def IBOutlet : InheritableAttr {
- let Spellings = [GNU<"iboutlet">];
+ let Spellings = [Clang<"iboutlet">];
// let Subjects = [ObjCIvar, ObjCProperty];
let Documentation = [Undocumented];
}
def IBOutletCollection : InheritableAttr {
- let Spellings = [GNU<"iboutletcollection">];
+ let Spellings = [Clang<"iboutletcollection">];
let Args = [TypeArgument<"Interface", 1>];
// let Subjects = [ObjCIvar, ObjCProperty];
let Documentation = [Undocumented];
@@ -1153,23 +1164,23 @@ def MSABI : InheritableAttr {
def MSP430Interrupt : InheritableAttr, TargetSpecificAttr<TargetMSP430> {
// NOTE: If you add any additional spellings, ARMInterrupt's, MipsInterrupt's
// and AnyX86Interrupt's spellings must match.
- let Spellings = [GNU<"interrupt">];
+ let Spellings = [GCC<"interrupt">];
let Args = [UnsignedArgument<"Number">];
let ParseKind = "Interrupt";
let HasCustomParsing = 1;
let Documentation = [Undocumented];
}
-def Mips16 : InheritableAttr, TargetSpecificAttr<TargetMips> {
+def Mips16 : InheritableAttr, TargetSpecificAttr<TargetMips32> {
let Spellings = [GCC<"mips16">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [Undocumented];
}
-def MipsInterrupt : InheritableAttr, TargetSpecificAttr<TargetMips> {
+def MipsInterrupt : InheritableAttr, TargetSpecificAttr<TargetMips32> {
// NOTE: If you add any additional spellings, ARMInterrupt's,
// MSP430Interrupt's and AnyX86Interrupt's spellings must match.
- let Spellings = [GNU<"interrupt">];
+ let Spellings = [GCC<"interrupt">];
let Subjects = SubjectList<[Function]>;
let Args = [EnumArgument<"Interrupt", "InterruptType",
["vector=sw0", "vector=sw1", "vector=hw0",
@@ -1182,16 +1193,27 @@ def MipsInterrupt : InheritableAttr, TargetSpecificAttr<TargetMips> {
let Documentation = [MipsInterruptDocs];
}
-def MicroMips : InheritableAttr, TargetSpecificAttr<TargetMips> {
+def MicroMips : InheritableAttr, TargetSpecificAttr<TargetMips32> {
let Spellings = [GCC<"micromips">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [MicroMipsDocs];
}
+def MipsLongCall : InheritableAttr, TargetSpecificAttr<TargetAnyMips> {
+ let Spellings = [GCC<"long_call">, GCC<"far">];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [MipsLongCallStyleDocs];
+}
+
+def MipsShortCall : InheritableAttr, TargetSpecificAttr<TargetAnyMips> {
+ let Spellings = [GCC<"short_call">, GCC<"near">];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [MipsShortCallStyleDocs];
+}
+
def Mode : Attr {
let Spellings = [GCC<"mode">];
- let Subjects = SubjectList<[Var, Enum, TypedefName, Field], ErrorDiag,
- "ExpectedVariableEnumFieldOrTypedef">;
+ let Subjects = SubjectList<[Var, Enum, TypedefName, Field], ErrorDiag>;
let Args = [IdentifierArgument<"Mode">];
let Documentation = [Undocumented];
}
@@ -1203,13 +1225,13 @@ def Naked : InheritableAttr {
}
def NeonPolyVectorType : TypeAttr {
- let Spellings = [GNU<"neon_polyvector_type">];
+ let Spellings = [Clang<"neon_polyvector_type">];
let Args = [IntArgument<"NumElements">];
let Documentation = [Undocumented];
}
def NeonVectorType : TypeAttr {
- let Spellings = [GNU<"neon_vector_type">];
+ let Spellings = [Clang<"neon_vector_type">];
let Args = [IntArgument<"NumElements">];
let Documentation = [Undocumented];
}
@@ -1221,8 +1243,7 @@ def ReturnsTwice : InheritableAttr {
}
def DisableTailCalls : InheritableAttr {
- let Spellings = [GNU<"disable_tail_calls">,
- CXX11<"clang", "disable_tail_calls">];
+ let Spellings = [Clang<"disable_tail_calls">];
let Subjects = SubjectList<[Function, ObjCMethod]>;
let Documentation = [DisableTailCallsDocs];
}
@@ -1241,19 +1262,18 @@ def NoCommon : InheritableAttr {
def NoDebug : InheritableAttr {
let Spellings = [GCC<"nodebug">];
- let Subjects = SubjectList<[FunctionLike, ObjCMethod, NonParmVar], WarnDiag,
- "ExpectedVariableOrFunction">;
+ let Subjects = SubjectList<[FunctionLike, ObjCMethod, NonParmVar]>;
let Documentation = [NoDebugDocs];
}
def NoDuplicate : InheritableAttr {
- let Spellings = [GNU<"noduplicate">, CXX11<"clang", "noduplicate">];
+ let Spellings = [Clang<"noduplicate">];
let Subjects = SubjectList<[Function]>;
let Documentation = [NoDuplicateDocs];
}
def Convergent : InheritableAttr {
- let Spellings = [GNU<"convergent">, CXX11<"clang", "convergent">];
+ let Spellings = [Clang<"convergent">];
let Subjects = SubjectList<[Function]>;
let Documentation = [ConvergentDocs];
}
@@ -1264,13 +1284,13 @@ def NoInline : InheritableAttr {
let Documentation = [Undocumented];
}
-def NoMips16 : InheritableAttr, TargetSpecificAttr<TargetMips> {
+def NoMips16 : InheritableAttr, TargetSpecificAttr<TargetMips32> {
let Spellings = [GCC<"nomips16">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [Undocumented];
}
-def NoMicroMips : InheritableAttr, TargetSpecificAttr<TargetMips> {
+def NoMicroMips : InheritableAttr, TargetSpecificAttr<TargetMips32> {
let Spellings = [GCC<"nomicromips">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [MicroMipsDocs];
@@ -1294,31 +1314,31 @@ def NoMicroMips : InheritableAttr, TargetSpecificAttr<TargetMips> {
// this should be rejected on non-kernels.
def AMDGPUFlatWorkGroupSize : InheritableAttr {
- let Spellings = [GNU<"amdgpu_flat_work_group_size">];
+ let Spellings = [Clang<"amdgpu_flat_work_group_size">];
let Args = [UnsignedArgument<"Min">, UnsignedArgument<"Max">];
let Documentation = [AMDGPUFlatWorkGroupSizeDocs];
- let Subjects = SubjectList<[Function], ErrorDiag, "ExpectedKernelFunction">;
+ let Subjects = SubjectList<[Function], ErrorDiag, "kernel functions">;
}
def AMDGPUWavesPerEU : InheritableAttr {
- let Spellings = [GNU<"amdgpu_waves_per_eu">];
+ let Spellings = [Clang<"amdgpu_waves_per_eu">];
let Args = [UnsignedArgument<"Min">, UnsignedArgument<"Max", 1>];
let Documentation = [AMDGPUWavesPerEUDocs];
- let Subjects = SubjectList<[Function], ErrorDiag, "ExpectedKernelFunction">;
+ let Subjects = SubjectList<[Function], ErrorDiag, "kernel functions">;
}
def AMDGPUNumSGPR : InheritableAttr {
- let Spellings = [GNU<"amdgpu_num_sgpr">];
+ let Spellings = [Clang<"amdgpu_num_sgpr">];
let Args = [UnsignedArgument<"NumSGPR">];
let Documentation = [AMDGPUNumSGPRNumVGPRDocs];
- let Subjects = SubjectList<[Function], ErrorDiag, "ExpectedKernelFunction">;
+ let Subjects = SubjectList<[Function], ErrorDiag, "kernel functions">;
}
def AMDGPUNumVGPR : InheritableAttr {
- let Spellings = [GNU<"amdgpu_num_vgpr">];
+ let Spellings = [Clang<"amdgpu_num_vgpr">];
let Args = [UnsignedArgument<"NumVGPR">];
let Documentation = [AMDGPUNumSGPRNumVGPRDocs];
- let Subjects = SubjectList<[Function], ErrorDiag, "ExpectedKernelFunction">;
+ let Subjects = SubjectList<[Function], ErrorDiag, "kernel functions">;
}
def NoSplitStack : InheritableAttr {
@@ -1330,7 +1350,7 @@ def NoSplitStack : InheritableAttr {
def NonNull : InheritableParamAttr {
let Spellings = [GCC<"nonnull">];
let Subjects = SubjectList<[ObjCMethod, HasFunctionProto, ParmVar], WarnDiag,
- "ExpectedFunctionMethodOrParameter">;
+ "functions, methods, and parameters">;
let Args = [VariadicUnsignedArgument<"Args">];
let AdditionalMembers =
[{bool isNonNull(unsigned idx) const {
@@ -1348,15 +1368,14 @@ def NonNull : InheritableParamAttr {
def ReturnsNonNull : InheritableAttr {
let Spellings = [GCC<"returns_nonnull">];
- let Subjects = SubjectList<[ObjCMethod, Function], WarnDiag,
- "ExpectedFunctionOrMethod">;
+ let Subjects = SubjectList<[ObjCMethod, Function]>;
let Documentation = [ReturnsNonNullDocs];
}
// pass_object_size(N) indicates that the parameter should have
// __builtin_object_size with Type=N evaluated on the parameter at the callsite.
def PassObjectSize : InheritableParamAttr {
- let Spellings = [GNU<"pass_object_size">];
+ let Spellings = [Clang<"pass_object_size">];
let Args = [IntArgument<"Type">];
let Subjects = SubjectList<[ParmVar]>;
let Documentation = [PassObjectSizeDocs];
@@ -1383,6 +1402,12 @@ def ObjCKindOf : TypeAttr {
let Documentation = [Undocumented];
}
+def NoEscape : Attr {
+ let Spellings = [Clang<"noescape">];
+ let Subjects = SubjectList<[ParmVar]>;
+ let Documentation = [NoEscapeDocs];
+}
+
def AssumeAligned : InheritableAttr {
let Spellings = [GCC<"assume_aligned">];
let Subjects = SubjectList<[ObjCMethod, Function]>;
@@ -1392,8 +1417,7 @@ def AssumeAligned : InheritableAttr {
def AllocAlign : InheritableAttr {
let Spellings = [GCC<"alloc_align">];
- let Subjects = SubjectList<[HasFunctionProto], WarnDiag,
- "ExpectedFunctionWithProtoType">;
+ let Subjects = SubjectList<[HasFunctionProto]>;
let Args = [IntArgument<"ParamIndex">];
let Documentation = [AllocAlignDocs];
}
@@ -1411,39 +1435,42 @@ def NoInstrumentFunction : InheritableAttr {
}
def NotTailCalled : InheritableAttr {
- let Spellings = [GNU<"not_tail_called">, CXX11<"clang", "not_tail_called">];
+ let Spellings = [Clang<"not_tail_called">];
let Subjects = SubjectList<[Function]>;
let Documentation = [NotTailCalledDocs];
}
def NoThrow : InheritableAttr {
let Spellings = [GCC<"nothrow">, Declspec<"nothrow">];
- let Documentation = [Undocumented];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [NoThrowDocs];
}
def NvWeak : IgnoredAttr {
// No Declspec spelling of this attribute; the CUDA headers use
- // __attribute__((nv_weak)) unconditionally.
+ // __attribute__((nv_weak)) unconditionally. Does not receive an [[]]
+ // spelling because it is a CUDA attribute.
let Spellings = [GNU<"nv_weak">];
let LangOpts = [CUDA];
}
def ObjCBridge : InheritableAttr {
- let Spellings = [GNU<"objc_bridge">];
- let Subjects = SubjectList<[Record, TypedefName], ErrorDiag,
- "ExpectedStructOrUnionOrTypedef">;
+ let Spellings = [Clang<"objc_bridge">];
+ let Subjects = SubjectList<[Record, TypedefName], ErrorDiag>;
let Args = [IdentifierArgument<"BridgedType">];
let Documentation = [Undocumented];
}
def ObjCBridgeMutable : InheritableAttr {
- let Spellings = [GNU<"objc_bridge_mutable">];
+ let Spellings = [Clang<"objc_bridge_mutable">];
let Subjects = SubjectList<[Record], ErrorDiag>;
let Args = [IdentifierArgument<"BridgedType">];
let Documentation = [Undocumented];
}
def ObjCBridgeRelated : InheritableAttr {
+ // TODO: this attribute does not have a [[]] spelling because it requires
+ // custom parsing support.
let Spellings = [GNU<"objc_bridge_related">];
let Subjects = SubjectList<[Record], ErrorDiag>;
let Args = [IdentifierArgument<"RelatedClass">,
@@ -1454,43 +1481,43 @@ def ObjCBridgeRelated : InheritableAttr {
}
def NSReturnsRetained : InheritableAttr {
- let Spellings = [GNU<"ns_returns_retained">];
+ let Spellings = [Clang<"ns_returns_retained">];
// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;
let Documentation = [Undocumented];
}
def NSReturnsNotRetained : InheritableAttr {
- let Spellings = [GNU<"ns_returns_not_retained">];
+ let Spellings = [Clang<"ns_returns_not_retained">];
// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;
let Documentation = [Undocumented];
}
def NSReturnsAutoreleased : InheritableAttr {
- let Spellings = [GNU<"ns_returns_autoreleased">];
+ let Spellings = [Clang<"ns_returns_autoreleased">];
// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;
let Documentation = [Undocumented];
}
def NSConsumesSelf : InheritableAttr {
- let Spellings = [GNU<"ns_consumes_self">];
+ let Spellings = [Clang<"ns_consumes_self">];
let Subjects = SubjectList<[ObjCMethod]>;
let Documentation = [Undocumented];
}
def NSConsumed : InheritableParamAttr {
- let Spellings = [GNU<"ns_consumed">];
+ let Spellings = [Clang<"ns_consumed">];
let Subjects = SubjectList<[ParmVar]>;
let Documentation = [Undocumented];
}
def ObjCException : InheritableAttr {
- let Spellings = [GNU<"objc_exception">];
+ let Spellings = [Clang<"objc_exception">];
let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
let Documentation = [Undocumented];
}
def ObjCMethodFamily : InheritableAttr {
- let Spellings = [GNU<"objc_method_family">];
+ let Spellings = [Clang<"objc_method_family">];
let Subjects = SubjectList<[ObjCMethod], ErrorDiag>;
let Args = [EnumArgument<"Family", "FamilyKind",
["none", "alloc", "copy", "init", "mutableCopy", "new"],
@@ -1500,85 +1527,84 @@ def ObjCMethodFamily : InheritableAttr {
}
def ObjCNSObject : InheritableAttr {
- let Spellings = [GNU<"NSObject">];
+ let Spellings = [Clang<"NSObject">];
let Documentation = [Undocumented];
}
def ObjCIndependentClass : InheritableAttr {
- let Spellings = [GNU<"objc_independent_class">];
+ let Spellings = [Clang<"objc_independent_class">];
let Documentation = [Undocumented];
}
def ObjCPreciseLifetime : InheritableAttr {
- let Spellings = [GNU<"objc_precise_lifetime">];
+ let Spellings = [Clang<"objc_precise_lifetime">];
let Subjects = SubjectList<[Var], ErrorDiag>;
let Documentation = [Undocumented];
}
def ObjCReturnsInnerPointer : InheritableAttr {
- let Spellings = [GNU<"objc_returns_inner_pointer">];
+ let Spellings = [Clang<"objc_returns_inner_pointer">];
let Subjects = SubjectList<[ObjCMethod, ObjCProperty], ErrorDiag>;
let Documentation = [Undocumented];
}
def ObjCRequiresSuper : InheritableAttr {
- let Spellings = [GNU<"objc_requires_super">];
+ let Spellings = [Clang<"objc_requires_super">];
let Subjects = SubjectList<[ObjCMethod], ErrorDiag>;
let Documentation = [ObjCRequiresSuperDocs];
}
def ObjCRootClass : InheritableAttr {
- let Spellings = [GNU<"objc_root_class">];
+ let Spellings = [Clang<"objc_root_class">];
let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
let Documentation = [Undocumented];
}
def ObjCSubclassingRestricted : InheritableAttr {
- let Spellings = [GNU<"objc_subclassing_restricted">];
+ let Spellings = [Clang<"objc_subclassing_restricted">];
let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
let Documentation = [ObjCSubclassingRestrictedDocs];
}
def ObjCExplicitProtocolImpl : InheritableAttr {
- let Spellings = [GNU<"objc_protocol_requires_explicit_implementation">];
+ let Spellings = [Clang<"objc_protocol_requires_explicit_implementation">];
let Subjects = SubjectList<[ObjCProtocol], ErrorDiag>;
let Documentation = [Undocumented];
}
def ObjCDesignatedInitializer : Attr {
- let Spellings = [GNU<"objc_designated_initializer">];
- let Subjects = SubjectList<[ObjCInterfaceDeclInitMethod], ErrorDiag,
- "ExpectedObjCInterfaceDeclInitMethod">;
+ let Spellings = [Clang<"objc_designated_initializer">];
+ let Subjects = SubjectList<[ObjCInterfaceDeclInitMethod], ErrorDiag>;
let Documentation = [Undocumented];
}
def ObjCRuntimeName : Attr {
- let Spellings = [GNU<"objc_runtime_name">];
+ let Spellings = [Clang<"objc_runtime_name">];
let Subjects = SubjectList<[ObjCInterface, ObjCProtocol], ErrorDiag>;
let Args = [StringArgument<"MetadataName">];
let Documentation = [ObjCRuntimeNameDocs];
}
def ObjCRuntimeVisible : Attr {
- let Spellings = [GNU<"objc_runtime_visible">];
+ let Spellings = [Clang<"objc_runtime_visible">];
let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
let Documentation = [ObjCRuntimeVisibleDocs];
}
def ObjCBoxable : Attr {
- let Spellings = [GNU<"objc_boxable">];
- let Subjects = SubjectList<[Record], ErrorDiag, "ExpectedStructOrUnion">;
+ let Spellings = [Clang<"objc_boxable">];
+ let Subjects = SubjectList<[Record], ErrorDiag>;
let Documentation = [ObjCBoxableDocs];
}
def OptimizeNone : InheritableAttr {
- let Spellings = [GNU<"optnone">, CXX11<"clang", "optnone">];
+ let Spellings = [Clang<"optnone">];
let Subjects = SubjectList<[Function, ObjCMethod]>;
let Documentation = [OptnoneDocs];
}
def Overloadable : Attr {
- let Spellings = [GNU<"overloadable">];
+ let Spellings = [Clang<"overloadable">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [OverloadableDocs];
}
@@ -1590,11 +1616,11 @@ def Override : InheritableAttr {
}
def Ownership : InheritableAttr {
- let Spellings = [GNU<"ownership_holds">, GNU<"ownership_returns">,
- GNU<"ownership_takes">];
- let Accessors = [Accessor<"isHolds", [GNU<"ownership_holds">]>,
- Accessor<"isReturns", [GNU<"ownership_returns">]>,
- Accessor<"isTakes", [GNU<"ownership_takes">]>];
+ let Spellings = [Clang<"ownership_holds">, Clang<"ownership_returns">,
+ Clang<"ownership_takes">];
+ let Accessors = [Accessor<"isHolds", [Clang<"ownership_holds">]>,
+ Accessor<"isReturns", [Clang<"ownership_returns">]>,
+ Accessor<"isTakes", [Clang<"ownership_takes">]>];
let AdditionalMembers = [{
enum OwnershipKind { Holds, Returns, Takes };
OwnershipKind getOwnKind() const {
@@ -1604,8 +1630,7 @@ def Ownership : InheritableAttr {
}
}];
let Args = [IdentifierArgument<"Module">, VariadicUnsignedArgument<"Args">];
- let Subjects = SubjectList<[HasFunctionProto], WarnDiag,
- "ExpectedFunctionWithProtoType">;
+ let Subjects = SubjectList<[HasFunctionProto]>;
let Documentation = [Undocumented];
}
@@ -1616,7 +1641,7 @@ def Packed : InheritableAttr {
}
def IntelOclBicc : InheritableAttr {
- let Spellings = [GNU<"intel_ocl_bicc">];
+ let Spellings = [Clang<"intel_ocl_bicc">];
// let Subjects = [Function, ObjCMethod];
let Documentation = [Undocumented];
}
@@ -1642,6 +1667,7 @@ def Regparm : TypeAttr {
}
def ReqdWorkGroupSize : InheritableAttr {
+ // Does not have a [[]] spelling because it is an OpenCL-related attribute.
let Spellings = [GNU<"reqd_work_group_size">];
let Args = [UnsignedArgument<"XDim">, UnsignedArgument<"YDim">,
UnsignedArgument<"ZDim">];
@@ -1650,15 +1676,14 @@ def ReqdWorkGroupSize : InheritableAttr {
}
def RequireConstantInit : InheritableAttr {
- let Spellings = [GNU<"require_constant_initialization">,
- CXX11<"clang", "require_constant_initialization">];
- let Subjects = SubjectList<[GlobalVar], ErrorDiag,
- "ExpectedStaticOrTLSVar">;
+ let Spellings = [Clang<"require_constant_initialization">];
+ let Subjects = SubjectList<[GlobalVar], ErrorDiag>;
let Documentation = [RequireConstantInitDocs];
let LangOpts = [CPlusPlus];
}
def WorkGroupSizeHint : InheritableAttr {
+ // Does not have a [[]] spelling because it is an OpenCL-related attribute.
let Spellings = [GNU<"work_group_size_hint">];
let Args = [UnsignedArgument<"XDim">,
UnsignedArgument<"YDim">,
@@ -1668,7 +1693,7 @@ def WorkGroupSizeHint : InheritableAttr {
}
def InitPriority : InheritableAttr {
- let Spellings = [GNU<"init_priority">];
+ let Spellings = [GCC<"init_priority">];
let Args = [UnsignedArgument<"Priority">];
let Subjects = SubjectList<[Var], ErrorDiag>;
let Documentation = [Undocumented];
@@ -1677,9 +1702,8 @@ def InitPriority : InheritableAttr {
def Section : InheritableAttr {
let Spellings = [GCC<"section">, Declspec<"allocate">];
let Args = [StringArgument<"Name">];
- let Subjects = SubjectList<[Function, GlobalVar,
- ObjCMethod, ObjCProperty], ErrorDiag,
- "ExpectedFunctionGlobalVarMethodOrProperty">;
+ let Subjects =
+ SubjectList<[ Function, GlobalVar, ObjCMethod, ObjCProperty ], ErrorDiag>;
let Documentation = [SectionDocs];
}
@@ -1687,8 +1711,7 @@ def PragmaClangBSSSection : InheritableAttr {
// This attribute has no spellings as it is only ever created implicitly.
let Spellings = [];
let Args = [StringArgument<"Name">];
- let Subjects = SubjectList<[GlobalVar], ErrorDiag,
- "ExpectedFunctionMethodOrGlobalVar">;
+ let Subjects = SubjectList<[GlobalVar], ErrorDiag>;
let Documentation = [Undocumented];
}
@@ -1696,8 +1719,7 @@ def PragmaClangDataSection : InheritableAttr {
// This attribute has no spellings as it is only ever created implicitly.
let Spellings = [];
let Args = [StringArgument<"Name">];
- let Subjects = SubjectList<[GlobalVar], ErrorDiag,
- "ExpectedFunctionMethodOrGlobalVar">;
+ let Subjects = SubjectList<[GlobalVar], ErrorDiag>;
let Documentation = [Undocumented];
}
@@ -1705,8 +1727,7 @@ def PragmaClangRodataSection : InheritableAttr {
// This attribute has no spellings as it is only ever created implicitly.
let Spellings = [];
let Args = [StringArgument<"Name">];
- let Subjects = SubjectList<[GlobalVar], ErrorDiag,
- "ExpectedFunctionMethodOrGlobalVar">;
+ let Subjects = SubjectList<[GlobalVar], ErrorDiag>;
let Documentation = [Undocumented];
}
@@ -1714,8 +1735,7 @@ def PragmaClangTextSection : InheritableAttr {
// This attribute has no spellings as it is only ever created implicitly.
let Spellings = [];
let Args = [StringArgument<"Name">];
- let Subjects = SubjectList<[Function], ErrorDiag,
- "ExpectedFunctionMethodOrGlobalVar">;
+ let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [Undocumented];
}
@@ -1734,23 +1754,23 @@ def StdCall : InheritableAttr {
}
def SwiftCall : InheritableAttr {
- let Spellings = [GCC<"swiftcall">];
+ let Spellings = [Clang<"swiftcall">];
// let Subjects = SubjectList<[Function]>;
let Documentation = [SwiftCallDocs];
}
def SwiftContext : ParameterABIAttr {
- let Spellings = [GCC<"swift_context">];
+ let Spellings = [Clang<"swift_context">];
let Documentation = [SwiftContextDocs];
}
def SwiftErrorResult : ParameterABIAttr {
- let Spellings = [GCC<"swift_error_result">];
+ let Spellings = [Clang<"swift_error_result">];
let Documentation = [SwiftErrorResultDocs];
}
def SwiftIndirectResult : ParameterABIAttr {
- let Spellings = [GCC<"swift_indirect_result">];
+ let Spellings = [Clang<"swift_indirect_result">];
let Documentation = [SwiftIndirectResultDocs];
}
@@ -1774,25 +1794,25 @@ def ThisCall : InheritableAttr {
}
def VectorCall : InheritableAttr {
- let Spellings = [GNU<"vectorcall">, Keyword<"__vectorcall">,
+ let Spellings = [Clang<"vectorcall">, Keyword<"__vectorcall">,
Keyword<"_vectorcall">];
// let Subjects = [Function, ObjCMethod];
let Documentation = [VectorCallDocs];
}
def Pascal : InheritableAttr {
- let Spellings = [GNU<"pascal">, Keyword<"__pascal">, Keyword<"_pascal">];
+ let Spellings = [Clang<"pascal">, Keyword<"__pascal">, Keyword<"_pascal">];
// let Subjects = [Function, ObjCMethod];
let Documentation = [Undocumented];
}
def PreserveMost : InheritableAttr {
- let Spellings = [GNU<"preserve_most">];
+ let Spellings = [Clang<"preserve_most">];
let Documentation = [PreserveMostDocs];
}
def PreserveAll : InheritableAttr {
- let Spellings = [GNU<"preserve_all">];
+ let Spellings = [Clang<"preserve_all">];
let Documentation = [PreserveAllDocs];
}
@@ -1853,7 +1873,7 @@ def TransparentUnion : InheritableAttr {
}
def Unavailable : InheritableAttr {
- let Spellings = [GNU<"unavailable">];
+ let Spellings = [Clang<"unavailable">];
let Args = [StringArgument<"Message", 1>,
EnumArgument<"ImplicitReason", "ImplicitReason",
["", "", "", ""],
@@ -1867,6 +1887,9 @@ def Unavailable : InheritableAttr {
}
def DiagnoseIf : InheritableAttr {
+ // Does not have a [[]] spelling because this attribute requires the ability
+ // to parse function arguments but the attribute is not written in the type
+ // position.
let Spellings = [GNU<"diagnose_if">];
let Subjects = SubjectList<[Function, ObjCMethod, ObjCProperty]>;
let Args = [ExprArgument<"Cond">, StringArgument<"Message">,
@@ -1887,35 +1910,35 @@ def DiagnoseIf : InheritableAttr {
}
def ArcWeakrefUnavailable : InheritableAttr {
- let Spellings = [GNU<"objc_arc_weak_reference_unavailable">];
+ let Spellings = [Clang<"objc_arc_weak_reference_unavailable">];
let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
let Documentation = [Undocumented];
}
def ObjCGC : TypeAttr {
- let Spellings = [GNU<"objc_gc">];
+ let Spellings = [Clang<"objc_gc">];
let Args = [IdentifierArgument<"Kind">];
let Documentation = [Undocumented];
}
def ObjCOwnership : InheritableAttr {
- let Spellings = [GNU<"objc_ownership">];
+ let Spellings = [Clang<"objc_ownership">];
let Args = [IdentifierArgument<"Kind">];
let ASTNode = 0;
let Documentation = [Undocumented];
}
def ObjCRequiresPropertyDefs : InheritableAttr {
- let Spellings = [GNU<"objc_requires_property_definitions">];
+ let Spellings = [Clang<"objc_requires_property_definitions">];
let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
let Documentation = [Undocumented];
}
def Unused : InheritableAttr {
- let Spellings = [CXX11<"", "maybe_unused", 201603>, GCC<"unused">];
+ let Spellings = [CXX11<"", "maybe_unused", 201603>, GCC<"unused">,
+ C2x<"", "maybe_unused">];
let Subjects = SubjectList<[Var, ObjCIvar, Type, Enum, EnumConstant, Label,
- Field, ObjCMethod, FunctionLike], WarnDiag,
- "ExpectedForMaybeUnused">;
+ Field, ObjCMethod, FunctionLike]>;
let Documentation = [WarnMaybeUnusedDocs];
}
@@ -1927,7 +1950,7 @@ def Used : InheritableAttr {
def Uuid : InheritableAttr {
let Spellings = [Declspec<"uuid">, Microsoft<"uuid">];
let Args = [StringArgument<"Guid">];
- let Subjects = SubjectList<[Record, Enum], WarnDiag, "ExpectedEnumOrClass">;
+ let Subjects = SubjectList<[Record, Enum]>;
// FIXME: Allow expressing logical AND for LangOpts. Our condition should be:
// CPlusPlus && (MicrosoftExt || Borland)
let LangOpts = [MicrosoftExt, Borland];
@@ -1941,6 +1964,7 @@ def VectorSize : TypeAttr {
}
def VecTypeHint : InheritableAttr {
+ // Does not have a [[]] spelling because it is an OpenCL-related attribute.
let Spellings = [GNU<"vec_type_hint">];
let Args = [TypeArgument<"TypeHint">];
let Subjects = SubjectList<[Function], ErrorDiag>;
@@ -1959,7 +1983,7 @@ def Visibility : InheritableAttr {
def TypeVisibility : InheritableAttr {
let Clone = 0;
- let Spellings = [GNU<"type_visibility">, CXX11<"clang", "type_visibility">];
+ let Spellings = [Clang<"type_visibility">];
let Args = [EnumArgument<"Visibility", "VisibilityType",
["default", "hidden", "internal", "protected"],
["Default", "Hidden", "Hidden", "Protected"]>];
@@ -1968,23 +1992,22 @@ def TypeVisibility : InheritableAttr {
}
def VecReturn : InheritableAttr {
- let Spellings = [GNU<"vecreturn">];
+ let Spellings = [Clang<"vecreturn">];
let Subjects = SubjectList<[CXXRecord], ErrorDiag>;
let Documentation = [Undocumented];
}
def WarnUnused : InheritableAttr {
- let Spellings = [GNU<"warn_unused">];
+ let Spellings = [GCC<"warn_unused">];
let Subjects = SubjectList<[Record]>;
let Documentation = [Undocumented];
}
def WarnUnusedResult : InheritableAttr {
- let Spellings = [CXX11<"", "nodiscard", 201603>,
+ let Spellings = [CXX11<"", "nodiscard", 201603>, C2x<"", "nodiscard">,
CXX11<"clang", "warn_unused_result">,
GCC<"warn_unused_result">];
- let Subjects = SubjectList<[ObjCMethod, Enum, CXXRecord, FunctionLike],
- WarnDiag, "ExpectedFunctionMethodEnumOrClass">;
+ let Subjects = SubjectList<[ObjCMethod, Enum, Record, FunctionLike]>;
let Documentation = [WarnUnusedResultsDocs];
}
@@ -1995,7 +2018,7 @@ def Weak : InheritableAttr {
}
def WeakImport : InheritableAttr {
- let Spellings = [GNU<"weak_import">];
+ let Spellings = [Clang<"weak_import">];
let Documentation = [Undocumented];
}
@@ -2008,7 +2031,7 @@ def WeakRef : InheritableAttr {
}
def LTOVisibilityPublic : InheritableAttr {
- let Spellings = [CXX11<"clang", "lto_visibility_public">];
+ let Spellings = [Clang<"lto_visibility_public">];
let Subjects = SubjectList<[Record]>;
let Documentation = [LTOVisibilityDocs];
}
@@ -2016,11 +2039,11 @@ def LTOVisibilityPublic : InheritableAttr {
def AnyX86Interrupt : InheritableAttr, TargetSpecificAttr<TargetAnyX86> {
// NOTE: If you add any additional spellings, ARMInterrupt's,
// MSP430Interrupt's and MipsInterrupt's spellings must match.
- let Spellings = [GNU<"interrupt">];
+ let Spellings = [GCC<"interrupt">];
let Subjects = SubjectList<[HasFunctionProto]>;
let ParseKind = "Interrupt";
let HasCustomParsing = 1;
- let Documentation = [AnyX86InterruptDocs];
+ let Documentation = [Undocumented];
}
def AnyX86NoCallerSavedRegisters : InheritableAttr,
@@ -2029,19 +2052,18 @@ def AnyX86NoCallerSavedRegisters : InheritableAttr,
let Documentation = [AnyX86NoCallerSavedRegistersDocs];
}
-def X86ForceAlignArgPointer : InheritableAttr, TargetSpecificAttr<TargetX86> {
- let Spellings = [GNU<"force_align_arg_pointer">];
+def X86ForceAlignArgPointer : InheritableAttr, TargetSpecificAttr<TargetAnyX86> {
+ let Spellings = [GCC<"force_align_arg_pointer">];
// Technically, this appertains to a FunctionDecl, but the target-specific
// code silently allows anything function-like (such as typedefs or function
// pointers), but does not apply the attribute to them.
- let Documentation = [Undocumented];
+ let Documentation = [X86ForceAlignArgPointerDocs];
}
def NoSanitize : InheritableAttr {
- let Spellings = [GNU<"no_sanitize">, CXX11<"clang", "no_sanitize">];
+ let Spellings = [Clang<"no_sanitize">];
let Args = [VariadicStringArgument<"Sanitizers">];
- let Subjects = SubjectList<[Function, ObjCMethod, GlobalVar], ErrorDiag,
- "ExpectedFunctionMethodOrGlobalVar">;
+ let Subjects = SubjectList<[Function, ObjCMethod, GlobalVar], ErrorDiag>;
let Documentation = [NoSanitizeDocs];
let AdditionalMembers = [{
SanitizerMask getMask() const {
@@ -2062,27 +2084,28 @@ def NoSanitizeSpecific : InheritableAttr {
let Spellings = [GCC<"no_address_safety_analysis">,
GCC<"no_sanitize_address">,
GCC<"no_sanitize_thread">,
- GNU<"no_sanitize_memory">];
- let Subjects = SubjectList<[Function, GlobalVar], ErrorDiag,
- "ExpectedFunctionOrGlobalVar">;
+ Clang<"no_sanitize_memory">];
+ let Subjects = SubjectList<[Function, GlobalVar], ErrorDiag>;
let Documentation = [NoSanitizeAddressDocs, NoSanitizeThreadDocs,
NoSanitizeMemoryDocs];
let ASTNode = 0;
}
// C/C++ Thread safety attributes (e.g. for deadlock, data race checking)
-
+// Not all of these attributes will be given a [[]] spelling. The attributes
+// which require access to function parameter names cannot use the [[]] spelling
+// because they are not written in the type position. Some attributes are given
+// an updated captability-based name and the older name will only be supported
+// under the GNU-style spelling.
def GuardedVar : InheritableAttr {
- let Spellings = [GNU<"guarded_var">];
- let Subjects = SubjectList<[Field, SharedVar], WarnDiag,
- "ExpectedFieldOrGlobalVar">;
+ let Spellings = [Clang<"guarded_var">];
+ let Subjects = SubjectList<[Field, SharedVar]>;
let Documentation = [Undocumented];
}
def PtGuardedVar : InheritableAttr {
- let Spellings = [GNU<"pt_guarded_var">];
- let Subjects = SubjectList<[Field, SharedVar], WarnDiag,
- "ExpectedFieldOrGlobalVar">;
+ let Spellings = [Clang<"pt_guarded_var">];
+ let Subjects = SubjectList<[Field, SharedVar]>;
let Documentation = [Undocumented];
}
@@ -2094,21 +2117,17 @@ def Lockable : InheritableAttr {
}
def ScopedLockable : InheritableAttr {
- let Spellings = [GNU<"scoped_lockable">];
+ let Spellings = [Clang<"scoped_lockable">];
let Subjects = SubjectList<[Record]>;
let Documentation = [Undocumented];
}
def Capability : InheritableAttr {
- let Spellings = [GNU<"capability">, CXX11<"clang", "capability">,
- GNU<"shared_capability">,
- CXX11<"clang", "shared_capability">];
- let Subjects = SubjectList<[Record, TypedefName], ErrorDiag,
- "ExpectedStructOrUnionOrTypedef">;
+ let Spellings = [Clang<"capability">, Clang<"shared_capability">];
+ let Subjects = SubjectList<[Record, TypedefName], ErrorDiag>;
let Args = [StringArgument<"Name">];
let Accessors = [Accessor<"isShared",
- [GNU<"shared_capability">,
- CXX11<"clang","shared_capability">]>];
+ [Clang<"shared_capability">]>];
let Documentation = [Undocumented];
let AdditionalMembers = [{
bool isMutex() const { return getName().equals_lower("mutex"); }
@@ -2117,27 +2136,22 @@ def Capability : InheritableAttr {
}
def AssertCapability : InheritableAttr {
- let Spellings = [GNU<"assert_capability">,
- CXX11<"clang", "assert_capability">,
- GNU<"assert_shared_capability">,
- CXX11<"clang", "assert_shared_capability">];
+ let Spellings = [Clang<"assert_capability">,
+ Clang<"assert_shared_capability">];
let Subjects = SubjectList<[Function]>;
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let DuplicatesAllowedWhileMerging = 1;
- let Args = [ExprArgument<"Expr">];
+ let Args = [VariadicExprArgument<"Args">];
let Accessors = [Accessor<"isShared",
- [GNU<"assert_shared_capability">,
- CXX11<"clang", "assert_shared_capability">]>];
+ [Clang<"assert_shared_capability">]>];
let Documentation = [AssertCapabilityDocs];
}
def AcquireCapability : InheritableAttr {
- let Spellings = [GNU<"acquire_capability">,
- CXX11<"clang", "acquire_capability">,
- GNU<"acquire_shared_capability">,
- CXX11<"clang", "acquire_shared_capability">,
+ let Spellings = [Clang<"acquire_capability">,
+ Clang<"acquire_shared_capability">,
GNU<"exclusive_lock_function">,
GNU<"shared_lock_function">];
let Subjects = SubjectList<[Function]>;
@@ -2147,17 +2161,14 @@ def AcquireCapability : InheritableAttr {
let DuplicatesAllowedWhileMerging = 1;
let Args = [VariadicExprArgument<"Args">];
let Accessors = [Accessor<"isShared",
- [GNU<"acquire_shared_capability">,
- CXX11<"clang", "acquire_shared_capability">,
+ [Clang<"acquire_shared_capability">,
GNU<"shared_lock_function">]>];
let Documentation = [AcquireCapabilityDocs];
}
def TryAcquireCapability : InheritableAttr {
- let Spellings = [GNU<"try_acquire_capability">,
- CXX11<"clang", "try_acquire_capability">,
- GNU<"try_acquire_shared_capability">,
- CXX11<"clang", "try_acquire_shared_capability">];
+ let Spellings = [Clang<"try_acquire_capability">,
+ Clang<"try_acquire_shared_capability">];
let Subjects = SubjectList<[Function],
ErrorDiag>;
let LateParsed = 1;
@@ -2166,19 +2177,15 @@ def TryAcquireCapability : InheritableAttr {
let DuplicatesAllowedWhileMerging = 1;
let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">];
let Accessors = [Accessor<"isShared",
- [GNU<"try_acquire_shared_capability">,
- CXX11<"clang", "try_acquire_shared_capability">]>];
+ [Clang<"try_acquire_shared_capability">]>];
let Documentation = [TryAcquireCapabilityDocs];
}
def ReleaseCapability : InheritableAttr {
- let Spellings = [GNU<"release_capability">,
- CXX11<"clang", "release_capability">,
- GNU<"release_shared_capability">,
- CXX11<"clang", "release_shared_capability">,
- GNU<"release_generic_capability">,
- CXX11<"clang", "release_generic_capability">,
- GNU<"unlock_function">];
+ let Spellings = [Clang<"release_capability">,
+ Clang<"release_shared_capability">,
+ Clang<"release_generic_capability">,
+ Clang<"unlock_function">];
let Subjects = SubjectList<[Function]>;
let LateParsed = 1;
let TemplateDependent = 1;
@@ -2186,36 +2193,31 @@ def ReleaseCapability : InheritableAttr {
let DuplicatesAllowedWhileMerging = 1;
let Args = [VariadicExprArgument<"Args">];
let Accessors = [Accessor<"isShared",
- [GNU<"release_shared_capability">,
- CXX11<"clang", "release_shared_capability">]>,
+ [Clang<"release_shared_capability">]>,
Accessor<"isGeneric",
- [GNU<"release_generic_capability">,
- CXX11<"clang", "release_generic_capability">,
- GNU<"unlock_function">]>];
+ [Clang<"release_generic_capability">,
+ Clang<"unlock_function">]>];
let Documentation = [ReleaseCapabilityDocs];
}
def RequiresCapability : InheritableAttr {
- let Spellings = [GNU<"requires_capability">,
- CXX11<"clang", "requires_capability">,
- GNU<"exclusive_locks_required">,
- GNU<"requires_shared_capability">,
- CXX11<"clang", "requires_shared_capability">,
- GNU<"shared_locks_required">];
+ let Spellings = [Clang<"requires_capability">,
+ Clang<"exclusive_locks_required">,
+ Clang<"requires_shared_capability">,
+ Clang<"shared_locks_required">];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let DuplicatesAllowedWhileMerging = 1;
let Subjects = SubjectList<[Function]>;
- let Accessors = [Accessor<"isShared", [GNU<"requires_shared_capability">,
- GNU<"shared_locks_required">,
- CXX11<"clang","requires_shared_capability">]>];
+ let Accessors = [Accessor<"isShared", [Clang<"requires_shared_capability">,
+ Clang<"shared_locks_required">]>];
let Documentation = [Undocumented];
}
def NoThreadSafetyAnalysis : InheritableAttr {
- let Spellings = [GNU<"no_thread_safety_analysis">];
+ let Spellings = [Clang<"no_thread_safety_analysis">];
let Subjects = SubjectList<[Function]>;
let Documentation = [Undocumented];
}
@@ -2227,8 +2229,7 @@ def GuardedBy : InheritableAttr {
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let DuplicatesAllowedWhileMerging = 1;
- let Subjects = SubjectList<[Field, SharedVar], WarnDiag,
- "ExpectedFieldOrGlobalVar">;
+ let Subjects = SubjectList<[Field, SharedVar]>;
let Documentation = [Undocumented];
}
@@ -2239,8 +2240,7 @@ def PtGuardedBy : InheritableAttr {
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let DuplicatesAllowedWhileMerging = 1;
- let Subjects = SubjectList<[Field, SharedVar], WarnDiag,
- "ExpectedFieldOrGlobalVar">;
+ let Subjects = SubjectList<[Field, SharedVar]>;
let Documentation = [Undocumented];
}
@@ -2251,8 +2251,7 @@ def AcquiredAfter : InheritableAttr {
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let DuplicatesAllowedWhileMerging = 1;
- let Subjects = SubjectList<[Field, SharedVar], WarnDiag,
- "ExpectedFieldOrGlobalVar">;
+ let Subjects = SubjectList<[Field, SharedVar]>;
let Documentation = [Undocumented];
}
@@ -2263,8 +2262,7 @@ def AcquiredBefore : InheritableAttr {
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let DuplicatesAllowedWhileMerging = 1;
- let Subjects = SubjectList<[Field, SharedVar], WarnDiag,
- "ExpectedFieldOrGlobalVar">;
+ let Subjects = SubjectList<[Field, SharedVar]>;
let Documentation = [Undocumented];
}
@@ -2340,7 +2338,7 @@ def LocksExcluded : InheritableAttr {
// C/C++ consumed attributes.
def Consumable : InheritableAttr {
- let Spellings = [GNU<"consumable">];
+ let Spellings = [Clang<"consumable">];
let Subjects = SubjectList<[CXXRecord]>;
let Args = [EnumArgument<"DefaultState", "ConsumedState",
["unknown", "consumed", "unconsumed"],
@@ -2349,19 +2347,19 @@ def Consumable : InheritableAttr {
}
def ConsumableAutoCast : InheritableAttr {
- let Spellings = [GNU<"consumable_auto_cast_state">];
+ let Spellings = [Clang<"consumable_auto_cast_state">];
let Subjects = SubjectList<[CXXRecord]>;
let Documentation = [Undocumented];
}
def ConsumableSetOnRead : InheritableAttr {
- let Spellings = [GNU<"consumable_set_state_on_read">];
+ let Spellings = [Clang<"consumable_set_state_on_read">];
let Subjects = SubjectList<[CXXRecord]>;
let Documentation = [Undocumented];
}
def CallableWhen : InheritableAttr {
- let Spellings = [GNU<"callable_when">];
+ let Spellings = [Clang<"callable_when">];
let Subjects = SubjectList<[CXXMethod]>;
let Args = [VariadicEnumArgument<"CallableStates", "ConsumedState",
["unknown", "consumed", "unconsumed"],
@@ -2370,7 +2368,7 @@ def CallableWhen : InheritableAttr {
}
def ParamTypestate : InheritableAttr {
- let Spellings = [GNU<"param_typestate">];
+ let Spellings = [Clang<"param_typestate">];
let Subjects = SubjectList<[ParmVar]>;
let Args = [EnumArgument<"ParamState", "ConsumedState",
["unknown", "consumed", "unconsumed"],
@@ -2379,7 +2377,7 @@ def ParamTypestate : InheritableAttr {
}
def ReturnTypestate : InheritableAttr {
- let Spellings = [GNU<"return_typestate">];
+ let Spellings = [Clang<"return_typestate">];
let Subjects = SubjectList<[Function, ParmVar]>;
let Args = [EnumArgument<"State", "ConsumedState",
["unknown", "consumed", "unconsumed"],
@@ -2388,7 +2386,7 @@ def ReturnTypestate : InheritableAttr {
}
def SetTypestate : InheritableAttr {
- let Spellings = [GNU<"set_typestate">];
+ let Spellings = [Clang<"set_typestate">];
let Subjects = SubjectList<[CXXMethod]>;
let Args = [EnumArgument<"NewState", "ConsumedState",
["unknown", "consumed", "unconsumed"],
@@ -2397,7 +2395,7 @@ def SetTypestate : InheritableAttr {
}
def TestTypestate : InheritableAttr {
- let Spellings = [GNU<"test_typestate">];
+ let Spellings = [Clang<"test_typestate">];
let Subjects = SubjectList<[CXXMethod]>;
let Args = [EnumArgument<"TestState", "ConsumedState",
["consumed", "unconsumed"],
@@ -2673,6 +2671,14 @@ def OMPCaptureNoInit : InheritableAttr {
let Documentation = [Undocumented];
}
+def OMPCaptureKind : Attr {
+ // This attribute has no spellings as it is only ever created implicitly.
+ let Spellings = [];
+ let SemaHandler = 0;
+ let Args = [UnsignedArgument<"CaptureKind">];
+ let Documentation = [Undocumented];
+}
+
def OMPDeclareSimdDecl : Attr {
let Spellings = [Pragma<"omp", "declare simd">];
let Subjects = SubjectList<[Function]>;
@@ -2759,7 +2765,7 @@ def OMPDeclareTargetDecl : Attr {
}
def InternalLinkage : InheritableAttr {
- let Spellings = [GNU<"internal_linkage">, CXX11<"clang", "internal_linkage">];
+ let Spellings = [Clang<"internal_linkage">];
let Subjects = SubjectList<[Var, Function, CXXRecord]>;
let Documentation = [InternalLinkageDocs];
}
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/AttrDocs.td b/contrib/llvm/tools/clang/include/clang/Basic/AttrDocs.td
index 567c7a3a53b06..ecff329c4ccba 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/AttrDocs.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/AttrDocs.td
@@ -7,6 +7,24 @@
//
//===---------------------------------------------------------------------===//
+// To test that the documentation builds cleanly, you must run clang-tblgen to
+// convert the .td file into a .rst file, and then run sphinx to convert the
+// .rst file into an HTML file. After completing testing, you should revert the
+// generated .rst file so that the modified version does not get checked in to
+// version control.
+//
+// To run clang-tblgen to generate the .rst file:
+// clang-tblgen -gen-attr-docs -I <root>/llvm/tools/clang/include
+// <root>/llvm/tools/clang/include/clang/Basic/Attr.td -o
+// <root>/llvm/tools/clang/docs/AttributeReference.rst
+//
+// To run sphinx to generate the .html files (note that sphinx-build must be
+// available on the PATH):
+// Windows (from within the clang\docs directory):
+// make.bat html
+// Non-Windows (from within the clang\docs directory):
+// make -f Makefile.sphinx html
+
def GlobalDocumentation {
code Intro =[{..
-------------------------------------------------------------------
@@ -112,6 +130,50 @@ members, and static locals.
}];
}
+def NoEscapeDocs : Documentation {
+ let Category = DocCatVariable;
+ let Content = [{
+``noescape`` placed on a function parameter of a pointer type is used to inform
+the compiler that the pointer cannot escape: that is, no reference to the object
+the pointer points to that is derived from the parameter value will survive
+after the function returns. Users are responsible for making sure parameters
+annotated with ``noescape`` do not actuallly escape.
+
+For example:
+
+.. code-block:: c
+
+ int *gp;
+
+ void nonescapingFunc(__attribute__((noescape)) int *p) {
+ *p += 100; // OK.
+ }
+
+ void escapingFunc(__attribute__((noescape)) int *p) {
+ gp = p; // Not OK.
+ }
+
+Additionally, when the parameter is a `block pointer
+<https://clang.llvm.org/docs/BlockLanguageSpec.html>`, the same restriction
+applies to copies of the block. For example:
+
+.. code-block:: c
+
+ typedef void (^BlockTy)();
+ BlockTy g0, g1;
+
+ void nonescapingFunc(__attribute__((noescape)) BlockTy block) {
+ block(); // OK.
+ }
+
+ void escapingFunc(__attribute__((noescape)) BlockTy block) {
+ g0 = block; // Not OK.
+ g1 = Block_copy(block); // Not OK either.
+ }
+
+ }];
+}
+
def CarriesDependencyDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
@@ -1231,6 +1293,7 @@ Here is an example:
def ARMInterruptDocs : Documentation {
let Category = DocCatFunction;
+ let Heading = "interrupt (ARM)";
let Content = [{
Clang supports the GNU style ``__attribute__((interrupt("TYPE")))`` attribute on
ARM targets. This attribute may be attached to a function definition and
@@ -1272,6 +1335,7 @@ The semantics are as follows:
def MipsInterruptDocs : Documentation {
let Category = DocCatFunction;
+ let Heading = "interrupt (MIPS)";
let Content = [{
Clang supports the GNU style ``__attribute__((interrupt("ARGUMENT")))`` attribute on
MIPS targets. This attribute may be attached to a function definition and instructs
@@ -1323,8 +1387,52 @@ on the command line.
}];
}
+def MipsLongCallStyleDocs : Documentation {
+ let Category = DocCatFunction;
+ let Heading = "long_call (gnu::long_call, gnu::far)";
+ let Content = [{
+Clang supports the ``__attribute__((long_call))``, ``__attribute__((far))``,
+and ``__attribute__((near))`` attributes on MIPS targets. These attributes may
+only be added to function declarations and change the code generated
+by the compiler when directly calling the function. The ``near`` attribute
+allows calls to the function to be made using the ``jal`` instruction, which
+requires the function to be located in the same naturally aligned 256MB
+segment as the caller. The ``long_call`` and ``far`` attributes are synonyms
+and require the use of a different call sequence that works regardless
+of the distance between the functions.
+
+These attributes have no effect for position-independent code.
+
+These attributes take priority over command line switches such
+as ``-mlong-calls`` and ``-mno-long-calls``.
+ }];
+}
+
+def MipsShortCallStyleDocs : Documentation {
+ let Category = DocCatFunction;
+ let Heading = "short_call (gnu::short_call, gnu::near)";
+ let Content = [{
+Clang supports the ``__attribute__((long_call))``, ``__attribute__((far))``,
+``__attribute__((short__call))``, and ``__attribute__((near))`` attributes
+on MIPS targets. These attributes may only be added to function declarations
+and change the code generated by the compiler when directly calling
+the function. The ``short_call`` and ``near`` attributes are synonyms and
+allow calls to the function to be made using the ``jal`` instruction, which
+requires the function to be located in the same naturally aligned 256MB segment
+as the caller. The ``long_call`` and ``far`` attributes are synonyms and
+require the use of a different call sequence that works regardless
+of the distance between the functions.
+
+These attributes have no effect for position-independent code.
+
+These attributes take priority over command line switches such
+as ``-mlong-calls`` and ``-mno-long-calls``.
+ }];
+}
+
def AVRInterruptDocs : Documentation {
let Category = DocCatFunction;
+ let Heading = "interrupt (AVR)";
let Content = [{
Clang supports the GNU style ``__attribute__((interrupt))`` attribute on
AVR targets. This attribute may be attached to a function definition and instructs
@@ -2625,6 +2733,18 @@ Marking virtual functions as ``not_tail_called`` is an error:
}];
}
+def NoThrowDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+Clang supports the GNU style ``__attribute__((nothrow))`` and Microsoft style
+``__declspec(nothrow)`` attribute as an equivilent of `noexcept` on function
+declarations. This attribute informs the compiler that the annotated function
+does not throw an exception. This prevents exception-unwinding. This attribute
+is particularly useful on functions in the C Standard Library that are
+guaranteed to not throw an exception.
+ }];
+}
+
def InternalLinkageDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
@@ -2673,59 +2793,6 @@ Marking virtual functions as ``disable_tail_calls`` is legal.
}];
}
-def AnyX86InterruptDocs : Documentation {
- let Category = DocCatFunction;
- let Content = [{
-Clang supports the GNU style ``__attribute__((interrupt))`` attribute on
-x86/x86-64 targets.The compiler generates function entry and exit sequences
-suitable for use in an interrupt handler when this attribute is present.
-The 'IRET' instruction, instead of the 'RET' instruction, is used to return
-from interrupt or exception handlers. All registers, except for the EFLAGS
-register which is restored by the 'IRET' instruction, are preserved by the
-compiler.
-
-Any interruptible-without-stack-switch code must be compiled with
--mno-red-zone since interrupt handlers can and will, because of the
-hardware design, touch the red zone.
-
-1. interrupt handler must be declared with a mandatory pointer argument:
-
- .. code-block:: c
-
- struct interrupt_frame
- {
- uword_t ip;
- uword_t cs;
- uword_t flags;
- uword_t sp;
- uword_t ss;
- };
-
- __attribute__ ((interrupt))
- void f (struct interrupt_frame *frame) {
- ...
- }
-
-2. exception handler:
-
- The exception handler is very similar to the interrupt handler with
- a different mandatory function signature:
-
- .. code-block:: c
-
- __attribute__ ((interrupt))
- void f (struct interrupt_frame *frame, uword_t error_code) {
- ...
- }
-
- and compiler pops 'ERROR_CODE' off stack before the 'IRET' instruction.
-
- The exception handler should only be used for exceptions which push an
- error code and all other exceptions must use the interrupt handler.
- The system will crash if the wrong handler is used.
- }];
-}
-
def AnyX86NoCallerSavedRegistersDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
@@ -2760,6 +2827,31 @@ For example:
}];
}
+def X86ForceAlignArgPointerDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+Use this attribute to force stack alignment.
+
+Legacy x86 code uses 4-byte stack alignment. Newer aligned SSE instructions
+(like 'movaps') that work with the stack require operands to be 16-byte aligned.
+This attribute realigns the stack in the function prologue to make sure the
+stack can be used with SSE instructions.
+
+Note that the x86_64 ABI forces 16-byte stack alignment at the call site.
+Because of this, 'force_align_arg_pointer' is not needed on x86_64, except in
+rare cases where the caller does not align the stack properly (e.g. flow
+jumps from i386 arch code).
+
+ .. code-block:: c
+
+ __attribute__ ((force_align_arg_pointer))
+ void f () {
+ ...
+ }
+
+ }];
+}
+
def SwiftCallDocs : Documentation {
let Category = DocCatVariable;
let Content = [{
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Attributes.h b/contrib/llvm/tools/clang/include/clang/Basic/Attributes.h
index ea9e28ae681ae..c651abacd482b 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Attributes.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Attributes.h
@@ -26,6 +26,8 @@ enum class AttrSyntax {
Microsoft,
// Is the identifier known as a C++-style attribute?
CXX,
+ // Is the identifier known as a C-style attribute?
+ C,
// Is the identifier known as a pragma attribute?
Pragma
};
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def
index 1ddb9beaf9133..3d4deb5ed3064 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def
@@ -103,9 +103,9 @@
#endif
// Standard libc/libm functions:
-BUILTIN(__builtin_atan2 , "ddd" , "Fnc")
-BUILTIN(__builtin_atan2f, "fff" , "Fnc")
-BUILTIN(__builtin_atan2l, "LdLdLd", "Fnc")
+BUILTIN(__builtin_atan2 , "ddd" , "Fne")
+BUILTIN(__builtin_atan2f, "fff" , "Fne")
+BUILTIN(__builtin_atan2l, "LdLdLd", "Fne")
BUILTIN(__builtin_abs , "ii" , "ncF")
BUILTIN(__builtin_copysign, "ddd", "ncF")
BUILTIN(__builtin_copysignf, "fff", "ncF")
@@ -113,9 +113,9 @@ BUILTIN(__builtin_copysignl, "LdLdLd", "ncF")
BUILTIN(__builtin_fabs , "dd" , "ncF")
BUILTIN(__builtin_fabsf, "ff" , "ncF")
BUILTIN(__builtin_fabsl, "LdLd", "ncF")
-BUILTIN(__builtin_fmod , "ddd" , "Fnc")
-BUILTIN(__builtin_fmodf, "fff" , "Fnc")
-BUILTIN(__builtin_fmodl, "LdLdLd", "Fnc")
+BUILTIN(__builtin_fmod , "ddd" , "Fne")
+BUILTIN(__builtin_fmodf, "fff" , "Fne")
+BUILTIN(__builtin_fmodl, "LdLdLd", "Fne")
BUILTIN(__builtin_frexp , "ddi*" , "Fn")
BUILTIN(__builtin_frexpf, "ffi*" , "Fn")
BUILTIN(__builtin_frexpl, "LdLdi*", "Fn")
@@ -127,9 +127,9 @@ BUILTIN(__builtin_inff , "f" , "nc")
BUILTIN(__builtin_infl , "Ld" , "nc")
BUILTIN(__builtin_labs , "LiLi" , "Fnc")
BUILTIN(__builtin_llabs, "LLiLLi", "Fnc")
-BUILTIN(__builtin_ldexp , "ddi" , "Fnc")
-BUILTIN(__builtin_ldexpf, "ffi" , "Fnc")
-BUILTIN(__builtin_ldexpl, "LdLdi", "Fnc")
+BUILTIN(__builtin_ldexp , "ddi" , "Fne")
+BUILTIN(__builtin_ldexpf, "ffi" , "Fne")
+BUILTIN(__builtin_ldexpl, "LdLdi", "Fne")
BUILTIN(__builtin_modf , "ddd*" , "Fn")
BUILTIN(__builtin_modff, "fff*" , "Fn")
BUILTIN(__builtin_modfl, "LdLdLd*", "Fn")
@@ -142,119 +142,119 @@ BUILTIN(__builtin_nansl, "LdcC*", "ncF")
BUILTIN(__builtin_powi , "ddi" , "Fnc")
BUILTIN(__builtin_powif, "ffi" , "Fnc")
BUILTIN(__builtin_powil, "LdLdi", "Fnc")
-BUILTIN(__builtin_pow , "ddd" , "Fnc")
-BUILTIN(__builtin_powf, "fff" , "Fnc")
-BUILTIN(__builtin_powl, "LdLdLd", "Fnc")
+BUILTIN(__builtin_pow , "ddd" , "Fne")
+BUILTIN(__builtin_powf, "fff" , "Fne")
+BUILTIN(__builtin_powl, "LdLdLd", "Fne")
// Standard unary libc/libm functions with double/float/long double variants:
-BUILTIN(__builtin_acos , "dd" , "Fnc")
-BUILTIN(__builtin_acosf, "ff" , "Fnc")
-BUILTIN(__builtin_acosl, "LdLd", "Fnc")
-BUILTIN(__builtin_acosh , "dd" , "Fnc")
-BUILTIN(__builtin_acoshf, "ff" , "Fnc")
-BUILTIN(__builtin_acoshl, "LdLd", "Fnc")
-BUILTIN(__builtin_asin , "dd" , "Fnc")
-BUILTIN(__builtin_asinf, "ff" , "Fnc")
-BUILTIN(__builtin_asinl, "LdLd", "Fnc")
-BUILTIN(__builtin_asinh , "dd" , "Fnc")
-BUILTIN(__builtin_asinhf, "ff" , "Fnc")
-BUILTIN(__builtin_asinhl, "LdLd", "Fnc")
-BUILTIN(__builtin_atan , "dd" , "Fnc")
-BUILTIN(__builtin_atanf, "ff" , "Fnc")
-BUILTIN(__builtin_atanl, "LdLd", "Fnc")
-BUILTIN(__builtin_atanh , "dd", "Fnc")
-BUILTIN(__builtin_atanhf, "ff", "Fnc")
-BUILTIN(__builtin_atanhl, "LdLd", "Fnc")
+BUILTIN(__builtin_acos , "dd" , "Fne")
+BUILTIN(__builtin_acosf, "ff" , "Fne")
+BUILTIN(__builtin_acosl, "LdLd", "Fne")
+BUILTIN(__builtin_acosh , "dd" , "Fne")
+BUILTIN(__builtin_acoshf, "ff" , "Fne")
+BUILTIN(__builtin_acoshl, "LdLd", "Fne")
+BUILTIN(__builtin_asin , "dd" , "Fne")
+BUILTIN(__builtin_asinf, "ff" , "Fne")
+BUILTIN(__builtin_asinl, "LdLd", "Fne")
+BUILTIN(__builtin_asinh , "dd" , "Fne")
+BUILTIN(__builtin_asinhf, "ff" , "Fne")
+BUILTIN(__builtin_asinhl, "LdLd", "Fne")
+BUILTIN(__builtin_atan , "dd" , "Fne")
+BUILTIN(__builtin_atanf, "ff" , "Fne")
+BUILTIN(__builtin_atanl, "LdLd", "Fne")
+BUILTIN(__builtin_atanh , "dd", "Fne")
+BUILTIN(__builtin_atanhf, "ff", "Fne")
+BUILTIN(__builtin_atanhl, "LdLd", "Fne")
BUILTIN(__builtin_cbrt , "dd", "Fnc")
BUILTIN(__builtin_cbrtf, "ff", "Fnc")
BUILTIN(__builtin_cbrtl, "LdLd", "Fnc")
BUILTIN(__builtin_ceil , "dd" , "Fnc")
BUILTIN(__builtin_ceilf, "ff" , "Fnc")
BUILTIN(__builtin_ceill, "LdLd", "Fnc")
-BUILTIN(__builtin_cos , "dd" , "Fnc")
-BUILTIN(__builtin_cosf, "ff" , "Fnc")
-BUILTIN(__builtin_cosh , "dd" , "Fnc")
-BUILTIN(__builtin_coshf, "ff" , "Fnc")
-BUILTIN(__builtin_coshl, "LdLd", "Fnc")
-BUILTIN(__builtin_cosl, "LdLd", "Fnc")
-BUILTIN(__builtin_erf , "dd", "Fnc")
-BUILTIN(__builtin_erff, "ff", "Fnc")
-BUILTIN(__builtin_erfl, "LdLd", "Fnc")
-BUILTIN(__builtin_erfc , "dd", "Fnc")
-BUILTIN(__builtin_erfcf, "ff", "Fnc")
-BUILTIN(__builtin_erfcl, "LdLd", "Fnc")
-BUILTIN(__builtin_exp , "dd" , "Fnc")
-BUILTIN(__builtin_expf, "ff" , "Fnc")
-BUILTIN(__builtin_expl, "LdLd", "Fnc")
-BUILTIN(__builtin_exp2 , "dd" , "Fnc")
-BUILTIN(__builtin_exp2f, "ff" , "Fnc")
-BUILTIN(__builtin_exp2l, "LdLd", "Fnc")
-BUILTIN(__builtin_expm1 , "dd", "Fnc")
-BUILTIN(__builtin_expm1f, "ff", "Fnc")
-BUILTIN(__builtin_expm1l, "LdLd", "Fnc")
-BUILTIN(__builtin_fdim, "ddd", "Fnc")
-BUILTIN(__builtin_fdimf, "fff", "Fnc")
-BUILTIN(__builtin_fdiml, "LdLdLd", "Fnc")
+BUILTIN(__builtin_cos , "dd" , "Fne")
+BUILTIN(__builtin_cosf, "ff" , "Fne")
+BUILTIN(__builtin_cosh , "dd" , "Fne")
+BUILTIN(__builtin_coshf, "ff" , "Fne")
+BUILTIN(__builtin_coshl, "LdLd", "Fne")
+BUILTIN(__builtin_cosl, "LdLd", "Fne")
+BUILTIN(__builtin_erf , "dd", "Fne")
+BUILTIN(__builtin_erff, "ff", "Fne")
+BUILTIN(__builtin_erfl, "LdLd", "Fne")
+BUILTIN(__builtin_erfc , "dd", "Fne")
+BUILTIN(__builtin_erfcf, "ff", "Fne")
+BUILTIN(__builtin_erfcl, "LdLd", "Fne")
+BUILTIN(__builtin_exp , "dd" , "Fne")
+BUILTIN(__builtin_expf, "ff" , "Fne")
+BUILTIN(__builtin_expl, "LdLd", "Fne")
+BUILTIN(__builtin_exp2 , "dd" , "Fne")
+BUILTIN(__builtin_exp2f, "ff" , "Fne")
+BUILTIN(__builtin_exp2l, "LdLd", "Fne")
+BUILTIN(__builtin_expm1 , "dd", "Fne")
+BUILTIN(__builtin_expm1f, "ff", "Fne")
+BUILTIN(__builtin_expm1l, "LdLd", "Fne")
+BUILTIN(__builtin_fdim, "ddd", "Fne")
+BUILTIN(__builtin_fdimf, "fff", "Fne")
+BUILTIN(__builtin_fdiml, "LdLdLd", "Fne")
BUILTIN(__builtin_floor , "dd" , "Fnc")
BUILTIN(__builtin_floorf, "ff" , "Fnc")
BUILTIN(__builtin_floorl, "LdLd", "Fnc")
-BUILTIN(__builtin_fma, "dddd", "Fnc")
-BUILTIN(__builtin_fmaf, "ffff", "Fnc")
-BUILTIN(__builtin_fmal, "LdLdLdLd", "Fnc")
+BUILTIN(__builtin_fma, "dddd", "Fne")
+BUILTIN(__builtin_fmaf, "ffff", "Fne")
+BUILTIN(__builtin_fmal, "LdLdLdLd", "Fne")
BUILTIN(__builtin_fmax, "ddd", "Fnc")
BUILTIN(__builtin_fmaxf, "fff", "Fnc")
BUILTIN(__builtin_fmaxl, "LdLdLd", "Fnc")
BUILTIN(__builtin_fmin, "ddd", "Fnc")
BUILTIN(__builtin_fminf, "fff", "Fnc")
BUILTIN(__builtin_fminl, "LdLdLd", "Fnc")
-BUILTIN(__builtin_hypot , "ddd" , "Fnc")
-BUILTIN(__builtin_hypotf, "fff" , "Fnc")
-BUILTIN(__builtin_hypotl, "LdLdLd", "Fnc")
-BUILTIN(__builtin_ilogb , "id", "Fnc")
-BUILTIN(__builtin_ilogbf, "if", "Fnc")
-BUILTIN(__builtin_ilogbl, "iLd", "Fnc")
-BUILTIN(__builtin_lgamma , "dd", "Fnc")
-BUILTIN(__builtin_lgammaf, "ff", "Fnc")
-BUILTIN(__builtin_lgammal, "LdLd", "Fnc")
-BUILTIN(__builtin_llrint, "LLid", "Fnc")
-BUILTIN(__builtin_llrintf, "LLif", "Fnc")
-BUILTIN(__builtin_llrintl, "LLiLd", "Fnc")
-BUILTIN(__builtin_llround , "LLid", "Fnc")
-BUILTIN(__builtin_llroundf, "LLif", "Fnc")
-BUILTIN(__builtin_llroundl, "LLiLd", "Fnc")
-BUILTIN(__builtin_log , "dd" , "Fnc")
-BUILTIN(__builtin_log10 , "dd" , "Fnc")
-BUILTIN(__builtin_log10f, "ff" , "Fnc")
-BUILTIN(__builtin_log10l, "LdLd", "Fnc")
-BUILTIN(__builtin_log1p , "dd" , "Fnc")
-BUILTIN(__builtin_log1pf, "ff" , "Fnc")
-BUILTIN(__builtin_log1pl, "LdLd", "Fnc")
-BUILTIN(__builtin_log2, "dd" , "Fnc")
-BUILTIN(__builtin_log2f, "ff" , "Fnc")
-BUILTIN(__builtin_log2l, "LdLd" , "Fnc")
-BUILTIN(__builtin_logb , "dd", "Fnc")
-BUILTIN(__builtin_logbf, "ff", "Fnc")
-BUILTIN(__builtin_logbl, "LdLd", "Fnc")
-BUILTIN(__builtin_logf, "ff" , "Fnc")
-BUILTIN(__builtin_logl, "LdLd", "Fnc")
-BUILTIN(__builtin_lrint , "Lid", "Fnc")
-BUILTIN(__builtin_lrintf, "Lif", "Fnc")
-BUILTIN(__builtin_lrintl, "LiLd", "Fnc")
-BUILTIN(__builtin_lround , "Lid", "Fnc")
-BUILTIN(__builtin_lroundf, "Lif", "Fnc")
-BUILTIN(__builtin_lroundl, "LiLd", "Fnc")
+BUILTIN(__builtin_hypot , "ddd" , "Fne")
+BUILTIN(__builtin_hypotf, "fff" , "Fne")
+BUILTIN(__builtin_hypotl, "LdLdLd", "Fne")
+BUILTIN(__builtin_ilogb , "id", "Fne")
+BUILTIN(__builtin_ilogbf, "if", "Fne")
+BUILTIN(__builtin_ilogbl, "iLd", "Fne")
+BUILTIN(__builtin_lgamma , "dd", "Fn")
+BUILTIN(__builtin_lgammaf, "ff", "Fn")
+BUILTIN(__builtin_lgammal, "LdLd", "Fn")
+BUILTIN(__builtin_llrint, "LLid", "Fne")
+BUILTIN(__builtin_llrintf, "LLif", "Fne")
+BUILTIN(__builtin_llrintl, "LLiLd", "Fne")
+BUILTIN(__builtin_llround , "LLid", "Fne")
+BUILTIN(__builtin_llroundf, "LLif", "Fne")
+BUILTIN(__builtin_llroundl, "LLiLd", "Fne")
+BUILTIN(__builtin_log , "dd" , "Fne")
+BUILTIN(__builtin_log10 , "dd" , "Fne")
+BUILTIN(__builtin_log10f, "ff" , "Fne")
+BUILTIN(__builtin_log10l, "LdLd", "Fne")
+BUILTIN(__builtin_log1p , "dd" , "Fne")
+BUILTIN(__builtin_log1pf, "ff" , "Fne")
+BUILTIN(__builtin_log1pl, "LdLd", "Fne")
+BUILTIN(__builtin_log2, "dd" , "Fne")
+BUILTIN(__builtin_log2f, "ff" , "Fne")
+BUILTIN(__builtin_log2l, "LdLd" , "Fne")
+BUILTIN(__builtin_logb , "dd", "Fne")
+BUILTIN(__builtin_logbf, "ff", "Fne")
+BUILTIN(__builtin_logbl, "LdLd", "Fne")
+BUILTIN(__builtin_logf, "ff" , "Fne")
+BUILTIN(__builtin_logl, "LdLd", "Fne")
+BUILTIN(__builtin_lrint , "Lid", "Fne")
+BUILTIN(__builtin_lrintf, "Lif", "Fne")
+BUILTIN(__builtin_lrintl, "LiLd", "Fne")
+BUILTIN(__builtin_lround , "Lid", "Fne")
+BUILTIN(__builtin_lroundf, "Lif", "Fne")
+BUILTIN(__builtin_lroundl, "LiLd", "Fne")
BUILTIN(__builtin_nearbyint , "dd", "Fnc")
BUILTIN(__builtin_nearbyintf, "ff", "Fnc")
BUILTIN(__builtin_nearbyintl, "LdLd", "Fnc")
-BUILTIN(__builtin_nextafter , "ddd", "Fnc")
-BUILTIN(__builtin_nextafterf, "fff", "Fnc")
-BUILTIN(__builtin_nextafterl, "LdLdLd", "Fnc")
-BUILTIN(__builtin_nexttoward , "ddLd", "Fnc")
-BUILTIN(__builtin_nexttowardf, "ffLd", "Fnc")
-BUILTIN(__builtin_nexttowardl, "LdLdLd", "Fnc")
-BUILTIN(__builtin_remainder , "ddd", "Fnc")
-BUILTIN(__builtin_remainderf, "fff", "Fnc")
-BUILTIN(__builtin_remainderl, "LdLdLd", "Fnc")
+BUILTIN(__builtin_nextafter , "ddd", "Fne")
+BUILTIN(__builtin_nextafterf, "fff", "Fne")
+BUILTIN(__builtin_nextafterl, "LdLdLd", "Fne")
+BUILTIN(__builtin_nexttoward , "ddLd", "Fne")
+BUILTIN(__builtin_nexttowardf, "ffLd", "Fne")
+BUILTIN(__builtin_nexttowardl, "LdLdLd", "Fne")
+BUILTIN(__builtin_remainder , "ddd", "Fne")
+BUILTIN(__builtin_remainderf, "fff", "Fne")
+BUILTIN(__builtin_remainderl, "LdLdLd", "Fne")
BUILTIN(__builtin_remquo , "dddi*", "Fn")
BUILTIN(__builtin_remquof, "fffi*", "Fn")
BUILTIN(__builtin_remquol, "LdLdLdi*", "Fn")
@@ -264,101 +264,101 @@ BUILTIN(__builtin_rintl, "LdLd", "Fnc")
BUILTIN(__builtin_round, "dd" , "Fnc")
BUILTIN(__builtin_roundf, "ff" , "Fnc")
BUILTIN(__builtin_roundl, "LdLd" , "Fnc")
-BUILTIN(__builtin_scalbln , "ddLi", "Fnc")
-BUILTIN(__builtin_scalblnf, "ffLi", "Fnc")
-BUILTIN(__builtin_scalblnl, "LdLdLi", "Fnc")
-BUILTIN(__builtin_scalbn , "ddi", "Fnc")
-BUILTIN(__builtin_scalbnf, "ffi", "Fnc")
-BUILTIN(__builtin_scalbnl, "LdLdi", "Fnc")
-BUILTIN(__builtin_sin , "dd" , "Fnc")
-BUILTIN(__builtin_sinf, "ff" , "Fnc")
-BUILTIN(__builtin_sinh , "dd" , "Fnc")
-BUILTIN(__builtin_sinhf, "ff" , "Fnc")
-BUILTIN(__builtin_sinhl, "LdLd", "Fnc")
-BUILTIN(__builtin_sinl, "LdLd", "Fnc")
-BUILTIN(__builtin_sqrt , "dd" , "Fnc")
-BUILTIN(__builtin_sqrtf, "ff" , "Fnc")
-BUILTIN(__builtin_sqrtl, "LdLd", "Fnc")
-BUILTIN(__builtin_tan , "dd" , "Fnc")
-BUILTIN(__builtin_tanf, "ff" , "Fnc")
-BUILTIN(__builtin_tanh , "dd" , "Fnc")
-BUILTIN(__builtin_tanhf, "ff" , "Fnc")
-BUILTIN(__builtin_tanhl, "LdLd", "Fnc")
-BUILTIN(__builtin_tanl, "LdLd", "Fnc")
-BUILTIN(__builtin_tgamma , "dd", "Fnc")
-BUILTIN(__builtin_tgammaf, "ff", "Fnc")
-BUILTIN(__builtin_tgammal, "LdLd", "Fnc")
+BUILTIN(__builtin_scalbln , "ddLi", "Fne")
+BUILTIN(__builtin_scalblnf, "ffLi", "Fne")
+BUILTIN(__builtin_scalblnl, "LdLdLi", "Fne")
+BUILTIN(__builtin_scalbn , "ddi", "Fne")
+BUILTIN(__builtin_scalbnf, "ffi", "Fne")
+BUILTIN(__builtin_scalbnl, "LdLdi", "Fne")
+BUILTIN(__builtin_sin , "dd" , "Fne")
+BUILTIN(__builtin_sinf, "ff" , "Fne")
+BUILTIN(__builtin_sinh , "dd" , "Fne")
+BUILTIN(__builtin_sinhf, "ff" , "Fne")
+BUILTIN(__builtin_sinhl, "LdLd", "Fne")
+BUILTIN(__builtin_sinl, "LdLd", "Fne")
+BUILTIN(__builtin_sqrt , "dd" , "Fne")
+BUILTIN(__builtin_sqrtf, "ff" , "Fne")
+BUILTIN(__builtin_sqrtl, "LdLd", "Fne")
+BUILTIN(__builtin_tan , "dd" , "Fne")
+BUILTIN(__builtin_tanf, "ff" , "Fne")
+BUILTIN(__builtin_tanh , "dd" , "Fne")
+BUILTIN(__builtin_tanhf, "ff" , "Fne")
+BUILTIN(__builtin_tanhl, "LdLd", "Fne")
+BUILTIN(__builtin_tanl, "LdLd", "Fne")
+BUILTIN(__builtin_tgamma , "dd", "Fne")
+BUILTIN(__builtin_tgammaf, "ff", "Fne")
+BUILTIN(__builtin_tgammal, "LdLd", "Fne")
BUILTIN(__builtin_trunc , "dd", "Fnc")
BUILTIN(__builtin_truncf, "ff", "Fnc")
BUILTIN(__builtin_truncl, "LdLd", "Fnc")
// C99 complex builtins
-BUILTIN(__builtin_cabs, "dXd", "Fnc")
-BUILTIN(__builtin_cabsf, "fXf", "Fnc")
-BUILTIN(__builtin_cabsl, "LdXLd", "Fnc")
-BUILTIN(__builtin_cacos, "XdXd", "Fnc")
-BUILTIN(__builtin_cacosf, "XfXf", "Fnc")
-BUILTIN(__builtin_cacosh, "XdXd", "Fnc")
-BUILTIN(__builtin_cacoshf, "XfXf", "Fnc")
-BUILTIN(__builtin_cacoshl, "XLdXLd", "Fnc")
-BUILTIN(__builtin_cacosl, "XLdXLd", "Fnc")
-BUILTIN(__builtin_carg, "dXd", "Fnc")
-BUILTIN(__builtin_cargf, "fXf", "Fnc")
-BUILTIN(__builtin_cargl, "LdXLd", "Fnc")
-BUILTIN(__builtin_casin, "XdXd", "Fnc")
-BUILTIN(__builtin_casinf, "XfXf", "Fnc")
-BUILTIN(__builtin_casinh, "XdXd", "Fnc")
-BUILTIN(__builtin_casinhf, "XfXf", "Fnc")
-BUILTIN(__builtin_casinhl, "XLdXLd", "Fnc")
-BUILTIN(__builtin_casinl, "XLdXLd", "Fnc")
-BUILTIN(__builtin_catan, "XdXd", "Fnc")
-BUILTIN(__builtin_catanf, "XfXf", "Fnc")
-BUILTIN(__builtin_catanh, "XdXd", "Fnc")
-BUILTIN(__builtin_catanhf, "XfXf", "Fnc")
-BUILTIN(__builtin_catanhl, "XLdXLd", "Fnc")
-BUILTIN(__builtin_catanl, "XLdXLd", "Fnc")
-BUILTIN(__builtin_ccos, "XdXd", "Fnc")
-BUILTIN(__builtin_ccosf, "XfXf", "Fnc")
-BUILTIN(__builtin_ccosl, "XLdXLd", "Fnc")
-BUILTIN(__builtin_ccosh, "XdXd", "Fnc")
-BUILTIN(__builtin_ccoshf, "XfXf", "Fnc")
-BUILTIN(__builtin_ccoshl, "XLdXLd", "Fnc")
-BUILTIN(__builtin_cexp, "XdXd", "Fnc")
-BUILTIN(__builtin_cexpf, "XfXf", "Fnc")
-BUILTIN(__builtin_cexpl, "XLdXLd", "Fnc")
+BUILTIN(__builtin_cabs, "dXd", "Fne")
+BUILTIN(__builtin_cabsf, "fXf", "Fne")
+BUILTIN(__builtin_cabsl, "LdXLd", "Fne")
+BUILTIN(__builtin_cacos, "XdXd", "Fne")
+BUILTIN(__builtin_cacosf, "XfXf", "Fne")
+BUILTIN(__builtin_cacosh, "XdXd", "Fne")
+BUILTIN(__builtin_cacoshf, "XfXf", "Fne")
+BUILTIN(__builtin_cacoshl, "XLdXLd", "Fne")
+BUILTIN(__builtin_cacosl, "XLdXLd", "Fne")
+BUILTIN(__builtin_carg, "dXd", "Fne")
+BUILTIN(__builtin_cargf, "fXf", "Fne")
+BUILTIN(__builtin_cargl, "LdXLd", "Fne")
+BUILTIN(__builtin_casin, "XdXd", "Fne")
+BUILTIN(__builtin_casinf, "XfXf", "Fne")
+BUILTIN(__builtin_casinh, "XdXd", "Fne")
+BUILTIN(__builtin_casinhf, "XfXf", "Fne")
+BUILTIN(__builtin_casinhl, "XLdXLd", "Fne")
+BUILTIN(__builtin_casinl, "XLdXLd", "Fne")
+BUILTIN(__builtin_catan, "XdXd", "Fne")
+BUILTIN(__builtin_catanf, "XfXf", "Fne")
+BUILTIN(__builtin_catanh, "XdXd", "Fne")
+BUILTIN(__builtin_catanhf, "XfXf", "Fne")
+BUILTIN(__builtin_catanhl, "XLdXLd", "Fne")
+BUILTIN(__builtin_catanl, "XLdXLd", "Fne")
+BUILTIN(__builtin_ccos, "XdXd", "Fne")
+BUILTIN(__builtin_ccosf, "XfXf", "Fne")
+BUILTIN(__builtin_ccosl, "XLdXLd", "Fne")
+BUILTIN(__builtin_ccosh, "XdXd", "Fne")
+BUILTIN(__builtin_ccoshf, "XfXf", "Fne")
+BUILTIN(__builtin_ccoshl, "XLdXLd", "Fne")
+BUILTIN(__builtin_cexp, "XdXd", "Fne")
+BUILTIN(__builtin_cexpf, "XfXf", "Fne")
+BUILTIN(__builtin_cexpl, "XLdXLd", "Fne")
BUILTIN(__builtin_cimag, "dXd", "Fnc")
BUILTIN(__builtin_cimagf, "fXf", "Fnc")
BUILTIN(__builtin_cimagl, "LdXLd", "Fnc")
BUILTIN(__builtin_conj, "XdXd", "Fnc")
BUILTIN(__builtin_conjf, "XfXf", "Fnc")
BUILTIN(__builtin_conjl, "XLdXLd", "Fnc")
-BUILTIN(__builtin_clog, "XdXd", "Fnc")
-BUILTIN(__builtin_clogf, "XfXf", "Fnc")
-BUILTIN(__builtin_clogl, "XLdXLd", "Fnc")
+BUILTIN(__builtin_clog, "XdXd", "Fne")
+BUILTIN(__builtin_clogf, "XfXf", "Fne")
+BUILTIN(__builtin_clogl, "XLdXLd", "Fne")
BUILTIN(__builtin_cproj, "XdXd", "Fnc")
BUILTIN(__builtin_cprojf, "XfXf", "Fnc")
BUILTIN(__builtin_cprojl, "XLdXLd", "Fnc")
-BUILTIN(__builtin_cpow, "XdXdXd", "Fnc")
-BUILTIN(__builtin_cpowf, "XfXfXf", "Fnc")
-BUILTIN(__builtin_cpowl, "XLdXLdXLd", "Fnc")
+BUILTIN(__builtin_cpow, "XdXdXd", "Fne")
+BUILTIN(__builtin_cpowf, "XfXfXf", "Fne")
+BUILTIN(__builtin_cpowl, "XLdXLdXLd", "Fne")
BUILTIN(__builtin_creal, "dXd", "Fnc")
BUILTIN(__builtin_crealf, "fXf", "Fnc")
BUILTIN(__builtin_creall, "LdXLd", "Fnc")
-BUILTIN(__builtin_csin, "XdXd", "Fnc")
-BUILTIN(__builtin_csinf, "XfXf", "Fnc")
-BUILTIN(__builtin_csinl, "XLdXLd", "Fnc")
-BUILTIN(__builtin_csinh, "XdXd", "Fnc")
-BUILTIN(__builtin_csinhf, "XfXf", "Fnc")
-BUILTIN(__builtin_csinhl, "XLdXLd", "Fnc")
-BUILTIN(__builtin_csqrt, "XdXd", "Fnc")
-BUILTIN(__builtin_csqrtf, "XfXf", "Fnc")
-BUILTIN(__builtin_csqrtl, "XLdXLd", "Fnc")
-BUILTIN(__builtin_ctan, "XdXd", "Fnc")
-BUILTIN(__builtin_ctanf, "XfXf", "Fnc")
-BUILTIN(__builtin_ctanl, "XLdXLd", "Fnc")
-BUILTIN(__builtin_ctanh, "XdXd", "Fnc")
-BUILTIN(__builtin_ctanhf, "XfXf", "Fnc")
-BUILTIN(__builtin_ctanhl, "XLdXLd", "Fnc")
+BUILTIN(__builtin_csin, "XdXd", "Fne")
+BUILTIN(__builtin_csinf, "XfXf", "Fne")
+BUILTIN(__builtin_csinl, "XLdXLd", "Fne")
+BUILTIN(__builtin_csinh, "XdXd", "Fne")
+BUILTIN(__builtin_csinhf, "XfXf", "Fne")
+BUILTIN(__builtin_csinhl, "XLdXLd", "Fne")
+BUILTIN(__builtin_csqrt, "XdXd", "Fne")
+BUILTIN(__builtin_csqrtf, "XfXf", "Fne")
+BUILTIN(__builtin_csqrtl, "XLdXLd", "Fne")
+BUILTIN(__builtin_ctan, "XdXd", "Fne")
+BUILTIN(__builtin_ctanf, "XfXf", "Fne")
+BUILTIN(__builtin_ctanl, "XLdXLd", "Fne")
+BUILTIN(__builtin_ctanh, "XdXd", "Fne")
+BUILTIN(__builtin_ctanhf, "XfXf", "Fne")
+BUILTIN(__builtin_ctanhl, "XLdXLd", "Fne")
// FP Comparisons.
BUILTIN(__builtin_isgreater , "i.", "Fnc")
@@ -700,6 +700,21 @@ BUILTIN(__atomic_signal_fence, "vi", "n")
BUILTIN(__atomic_always_lock_free, "izvCD*", "n")
BUILTIN(__atomic_is_lock_free, "izvCD*", "n")
+// OpenCL 2.0 atomic builtins.
+ATOMIC_BUILTIN(__opencl_atomic_init, "v.", "t")
+ATOMIC_BUILTIN(__opencl_atomic_load, "v.", "t")
+ATOMIC_BUILTIN(__opencl_atomic_store, "v.", "t")
+ATOMIC_BUILTIN(__opencl_atomic_exchange, "v.", "t")
+ATOMIC_BUILTIN(__opencl_atomic_compare_exchange_strong, "v.", "t")
+ATOMIC_BUILTIN(__opencl_atomic_compare_exchange_weak, "v.", "t")
+ATOMIC_BUILTIN(__opencl_atomic_fetch_add, "v.", "t")
+ATOMIC_BUILTIN(__opencl_atomic_fetch_sub, "v.", "t")
+ATOMIC_BUILTIN(__opencl_atomic_fetch_and, "v.", "t")
+ATOMIC_BUILTIN(__opencl_atomic_fetch_or, "v.", "t")
+ATOMIC_BUILTIN(__opencl_atomic_fetch_xor, "v.", "t")
+ATOMIC_BUILTIN(__opencl_atomic_fetch_min, "v.", "t")
+ATOMIC_BUILTIN(__opencl_atomic_fetch_max, "v.", "t")
+
#undef ATOMIC_BUILTIN
// Non-overloaded atomic builtins.
@@ -717,6 +732,7 @@ BUILTIN(__builtin_rindex, "c*cC*i", "Fn")
// Microsoft builtins. These are only active with -fms-extensions.
LANGBUILTIN(_alloca, "v*z", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(__annotation, "wC*.","n", ALL_MS_LANGUAGES)
LANGBUILTIN(__assume, "vb", "n", ALL_MS_LANGUAGES)
LIBBUILTIN(_byteswap_ushort, "UsUs", "fnc", "stdlib.h", ALL_MS_LANGUAGES)
LIBBUILTIN(_byteswap_ulong, "UNiUNi", "fnc", "stdlib.h", ALL_MS_LANGUAGES)
@@ -992,9 +1008,9 @@ LIBBUILTIN(modf, "ddd*", "fn", "math.h", ALL_LANGUAGES)
LIBBUILTIN(modff, "fff*", "fn", "math.h", ALL_LANGUAGES)
LIBBUILTIN(modfl, "LdLdLd*", "fn", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(nan, "dcC*", "fnc", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(nanf, "fcC*", "fnc", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(nanl, "LdcC*", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(nan, "dcC*", "fUn", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(nanf, "fcC*", "fUn", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(nanl, "LdcC*", "fUn", "math.h", ALL_LANGUAGES)
LIBBUILTIN(pow, "ddd", "fne", "math.h", ALL_LANGUAGES)
LIBBUILTIN(powf, "fff", "fne", "math.h", ALL_LANGUAGES)
@@ -1024,9 +1040,9 @@ LIBBUILTIN(atanh, "dd", "fne", "math.h", ALL_LANGUAGES)
LIBBUILTIN(atanhf, "ff", "fne", "math.h", ALL_LANGUAGES)
LIBBUILTIN(atanhl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(cbrt, "dd", "fne", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(cbrtf, "ff", "fne", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(cbrtl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(cbrt, "dd", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(cbrtf, "ff", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(cbrtl, "LdLd", "fnc", "math.h", ALL_LANGUAGES)
LIBBUILTIN(ceil, "dd", "fnc", "math.h", ALL_LANGUAGES)
LIBBUILTIN(ceilf, "ff", "fnc", "math.h", ALL_LANGUAGES)
@@ -1146,6 +1162,10 @@ LIBBUILTIN(remainder, "ddd", "fne", "math.h", ALL_LANGUAGES)
LIBBUILTIN(remainderf, "fff", "fne", "math.h", ALL_LANGUAGES)
LIBBUILTIN(remainderl, "LdLdLd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(remquo, "dddi*", "fn", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(remquof, "fffi*", "fn", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(remquol, "LdLdLdi*", "fn", "math.h", ALL_LANGUAGES)
+
LIBBUILTIN(rint, "dd", "fnc", "math.h", ALL_LANGUAGES)
LIBBUILTIN(rintf, "ff", "fnc", "math.h", ALL_LANGUAGES)
LIBBUILTIN(rintl, "LdLd", "fnc", "math.h", ALL_LANGUAGES)
@@ -1190,49 +1210,49 @@ LIBBUILTIN(trunc, "dd", "fnc", "math.h", ALL_LANGUAGES)
LIBBUILTIN(truncf, "ff", "fnc", "math.h", ALL_LANGUAGES)
LIBBUILTIN(truncl, "LdLd", "fnc", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(cabs, "dXd", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(cabsf, "fXf", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(cabsl, "LdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cabs, "dXd", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cabsf, "fXf", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cabsl, "LdXLd", "fne", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(cacos, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(cacosf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(cacosl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cacos, "XdXd", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cacosf, "XfXf", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cacosl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(cacosh, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(cacoshf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(cacoshl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cacosh, "XdXd", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cacoshf, "XfXf", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cacoshl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(carg, "dXd", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(cargf, "fXf", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(cargl, "LdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(carg, "dXd", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cargf, "fXf", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cargl, "LdXLd", "fne", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(casin, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(casinf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(casinl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(casin, "XdXd", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(casinf, "XfXf", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(casinl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(casinh, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(casinhf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(casinhl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(casinh, "XdXd", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(casinhf, "XfXf", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(casinhl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(catan, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(catanf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(catanl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(catan, "XdXd", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(catanf, "XfXf", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(catanl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(catanh, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(catanhf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(catanhl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(catanh, "XdXd", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(catanhf, "XfXf", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(catanhl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(ccos, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(ccosf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(ccosl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(ccos, "XdXd", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(ccosf, "XfXf", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(ccosl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(ccosh, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(ccoshf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(ccoshl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(ccosh, "XdXd", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(ccoshf, "XfXf", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(ccoshl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(cexp, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(cexpf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(cexpl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cexp, "XdXd", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cexpf, "XfXf", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cexpl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES)
LIBBUILTIN(cimag, "dXd", "fnc", "complex.h", ALL_LANGUAGES)
LIBBUILTIN(cimagf, "fXf", "fnc", "complex.h", ALL_LANGUAGES)
@@ -1242,41 +1262,41 @@ LIBBUILTIN(conj, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
LIBBUILTIN(conjf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
LIBBUILTIN(conjl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(clog, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(clogf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(clogl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(clog, "XdXd", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(clogf, "XfXf", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(clogl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES)
LIBBUILTIN(cproj, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
LIBBUILTIN(cprojf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
LIBBUILTIN(cprojl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(cpow, "XdXdXd", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(cpowf, "XfXfXf", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(cpowl, "XLdXLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cpow, "XdXdXd", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cpowf, "XfXfXf", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cpowl, "XLdXLdXLd", "fne", "complex.h", ALL_LANGUAGES)
LIBBUILTIN(creal, "dXd", "fnc", "complex.h", ALL_LANGUAGES)
LIBBUILTIN(crealf, "fXf", "fnc", "complex.h", ALL_LANGUAGES)
LIBBUILTIN(creall, "LdXLd", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(csin, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(csinf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(csinl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(csin, "XdXd", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(csinf, "XfXf", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(csinl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(csinh, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(csinhf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(csinhl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(csinh, "XdXd", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(csinhf, "XfXf", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(csinhl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(csqrt, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(csqrtf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(csqrtl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(csqrt, "XdXd", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(csqrtf, "XfXf", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(csqrtl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(ctan, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(ctanf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(ctanl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(ctan, "XdXd", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(ctanf, "XfXf", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(ctanl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(ctanh, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(ctanhf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(ctanhl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(ctanh, "XdXd", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(ctanhf, "XfXf", "fne", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(ctanhl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES)
// __sinpi and friends are OS X specific library functions, but otherwise much
// like the standard (non-complex) sin (etc).
@@ -1398,18 +1418,29 @@ LANGBUILTIN(get_pipe_max_packets, "Ui.", "tn", OCLC20_LANG)
// OpenCL v2.0 s6.13.17 - Enqueue kernel functions.
// Custom builtin check allows to perform special check of passed block arguments.
LANGBUILTIN(enqueue_kernel, "i.", "tn", OCLC20_LANG)
-LANGBUILTIN(get_kernel_work_group_size, "i.", "tn", OCLC20_LANG)
-LANGBUILTIN(get_kernel_preferred_work_group_size_multiple, "i.", "tn", OCLC20_LANG)
+LANGBUILTIN(get_kernel_work_group_size, "Ui.", "tn", OCLC20_LANG)
+LANGBUILTIN(get_kernel_preferred_work_group_size_multiple, "Ui.", "tn", OCLC20_LANG)
+LANGBUILTIN(get_kernel_max_sub_group_size_for_ndrange, "Ui.", "tn", OCLC20_LANG)
+LANGBUILTIN(get_kernel_sub_group_count_for_ndrange, "Ui.", "tn", OCLC20_LANG)
// OpenCL v2.0 s6.13.9 - Address space qualifier functions.
LANGBUILTIN(to_global, "v*v*", "tn", OCLC20_LANG)
LANGBUILTIN(to_local, "v*v*", "tn", OCLC20_LANG)
LANGBUILTIN(to_private, "v*v*", "tn", OCLC20_LANG)
+// OpenCL half load/store builtin
+LANGBUILTIN(__builtin_store_half, "vdh*", "n", ALL_OCLC_LANGUAGES)
+LANGBUILTIN(__builtin_store_halff, "vfh*", "n", ALL_OCLC_LANGUAGES)
+LANGBUILTIN(__builtin_load_half, "dhC*", "nc", ALL_OCLC_LANGUAGES)
+LANGBUILTIN(__builtin_load_halff, "fhC*", "nc", ALL_OCLC_LANGUAGES)
+
// Builtins for os_log/os_trace
BUILTIN(__builtin_os_log_format_buffer_size, "zcC*.", "p:0:nut")
BUILTIN(__builtin_os_log_format, "v*v*cC*.", "p:0:nt")
+// OpenMP 4.0
+LANGBUILTIN(omp_is_initial_device, "i", "nc", OMP_LANG)
+
// Builtins for XRay
BUILTIN(__xray_customevent, "vcC*z", "")
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h
index 87c1f93eedefe..963c72ea82e0e 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h
@@ -36,10 +36,13 @@ enum LanguageID {
CXX_LANG = 0x4, // builtin for cplusplus only.
OBJC_LANG = 0x8, // builtin for objective-c and objective-c++
MS_LANG = 0x10, // builtin requires MS mode.
- OCLC20_LANG = 0x20, // builtin for OpenCL C only.
+ OCLC20_LANG = 0x20, // builtin for OpenCL C 2.0 only.
+ OCLC1X_LANG = 0x40, // builtin for OpenCL C 1.x only.
+ OMP_LANG = 0x80, // builtin requires OpenMP.
ALL_LANGUAGES = C_LANG | CXX_LANG | OBJC_LANG, // builtin for all languages.
ALL_GNU_LANGUAGES = ALL_LANGUAGES | GNU_LANG, // builtin requires GNU mode.
- ALL_MS_LANGUAGES = ALL_LANGUAGES | MS_LANG // builtin requires MS mode.
+ ALL_MS_LANGUAGES = ALL_LANGUAGES | MS_LANG, // builtin requires MS mode.
+ ALL_OCLC_LANGUAGES = OCLC1X_LANG | OCLC20_LANG // builtin for OCLC languages.
};
namespace Builtin {
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAArch64.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAArch64.def
index 1db4c1471029b..55a4f70176d00 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAArch64.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAArch64.def
@@ -14,6 +14,10 @@
// The format of this database matches clang/Basic/Builtins.def.
+#if defined(BUILTIN) && !defined(LANGBUILTIN)
+# define LANGBUILTIN(ID, TYPE, ATTRS, BUILTIN_LANG) BUILTIN(ID, TYPE, ATTRS)
+#endif
+
// In libgcc
BUILTIN(__clear_cache, "vv*v*", "i")
@@ -61,4 +65,9 @@ BUILTIN(__builtin_arm_wsr, "vcC*Ui", "nc")
BUILTIN(__builtin_arm_wsr64, "vcC*LUi", "nc")
BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc")
+LANGBUILTIN(__dmb, "vUi", "nc", ALL_MS_LANGUAGES)
+LANGBUILTIN(__dsb, "vUi", "nc", ALL_MS_LANGUAGES)
+LANGBUILTIN(__isb, "vUi", "nc", ALL_MS_LANGUAGES)
+
#undef BUILTIN
+#undef LANGBUILTIN
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAMDGPU.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAMDGPU.def
index 6542acafe48a5..ec6a0fb917657 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAMDGPU.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAMDGPU.def
@@ -21,6 +21,7 @@
// SI+ only builtins.
//===----------------------------------------------------------------------===//
+BUILTIN(__builtin_amdgcn_dispatch_ptr, "Uc*2", "nc")
BUILTIN(__builtin_amdgcn_kernarg_segment_ptr, "Uc*2", "nc")
BUILTIN(__builtin_amdgcn_implicitarg_ptr, "Uc*2", "nc")
@@ -120,6 +121,8 @@ TARGET_BUILTIN(__builtin_amdgcn_fmed3h, "hhhh", "nc", "gfx9-insts")
// Special builtins.
//===----------------------------------------------------------------------===//
BUILTIN(__builtin_amdgcn_read_exec, "LUi", "nc")
+BUILTIN(__builtin_amdgcn_read_exec_lo, "Ui", "nc")
+BUILTIN(__builtin_amdgcn_read_exec_hi, "Ui", "nc")
//===----------------------------------------------------------------------===//
// R600-NI only builtins.
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsARM.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsARM.def
index 4e277f8a5a6b5..941d320d729f4 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsARM.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsARM.def
@@ -36,6 +36,7 @@ BUILTIN(__builtin_arm_smulwt, "iii", "nc")
// Saturating arithmetic
BUILTIN(__builtin_arm_qadd, "iii", "nc")
BUILTIN(__builtin_arm_qsub, "iii", "nc")
+BUILTIN(__builtin_arm_qdbl, "ii", "nc")
BUILTIN(__builtin_arm_ssat, "iiUi", "nc")
BUILTIN(__builtin_arm_usat, "UiiUi", "nc")
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsHexagon.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsHexagon.def
index 14fc4adc25bc0..fda50b53589bd 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsHexagon.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsHexagon.def
@@ -17,7 +17,6 @@
// The builtins below are not autogenerated from iset.py.
// Make sure you do not overwrite these.
-BUILTIN(__builtin_SI_to_SXTHI_asrh, "ii", "")
BUILTIN(__builtin_brev_ldd, "LLi*LLi*LLi*i", "")
BUILTIN(__builtin_brev_ldw, "i*i*i*i", "")
BUILTIN(__builtin_brev_ldh, "s*s*s*i", "")
@@ -882,6 +881,7 @@ BUILTIN(__builtin_HEXAGON_S2_ct0p,"iLLi","")
BUILTIN(__builtin_HEXAGON_S2_ct1p,"iLLi","")
BUILTIN(__builtin_HEXAGON_S2_interleave,"LLiLLi","")
BUILTIN(__builtin_HEXAGON_S2_deinterleave,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_prefetch,"vv*","")
BUILTIN(__builtin_HEXAGON_Y2_dccleana,"vv*","")
BUILTIN(__builtin_HEXAGON_Y2_dccleaninva,"vv*","")
BUILTIN(__builtin_HEXAGON_Y2_dcinva,"vv*","")
@@ -1470,14 +1470,6 @@ BUILTIN(__builtin_HEXAGON_V6_vassign,"V16iV16i","v:60:")
BUILTIN(__builtin_HEXAGON_V6_vassign_128B,"V32iV32i","v:60:")
BUILTIN(__builtin_HEXAGON_V6_vcombine,"V32iV16iV16i","v:60:")
BUILTIN(__builtin_HEXAGON_V6_vcombine_128B,"V64iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vlutb,"V16iV16iLLii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vlutb_128B,"V32iV32iLLii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vlutb_acc,"V16iV16iV16iLLii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vlutb_acc_128B,"V32iV32iV32iLLii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vlutb_dv,"V32iV32iLLii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vlutb_dv_128B,"V64iV64iLLii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vlutb_dv_acc,"V32iV32iV32iLLii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vlutb_dv_acc_128B,"V64iV64iV64iLLii","v:60:")
BUILTIN(__builtin_HEXAGON_V6_vdelta,"V16iV16iV16i","v:60:")
BUILTIN(__builtin_HEXAGON_V6_vdelta_128B,"V32iV32iV32i","v:60:")
BUILTIN(__builtin_HEXAGON_V6_vrdelta,"V16iV16iV16i","v:60:")
@@ -1508,4 +1500,216 @@ BUILTIN(__builtin_HEXAGON_V6_lo_128B,"V32iV64i","v:60:")
BUILTIN(__builtin_HEXAGON_V6_vassignp,"V32iV32i","v:60:")
BUILTIN(__builtin_HEXAGON_V6_vassignp_128B,"V64iV64i","v:60:")
+BUILTIN(__builtin_HEXAGON_V6_vS32b_qpred_ai,"vV16iv*V16i","v:60:")
+BUILTIN(__builtin_HEXAGON_V6_vS32b_nqpred_ai,"vV16iv*V16i","v:60:")
+BUILTIN(__builtin_HEXAGON_V6_vS32b_nt_qpred_ai,"vV16iv*V16i","v:60:")
+BUILTIN(__builtin_HEXAGON_V6_vS32b_nt_nqpred_ai,"vV16iv*V16i","v:60:")
+BUILTIN(__builtin_HEXAGON_V6_vS32b_qpred_ai_128B,"vV32iv*V32i","v:60:")
+BUILTIN(__builtin_HEXAGON_V6_vS32b_nqpred_ai_128B,"vV32iv*V32i","v:60:")
+BUILTIN(__builtin_HEXAGON_V6_vS32b_nt_qpred_ai_128B,"vV32iv*V32i","v:60:")
+BUILTIN(__builtin_HEXAGON_V6_vS32b_nt_nqpred_ai_128B,"vV32iv*V32i","v:60:")
+BUILTIN(__builtin_HEXAGON_V6_vmaskedstoreq,"vV16iv*V16i","v:60:")
+BUILTIN(__builtin_HEXAGON_V6_vmaskedstorenq,"vV16iv*V16i","v:60:")
+BUILTIN(__builtin_HEXAGON_V6_vmaskedstorentq,"vV16iv*V16i","v:60:")
+BUILTIN(__builtin_HEXAGON_V6_vmaskedstorentnq,"vV16iv*V16i","v:60:")
+BUILTIN(__builtin_HEXAGON_V6_vmaskedstoreq_128B,"vV32iv*V32i","v:60:")
+BUILTIN(__builtin_HEXAGON_V6_vmaskedstorenq_128B,"vV32iv*V32i","v:60:")
+BUILTIN(__builtin_HEXAGON_V6_vmaskedstorentq_128B,"vV32iv*V32i","v:60:")
+BUILTIN(__builtin_HEXAGON_V6_vmaskedstorentnq_128B,"vV32iv*V32i","v:60:")
+
+BUILTIN(__builtin_HEXAGON_M6_vabsdiffb,"LLiLLiLLi","v:62:")
+BUILTIN(__builtin_HEXAGON_M6_vabsdiffub,"LLiLLiLLi","v:62:")
+BUILTIN(__builtin_HEXAGON_A6_vminub_RdP,"LLiLLiLLi","v:62:")
+BUILTIN(__builtin_HEXAGON_S6_vsplatrbp,"LLii","v:62:")
+BUILTIN(__builtin_HEXAGON_S6_vtrunehb_ppp,"LLiLLiLLi","v:62:")
+BUILTIN(__builtin_HEXAGON_S6_vtrunohb_ppp,"LLiLLiLLi","v:62:")
+
+BUILTIN(__builtin_HEXAGON_V6_vlsrb,"V16iV16ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vlsrb_128B,"V32iV32ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vasrwuhrndsat,"V16iV16iV16ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vasrwuhrndsat_128B,"V32iV32iV32ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vasruwuhrndsat,"V16iV16iV16ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vasruwuhrndsat_128B,"V32iV32iV32ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vasrhbsat,"V16iV16iV16ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vasrhbsat_128B,"V32iV32iV32ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vrounduwuh,"V16iV16iV16i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vrounduwuh_128B,"V32iV32iV32i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vrounduhub,"V16iV16iV16i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vrounduhub_128B,"V32iV32iV32i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vadduwsat,"V16iV16iV16i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vadduwsat_128B,"V32iV32iV32i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vadduwsat_dv,"V32iV32iV32i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vadduwsat_dv_128B,"V64iV64iV64i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vsubuwsat,"V16iV16iV16i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vsubuwsat_128B,"V32iV32iV32i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vsubuwsat_dv,"V32iV32iV32i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vsubuwsat_dv_128B,"V64iV64iV64i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vaddbsat,"V16iV16iV16i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vaddbsat_128B,"V32iV32iV32i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vaddbsat_dv,"V32iV32iV32i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vaddbsat_dv_128B,"V64iV64iV64i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vsubbsat,"V16iV16iV16i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vsubbsat_128B,"V32iV32iV32i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vsubbsat_dv,"V32iV32iV32i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vsubbsat_dv_128B,"V64iV64iV64i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vaddububb_sat,"V16iV16iV16i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vaddububb_sat_128B,"V32iV32iV32i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vsubububb_sat,"V16iV16iV16i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vsubububb_sat_128B,"V32iV32iV32i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vaddhw_acc,"V32iV32iV16iV16i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vaddhw_acc_128B,"V64iV64iV32iV32i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vadduhw_acc,"V32iV32iV16iV16i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vadduhw_acc_128B,"V64iV64iV32iV32i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vaddubh_acc,"V32iV32iV16iV16i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vaddubh_acc_128B,"V64iV64iV32iV32i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vmpyewuh_64,"V32iV16iV16i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vmpyewuh_64_128B,"V64iV32iV32i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vmpyowh_64_acc,"V32iV32iV16iV16i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vmpyowh_64_acc_128B,"V64iV64iV32iV32i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vmpauhb,"V32iV32ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vmpauhb_128B,"V64iV64ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vmpauhb_acc,"V32iV32iV32ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vmpauhb_acc_128B,"V64iV64iV64ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vmpyiwub,"V16iV16ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vmpyiwub_128B,"V32iV32ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vmpyiwub_acc,"V16iV16iV16ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vmpyiwub_acc_128B,"V32iV32iV32ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vandnqrt,"V16iV16ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vandnqrt_128B,"V32iV32ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vandnqrt_acc,"V16iV16iV16ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vandnqrt_acc_128B,"V32iV32iV32ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vandvqv,"V16iV16iV16i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vandvqv_128B,"V32iV32iV32i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vandvnqv,"V16iV16iV16i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vandvnqv_128B,"V32iV32iV32i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_pred_scalar2v2,"V16ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_pred_scalar2v2_128B,"V32ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_shuffeqw,"V16iV16iV16i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_shuffeqw_128B,"V32iV32iV32i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_shuffeqh,"V16iV16iV16i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_shuffeqh_128B,"V32iV32iV32i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vmaxb,"V16iV16iV16i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vmaxb_128B,"V32iV32iV32i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vminb,"V16iV16iV16i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vminb_128B,"V32iV32iV32i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vsatuwuh,"V16iV16iV16i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vsatuwuh_128B,"V32iV32iV32i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_lvsplath,"V16ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_lvsplath_128B,"V32ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_lvsplatb,"V16ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_lvsplatb_128B,"V32ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vaddclbw,"V16iV16iV16i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vaddclbw_128B,"V32iV32iV32i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vaddclbh,"V16iV16iV16i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vaddclbh_128B,"V32iV32iV32i","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vlutvvbi,"V16iV16iV16ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vlutvvbi_128B,"V32iV32iV32ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vlutvvb_oracci,"V16iV16iV16iV16ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vlutvvb_oracci_128B,"V32iV32iV32iV32ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vlutvwhi,"V32iV16iV16ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vlutvwhi_128B,"V64iV32iV32ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vlutvwh_oracci,"V32iV32iV16iV16ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vlutvwh_oracci_128B,"V64iV64iV32iV32ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vlutvvb_nm,"V16iV16iV16ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vlutvvb_nm_128B,"V32iV32iV32ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vlutvwh_nm,"V32iV16iV16ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vlutvwh_nm_128B,"V64iV32iV32ii","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vaddcarry,"V16iV16iV16iv*","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vaddcarry_128B,"V32iV32iV32iv*","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vsubcarry,"V16iV16iV16iv*","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vsubcarry_128B,"V32iV32iV32iv*","v:62:")
+
+BUILTIN(__builtin_HEXAGON_A6_vcmpbeq_notany,"iLLiLLi","v:65:")
+BUILTIN(__builtin_HEXAGON_A6_vcmpbeq_notany_128B,"iLLiLLi","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vrmpyub_rtt,"V32iV16iLLi","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vrmpyub_rtt_128B,"V64iV32iLLi","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vrmpyub_rtt_acc,"V32iV32iV16iLLi","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vrmpyub_rtt_acc_128B,"V64iV64iV32iLLi","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vrmpybub_rtt,"V32iV16iLLi","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vrmpybub_rtt_128B,"V64iV32iLLi","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vrmpybub_rtt_acc,"V32iV32iV16iLLi","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vrmpybub_rtt_acc_128B,"V64iV64iV32iLLi","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vasruwuhsat,"V16iV16iV16ii","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vasruwuhsat_128B,"V32iV32iV32ii","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vasruhubsat,"V16iV16iV16ii","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vasruhubsat_128B,"V32iV32iV32ii","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vasruhubrndsat,"V16iV16iV16ii","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vasruhubrndsat_128B,"V32iV32iV32ii","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vaslh_acc,"V16iV16iV16ii","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vaslh_acc_128B,"V32iV32iV32ii","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vasrh_acc,"V16iV16iV16ii","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vasrh_acc_128B,"V32iV32iV32ii","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vavguw,"V16iV16iV16i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vavguw_128B,"V32iV32iV32i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vavguwrnd,"V16iV16iV16i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vavguwrnd_128B,"V32iV32iV32i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vavgb,"V16iV16iV16i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vavgb_128B,"V32iV32iV32i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vavgbrnd,"V16iV16iV16i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vavgbrnd_128B,"V32iV32iV32i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vnavgb,"V16iV16iV16i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vnavgb_128B,"V32iV32iV32i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vabsb,"V16iV16i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vabsb_128B,"V32iV32i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vabsb_sat,"V16iV16i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vabsb_sat_128B,"V32iV32i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vmpabuu,"V32iV32ii","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vmpabuu_128B,"V64iV64ii","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vmpabuu_acc,"V32iV32iV32ii","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vmpabuu_acc_128B,"V64iV64iV64ii","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vmpyh_acc,"V32iV32iV16ii","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vmpyh_acc_128B,"V64iV64iV32ii","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vmpahhsat,"V16iV16iV16iLLi","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vmpahhsat_128B,"V32iV32iV32iLLi","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vmpauhuhsat,"V16iV16iV16iLLi","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vmpauhuhsat_128B,"V32iV32iV32iLLi","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vmpsuhuhsat,"V16iV16iV16iLLi","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vmpsuhuhsat_128B,"V32iV32iV32iLLi","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vlut4,"V16iV16iLLi","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vlut4_128B,"V32iV32iLLi","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vmpyuhe,"V16iV16ii","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vmpyuhe_128B,"V32iV32ii","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vmpyuhe_acc,"V16iV16iV16ii","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vmpyuhe_acc_128B,"V32iV32iV32ii","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vgathermw,"vv*iiV16i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vgathermw_128B,"vv*iiV32i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vgathermh,"vv*iiV16i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vgathermh_128B,"vv*iiV32i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vgathermhw,"vv*iiV32i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vgathermhw_128B,"vv*iiV64i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vgathermwq,"vv*V16iiiV16i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vgathermwq_128B,"vv*V32iiiV32i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vgathermhq,"vv*V16iiiV16i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vgathermhq_128B,"vv*V32iiiV32i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vgathermhwq,"vv*V16iiiV32i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vgathermhwq_128B,"vv*V32iiiV64i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vscattermw,"viiV16iV16i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vscattermw_128B,"viiV32iV32i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vscattermh,"viiV16iV16i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vscattermh_128B,"viiV32iV32i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vscattermw_add,"viiV16iV16i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vscattermw_add_128B,"viiV32iV32i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vscattermh_add,"viiV16iV16i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vscattermh_add_128B,"viiV32iV32i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vscattermwq,"vV16iiiV16iV16i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vscattermwq_128B,"vV32iiiV32iV32i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vscattermhq,"vV16iiiV16iV16i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vscattermhq_128B,"vV32iiiV32iV32i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vscattermhw,"viiV32iV16i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vscattermhw_128B,"viiV64iV32i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vscattermhwq,"vV16iiiV32iV16i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vscattermhwq_128B,"vV32iiiV64iV32i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vscattermhw_add,"viiV32iV16i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vscattermhw_add_128B,"viiV64iV32i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vprefixqb,"V16iV16i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vprefixqb_128B,"V32iV32i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vprefixqh,"V16iV16i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vprefixqh_128B,"V32iV32i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vprefixqw,"V16iV16i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vprefixqw_128B,"V32iV32i","v:65:")
+
+BUILTIN(__builtin_HEXAGON_V6_vdd0,"V32i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vdd0_128B,"V64i","v:65:")
+
+
#undef BUILTIN
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsNVPTX.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsNVPTX.def
index afea6cb0f1b25..7bab73a3b110c 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsNVPTX.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsNVPTX.def
@@ -371,6 +371,9 @@ BUILTIN(__nvvm_bitcast_i2f, "fi", "")
BUILTIN(__nvvm_bitcast_ll2d, "dLLi", "")
BUILTIN(__nvvm_bitcast_d2ll, "LLid", "")
+// FNS
+TARGET_BUILTIN(__nvvm_fns, "UiUiUii", "n", "ptx60")
+
// Sync
BUILTIN(__syncthreads, "v", "")
@@ -378,6 +381,9 @@ BUILTIN(__nvvm_bar0_popc, "ii", "")
BUILTIN(__nvvm_bar0_and, "ii", "")
BUILTIN(__nvvm_bar0_or, "ii", "")
BUILTIN(__nvvm_bar_sync, "vi", "n")
+TARGET_BUILTIN(__nvvm_bar_warp_sync, "vUi", "n", "ptx60")
+TARGET_BUILTIN(__nvvm_barrier_sync, "vUi", "n", "ptx60")
+TARGET_BUILTIN(__nvvm_barrier_sync_cnt, "vUiUi", "n", "ptx60")
// Shuffle
@@ -390,6 +396,33 @@ BUILTIN(__nvvm_shfl_bfly_f32, "ffii", "")
BUILTIN(__nvvm_shfl_idx_i32, "iiii", "")
BUILTIN(__nvvm_shfl_idx_f32, "ffii", "")
+TARGET_BUILTIN(__nvvm_shfl_sync_down_i32, "iUiiii", "", "ptx60")
+TARGET_BUILTIN(__nvvm_shfl_sync_down_f32, "fUifii", "", "ptx60")
+TARGET_BUILTIN(__nvvm_shfl_sync_up_i32, "iUiiii", "", "ptx60")
+TARGET_BUILTIN(__nvvm_shfl_sync_up_f32, "fUifii", "", "ptx60")
+TARGET_BUILTIN(__nvvm_shfl_sync_bfly_i32, "iUiiii", "", "ptx60")
+TARGET_BUILTIN(__nvvm_shfl_sync_bfly_f32, "fUifii", "", "ptx60")
+TARGET_BUILTIN(__nvvm_shfl_sync_idx_i32, "iUiiii", "", "ptx60")
+TARGET_BUILTIN(__nvvm_shfl_sync_idx_f32, "fUifii", "", "ptx60")
+
+// Vote
+BUILTIN(__nvvm_vote_all, "bb", "")
+BUILTIN(__nvvm_vote_any, "bb", "")
+BUILTIN(__nvvm_vote_uni, "bb", "")
+BUILTIN(__nvvm_vote_ballot, "Uib", "")
+
+TARGET_BUILTIN(__nvvm_vote_all_sync, "bUib", "", "ptx60")
+TARGET_BUILTIN(__nvvm_vote_any_sync, "bUib", "", "ptx60")
+TARGET_BUILTIN(__nvvm_vote_uni_sync, "bUib", "", "ptx60")
+TARGET_BUILTIN(__nvvm_vote_ballot_sync, "UiUib", "", "ptx60")
+
+// Match
+TARGET_BUILTIN(__nvvm_match_any_sync_i32, "UiUiUi", "", "ptx60")
+TARGET_BUILTIN(__nvvm_match_any_sync_i64, "WiUiWi", "", "ptx60")
+// These return a pair {value, predicate}, which requires custom lowering.
+TARGET_BUILTIN(__nvvm_match_all_sync_i32p, "UiUiUii*", "", "ptx60")
+TARGET_BUILTIN(__nvvm_match_all_sync_i64p, "WiUiWii*", "", "ptx60")
+
// Membar
BUILTIN(__nvvm_membar_cta, "v", "")
@@ -451,7 +484,7 @@ TARGET_BUILTIN(__nvvm_atom_cta_add_gen_f, "ffD*f", "n", "satom")
TARGET_BUILTIN(__nvvm_atom_sys_add_gen_f, "ffD*f", "n", "satom")
BUILTIN(__nvvm_atom_add_g_d, "ddD*1d", "n")
BUILTIN(__nvvm_atom_add_s_d, "ddD*3d", "n")
-BUILTIN(__nvvm_atom_add_gen_d, "ddD*d", "n")
+TARGET_BUILTIN(__nvvm_atom_add_gen_d, "ddD*d", "n", "satom")
TARGET_BUILTIN(__nvvm_atom_cta_add_gen_d, "ddD*d", "n", "satom")
TARGET_BUILTIN(__nvvm_atom_sys_add_gen_d, "ddD*d", "n", "satom")
@@ -658,5 +691,18 @@ BUILTIN(__nvvm_ldg_f2, "E2fE2fC*", "")
BUILTIN(__nvvm_ldg_f4, "E4fE4fC*", "")
BUILTIN(__nvvm_ldg_d2, "E2dE2dC*", "")
+// Builtins to support WMMA instructions on sm_70
+TARGET_BUILTIN(__hmma_m16n16k16_ld_a, "vi*iC*UiIi", "", "ptx60")
+TARGET_BUILTIN(__hmma_m16n16k16_ld_b, "vi*iC*UiIi", "", "ptx60")
+TARGET_BUILTIN(__hmma_m16n16k16_ld_c_f16, "vi*iC*UiIi", "", "ptx60")
+TARGET_BUILTIN(__hmma_m16n16k16_ld_c_f32, "vf*fC*UiIi", "", "ptx60")
+TARGET_BUILTIN(__hmma_m16n16k16_st_c_f16, "vi*i*UiIi", "", "ptx60")
+TARGET_BUILTIN(__hmma_m16n16k16_st_c_f32, "vf*f*UiIi", "", "ptx60")
+
+TARGET_BUILTIN(__hmma_m16n16k16_mma_f16f16, "vi*iC*iC*iC*IiIi", "", "ptx60")
+TARGET_BUILTIN(__hmma_m16n16k16_mma_f32f16, "vf*iC*iC*iC*IiIi", "", "ptx60")
+TARGET_BUILTIN(__hmma_m16n16k16_mma_f32f32, "vf*iC*iC*fC*IiIi", "", "ptx60")
+TARGET_BUILTIN(__hmma_m16n16k16_mma_f16f32, "vi*iC*iC*fC*IiIi", "", "ptx60")
+
#undef BUILTIN
#undef TARGET_BUILTIN
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def
index 2f8f8919e5b30..d0be48467f1f0 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def
@@ -32,7 +32,9 @@
// Miscellaneous builtin for checking x86 cpu features.
// TODO: Make this somewhat generic so that other backends
// can use it?
+BUILTIN(__builtin_cpu_init, "v", "n")
BUILTIN(__builtin_cpu_supports, "bcC*", "nc")
+BUILTIN(__builtin_cpu_is, "bcC*", "nc")
// Undefined Values
//
@@ -264,8 +266,6 @@ TARGET_BUILTIN(__builtin_ia32_paddusw128, "V8sV8sV8s", "", "sse2")
TARGET_BUILTIN(__builtin_ia32_psubusb128, "V16cV16cV16c", "", "sse2")
TARGET_BUILTIN(__builtin_ia32_psubusw128, "V8sV8sV8s", "", "sse2")
TARGET_BUILTIN(__builtin_ia32_pmulhw128, "V8sV8sV8s", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_pavgb128, "V16cV16cV16c", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_pavgw128, "V8sV8sV8s", "", "sse2")
TARGET_BUILTIN(__builtin_ia32_pmaxub128, "V16cV16cV16c", "", "sse2")
TARGET_BUILTIN(__builtin_ia32_pmaxsw128, "V8sV8sV8s", "", "sse2")
TARGET_BUILTIN(__builtin_ia32_pminub128, "V16cV16cV16c", "", "sse2")
@@ -520,8 +520,6 @@ TARGET_BUILTIN(__builtin_ia32_paddusw256, "V16sV16sV16s", "", "avx2")
TARGET_BUILTIN(__builtin_ia32_psubusb256, "V32cV32cV32c", "", "avx2")
TARGET_BUILTIN(__builtin_ia32_psubusw256, "V16sV16sV16s", "", "avx2")
TARGET_BUILTIN(__builtin_ia32_palignr256, "V32cV32cV32cIi", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_pavgb256, "V32cV32cV32c", "", "avx2")
-TARGET_BUILTIN(__builtin_ia32_pavgw256, "V16sV16sV16s", "", "avx2")
TARGET_BUILTIN(__builtin_ia32_pblendvb256, "V32cV32cV32cV32c", "", "avx2")
TARGET_BUILTIN(__builtin_ia32_phaddw256, "V16sV16sV16s", "", "avx2")
TARGET_BUILTIN(__builtin_ia32_phaddd256, "V8iV8iV8i", "", "avx2")
@@ -640,8 +638,21 @@ TARGET_BUILTIN(__builtin_ia32_xrstors, "vv*ULLi", "", "xsaves")
TARGET_BUILTIN(__builtin_ia32_xsavec, "vv*ULLi", "", "xsavec")
TARGET_BUILTIN(__builtin_ia32_xsaves, "vv*ULLi", "", "xsaves")
+// SHSTK
+TARGET_BUILTIN(__builtin_ia32_incsspd, "vUi", "u", "shstk")
+TARGET_BUILTIN(__builtin_ia32_rdsspd, "UiUi", "Un", "shstk")
+TARGET_BUILTIN(__builtin_ia32_saveprevssp, "v", "", "shstk")
+TARGET_BUILTIN(__builtin_ia32_rstorssp, "vv*", "", "shstk")
+TARGET_BUILTIN(__builtin_ia32_wrssd, "vUiv*", "", "shstk")
+TARGET_BUILTIN(__builtin_ia32_wrussd, "vUiv*", "", "shstk")
+TARGET_BUILTIN(__builtin_ia32_setssbsy, "v", "", "shstk")
+TARGET_BUILTIN(__builtin_ia32_clrssbsy, "vv*", "", "shstk")
+
//CLFLUSHOPT
-TARGET_BUILTIN(__builtin_ia32_clflushopt, "vc*", "", "clflushopt")
+TARGET_BUILTIN(__builtin_ia32_clflushopt, "vvC*", "", "clflushopt")
+
+//CLWB
+TARGET_BUILTIN(__builtin_ia32_clwb, "vvC*", "", "clwb")
// ADX
TARGET_BUILTIN(__builtin_ia32_addcarryx_u32, "UcUcUiUiUi*", "", "adx")
@@ -681,36 +692,18 @@ TARGET_BUILTIN(__builtin_ia32_sha256msg2, "V4iV4iV4i", "", "sha")
// FMA
TARGET_BUILTIN(__builtin_ia32_vfmaddps, "V4fV4fV4fV4f", "", "fma|fma4")
TARGET_BUILTIN(__builtin_ia32_vfmaddpd, "V2dV2dV2dV2d", "", "fma|fma4")
-TARGET_BUILTIN(__builtin_ia32_vfmaddss, "V4fV4fV4fV4f", "", "fma|fma4")
-TARGET_BUILTIN(__builtin_ia32_vfmaddsd, "V2dV2dV2dV2d", "", "fma|fma4")
-TARGET_BUILTIN(__builtin_ia32_vfmsubps, "V4fV4fV4fV4f", "", "fma|fma4")
-TARGET_BUILTIN(__builtin_ia32_vfmsubpd, "V2dV2dV2dV2d", "", "fma|fma4")
-TARGET_BUILTIN(__builtin_ia32_vfmsubss, "V4fV4fV4fV4f", "", "fma|fma4")
-TARGET_BUILTIN(__builtin_ia32_vfmsubsd, "V2dV2dV2dV2d", "", "fma|fma4")
-TARGET_BUILTIN(__builtin_ia32_vfnmaddps, "V4fV4fV4fV4f", "", "fma|fma4")
-TARGET_BUILTIN(__builtin_ia32_vfnmaddpd, "V2dV2dV2dV2d", "", "fma|fma4")
-TARGET_BUILTIN(__builtin_ia32_vfnmaddss, "V4fV4fV4fV4f", "", "fma|fma4")
-TARGET_BUILTIN(__builtin_ia32_vfnmaddsd, "V2dV2dV2dV2d", "", "fma|fma4")
-TARGET_BUILTIN(__builtin_ia32_vfnmsubps, "V4fV4fV4fV4f", "", "fma|fma4")
-TARGET_BUILTIN(__builtin_ia32_vfnmsubpd, "V2dV2dV2dV2d", "", "fma|fma4")
-TARGET_BUILTIN(__builtin_ia32_vfnmsubss, "V4fV4fV4fV4f", "", "fma|fma4")
-TARGET_BUILTIN(__builtin_ia32_vfnmsubsd, "V2dV2dV2dV2d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmaddss3, "V4fV4fV4fV4f", "", "fma")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsd3, "V2dV2dV2dV2d", "", "fma")
+TARGET_BUILTIN(__builtin_ia32_vfmaddss, "V4fV4fV4fV4f", "", "fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsd, "V2dV2dV2dV2d", "", "fma4")
TARGET_BUILTIN(__builtin_ia32_vfmaddsubps, "V4fV4fV4fV4f", "", "fma|fma4")
TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd, "V2dV2dV2dV2d", "", "fma|fma4")
-TARGET_BUILTIN(__builtin_ia32_vfmsubaddps, "V4fV4fV4fV4f", "", "fma|fma4")
-TARGET_BUILTIN(__builtin_ia32_vfmsubaddpd, "V2dV2dV2dV2d", "", "fma|fma4")
TARGET_BUILTIN(__builtin_ia32_vfmaddps256, "V8fV8fV8fV8f", "", "fma|fma4")
TARGET_BUILTIN(__builtin_ia32_vfmaddpd256, "V4dV4dV4dV4d", "", "fma|fma4")
-TARGET_BUILTIN(__builtin_ia32_vfmsubps256, "V8fV8fV8fV8f", "", "fma|fma4")
-TARGET_BUILTIN(__builtin_ia32_vfmsubpd256, "V4dV4dV4dV4d", "", "fma|fma4")
TARGET_BUILTIN(__builtin_ia32_vfnmaddps256, "V8fV8fV8fV8f", "", "fma|fma4")
TARGET_BUILTIN(__builtin_ia32_vfnmaddpd256, "V4dV4dV4dV4d", "", "fma|fma4")
-TARGET_BUILTIN(__builtin_ia32_vfnmsubps256, "V8fV8fV8fV8f", "", "fma|fma4")
-TARGET_BUILTIN(__builtin_ia32_vfnmsubpd256, "V4dV4dV4dV4d", "", "fma|fma4")
TARGET_BUILTIN(__builtin_ia32_vfmaddsubps256, "V8fV8fV8fV8f", "", "fma|fma4")
TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd256, "V4dV4dV4dV4d", "", "fma|fma4")
-TARGET_BUILTIN(__builtin_ia32_vfmsubaddps256, "V8fV8fV8fV8f", "", "fma|fma4")
-TARGET_BUILTIN(__builtin_ia32_vfmsubaddpd256, "V4dV4dV4dV4d", "", "fma|fma4")
TARGET_BUILTIN(__builtin_ia32_vfmaddpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
TARGET_BUILTIN(__builtin_ia32_vfmaddpd128_mask3, "V2dV2dV2dV2dUc", "", "avx512vl")
@@ -909,39 +902,10 @@ TARGET_BUILTIN(__builtin_ia32_cvttps2dq512_mask, "V16iV16fV16iUsIi", "", "avx512
TARGET_BUILTIN(__builtin_ia32_cvttps2udq512_mask, "V16iV16fV16iUsIi", "", "avx512f")
TARGET_BUILTIN(__builtin_ia32_cvttpd2dq512_mask, "V8iV8dV8iUcIi", "", "avx512f")
TARGET_BUILTIN(__builtin_ia32_cvttpd2udq512_mask, "V8iV8dV8iUcIi", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_cmpps512_mask, "UsV16fV16fIiUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cmpps512_mask, "UsV16fV16fIiUsIi", "", "avx512f")
TARGET_BUILTIN(__builtin_ia32_cmpps256_mask, "UcV8fV8fIiUc", "", "avx512vl")
TARGET_BUILTIN(__builtin_ia32_cmpps128_mask, "UcV4fV4fIiUc", "", "avx512vl")
-
-TARGET_BUILTIN(__builtin_ia32_pcmpeqb512_mask, "LLiV64cV64cLLi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pcmpeqd512_mask, "sV16iV16is", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_pcmpeqq512_mask, "cV8LLiV8LLic", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_pcmpeqw512_mask, "iV32sV32si", "", "avx512bw")
-
-TARGET_BUILTIN(__builtin_ia32_pcmpeqb256_mask, "iV32cV32ci", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pcmpeqd256_mask, "cV8iV8ic", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pcmpeqq256_mask, "cV4LLiV4LLic", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pcmpeqw256_mask, "sV16sV16ss", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pcmpeqb128_mask, "sV16cV16cs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pcmpeqd128_mask, "cV4iV4ic", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pcmpeqq128_mask, "cV2LLiV2LLic", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pcmpeqw128_mask, "cV8sV8sc", "", "avx512vl,avx512bw")
-
-TARGET_BUILTIN(__builtin_ia32_pcmpgtb512_mask, "LLiV64cV64cLLi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pcmpgtd512_mask, "sV16iV16is", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_pcmpgtq512_mask, "cV8LLiV8LLic", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_pcmpgtw512_mask, "iV32sV32si", "", "avx512bw")
-
-TARGET_BUILTIN(__builtin_ia32_pcmpgtb256_mask, "iV32cV32ci", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pcmpgtd256_mask, "cV8iV8ic", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pcmpgtq256_mask, "cV4LLiV4LLic", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pcmpgtw256_mask, "sV16sV16ss", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pcmpgtb128_mask, "sV16cV16cs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pcmpgtd128_mask, "cV4iV4ic", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pcmpgtq128_mask, "cV2LLiV2LLic", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pcmpgtw128_mask, "cV8sV8sc", "", "avx512vl,avx512bw")
-
TARGET_BUILTIN(__builtin_ia32_cmppd512_mask, "UcV8dV8dIiUcIi", "", "avx512f")
TARGET_BUILTIN(__builtin_ia32_cmppd256_mask, "UcV4dV4dIiUc", "", "avx512vl")
TARGET_BUILTIN(__builtin_ia32_cmppd128_mask, "UcV2dV2dIiUc", "", "avx512vl")
@@ -973,9 +937,6 @@ TARGET_BUILTIN(__builtin_ia32_pminud512_mask, "V16iV16iV16iV16iUs", "", "avx512f
TARGET_BUILTIN(__builtin_ia32_pminuq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f")
TARGET_BUILTIN(__builtin_ia32_pmuldq512, "V8LLiV16iV16i", "", "avx512f")
TARGET_BUILTIN(__builtin_ia32_pmuludq512, "V8LLiV16iV16i", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_ptestmd512, "UsV16iV16iUs", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_ptestmq512, "UcV8LLiV8LLiUc", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_pbroadcastd512_gpr_mask, "V16iiV16iUs", "", "avx512f")
TARGET_BUILTIN(__builtin_ia32_loaddqusi512_mask, "V16iiC*V16iUs", "", "avx512f")
TARGET_BUILTIN(__builtin_ia32_loaddqudi512_mask, "V8LLiLLiC*V8LLiUc", "", "avx512f")
TARGET_BUILTIN(__builtin_ia32_loadups512_mask, "V16ffC*V16fUs", "", "avx512f")
@@ -1072,8 +1033,6 @@ TARGET_BUILTIN(__builtin_ia32_paddsb512_mask, "V64cV64cV64cV64cULLi", "", "avx51
TARGET_BUILTIN(__builtin_ia32_paddsw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_paddusb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_paddusw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pavgb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pavgw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_pmaxsb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_pmaxsw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_pmaxub512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
@@ -1101,6 +1060,10 @@ TARGET_BUILTIN(__builtin_ia32_vpconflictsi_512_mask, "V16iV16iV16iUs", "", "avx5
TARGET_BUILTIN(__builtin_ia32_vplzcntd_512_mask, "V16iV16iV16iUs", "", "avx512cd")
TARGET_BUILTIN(__builtin_ia32_vplzcntq_512_mask, "V8LLiV8LLiV8LLiUc", "", "avx512cd")
+TARGET_BUILTIN(__builtin_ia32_vpopcntd_128, "V4iV4i", "", "avx512vpopcntdq,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpopcntq_128, "V2LLiV2LLi", "", "avx512vpopcntdq,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpopcntd_256, "V8iV8i", "", "avx512vpopcntdq,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpopcntq_256, "V4LLiV4LLi", "", "avx512vpopcntdq,avx512vl")
TARGET_BUILTIN(__builtin_ia32_vpopcntd_512, "V16iV16i", "", "avx512vpopcntdq")
TARGET_BUILTIN(__builtin_ia32_vpopcntq_512, "V8LLiV8LLi", "", "avx512vpopcntdq")
@@ -1378,11 +1341,6 @@ TARGET_BUILTIN(__builtin_ia32_movdqa64load128_mask, "V2LLiV2LLiC*V2LLiUc","","av
TARGET_BUILTIN(__builtin_ia32_movdqa64load256_mask, "V4LLiV4LLiC*V4LLiUc","","avx512vl")
TARGET_BUILTIN(__builtin_ia32_movdqa64store128_mask, "vV2LLi*V2LLiUc","","avx512f")
TARGET_BUILTIN(__builtin_ia32_movdqa64store256_mask, "vV4LLi*V4LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pbroadcastb512_gpr_mask, "V64ccV64cULLi","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pbroadcastb128_gpr_mask, "V16ccV16cUs","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pbroadcastb256_gpr_mask, "V32ccV32cUi","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pbroadcastd128_gpr_mask, "V4iiV4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pbroadcastd256_gpr_mask, "V8iiV8iUc","","avx512vl")
TARGET_BUILTIN(__builtin_ia32_vpmadd52huq512_mask, "V8LLiV8LLiV8LLiV8LLiUc","","avx512ifma")
TARGET_BUILTIN(__builtin_ia32_vpmadd52huq512_maskz, "V8LLiV8LLiV8LLiV8LLiUc","","avx512ifma")
TARGET_BUILTIN(__builtin_ia32_vpmadd52luq512_mask, "V8LLiV8LLiV8LLiV8LLiUc","","avx512ifma")
@@ -1494,28 +1452,6 @@ TARGET_BUILTIN(__builtin_ia32_vpermt2vard512_maskz, "V16iV16iV16iV16iUs","","avx
TARGET_BUILTIN(__builtin_ia32_vpermt2varpd512_maskz, "V8dV8LLiV8dV8dUc","","avx512f")
TARGET_BUILTIN(__builtin_ia32_vpermt2varps512_maskz, "V16fV16iV16fV16fUs","","avx512f")
TARGET_BUILTIN(__builtin_ia32_vpermt2varq512_maskz, "V8LLiV8LLiV8LLiV8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_ptestmb512, "ULLiV64cV64cULLi","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_ptestmw512, "UiV32sV32sUi","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_ptestnmb512, "ULLiV64cV64cULLi","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_ptestnmw512, "UiV32sV32sUi","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_ptestmb128, "UsV16cV16cUs","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_ptestmb256, "UiV32cV32cUi","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_ptestmw128, "UcV8sV8sUc","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_ptestmw256, "UsV16sV16sUs","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_ptestnmb128, "UsV16cV16cUs","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_ptestnmb256, "UiV32cV32cUi","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_ptestnmw128, "UcV8sV8sUc","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_ptestnmw256, "UsV16sV16sUs","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_ptestmd128, "UcV4iV4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_ptestmd256, "UcV8iV8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_ptestmq128, "UcV2LLiV2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_ptestmq256, "UcV4LLiV4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_ptestnmd128, "UcV4iV4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_ptestnmd256, "UcV8iV8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_ptestnmq128, "UcV2LLiV2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_ptestnmq256, "UcV4LLiV4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_ptestnmd512, "UsV16iV16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_ptestnmq512, "UcV8LLiV8LLiUc","","avx512f")
TARGET_BUILTIN(__builtin_ia32_rndscalesd_round_mask, "V2dV2dV2dV2dUcIiIi","","avx512f")
TARGET_BUILTIN(__builtin_ia32_rndscaless_round_mask, "V4fV4fV4fV4fUcIiIi","","avx512f")
TARGET_BUILTIN(__builtin_ia32_scalefpd512_mask, "V8dV8dV8dV8dUcIi","","avx512f")
@@ -1587,20 +1523,6 @@ TARGET_BUILTIN(__builtin_ia32_cvtmask2q128, "V2LLiUc","","avx512dq,avx512vl")
TARGET_BUILTIN(__builtin_ia32_cvtmask2q256, "V4LLiUc","","avx512dq,avx512vl")
TARGET_BUILTIN(__builtin_ia32_cvtq2mask128, "UcV2LLi","","avx512dq,avx512vl")
TARGET_BUILTIN(__builtin_ia32_cvtq2mask256, "UcV4LLi","","avx512dq,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_broadcastmb512, "V8LLiUc","","avx512cd")
-TARGET_BUILTIN(__builtin_ia32_broadcastmw512, "V16iUs","","avx512cd")
-TARGET_BUILTIN(__builtin_ia32_broadcastmb128, "V2LLiUc","","avx512cd,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_broadcastmb256, "V4LLiUc","","avx512cd,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_broadcastmw128, "V4iUs","","avx512cd,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_broadcastmw256, "V8iUs","","avx512cd,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_broadcastf32x2_512_mask, "V16fV4fV16fUs","","avx512dq")
-TARGET_BUILTIN(__builtin_ia32_broadcasti32x2_512_mask, "V16iV4iV16iUs","","avx512dq")
-TARGET_BUILTIN(__builtin_ia32_broadcastf32x2_256_mask, "V8fV4fV8fUc","","avx512dq,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_broadcasti32x2_128_mask, "V4iV4iV4iUc","","avx512dq,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_broadcasti32x2_256_mask, "V8iV4iV8iUc","","avx512dq,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pbroadcastw512_gpr_mask, "V32shV32sUi","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pbroadcastw256_gpr_mask, "V16shV16sUs","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pbroadcastw128_gpr_mask, "V8ssV8sUc","","avx512bw,avx512vl")
TARGET_BUILTIN(__builtin_ia32_pmovsdb512_mask, "V16cV16iV16cUs","","avx512f")
TARGET_BUILTIN(__builtin_ia32_pmovsdb512mem_mask, "vV16c*V16iUs","","avx512f")
TARGET_BUILTIN(__builtin_ia32_pmovswb512mem_mask, "vV32c*V32sUi","","avx512bw")
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86_64.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86_64.def
index 4cde153d83722..fe2c887c7e0f5 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86_64.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86_64.def
@@ -40,6 +40,7 @@ TARGET_HEADER_BUILTIN(_InterlockedExchangeSub64, "LLiLLiD*LLi", "nh", "intrin.h"
TARGET_HEADER_BUILTIN(_InterlockedIncrement64, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedOr64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedXor64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange128, "UcLLiD*LLiLLiLLi*", "nh", "intrin.h", ALL_MS_LANGUAGES, "cx16")
TARGET_BUILTIN(__builtin_ia32_readeflags_u64, "ULLi", "n", "")
TARGET_BUILTIN(__builtin_ia32_writeeflags_u64, "vULLi", "n", "")
@@ -60,6 +61,10 @@ TARGET_BUILTIN(__builtin_ia32_xsaveopt64, "vv*ULLi", "", "xsaveopt")
TARGET_BUILTIN(__builtin_ia32_xrstors64, "vv*ULLi", "", "xsaves")
TARGET_BUILTIN(__builtin_ia32_xsavec64, "vv*ULLi", "", "xsavec")
TARGET_BUILTIN(__builtin_ia32_xsaves64, "vv*ULLi", "", "xsaves")
+TARGET_BUILTIN(__builtin_ia32_incsspq, "vULLi", "u", "shstk")
+TARGET_BUILTIN(__builtin_ia32_rdsspq, "ULLiULLi", "Un", "shstk")
+TARGET_BUILTIN(__builtin_ia32_wrssq, "vULLiv*", "", "shstk")
+TARGET_BUILTIN(__builtin_ia32_wrussq, "vULLiv*", "", "shstk")
TARGET_BUILTIN(__builtin_ia32_addcarryx_u64, "UcUcULLiULLiULLi*", "", "adx")
TARGET_BUILTIN(__builtin_ia32_addcarry_u64, "UcUcULLiULLiULLi*", "", "")
TARGET_BUILTIN(__builtin_ia32_subborrow_u64, "UcUcULLiULLiULLi*", "", "")
@@ -71,9 +76,6 @@ TARGET_BUILTIN(__builtin_ia32_pext_di, "ULLiULLiULLi", "", "bmi2")
TARGET_BUILTIN(__builtin_ia32_bextri_u64, "ULLiULLiIULLi", "", "tbm")
TARGET_BUILTIN(__builtin_ia32_lwpins64, "UcULLiUiUi", "", "lwp")
TARGET_BUILTIN(__builtin_ia32_lwpval64, "vULLiUiUi", "", "lwp")
-TARGET_BUILTIN(__builtin_ia32_pbroadcastq512_gpr_mask, "V8LLiLLiV8LLiUc", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_pbroadcastq128_gpr_mask, "V2LLiULLiV2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pbroadcastq256_gpr_mask, "V4LLiULLiV4LLiUc","","avx512vl")
TARGET_BUILTIN(__builtin_ia32_vcvtsd2si64, "LLiV2dIi","","avx512f")
TARGET_BUILTIN(__builtin_ia32_vcvtsd2usi64, "ULLiV2dIi","","avx512f")
TARGET_BUILTIN(__builtin_ia32_vcvtss2si64, "LLiV4fIi","","avx512f")
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/CharInfo.h b/contrib/llvm/tools/clang/include/clang/Basic/CharInfo.h
index dd9c55431e015..cc27bbb48e0d1 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/CharInfo.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/CharInfo.h
@@ -40,14 +40,14 @@ namespace charinfo {
} // end namespace charinfo
/// Returns true if this is an ASCII character.
-LLVM_READNONE static inline bool isASCII(char c) {
+LLVM_READNONE inline bool isASCII(char c) {
return static_cast<unsigned char>(c) <= 127;
}
/// Returns true if this is a valid first character of a C identifier,
/// which is [a-zA-Z_].
-LLVM_READONLY static inline bool isIdentifierHead(unsigned char c,
- bool AllowDollar = false) {
+LLVM_READONLY inline bool isIdentifierHead(unsigned char c,
+ bool AllowDollar = false) {
using namespace charinfo;
if (InfoTable[c] & (CHAR_UPPER|CHAR_LOWER|CHAR_UNDER))
return true;
@@ -56,8 +56,8 @@ LLVM_READONLY static inline bool isIdentifierHead(unsigned char c,
/// Returns true if this is a body character of a C identifier,
/// which is [a-zA-Z0-9_].
-LLVM_READONLY static inline bool isIdentifierBody(unsigned char c,
- bool AllowDollar = false) {
+LLVM_READONLY inline bool isIdentifierBody(unsigned char c,
+ bool AllowDollar = false) {
using namespace charinfo;
if (InfoTable[c] & (CHAR_UPPER|CHAR_LOWER|CHAR_DIGIT|CHAR_UNDER))
return true;
@@ -68,7 +68,7 @@ LLVM_READONLY static inline bool isIdentifierBody(unsigned char c,
/// ' ', '\\t', '\\f', '\\v'.
///
/// Note that this returns false for '\\0'.
-LLVM_READONLY static inline bool isHorizontalWhitespace(unsigned char c) {
+LLVM_READONLY inline bool isHorizontalWhitespace(unsigned char c) {
using namespace charinfo;
return (InfoTable[c] & (CHAR_HORZ_WS|CHAR_SPACE)) != 0;
}
@@ -76,7 +76,7 @@ LLVM_READONLY static inline bool isHorizontalWhitespace(unsigned char c) {
/// Returns true if this character is vertical ASCII whitespace: '\\n', '\\r'.
///
/// Note that this returns false for '\\0'.
-LLVM_READONLY static inline bool isVerticalWhitespace(unsigned char c) {
+LLVM_READONLY inline bool isVerticalWhitespace(unsigned char c) {
using namespace charinfo;
return (InfoTable[c] & CHAR_VERT_WS) != 0;
}
@@ -85,43 +85,43 @@ LLVM_READONLY static inline bool isVerticalWhitespace(unsigned char c) {
/// ' ', '\\t', '\\f', '\\v', '\\n', '\\r'.
///
/// Note that this returns false for '\\0'.
-LLVM_READONLY static inline bool isWhitespace(unsigned char c) {
+LLVM_READONLY inline bool isWhitespace(unsigned char c) {
using namespace charinfo;
return (InfoTable[c] & (CHAR_HORZ_WS|CHAR_VERT_WS|CHAR_SPACE)) != 0;
}
/// Return true if this character is an ASCII digit: [0-9]
-LLVM_READONLY static inline bool isDigit(unsigned char c) {
+LLVM_READONLY inline bool isDigit(unsigned char c) {
using namespace charinfo;
return (InfoTable[c] & CHAR_DIGIT) != 0;
}
/// Return true if this character is a lowercase ASCII letter: [a-z]
-LLVM_READONLY static inline bool isLowercase(unsigned char c) {
+LLVM_READONLY inline bool isLowercase(unsigned char c) {
using namespace charinfo;
return (InfoTable[c] & CHAR_LOWER) != 0;
}
/// Return true if this character is an uppercase ASCII letter: [A-Z]
-LLVM_READONLY static inline bool isUppercase(unsigned char c) {
+LLVM_READONLY inline bool isUppercase(unsigned char c) {
using namespace charinfo;
return (InfoTable[c] & CHAR_UPPER) != 0;
}
/// Return true if this character is an ASCII letter: [a-zA-Z]
-LLVM_READONLY static inline bool isLetter(unsigned char c) {
+LLVM_READONLY inline bool isLetter(unsigned char c) {
using namespace charinfo;
return (InfoTable[c] & (CHAR_UPPER|CHAR_LOWER)) != 0;
}
/// Return true if this character is an ASCII letter or digit: [a-zA-Z0-9]
-LLVM_READONLY static inline bool isAlphanumeric(unsigned char c) {
+LLVM_READONLY inline bool isAlphanumeric(unsigned char c) {
using namespace charinfo;
return (InfoTable[c] & (CHAR_DIGIT|CHAR_UPPER|CHAR_LOWER)) != 0;
}
/// Return true if this character is an ASCII hex digit: [0-9a-fA-F]
-LLVM_READONLY static inline bool isHexDigit(unsigned char c) {
+LLVM_READONLY inline bool isHexDigit(unsigned char c) {
using namespace charinfo;
return (InfoTable[c] & (CHAR_DIGIT|CHAR_XLETTER)) != 0;
}
@@ -129,7 +129,7 @@ LLVM_READONLY static inline bool isHexDigit(unsigned char c) {
/// Return true if this character is an ASCII punctuation character.
///
/// Note that '_' is both a punctuation character and an identifier character!
-LLVM_READONLY static inline bool isPunctuation(unsigned char c) {
+LLVM_READONLY inline bool isPunctuation(unsigned char c) {
using namespace charinfo;
return (InfoTable[c] & (CHAR_UNDER|CHAR_PERIOD|CHAR_RAWDEL|CHAR_PUNCT)) != 0;
}
@@ -137,7 +137,7 @@ LLVM_READONLY static inline bool isPunctuation(unsigned char c) {
/// Return true if this character is an ASCII printable character; that is, a
/// character that should take exactly one column to print in a fixed-width
/// terminal.
-LLVM_READONLY static inline bool isPrintable(unsigned char c) {
+LLVM_READONLY inline bool isPrintable(unsigned char c) {
using namespace charinfo;
return (InfoTable[c] & (CHAR_UPPER|CHAR_LOWER|CHAR_PERIOD|CHAR_PUNCT|
CHAR_DIGIT|CHAR_UNDER|CHAR_RAWDEL|CHAR_SPACE)) != 0;
@@ -145,14 +145,14 @@ LLVM_READONLY static inline bool isPrintable(unsigned char c) {
/// Return true if this is the body character of a C preprocessing number,
/// which is [a-zA-Z0-9_.].
-LLVM_READONLY static inline bool isPreprocessingNumberBody(unsigned char c) {
+LLVM_READONLY inline bool isPreprocessingNumberBody(unsigned char c) {
using namespace charinfo;
return (InfoTable[c] &
(CHAR_UPPER|CHAR_LOWER|CHAR_DIGIT|CHAR_UNDER|CHAR_PERIOD)) != 0;
}
/// Return true if this is the body character of a C++ raw string delimiter.
-LLVM_READONLY static inline bool isRawStringDelimBody(unsigned char c) {
+LLVM_READONLY inline bool isRawStringDelimBody(unsigned char c) {
using namespace charinfo;
return (InfoTable[c] & (CHAR_UPPER|CHAR_LOWER|CHAR_PERIOD|
CHAR_DIGIT|CHAR_UNDER|CHAR_RAWDEL)) != 0;
@@ -162,7 +162,7 @@ LLVM_READONLY static inline bool isRawStringDelimBody(unsigned char c) {
/// Converts the given ASCII character to its lowercase equivalent.
///
/// If the character is not an uppercase character, it is returned as is.
-LLVM_READONLY static inline char toLowercase(char c) {
+LLVM_READONLY inline char toLowercase(char c) {
if (isUppercase(c))
return c + 'a' - 'A';
return c;
@@ -171,7 +171,7 @@ LLVM_READONLY static inline char toLowercase(char c) {
/// Converts the given ASCII character to its uppercase equivalent.
///
/// If the character is not a lowercase character, it is returned as is.
-LLVM_READONLY static inline char toUppercase(char c) {
+LLVM_READONLY inline char toUppercase(char c) {
if (isLowercase(c))
return c + 'A' - 'a';
return c;
@@ -182,7 +182,7 @@ LLVM_READONLY static inline char toUppercase(char c) {
///
/// Note that this is a very simple check; it does not accept '$' or UCNs as
/// valid identifier characters.
-LLVM_READONLY static inline bool isValidIdentifier(StringRef S) {
+LLVM_READONLY inline bool isValidIdentifier(StringRef S) {
if (S.empty() || !isIdentifierHead(S[0]))
return false;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Cuda.h b/contrib/llvm/tools/clang/include/clang/Basic/Cuda.h
index ad1139b8c197e..1a0731c37a35f 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Cuda.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Cuda.h
@@ -21,6 +21,8 @@ enum class CudaVersion {
CUDA_70,
CUDA_75,
CUDA_80,
+ CUDA_90,
+ LATEST = CUDA_90,
};
const char *CudaVersionToString(CudaVersion V);
@@ -41,6 +43,7 @@ enum class CudaArch {
SM_60,
SM_61,
SM_62,
+ SM_70,
};
const char *CudaArchToString(CudaArch A);
@@ -60,6 +63,7 @@ enum class CudaVirtualArch {
COMPUTE_60,
COMPUTE_61,
COMPUTE_62,
+ COMPUTE_70,
};
const char *CudaVirtualArchToString(CudaVirtualArch A);
@@ -72,6 +76,9 @@ CudaVirtualArch VirtualArchForCudaArch(CudaArch A);
/// Get the earliest CudaVersion that supports the given CudaArch.
CudaVersion MinVersionForCudaArch(CudaArch A);
+/// Get the latest CudaVersion that supports the given CudaArch.
+CudaVersion MaxVersionForCudaArch(CudaArch A);
+
} // namespace clang
#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DeclNodes.td b/contrib/llvm/tools/clang/include/clang/Basic/DeclNodes.td
index 3298a80e51341..67ca9e5c6c62c 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DeclNodes.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DeclNodes.td
@@ -1,66 +1,68 @@
class AttrSubject;
-class Decl<bit abstract = 0> : AttrSubject {
+class Decl<string diagSpelling = "", bit abstract = 0> : AttrSubject {
bit Abstract = abstract;
+ string DiagSpelling = diagSpelling;
}
-class DDecl<Decl base, bit abstract = 0> : Decl<abstract> {
+class DDecl<Decl base, string diagSpelling = "", bit abstract = 0>
+ : Decl<diagSpelling, abstract> {
Decl Base = base;
}
-class DeclContext { }
+class DeclContext {}
def TranslationUnit : Decl, DeclContext;
def PragmaComment : Decl;
def PragmaDetectMismatch : Decl;
def ExternCContext : Decl, DeclContext;
-def Named : Decl<1>;
- def Namespace : DDecl<Named>, DeclContext;
+def Named : Decl<"named declarations", 1>;
+ def Namespace : DDecl<Named, "namespaces">, DeclContext;
def UsingDirective : DDecl<Named>;
def NamespaceAlias : DDecl<Named>;
- def Label : DDecl<Named>;
- def Type : DDecl<Named, 1>;
- def TypedefName : DDecl<Type, 1>;
+ def Label : DDecl<Named, "labels">;
+ def Type : DDecl<Named, "types", 1>;
+ def TypedefName : DDecl<Type, "typedefs", 1>;
def Typedef : DDecl<TypedefName>;
def TypeAlias : DDecl<TypedefName>;
def ObjCTypeParam : DDecl<TypedefName>;
def UnresolvedUsingTypename : DDecl<Type>;
- def Tag : DDecl<Type, 1>, DeclContext;
- def Enum : DDecl<Tag>;
- def Record : DDecl<Tag>;
- def CXXRecord : DDecl<Record>;
+ def Tag : DDecl<Type, "tag types", 1>, DeclContext;
+ def Enum : DDecl<Tag, "enums">;
+ def Record : DDecl<Tag, "structs, unions, classes">;
+ def CXXRecord : DDecl<Record, "classes">;
def ClassTemplateSpecialization : DDecl<CXXRecord>;
def ClassTemplatePartialSpecialization
: DDecl<ClassTemplateSpecialization>;
def TemplateTypeParm : DDecl<Type>;
- def Value : DDecl<Named, 1>;
- def EnumConstant : DDecl<Value>;
+ def Value : DDecl<Named, "value declarations", 1>;
+ def EnumConstant : DDecl<Value, "enumerators">;
def UnresolvedUsingValue : DDecl<Value>;
def IndirectField : DDecl<Value>;
def Binding : DDecl<Value>;
def OMPDeclareReduction : DDecl<Value>, DeclContext;
- def Declarator : DDecl<Value, 1>;
- def Field : DDecl<Declarator>;
+ def Declarator : DDecl<Value, "declarators", 1>;
+ def Field : DDecl<Declarator, "non-static data members">;
def ObjCIvar : DDecl<Field>;
def ObjCAtDefsField : DDecl<Field>;
def MSProperty : DDecl<Declarator>;
- def Function : DDecl<Declarator>, DeclContext;
+ def Function : DDecl<Declarator, "functions">, DeclContext;
def CXXDeductionGuide : DDecl<Function>;
def CXXMethod : DDecl<Function>;
def CXXConstructor : DDecl<CXXMethod>;
def CXXDestructor : DDecl<CXXMethod>;
def CXXConversion : DDecl<CXXMethod>;
- def Var : DDecl<Declarator>;
+ def Var : DDecl<Declarator, "variables">;
def VarTemplateSpecialization : DDecl<Var>;
def VarTemplatePartialSpecialization
: DDecl<VarTemplateSpecialization>;
def ImplicitParam : DDecl<Var>;
- def ParmVar : DDecl<Var>;
+ def ParmVar : DDecl<Var, "parameters">;
def Decomposition : DDecl<Var>;
def OMPCapturedExpr : DDecl<Var>;
def NonTypeTemplateParm : DDecl<Declarator>;
- def Template : DDecl<Named, 1>;
- def RedeclarableTemplate : DDecl<Template, 1>;
+ def Template : DDecl<Named, "templates", 1>;
+ def RedeclarableTemplate : DDecl<Template, "redeclarable templates", 1>;
def FunctionTemplate : DDecl<RedeclarableTemplate>;
def ClassTemplate : DDecl<RedeclarableTemplate>;
def VarTemplate : DDecl<RedeclarableTemplate>;
@@ -71,15 +73,16 @@ def Named : Decl<1>;
def UsingPack : DDecl<Named>;
def UsingShadow : DDecl<Named>;
def ConstructorUsingShadow : DDecl<UsingShadow>;
- def ObjCMethod : DDecl<Named>, DeclContext;
- def ObjCContainer : DDecl<Named, 1>, DeclContext;
+ def ObjCMethod : DDecl<Named, "Objective-C methods">, DeclContext;
+ def ObjCContainer : DDecl<Named, "Objective-C containers", 1>, DeclContext;
def ObjCCategory : DDecl<ObjCContainer>;
- def ObjCProtocol : DDecl<ObjCContainer>;
- def ObjCInterface : DDecl<ObjCContainer>;
- def ObjCImpl : DDecl<ObjCContainer, 1>;
+ def ObjCProtocol : DDecl<ObjCContainer, "Objective-C protocols">;
+ def ObjCInterface : DDecl<ObjCContainer, "Objective-C interfaces">;
+ def ObjCImpl
+ : DDecl<ObjCContainer, "Objective-C implementation declarations", 1>;
def ObjCCategoryImpl : DDecl<ObjCImpl>;
def ObjCImplementation : DDecl<ObjCImpl>;
- def ObjCProperty : DDecl<Named>;
+ def ObjCProperty : DDecl<Named, "Objective-C properties">;
def ObjCCompatibleAlias : DDecl<Named>;
def LinkageSpec : Decl, DeclContext;
def Export : Decl, DeclContext;
@@ -89,7 +92,7 @@ def AccessSpec : Decl;
def Friend : Decl;
def FriendTemplate : Decl;
def StaticAssert : Decl;
-def Block : Decl, DeclContext;
+def Block : Decl<"blocks">, DeclContext;
def Captured : Decl, DeclContext;
def ClassScopeFunctionSpecialization : Decl;
def Import : Decl;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h
index 22cded21c12df..a7458d45618ee 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h
@@ -575,13 +575,15 @@ public:
OverloadsShown getShowOverloads() const { return ShowOverloads; }
/// \brief Pretend that the last diagnostic issued was ignored, so any
- /// subsequent notes will be suppressed.
+ /// subsequent notes will be suppressed, or restore a prior ignoring
+ /// state after ignoring some diagnostics and their notes, possibly in
+ /// the middle of another diagnostic.
///
/// This can be used by clients who suppress diagnostics themselves.
- void setLastDiagnosticIgnored() {
+ void setLastDiagnosticIgnored(bool Ignored = true) {
if (LastDiagLevel == DiagnosticIDs::Fatal)
FatalErrorOccurred = true;
- LastDiagLevel = DiagnosticIDs::Ignored;
+ LastDiagLevel = Ignored ? DiagnosticIDs::Ignored : DiagnosticIDs::Warning;
}
/// \brief Determine whether the previous diagnostic was ignored. This can
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td
index f25068eca1322..52ccf350e651e 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td
@@ -133,10 +133,12 @@ include "DiagnosticASTKinds.td"
include "DiagnosticAnalysisKinds.td"
include "DiagnosticCommentKinds.td"
include "DiagnosticCommonKinds.td"
+include "DiagnosticCrossTUKinds.td"
include "DiagnosticDriverKinds.td"
include "DiagnosticFrontendKinds.td"
include "DiagnosticLexKinds.td"
include "DiagnosticParseKinds.td"
+include "DiagnosticRefactoringKinds.td"
include "DiagnosticSemaKinds.td"
include "DiagnosticSerializationKinds.td"
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticASTKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticASTKinds.td
index b3cba2066edd8..215580b2e9b66 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticASTKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticASTKinds.td
@@ -127,6 +127,10 @@ def note_constexpr_access_null : Note<
def note_constexpr_access_past_end : Note<
"%select{read of|assignment to|increment of|decrement of}0 "
"dereferenced one-past-the-end pointer is not allowed in a constant expression">;
+def note_constexpr_access_unsized_array : Note<
+ "%select{read of|assignment to|increment of|decrement of}0 "
+ "pointer to element of array without known bound "
+ "is not allowed in a constant expression">;
def note_constexpr_access_inactive_union_member : Note<
"%select{read of|assignment to|increment of|decrement of}0 "
"member %1 of union with %select{active member %3|no active member}2 "
@@ -154,6 +158,11 @@ def note_constexpr_baa_insufficient_alignment : Note<
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 note_constexpr_unsupported_unsized_array : Note<
+ "array-to-pointer decay of array member without known bound is not supported">;
+def note_constexpr_unsized_array_indexed : Note<
+ "indexing of array without known bound is not allowed "
+ "in a constant expression">;
def warn_integer_constant_overflow : Warning<
"overflow in expression; result is %0 with type %1">,
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td
index 98fd3c4d57ac0..82ca27b7345e3 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td
@@ -185,6 +185,8 @@ def note_invalid_subexpr_in_const_expr : Note<
def err_target_unknown_triple : Error<
"unknown target triple '%0', please use -triple or -arch">;
def err_target_unknown_cpu : Error<"unknown target CPU '%0'">;
+def err_target_unsupported_cpu_for_micromips : Error<
+ "micromips is not supported for target CPU '%0'">;
def err_target_unknown_abi : Error<"unknown target ABI '%0'">;
def err_target_unsupported_abi : Error<"ABI '%0' is not supported on CPU '%1'">;
def err_target_unsupported_abi_for_triple : Error<
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCrossTUKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCrossTUKinds.td
new file mode 100644
index 0000000000000..8b6d8b681445d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCrossTUKinds.td
@@ -0,0 +1,18 @@
+//==--- DiagnosticCrossTUKinds.td - Cross Translation Unit diagnostics ----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+let Component = "CrossTU" in {
+
+def err_fnmap_parsing : Error<
+ "error parsing index file: '%0' line: %1 'UniqueID filename' format "
+ "expected">;
+
+def err_multiple_def_index : Error<
+ "multiple definitions are found for the same key in index ">;
+}
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td
index fcef881fa0aef..41b5e42b44322 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -29,9 +29,10 @@ def err_drv_no_cuda_installation : Error<
def err_drv_no_cuda_libdevice : Error<
"cannot find libdevice for %0. Provide path to different CUDA installation "
"via --cuda-path, or pass -nocudalib to build without linking with libdevice.">;
-def err_drv_cuda_version_too_low : Error<
- "GPU arch %1 requires CUDA version at least %3, but installation at %0 is %2. "
- "Use --cuda-path to specify a different CUDA install, or pass "
+def err_drv_cuda_version_unsupported : Error<
+ "GPU arch %0 is supported by CUDA versions between %1 and %2 (inclusive), "
+ "but installation at %3 is %4. Use --cuda-path to specify a different CUDA "
+ "install, pass a different GPU arch with --cuda-gpu-arch, or pass "
"--no-cuda-version-check.">;
def err_drv_cuda_nvptx_host : Error<"unsupported use of NVPTX for host compilation.">;
def err_drv_invalid_thread_model_for_target : Error<
@@ -69,6 +70,10 @@ def err_drv_invalid_Xarch_argument_with_args : Error<
"invalid Xarch argument: '%0', options requiring arguments are unsupported">;
def err_drv_invalid_Xarch_argument_isdriver : Error<
"invalid Xarch argument: '%0', cannot change driver behavior inside Xarch argument">;
+def err_drv_Xopenmp_target_missing_triple : Error<
+ "cannot deduce implicit triple value for -Xopenmp-target, specify triple using -Xopenmp-target=<triple>">;
+def err_drv_invalid_Xopenmp_target_with_args : Error<
+ "invalid -Xopenmp-target argument: '%0', options requiring arguments are unsupported">;
def err_drv_argument_only_allowed_with : Error<
"invalid argument '%0' only allowed with '%1'">;
def err_drv_argument_not_allowed_with : Error<
@@ -97,6 +102,10 @@ def err_drv_force_crash : Error<
"failing because %select{environment variable 'FORCE_CLANG_DIAGNOSTICS_CRASH' is set|'-gen-reproducer' is used}0">;
def err_drv_invalid_mfloat_abi : Error<
"invalid float ABI '%0'">;
+def err_drv_invalid_mtp : Error<
+ "invalid thread pointer reading mode '%0'">;
+def err_drv_missing_arg_mtp : Error<
+ "missing argument to '%0'">;
def err_drv_invalid_libcxx_deployment : Error<
"invalid deployment target for -stdlib=libc++ (requires %0 or later)">;
def err_drv_invalid_argument_to_fdebug_prefix_map : Error<
@@ -106,6 +115,10 @@ def err_drv_malformed_sanitizer_blacklist : Error<
def err_target_unsupported_arch
: Error<"the target architecture '%0' is not supported by the target '%1'">;
+def err_cpu_unsupported_isa
+ : Error<"CPU '%0' does not support '%1' execution mode">;
+def err_arch_unsupported_isa
+ : Error<"Architecture '%0' does not support '%1' execution mode">;
def err_drv_I_dash_not_supported : Error<
"'%0' not supported, please use -iquote instead">;
@@ -231,7 +244,7 @@ def warn_drv_enabling_rtti_with_exceptions : Warning<
InGroup<DiagGroup<"rtti-for-exceptions">>;
def warn_drv_disabling_vptr_no_rtti_default : Warning<
"implicitly disabling vptr sanitizer because rtti wasn't enabled">,
- InGroup<DiagGroup<"auto-disable-vptr-sanitizer">>;
+ InGroup<AutoDisableVptrSanitizer>;
def warn_drv_object_size_disabled_O0 : Warning<
"the object size sanitizer has no effect at -O0, but is explicitly enabled: %0">,
InGroup<InvalidCommandLineArgument>;
@@ -251,6 +264,9 @@ def err_analyzer_config_no_value : Error<
def err_analyzer_config_multiple_values : Error<
"analyzer-config option '%0' should contain only one '='">;
+def err_drv_invalid_hvx_length : Error<
+ "-mhvx-length is not supported without a -mhvx/-mhvx= flag">;
+
def err_drv_modules_validate_once_requires_timestamp : Error<
"option '-fmodules-validate-once-per-build-session' requires "
"'-fbuild-session-timestamp=<seconds since Epoch>' or '-fbuild-session-file=<file>'">;
@@ -277,9 +293,27 @@ def warn_target_unsupported_nan2008 : Warning<
def warn_target_unsupported_nanlegacy : Warning<
"ignoring '-mnan=legacy' option because the '%0' architecture does not support it">,
InGroup<UnsupportedNan>;
+def warn_target_unsupported_abslegacy : Warning<
+ "ignoring '-mabs=legacy' option because the '%0' architecture does not support it">,
+ InGroup<UnsupportedAbs>;
+def warn_target_unsupported_abs2008 : Warning<
+ "ignoring '-mabs=2008' option because the '%0' architecture does not support it">,
+ InGroup<UnsupportedAbs>;
def warn_target_unsupported_compact_branches : Warning<
"ignoring '-mcompact-branches=' option because the '%0' architecture does not"
" support it">, InGroup<UnsupportedCB>;
+def warn_drv_unsupported_gpopt : Warning<
+ "ignoring '-mgpopt' option as it cannot be used with %select{|the implicit"
+ " usage of }0-mabicalls">,
+ InGroup<UnsupportedGPOpt>;
+def warn_drv_unsupported_longcalls : Warning<
+ "ignoring '-mlong-calls' option as it is not currently supported with "
+ "%select{|the implicit usage of }0-mabicalls">,
+ InGroup<OptionIgnored>;
+def warn_drv_unsupported_abicalls : Warning<
+ "ignoring '-mabicalls' option as it cannot be used with "
+ "non position-independent code and the N64 ABI">,
+ InGroup<OptionIgnored>;
def warn_drv_unable_to_find_directory_expected : Warning<
"unable to find %0 directory, expected to be in '%1'">,
@@ -300,4 +334,12 @@ def warn_drv_msvc_not_found : Warning<
"unable to find a Visual Studio installation; "
"try running Clang from a developer command prompt">,
InGroup<DiagGroup<"msvc-not-found">>;
+
+def warn_drv_fine_grained_bitfield_accesses_ignored : Warning<
+ "option '-ffine-grained-bitfield-accesses' cannot be enabled together with a sanitizer; flag ignored">,
+ InGroup<OptionIgnored>;
+
+def note_drv_verify_prefix_spelling : Note<
+ "-verify prefixes must start with a letter and contain only alphanumeric"
+ " characters, hyphens, and underscores">;
}
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticError.h b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticError.h
new file mode 100644
index 0000000000000..6b4b073736a8d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticError.h
@@ -0,0 +1,61 @@
+//===--- DiagnosticError.h - Diagnostic payload for llvm::Error -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_DIAGNOSTIC_ERROR_H
+#define LLVM_CLANG_BASIC_DIAGNOSTIC_ERROR_H
+
+#include "clang/Basic/PartialDiagnostic.h"
+#include "llvm/Support/Error.h"
+
+namespace clang {
+
+/// \brief Carries a Clang diagnostic in an llvm::Error.
+///
+/// Users should emit the stored diagnostic using the DiagnosticsEngine.
+class DiagnosticError : public llvm::ErrorInfo<DiagnosticError> {
+public:
+ DiagnosticError(PartialDiagnosticAt Diag) : Diag(std::move(Diag)) {}
+
+ void log(raw_ostream &OS) const override { OS << "clang diagnostic"; }
+
+ PartialDiagnosticAt &getDiagnostic() { return Diag; }
+ const PartialDiagnosticAt &getDiagnostic() const { return Diag; }
+
+ /// Creates a new \c DiagnosticError that contains the given diagnostic at
+ /// the given location.
+ static llvm::Error create(SourceLocation Loc, PartialDiagnostic Diag) {
+ return llvm::make_error<DiagnosticError>(
+ PartialDiagnosticAt(Loc, std::move(Diag)));
+ }
+
+ /// Extracts and returns the diagnostic payload from the given \c Error if
+ /// the error is a \c DiagnosticError. Returns none if the given error is not
+ /// a \c DiagnosticError.
+ static Optional<PartialDiagnosticAt> take(llvm::Error &Err) {
+ Optional<PartialDiagnosticAt> Result;
+ Err = llvm::handleErrors(std::move(Err), [&](DiagnosticError &E) {
+ Result = std::move(E.getDiagnostic());
+ });
+ return Result;
+ }
+
+ static char ID;
+
+private:
+ // Users are not expected to use error_code.
+ std::error_code convertToErrorCode() const override {
+ return llvm::inconvertibleErrorCode();
+ }
+
+ PartialDiagnosticAt Diag;
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_BASIC_DIAGNOSTIC_ERROR_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index 57c24e9be73a7..392a340a3bb72 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -116,6 +116,8 @@ def err_fe_action_not_available : Error<
"action %0 not compiled in">;
def err_fe_invalid_alignment : Error<
"invalid value '%1' in '%0'; alignment must be a power of 2">;
+def err_fe_invalid_wchar_type
+ : Error<"invalid wchar_t type '%0'; must be one of 'char', 'short', 'int'">;
def warn_fe_serialized_diag_merge_failure : Warning<
"unable to merge a subprocess's serialized diagnostics">,
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td
index 23e4d4633ae2c..c23183c81ac8b 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td
@@ -27,11 +27,16 @@ def GNUAnonymousStruct : DiagGroup<"gnu-anonymous-struct">;
def GNUAutoType : DiagGroup<"gnu-auto-type">;
def ArrayBounds : DiagGroup<"array-bounds">;
def ArrayBoundsPointerArithmetic : DiagGroup<"array-bounds-pointer-arithmetic">;
+def AutoDisableVptrSanitizer : DiagGroup<"auto-disable-vptr-sanitizer">;
def Availability : DiagGroup<"availability">;
def Section : DiagGroup<"section">;
def AutoImport : DiagGroup<"auto-import">;
def CXX14BinaryLiteral : DiagGroup<"c++14-binary-literal">;
+def CXXPre14CompatBinaryLiteral : DiagGroup<"c++98-c++11-compat-binary-literal">;
def GNUBinaryLiteral : DiagGroup<"gnu-binary-literal">;
+def BinaryLiteral : DiagGroup<"binary-literal", [CXX14BinaryLiteral,
+ CXXPre14CompatBinaryLiteral,
+ GNUBinaryLiteral]>;
def GNUCompoundLiteralInitializer : DiagGroup<"gnu-compound-literal-initializer">;
def BitFieldConstantConversion : DiagGroup<"bitfield-constant-conversion">;
def BitFieldEnumConversion : DiagGroup<"bitfield-enum-conversion">;
@@ -60,7 +65,9 @@ def FloatConversion :
def DoublePromotion : DiagGroup<"double-promotion">;
def EnumTooLarge : DiagGroup<"enum-too-large">;
def UnsupportedNan : DiagGroup<"unsupported-nan">;
+def UnsupportedAbs : DiagGroup<"unsupported-abs">;
def UnsupportedCB : DiagGroup<"unsupported-cb">;
+def UnsupportedGPOpt : DiagGroup<"unsupported-gpopt">;
def NonLiteralNullConversion : DiagGroup<"non-literal-null-conversion">;
def NullConversion : DiagGroup<"null-conversion">;
def ImplicitConversionFloatingPointToBool :
@@ -87,6 +94,7 @@ def GNUStringLiteralOperatorTemplate :
DiagGroup<"gnu-string-literal-operator-template">;
def UndefinedVarTemplate : DiagGroup<"undefined-var-template">;
def UndefinedFuncTemplate : DiagGroup<"undefined-func-template">;
+def MissingNoEscape : DiagGroup<"missing-noescape">;
def DeleteIncomplete : DiagGroup<"delete-incomplete">;
def DeleteNonVirtualDtor : DiagGroup<"delete-non-virtual-dtor">;
@@ -162,10 +170,14 @@ def NoexceptType : DiagGroup<"noexcept-type", [CXX17CompatMangling]>;
// Warnings for C++1y code which is not compatible with prior C++ standards.
def CXXPre14Compat : DiagGroup<"c++98-c++11-compat">;
def CXXPre14CompatPedantic : DiagGroup<"c++98-c++11-compat-pedantic",
- [CXXPre14Compat]>;
-def CXXPre1zCompat : DiagGroup<"c++98-c++11-c++14-compat">;
-def CXXPre1zCompatPedantic : DiagGroup<"c++98-c++11-c++14-compat-pedantic",
- [CXXPre1zCompat]>;
+ [CXXPre14Compat,
+ CXXPre14CompatBinaryLiteral]>;
+def CXXPre17Compat : DiagGroup<"c++98-c++11-c++14-compat">;
+def CXXPre17CompatPedantic : DiagGroup<"c++98-c++11-c++14-compat-pedantic",
+ [CXXPre17Compat]>;
+def CXXPre2aCompat : DiagGroup<"c++98-c++11-c++14-c++17-compat">;
+def CXXPre2aCompatPedantic : DiagGroup<"c++98-c++11-c++14-c++17-compat-pedantic",
+ [CXXPre2aCompat]>;
def CXX98CompatBindToTemporaryCopy :
DiagGroup<"c++98-compat-bind-to-temporary-copy">;
@@ -178,13 +190,15 @@ def CXX98Compat : DiagGroup<"c++98-compat",
[CXX98CompatLocalTypeTemplateArgs,
CXX98CompatUnnamedTypeTemplateArgs,
CXXPre14Compat,
- CXXPre1zCompat]>;
+ CXXPre17Compat,
+ CXXPre2aCompat]>;
// Warnings for C++11 features which are Extensions in C++98 mode.
def CXX98CompatPedantic : DiagGroup<"c++98-compat-pedantic",
[CXX98Compat,
CXX98CompatBindToTemporaryCopy,
CXXPre14CompatPedantic,
- CXXPre1zCompatPedantic]>;
+ CXXPre17CompatPedantic,
+ CXXPre2aCompatPedantic]>;
def CXX11Narrowing : DiagGroup<"c++11-narrowing">;
@@ -209,21 +223,35 @@ def CXX11Compat : DiagGroup<"c++11-compat",
CXX11CompatReservedUserDefinedLiteral,
CXX11CompatDeprecatedWritableStr,
CXXPre14Compat,
- CXXPre1zCompat]>;
+ CXXPre17Compat,
+ CXXPre2aCompat]>;
def : DiagGroup<"c++0x-compat", [CXX11Compat]>;
def CXX11CompatPedantic : DiagGroup<"c++11-compat-pedantic",
- [CXXPre14CompatPedantic,
- CXXPre1zCompatPedantic]>;
+ [CXX11Compat,
+ CXXPre14CompatPedantic,
+ CXXPre17CompatPedantic,
+ CXXPre2aCompatPedantic]>;
-def CXX14Compat : DiagGroup<"c++14-compat", [CXXPre1zCompat]>;
+def CXX14Compat : DiagGroup<"c++14-compat", [CXXPre17Compat,
+ CXXPre2aCompat]>;
def CXX14CompatPedantic : DiagGroup<"c++14-compat-pedantic",
- [CXXPre1zCompatPedantic]>;
+ [CXX14Compat,
+ CXXPre17CompatPedantic,
+ CXXPre2aCompatPedantic]>;
def CXX17Compat : DiagGroup<"c++17-compat", [DeprecatedRegister,
DeprecatedIncrementBool,
- CXX17CompatMangling]>;
+ CXX17CompatMangling,
+ CXXPre2aCompat]>;
+def CXX17CompatPedantic : DiagGroup<"c++17-compat-pedantic",
+ [CXX17Compat,
+ CXXPre2aCompatPedantic]>;
def : DiagGroup<"c++1z-compat", [CXX17Compat]>;
+def CXX2aCompat : DiagGroup<"c++2a-compat">;
+def CXX2aCompatPedantic : DiagGroup<"c++2a-compat-pedantic",
+ [CXX2aCompat]>;
+
def ExitTimeDestructors : DiagGroup<"exit-time-destructors">;
def FlexibleArrayExtensions : DiagGroup<"flexible-array-extensions">;
def FourByteMultiChar : DiagGroup<"four-char-constants">;
@@ -316,6 +344,7 @@ def NonPODVarargs : DiagGroup<"non-pod-varargs">;
def ClassVarargs : DiagGroup<"class-varargs", [NonPODVarargs]>;
def : DiagGroup<"nonportable-cfstrings">;
def NonVirtualDtor : DiagGroup<"non-virtual-dtor">;
+def NullPointerArithmetic : DiagGroup<"null-pointer-arithmetic">;
def : DiagGroup<"effc++", [NonVirtualDtor]>;
def OveralignedType : DiagGroup<"over-aligned">;
def AlignedAllocationUnavailable : DiagGroup<"aligned-allocation-unavailable">;
@@ -345,6 +374,7 @@ 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 ObjCFlexibleArray : DiagGroup<"objc-flexible-array">;
def OpenCLUnsupportedRGBA: DiagGroup<"opencl-unsupported-rgba">;
def DeprecatedObjCIsaUsage : DiagGroup<"deprecated-objc-isa-usage">;
def ExplicitInitializeCall : DiagGroup<"explicit-initialize-call">;
@@ -405,12 +435,18 @@ def StringCompare : DiagGroup<"string-compare">;
def StringPlusInt : DiagGroup<"string-plus-int">;
def StringPlusChar : DiagGroup<"string-plus-char">;
def StrncatSize : DiagGroup<"strncat-size">;
+def TautologicalUnsignedZeroCompare : DiagGroup<"tautological-unsigned-zero-compare">;
+def TautologicalUnsignedEnumZeroCompare : DiagGroup<"tautological-unsigned-enum-zero-compare">;
def TautologicalOutOfRangeCompare : DiagGroup<"tautological-constant-out-of-range-compare">;
+def TautologicalConstantCompare : DiagGroup<"tautological-constant-compare",
+ [TautologicalUnsignedZeroCompare,
+ TautologicalUnsignedEnumZeroCompare,
+ TautologicalOutOfRangeCompare]>;
def TautologicalPointerCompare : DiagGroup<"tautological-pointer-compare">;
def TautologicalOverlapCompare : DiagGroup<"tautological-overlap-compare">;
def TautologicalUndefinedCompare : DiagGroup<"tautological-undefined-compare">;
def TautologicalCompare : DiagGroup<"tautological-compare",
- [TautologicalOutOfRangeCompare,
+ [TautologicalConstantCompare,
TautologicalPointerCompare,
TautologicalOverlapCompare,
TautologicalUndefinedCompare]>;
@@ -454,6 +490,8 @@ def CoveredSwitchDefault : DiagGroup<"covered-switch-default">;
def SwitchBool : DiagGroup<"switch-bool">;
def SwitchEnum : DiagGroup<"switch-enum">;
def Switch : DiagGroup<"switch">;
+def EnumCompareSwitch : DiagGroup<"enum-compare-switch">;
+def EnumCompare : DiagGroup<"enum-compare", [EnumCompareSwitch]>;
def ImplicitFallthroughPerFunction :
DiagGroup<"implicit-fallthrough-per-function">;
def ImplicitFallthrough : DiagGroup<"implicit-fallthrough",
@@ -474,10 +512,15 @@ def IgnoredPragmaIntrinsic : DiagGroup<"ignored-pragma-intrinsic">;
def UnknownPragmas : DiagGroup<"unknown-pragmas">;
def IgnoredPragmas : DiagGroup<"ignored-pragmas", [IgnoredPragmaIntrinsic]>;
def PragmaClangAttribute : DiagGroup<"pragma-clang-attribute">;
+def PragmaPackSuspiciousInclude : DiagGroup<"pragma-pack-suspicious-include">;
+def PragmaPack : DiagGroup<"pragma-pack", [PragmaPackSuspiciousInclude]>;
def Pragmas : DiagGroup<"pragmas", [UnknownPragmas, IgnoredPragmas,
- PragmaClangAttribute]>;
+ PragmaClangAttribute, PragmaPack]>;
def UnknownWarningOption : DiagGroup<"unknown-warning-option">;
def NSobjectAttribute : DiagGroup<"NSObject-attribute">;
+def NSConsumedMismatch : DiagGroup<"nsconsumed-mismatch">;
+def NSReturnsMismatch : DiagGroup<"nsreturns-mismatch">;
+
def IndependentClassAttribute : DiagGroup<"IndependentClass-attribute">;
def UnknownAttributes : DiagGroup<"unknown-attributes">;
def IgnoredAttributes : DiagGroup<"ignored-attributes">;
@@ -678,7 +721,8 @@ def Extra : DiagGroup<"extra", [
SemiBeforeMethodBody,
MissingMethodReturnType,
SignCompare,
- UnusedParameter
+ UnusedParameter,
+ NullPointerArithmetic
]>;
def Most : DiagGroup<"most", [
@@ -707,6 +751,7 @@ def Most : DiagGroup<"most", [
VolatileRegisterVar,
ObjCMissingSuperCalls,
ObjCDesignatedInit,
+ ObjCFlexibleArray,
OverloadedVirtual,
PrivateExtern,
SelTypeCast,
@@ -772,10 +817,14 @@ def CXX11 : DiagGroup<"c++11-extensions", [CXX11ExtraSemi, CXX11InlineNamespace,
// earlier C++ versions.
def CXX14 : DiagGroup<"c++14-extensions", [CXX14BinaryLiteral]>;
-// A warning group for warnings about using C++1z features as extensions in
+// A warning group for warnings about using C++17 features as extensions in
// earlier C++ versions.
def CXX17 : DiagGroup<"c++17-extensions">;
+// A warning group for warnings about using C++2a features as extensions in
+// earlier C++ versions.
+def CXX2a : DiagGroup<"c++2a-extensions">;
+
def : DiagGroup<"c++0x-extensions", [CXX11]>;
def : DiagGroup<"c++1y-extensions", [CXX14]>;
def : DiagGroup<"c++1z-extensions", [CXX17]>;
@@ -841,6 +890,7 @@ def MicrosoftVoidPseudoDtor : DiagGroup<"microsoft-void-pseudo-dtor">;
def MicrosoftAnonTag : DiagGroup<"microsoft-anon-tag">;
def MicrosoftCommentPaste : DiagGroup<"microsoft-comment-paste">;
def MicrosoftEndOfFile : DiagGroup<"microsoft-end-of-file">;
+def MicrosoftInaccessibleBase : DiagGroup<"microsoft-inaccessible-base">;
// Aliases.
def : DiagGroup<"msvc-include", [MicrosoftInclude]>;
// -Wmsvc-include = -Wmicrosoft-include
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h
index cdd358542a0d3..43183a120bb9a 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h
@@ -26,19 +26,36 @@ namespace clang {
// Import the diagnostic enums themselves.
namespace diag {
+ // Size of each of the diagnostic categories.
+ enum {
+ DIAG_SIZE_COMMON = 300,
+ DIAG_SIZE_DRIVER = 200,
+ DIAG_SIZE_FRONTEND = 100,
+ DIAG_SIZE_SERIALIZATION = 120,
+ DIAG_SIZE_LEX = 400,
+ DIAG_SIZE_PARSE = 500,
+ DIAG_SIZE_AST = 150,
+ DIAG_SIZE_COMMENT = 100,
+ DIAG_SIZE_CROSSTU = 100,
+ DIAG_SIZE_SEMA = 3500,
+ DIAG_SIZE_ANALYSIS = 100,
+ DIAG_SIZE_REFACTORING = 1000,
+ };
// Start position for diagnostics.
enum {
- DIAG_START_COMMON = 0,
- DIAG_START_DRIVER = DIAG_START_COMMON + 300,
- DIAG_START_FRONTEND = DIAG_START_DRIVER + 200,
- DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + 100,
- DIAG_START_LEX = DIAG_START_SERIALIZATION + 120,
- DIAG_START_PARSE = DIAG_START_LEX + 400,
- DIAG_START_AST = DIAG_START_PARSE + 500,
- DIAG_START_COMMENT = DIAG_START_AST + 110,
- DIAG_START_SEMA = DIAG_START_COMMENT + 100,
- DIAG_START_ANALYSIS = DIAG_START_SEMA + 3500,
- DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + 100
+ DIAG_START_COMMON = 0,
+ DIAG_START_DRIVER = DIAG_START_COMMON + DIAG_SIZE_COMMON,
+ DIAG_START_FRONTEND = DIAG_START_DRIVER + DIAG_SIZE_DRIVER,
+ DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + DIAG_SIZE_FRONTEND,
+ DIAG_START_LEX = DIAG_START_SERIALIZATION + DIAG_SIZE_SERIALIZATION,
+ DIAG_START_PARSE = DIAG_START_LEX + DIAG_SIZE_LEX,
+ DIAG_START_AST = DIAG_START_PARSE + DIAG_SIZE_PARSE,
+ DIAG_START_COMMENT = DIAG_START_AST + DIAG_SIZE_AST,
+ DIAG_START_CROSSTU = DIAG_START_COMMENT + DIAG_SIZE_CROSSTU,
+ DIAG_START_SEMA = DIAG_START_CROSSTU + DIAG_SIZE_COMMENT,
+ DIAG_START_ANALYSIS = DIAG_START_SEMA + DIAG_SIZE_SEMA,
+ DIAG_START_REFACTORING = DIAG_START_ANALYSIS + DIAG_SIZE_ANALYSIS,
+ DIAG_UPPER_LIMIT = DIAG_START_REFACTORING + DIAG_SIZE_REFACTORING
};
class CustomDiagInfo;
@@ -279,8 +296,8 @@ public:
SmallVectorImpl<diag::kind> &Diags) const;
/// \brief Get the set of all diagnostic IDs.
- void getAllDiagnostics(diag::Flavor Flavor,
- SmallVectorImpl<diag::kind> &Diags) const;
+ static void getAllDiagnostics(diag::Flavor Flavor,
+ SmallVectorImpl<diag::kind> &Diags);
/// \brief Get the diagnostic option with the closest edit distance to the
/// given group name.
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td
index 706881bfdc5d7..c664281ffcd48 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -31,6 +31,14 @@ def warn_cxx98_compat_less_colon_colon : Warning<
"'<::' is treated as digraph '<:' (aka '[') followed by ':' in C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
+def warn_cxx17_compat_spaceship : Warning<
+ "'<=>' operator is incompatible with C++ standards before C++2a">,
+ InGroup<CXXPre2aCompat>, DefaultIgnore;
+def warn_cxx2a_compat_spaceship : Warning<
+ "'<=>' is a single token in C++2a; "
+ "add a space to avoid a change in behavior">,
+ InGroup<CXX2aCompat>;
+
// Trigraphs.
def trigraph_ignored : Warning<"trigraph ignored">, InGroup<Trigraphs>;
def trigraph_ignored_block_comment : Warning<
@@ -71,6 +79,8 @@ def ext_token_used : Extension<"extension used">,
def warn_cxx11_keyword : Warning<"'%0' is a keyword in C++11">,
InGroup<CXX11Compat>, DefaultIgnore;
+def warn_cxx2a_keyword : Warning<"'%0' is a keyword in C++2a">,
+ InGroup<CXX2aCompat>, DefaultIgnore;
def ext_unterminated_char_or_string : ExtWarn<
"missing terminating %select{'|'\"'}0 character">, InGroup<InvalidPPToken>;
@@ -109,6 +119,9 @@ def err_non_ascii : Error<
def ext_unicode_whitespace : ExtWarn<
"treating Unicode character as whitespace">,
InGroup<DiagGroup<"unicode-whitespace">>;
+def warn_utf8_symbol_homoglyph : Warning<
+ "treating Unicode character <U+%0> as identifier character rather than "
+ "as '%1' symbol">, InGroup<DiagGroup<"unicode-homoglyph">>;
def err_hex_escape_no_digits : Error<
"\\%0 used with no following hex digits">;
@@ -173,8 +186,6 @@ def warn_char_constant_too_large : Warning<
def err_multichar_utf_character_literal : Error<
"Unicode character literals may not contain multiple characters">;
def err_exponent_has_no_digits : Error<"exponent has no digits">;
-def ext_imaginary_constant : Extension<
- "imaginary constants are a GNU extension">, InGroup<GNUImaginaryConstant>;
def err_hex_constant_requires : Error<
"hexadecimal floating %select{constant|literal}0 requires "
"%select{an exponent|a significand}1">;
@@ -182,17 +193,17 @@ def ext_hex_constant_invalid : Extension<
"hexadecimal floating constants are a C99 feature">, InGroup<C99>;
def ext_hex_literal_invalid : Extension<
"hexadecimal floating literals are a C++17 feature">, InGroup<CXX17>;
-def warn_cxx1z_hex_literal : Warning<
+def warn_cxx17_hex_literal : Warning<
"hexadecimal floating literals are incompatible with "
"C++ standards before C++17">,
- InGroup<CXXPre1zCompatPedantic>, DefaultIgnore;
+ InGroup<CXXPre17CompatPedantic>, DefaultIgnore;
def ext_binary_literal : Extension<
"binary integer literals are a GNU extension">, InGroup<GNUBinaryLiteral>;
def ext_binary_literal_cxx14 : Extension<
"binary integer literals are a C++14 extension">, InGroup<CXX14BinaryLiteral>;
def warn_cxx11_compat_binary_literal : Warning<
"binary integer literals are incompatible with C++ standards before C++14">,
- InGroup<CXXPre14CompatPedantic>, DefaultIgnore;
+ InGroup<CXXPre14CompatBinaryLiteral>, DefaultIgnore;
def err_pascal_string_too_long : Error<"Pascal string is too long">;
def err_escape_too_large : Error<
"%select{hex|octal}0 escape sequence out of range">;
@@ -209,7 +220,7 @@ def warn_cxx98_compat_unicode_literal : Warning<
InGroup<CXX98Compat>, DefaultIgnore;
def warn_cxx14_compat_u8_character_literal : Warning<
"unicode literals are incompatible with C++ standards before C++17">,
- InGroup<CXXPre1zCompat>, DefaultIgnore;
+ InGroup<CXXPre17Compat>, 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;
@@ -346,6 +357,23 @@ def ext_pp_extra_tokens_at_eol : ExtWarn<
def ext_pp_comma_expr : Extension<"comma operator in operand of #if">;
def ext_pp_bad_vaargs_use : Extension<
"__VA_ARGS__ can only appear in the expansion of a C99 variadic macro">;
+
+def ext_pp_bad_vaopt_use
+ : ExtWarn<
+ "__VA_OPT__ can only appear in the expansion of a variadic macro">,
+ InGroup<VariadicMacros>;
+
+def err_pp_missing_lparen_in_vaopt_use : Error<
+ "missing '(' following __VA_OPT__">;
+def err_pp_vaopt_nested_use : Error<
+ "__VA_OPT__ cannot be nested within its own replacement tokens">;
+
+def err_vaopt_paste_at_start : Error<
+ "'##' cannot appear at start of __VA_OPT__ argument">;
+
+def err_vaopt_paste_at_end
+ : Error<"'##' cannot appear at end of __VA_OPT__ argument">;
+
def ext_pp_macro_redef : ExtWarn<"%0 macro redefined">, InGroup<MacroRedefined>;
def ext_variadic_macro : Extension<"variadic macros are a C99 feature">,
InGroup<VariadicMacros>;
@@ -674,6 +702,13 @@ def err_mmap_invalid_header_attribute_value : Error<
"expected integer literal as value for header attribute '%0'">;
def err_mmap_expected_header_attribute : Error<
"expected a header attribute name ('size' or 'mtime')">;
+def err_mmap_conflicting_export_as : Error<
+ "conflicting re-export of module '%0' as '%1' or '%2'">;
+def warn_mmap_redundant_export_as : Warning<
+ "module '%0' already re-exported as '%1'">,
+ InGroup<PrivateModule>;
+def err_mmap_submodule_export_as : Error<
+ "only top-level modules can be re-exported as public">;
def warn_auto_module_import : Warning<
"treating #%select{include|import|include_next|__include_macros}0 as an "
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticOptions.h b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticOptions.h
index c195003de5c45..3844eb63f0eaf 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticOptions.h
@@ -100,6 +100,10 @@ public:
/// prefixes removed.
std::vector<std::string> Remarks;
+ /// The prefixes for comment directives sought by -verify ("expected" by
+ /// default).
+ std::vector<std::string> VerifyPrefixes;
+
public:
// Define accessors/mutators for diagnostic options of enumeration type.
#define DIAGOPT(Name, Bits, Default)
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td
index 5170c07bf6668..a8d6955da3c09 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -215,7 +215,7 @@ def ext_nested_namespace_definition : ExtWarn<
"define each namespace separately">, InGroup<CXX17>;
def warn_cxx14_compat_nested_namespace_definition : Warning<
"nested namespace definition is incompatible with C++ standards before C++17">,
- InGroup<CXXPre1zCompat>, DefaultIgnore;
+ InGroup<CXXPre17Compat>, DefaultIgnore;
def err_inline_nested_namespace_definition : Error<
"nested namespace definition cannot be 'inline'">;
def err_expected_semi_after_attribute_list : Error<
@@ -525,13 +525,13 @@ def ext_constexpr_if : ExtWarn<
"constexpr if is a C++17 extension">, InGroup<CXX17>;
def warn_cxx14_compat_constexpr_if : Warning<
"constexpr if is incompatible with C++ standards before C++17">,
- DefaultIgnore, InGroup<CXXPre1zCompat>;
+ DefaultIgnore, InGroup<CXXPre17Compat>;
def ext_init_statement : ExtWarn<
"'%select{if|switch}0' initialization statements are a C++17 extension">,
InGroup<CXX17>;
def warn_cxx14_compat_init_statement : Warning<
"%select{if|switch}0 initialization statements are incompatible with "
- "C++ standards before C++17">, DefaultIgnore, InGroup<CXXPre1zCompat>;
+ "C++ standards before C++17">, DefaultIgnore, InGroup<CXXPre17Compat>;
// C++ derived classes
def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;
@@ -558,10 +558,13 @@ 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<
+def ext_ns_enum_attribute : Extension<
+ "attributes on %select{a namespace|an enumerator}0 declaration are "
+ "a C++17 extension">, InGroup<CXX17>;
+def warn_cxx14_compat_ns_enum_attribute : Warning<
"attributes on %select{a namespace|an enumerator}0 declaration are "
"incompatible with C++ standards before C++17">,
- InGroup<CXXPre1zCompat>, DefaultIgnore;
+ InGroup<CXXPre17CompatPedantic>, DefaultIgnore;
def warn_cxx98_compat_alignas : Warning<"'alignas' is incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
def warn_cxx98_compat_attribute : Warning<
@@ -577,7 +580,7 @@ def err_cxx11_attribute_repeated : Error<
"attribute %0 cannot appear multiple times in an attribute specifier">;
def warn_cxx14_compat_using_attribute_ns : Warning<
"default scope specifier for attributes is incompatible with C++ standards "
- "before C++17">, InGroup<CXXPre1zCompat>, DefaultIgnore;
+ "before C++17">, InGroup<CXXPre17Compat>, DefaultIgnore;
def ext_using_attribute_ns : ExtWarn<
"default scope specifier for attributes is a C++17 extension">,
InGroup<CXX17>;
@@ -622,7 +625,7 @@ def ext_template_template_param_typename : ExtWarn<
def warn_cxx14_compat_template_template_param_typename : Warning<
"template template parameter using 'typename' is "
"incompatible with C++ standards before C++17">,
- InGroup<CXXPre1zCompat>, DefaultIgnore;
+ InGroup<CXXPre17Compat>, DefaultIgnore;
def err_template_spec_syntax_non_template : Error<
"identifier followed by '<' indicates a class template specialization but "
"%0 %select{does not refer to a template|refers to a function template|"
@@ -699,7 +702,7 @@ def ext_fold_expression : ExtWarn<
InGroup<CXX17>;
def warn_cxx14_compat_fold_expression : Warning<
"pack fold expression is incompatible with C++ standards before C++17">,
- InGroup<CXXPre1zCompat>, DefaultIgnore;
+ InGroup<CXXPre17Compat>, DefaultIgnore;
def err_expected_fold_operator : Error<
"expected a foldable binary operator in fold expression">;
def err_fold_operator_mismatch : Error<
@@ -730,8 +733,12 @@ def ext_nonstatic_member_init : ExtWarn<
def warn_cxx98_compat_nonstatic_member_init : Warning<
"in-class initialization of non-static data members is incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
-def err_bitfield_member_init: Error<
- "bit-field member cannot have an in-class initializer">;
+def ext_bitfield_member_init: ExtWarn<
+ "default member initializer for bit-field is a C++2a extension">,
+ InGroup<CXX2a>;
+def warn_cxx17_compat_bitfield_member_init: Warning<
+ "default member initializer for bit-field is incompatible with "
+ "C++ standards before C++2a">, InGroup<CXXPre2aCompat>, DefaultIgnore;
def err_incomplete_array_member_init: Error<
"array bound cannot be deduced from an in-class initializer">;
@@ -748,19 +755,19 @@ def err_alias_declaration_specialization : Error<
def err_alias_declaration_pack_expansion : Error<
"alias declaration cannot be a pack expansion">;
-// C++1z using-declaration pack expansions
+// C++17 using-declaration pack expansions
def ext_multi_using_declaration : ExtWarn<
"use of multiple declarators in a single using declaration is "
"a C++17 extension">, InGroup<CXX17>;
-def warn_cxx1z_compat_multi_using_declaration : Warning<
+def warn_cxx17_compat_multi_using_declaration : Warning<
"use of multiple declarators in a single using declaration is "
"incompatible with C++ standards before C++17">,
- InGroup<CXXPre1zCompat>, DefaultIgnore;
+ InGroup<CXXPre17Compat>, DefaultIgnore;
def ext_using_declaration_pack : ExtWarn<
"pack expansion of using declaration is a C++17 extension">, InGroup<CXX17>;
-def warn_cxx1z_compat_using_declaration_pack : Warning<
+def warn_cxx17_compat_using_declaration_pack : Warning<
"pack expansion using declaration is incompatible with C++ standards "
- "before C++17">, InGroup<CXXPre1zCompat>, DefaultIgnore;
+ "before C++17">, InGroup<CXXPre17Compat>, DefaultIgnore;
// C++11 override control
def ext_override_control_keyword : ExtWarn<
@@ -811,15 +818,15 @@ def err_lambda_missing_parens : Error<
"attribute specifier|'constexpr'}0">;
def err_lambda_decl_specifier_repeated : Error<
"%select{'mutable'|'constexpr'}0 cannot appear multiple times in a lambda declarator">;
-// C++1z lambda expressions
+// C++17 lambda expressions
def err_expected_star_this_capture : Error<
"expected 'this' following '*' in lambda capture list">;
-// C++1z constexpr lambda expressions
+// C++17 constexpr lambda expressions
def warn_cxx14_compat_constexpr_on_lambda : Warning<
"constexpr on lambda expressions is incompatible with C++ standards before C++17">,
- InGroup<CXXPre1zCompat>, DefaultIgnore;
-def ext_constexpr_on_lambda_cxx1z : ExtWarn<
+ InGroup<CXXPre17Compat>, DefaultIgnore;
+def ext_constexpr_on_lambda_cxx17 : ExtWarn<
"'constexpr' on lambda expressions is a C++17 extension">, InGroup<CXX17>;
// Availability attribute
@@ -893,8 +900,6 @@ def err_pragma_expected_clang_section_name : Error<
"expected one of [bss|data|rodata|text] section kind in '#pragma %0'">;
def err_pragma_clang_section_expected_equal : Error<
"expected '=' following '#pragma clang section %select{invalid|bss|data|rodata|text}0'">;
-def err_pragma_clang_section_expected_name_or_clear : Error<
- "expected section name or '\"\"' following '#pragma clang section %select{invalid|bss|data|rodata|text}0'">;
def warn_pragma_expected_section_name : Warning<
"expected a string literal for the section name in '#pragma %0' - ignored">,
InGroup<IgnoredPragmas>;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticRefactoringKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticRefactoringKinds.td
new file mode 100644
index 0000000000000..ee396b9307299
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticRefactoringKinds.td
@@ -0,0 +1,34 @@
+//==--- DiagnosticRefactoringKinds.td - refactoring diagnostics -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Refactoring Diagnostics
+//===----------------------------------------------------------------------===//
+
+let Component = "Refactoring" in {
+
+let CategoryName = "Refactoring Invocation Issue" in {
+
+def err_refactor_no_selection : Error<"refactoring action can't be initiated "
+ "without a selection">;
+def err_refactor_selection_no_symbol : Error<"there is no symbol at the given "
+ "location">;
+def err_refactor_selection_invalid_ast : Error<"the provided selection does "
+ "not overlap with the AST nodes of interest">;
+
+def err_refactor_code_outside_of_function : Error<"the selected code is not a "
+ "part of a function's / method's body">;
+def err_refactor_extract_simple_expression : Error<"the selected expression "
+ "is too simple to extract">;
+def err_refactor_extract_prohibited_expression : Error<"the selected "
+ "expression can't be extracted">;
+
+}
+
+} // end of Refactoring diagnostics
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 8dc6e7b460e86..29236eab5446c 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -141,6 +141,10 @@ def err_vla_decl_has_extern_linkage : Error<
"variable length array declaration cannot have 'extern' linkage">;
def ext_vla_folded_to_constant : Extension<
"variable length array folded to constant array as an extension">, InGroup<GNUFoldingConstant>;
+def err_vla_unsupported : Error<
+ "variable length arrays are not supported for the current target">;
+def note_vla_unsupported : Note<
+ "variable length arrays are not supported for the current target">;
// C99 variably modified types
def err_variably_modified_template_arg : Error<
@@ -194,6 +198,8 @@ def warn_duplicate_declspec : Warning<"duplicate '%0' declaration specifier">,
InGroup<DuplicateDeclSpecifier>;
def ext_plain_complex : ExtWarn<
"plain '_Complex' requires a type specifier; assuming '_Complex double'">;
+def ext_imaginary_constant : Extension<
+ "imaginary constants are a GNU extension">, InGroup<GNUImaginaryConstant>;
def ext_integer_complex : Extension<
"complex integer types are a GNU extension">, InGroup<GNUComplexInteger>;
@@ -293,8 +299,20 @@ def warn_empty_parens_are_function_decl : Warning<
def warn_parens_disambiguated_as_function_declaration : Warning<
"parentheses were disambiguated as a function declaration">,
InGroup<VexingParse>;
+def warn_parens_disambiguated_as_variable_declaration : Warning<
+ "parentheses were disambiguated as redundant parentheses around declaration "
+ "of variable named %0">, InGroup<VexingParse>;
+def warn_redundant_parens_around_declarator : Warning<
+ "redundant parentheses surrounding declarator">,
+ InGroup<DiagGroup<"redundant-parens">>, DefaultIgnore;
def note_additional_parens_for_variable_declaration : Note<
"add a pair of parentheses to declare a variable">;
+def note_raii_guard_add_name : Note<
+ "add a variable name to declare a %0 initialized with %1">;
+def note_function_style_cast_add_parentheses : Note<
+ "add enclosing parentheses to perform a function-style cast">;
+def note_remove_parens_for_variable_declaration : Note<
+ "remove parentheses to silence this warning">;
def note_empty_parens_function_call : Note<
"change this ',' to a ';' to call %0">;
def note_empty_parens_default_ctor : Note<
@@ -341,7 +359,7 @@ def warn_implicit_function_decl : Warning<
"implicit declaration of function %0">,
InGroup<ImplicitFunctionDeclare>, DefaultIgnore;
def ext_implicit_function_decl : ExtWarn<
- "implicit declaration of function %0 is invalid in C99">,
+ "implicit declaration of function %0 is invalid in %select{C99|OpenCL}1">,
InGroup<ImplicitFunctionDeclare>;
def note_function_suggestion : Note<"did you mean %0?">;
@@ -352,8 +370,10 @@ def err_language_linkage_spec_unknown : Error<"unknown linkage language">;
def err_language_linkage_spec_not_ascii : Error<
"string literal in language linkage specifier cannot have an "
"encoding-prefix">;
-def warn_use_out_of_scope_declaration : Warning<
- "use of out-of-scope declaration of %0">;
+def ext_use_out_of_scope_declaration : ExtWarn<
+ "use of out-of-scope declaration of %0%select{| whose type is not "
+ "compatible with that of an implicit declaration}1">,
+ InGroup<DiagGroup<"out-of-scope-function">>;
def err_inline_non_function : Error<
"'inline' can only appear on functions%select{| and non-local variables}0">;
def err_noreturn_non_function : Error<
@@ -391,9 +411,12 @@ def err_decomp_decl_context : Error<
"decomposition declaration not permitted in this context">;
def warn_cxx14_compat_decomp_decl : Warning<
"decomposition declarations are incompatible with "
- "C++ standards before C++17">, DefaultIgnore, InGroup<CXXPre1zCompat>;
+ "C++ standards before C++17">, DefaultIgnore, InGroup<CXXPre17Compat>;
def ext_decomp_decl : ExtWarn<
"decomposition declarations are a C++17 extension">, InGroup<CXX17>;
+def ext_decomp_decl_cond : ExtWarn<
+ "ISO C++17 does not permit structured binding declaration in a condition">,
+ InGroup<DiagGroup<"binding-in-condition">>;
def err_decomp_decl_spec : Error<
"decomposition declaration cannot be declared "
"%plural{1:'%1'|:with '%1' specifiers}0">;
@@ -505,7 +528,7 @@ def warn_deprecated_copy_operation : Warning<
"for %0 is deprecated because it has a user-declared "
"%select{copy %select{assignment operator|constructor}1|destructor}2">,
InGroup<Deprecated>, DefaultIgnore;
-def warn_cxx1z_compat_exception_spec_in_signature : Warning<
+def warn_cxx17_compat_exception_spec_in_signature : Warning<
"mangled name of %0 will change in C++17 due to non-throwing exception "
"specification in function signature">, InGroup<CXX17CompatMangling>;
@@ -581,6 +604,7 @@ def warn_redecl_library_builtin : Warning<
def err_builtin_definition : Error<"definition of builtin function %0">;
def err_arm_invalid_specialreg : Error<"invalid special register for builtin">;
def err_invalid_cpu_supports : Error<"invalid cpu feature string for builtin">;
+def err_invalid_cpu_is : Error<"invalid cpu name for builtin">;
def err_builtin_needs_feature : Error<"%0 needs target feature %1">;
def err_function_needs_feature
: Error<"always_inline function %1 requires target feature '%2', but would "
@@ -712,6 +736,19 @@ def err_pragma_options_align_mac68k_target_unsupported : Error<
def warn_pragma_pack_invalid_alignment : Warning<
"expected #pragma pack parameter to be '1', '2', '4', '8', or '16'">,
InGroup<IgnoredPragmas>;
+def warn_pragma_pack_non_default_at_include : Warning<
+ "non-default #pragma pack value changes the alignment of struct or union "
+ "members in the included file">, InGroup<PragmaPackSuspiciousInclude>,
+ DefaultIgnore;
+def warn_pragma_pack_modified_after_include : Warning<
+ "the current #pragma pack aligment value is modified in the included "
+ "file">, InGroup<PragmaPack>;
+def warn_pragma_pack_no_pop_eof : Warning<"unterminated "
+ "'#pragma pack (push, ...)' at end of file">, InGroup<PragmaPack>;
+def note_pragma_pack_here : Note<
+ "previous '#pragma pack' directive that modifies alignment is here">;
+def note_pragma_pack_pop_instead_reset : Note<
+ "did you intend to use '#pragma pack (pop)' instead of '#pragma pack()'?">;
// Follow the Microsoft implementation.
def warn_pragma_pack_show : Warning<"value of #pragma pack(show) == %0">;
def warn_pragma_pack_pop_identifer_and_alignment : Warning<
@@ -1195,21 +1232,27 @@ def err_objc_method_unsupported_param_ret_type : Error<
"%0 %select{parameter|return}1 type is unsupported; "
"support for vector types for this target is introduced in %2">;
+def warn_messaging_unqualified_id : Warning<
+ "messaging unqualified id">, DefaultIgnore,
+ InGroup<DiagGroup<"objc-messaging-id">>;
+
// C++ declarations
def err_static_assert_expression_is_not_constant : Error<
"static_assert expression is not an integral constant expression">;
def err_static_assert_failed : Error<"static_assert failed%select{ %1|}0">;
+def err_static_assert_requirement_failed : Error<
+ "static_assert failed due to requirement '%0'%select{ %2|}1">;
def ext_static_assert_no_message : ExtWarn<
"static_assert with no message is a C++17 extension">, InGroup<CXX17>;
def warn_cxx14_compat_static_assert_no_message : Warning<
"static_assert with no message is incompatible with C++ standards before C++17">,
- DefaultIgnore, InGroup<CXXPre1zCompat>;
+ DefaultIgnore, InGroup<CXXPre17Compat>;
def ext_inline_variable : ExtWarn<
"inline variables are a C++17 extension">, InGroup<CXX17>;
def warn_cxx14_compat_inline_variable : Warning<
"inline variables are incompatible with C++ standards before C++17">,
- DefaultIgnore, InGroup<CXXPre1zCompat>;
+ DefaultIgnore, InGroup<CXXPre17Compat>;
def warn_inline_namespace_reopened_noninline : Warning<
"inline namespace reopened as a non-inline namespace">;
@@ -1313,6 +1356,8 @@ def err_type_defined_in_alias_template : Error<
"%0 cannot be defined in a type alias template">;
def err_type_defined_in_condition : Error<
"%0 cannot be defined in a condition">;
+def err_type_defined_in_enum : Error<
+ "%0 cannot be defined in an enumeration">;
def note_pure_virtual_function : Note<
"unimplemented pure virtual method %0 in %1">;
@@ -1637,6 +1682,11 @@ def err_conflicting_overriding_cc_attributes : Error<
"virtual function %0 has different calling convention attributes "
"%diff{($) than the function it overrides (which has calling convention $)|"
"than the function it overrides}1,2">;
+def warn_overriding_method_missing_noescape : Warning<
+ "parameter of overriding method should be annotated with "
+ "__attribute__((noescape))">, InGroup<MissingNoEscape>;
+def note_overridden_marked_noescape : Note<
+ "parameter of overridden method is annotated with __attribute__((noescape))">;
def err_covariant_return_inaccessible_base : Error<
"invalid covariant return for virtual function: %1 is a "
@@ -1938,8 +1988,9 @@ def err_auto_var_requires_init : Error<
"declaration of variable %0 with deduced type %1 requires an initializer">;
def err_auto_new_requires_ctor_arg : Error<
"new expression for type %0 requires a constructor argument">;
-def err_auto_new_list_init : Error<
- "new expression for type %0 cannot use list-initialization">;
+def ext_auto_new_list_init : Extension<
+ "ISO C++ standards before C++17 do not allow new expression for "
+ "type %0 to use list-initialization">, InGroup<CXX17>;
def err_auto_var_init_no_expression : Error<
"initializer for variable %0 with type %1 is empty">;
def err_auto_var_init_multiple_expressions : Error<
@@ -1964,6 +2015,9 @@ def err_auto_var_deduction_failure_from_init_list : Error<
"cannot deduce actual type for variable %0 with type %1 from initializer list">;
def err_auto_new_deduction_failure : Error<
"new expression for type %0 has incompatible constructor argument of type %1">;
+def err_auto_inconsistent_deduction : Error<
+ "deduced conflicting types %diff{($ vs $) |}0,1"
+ "for initializer list element type">;
def err_auto_different_deductions : Error<
"%select{'auto'|'decltype(auto)'|'__auto_type'|template arguments}0 "
"deduced as %1 in declaration of %2 and "
@@ -1999,7 +2053,7 @@ def err_decltype_auto_compound_type : Error<
def err_decltype_auto_initializer_list : Error<
"cannot deduce 'decltype(auto)' from initializer list">;
-// C++1z deduced class template specialization types
+// C++17 deduced class template specialization types
def err_deduced_class_template_compound_type : Error<
"cannot %select{form pointer to|form reference to|form array of|"
"form function returning|use parentheses when declaring variable with}0 "
@@ -2151,7 +2205,7 @@ def ext_for_range_begin_end_types_differ : ExtWarn<
InGroup<CXX17>;
def warn_for_range_begin_end_types_differ : Warning<
"'begin' and 'end' returning different types (%0 and %1) is incompatible "
- "with C++ standards before C++17">, InGroup<CXXPre1zCompat>, DefaultIgnore;
+ "with C++ standards before C++17">, InGroup<CXXPre17Compat>, DefaultIgnore;
def note_in_for_range: Note<
"when looking up '%select{begin|end}0' function for range expression "
"of type %1">;
@@ -2387,8 +2441,9 @@ def err_attribute_requires_positive_integer : Error<
def err_attribute_requires_opencl_version : Error<
"%0 attribute requires OpenCL version %1%select{| or above}2">;
def warn_unsupported_target_attribute
- : Warning<"Ignoring unsupported '%0' in the target attribute string">,
- InGroup<IgnoredAttributes>;
+ : Warning<"ignoring %select{unsupported|duplicate}0"
+ "%select{| architecture}1 '%2' in the target attribute string">,
+ InGroup<IgnoredAttributes>;
def err_attribute_unsupported
: Error<"%0 attribute is not supported for this target">;
// The err_*_attribute_argument_not_int are separate because they're used by
@@ -2587,6 +2642,8 @@ def err_attribute_section_invalid_for_target : Error<
"argument to 'section' attribute is not valid for this target: %0">;
def warn_mismatched_section : Warning<
"section does not match previous declaration">, InGroup<Section>;
+def warn_attribute_section_on_redeclaration : Warning<
+ "section attribute is specified on redeclared variable">, InGroup<Section>;
def err_anonymous_property: Error<
"anonymous property is not supported">;
@@ -2729,7 +2786,7 @@ def err_attribute_weakref_not_global_context : Error<
def err_attribute_weakref_without_alias : Error<
"weakref declaration of %0 must also have an alias attribute">;
def err_alias_not_supported_on_darwin : Error <
- "only weak aliases are supported on darwin">;
+ "aliases are not supported on darwin">;
def err_alias_to_undefined : Error<
"%select{alias|ifunc}0 must point to a defined %select{variable or |}1function">;
def warn_alias_to_weak_alias : Warning<
@@ -2746,55 +2803,26 @@ def err_ifunc_resolver_return : Error<
"ifunc resolver function must return a pointer">;
def err_ifunc_resolver_params : Error<
"ifunc resolver function must have no parameters">;
+def warn_attribute_wrong_decl_type_str : Warning<
+ "%0 attribute only applies to %1">, InGroup<IgnoredAttributes>;
+def err_attribute_wrong_decl_type_str : Error<
+ warn_attribute_wrong_decl_type_str.Text>;
def warn_attribute_wrong_decl_type : Warning<
"%0 attribute only applies to %select{"
"functions"
"|unions"
"|variables and functions"
- "|functions and global variables"
- "|functions, variables, and Objective-C interfaces"
"|functions and methods"
- "|parameters"
"|functions, methods and blocks"
- "|functions, methods, and classes"
"|functions, methods, and parameters"
- "|functions, methods, and global variables"
- "|classes"
- "|enums"
"|variables"
- "|methods"
- "|fields and global variables"
- "|structs"
- "|parameters and typedefs"
- "|variables and typedefs"
- "|thread-local variables"
"|variables and fields"
"|variables, data members and tag types"
"|types and namespaces"
- "|Objective-C interfaces"
- "|methods and properties"
- "|functions, methods, and properties"
- "|struct or union"
- "|struct, union or class"
- "|types"
- "|Objective-C instance methods"
- "|init methods of interface or class extension declarations"
"|variables, functions and classes"
- "|functions, variables, classes, and Objective-C interfaces"
- "|Objective-C protocols"
- "|variables with static or thread storage duration"
- "|functions, methods, properties, and global variables"
- "|structs, unions, and typedefs"
- "|structs and typedefs"
- "|interface or protocol declarations"
"|kernel functions"
"|non-K&R-style functions"
- "|variables, enums, fields and typedefs"
- "|functions, methods, enums, and classes"
- "|structs, classes, variables, functions, and inline namespaces"
- "|variables, functions, methods, types, enumerations, enumerators, labels, and non-static data members"
- "|classes and enumerations"
- "|named declarations}1">,
+ "|variables, functions, methods, types, enumerations, enumerators, labels, and non-static data members}1">,
InGroup<IgnoredAttributes>;
def err_attribute_wrong_decl_type : Error<warn_attribute_wrong_decl_type.Text>;
def warn_type_attribute_wrong_type : Warning<
@@ -2879,25 +2907,11 @@ def warn_unguarded_availability :
def warn_unguarded_availability_new :
Warning<warn_unguarded_availability.Text>,
InGroup<UnguardedAvailabilityNew>;
-def warn_partial_availability : Warning<"%0 is only available conditionally">,
- InGroup<UnguardedAvailability>, DefaultIgnore;
-def warn_partial_availability_new : Warning<warn_partial_availability.Text>,
- InGroup<UnguardedAvailabilityNew>;
-def note_partial_availability_silence : Note<
- "annotate %select{%1|anonymous %1}0 with an availability attribute to silence">;
+def note_decl_unguarded_availability_silence : Note<
+ "annotate %select{%1|anonymous %1}0 with an availability attribute to silence this warning">;
def note_unguarded_available_silence : Note<
"enclose %0 in %select{an @available|a __builtin_available}1 check to silence"
" this warning">;
-def warn_partial_message : Warning<"%0 is partial: %1">,
- InGroup<UnguardedAvailability>, DefaultIgnore;
-def warn_partial_message_new : Warning<warn_partial_message.Text>,
- InGroup<UnguardedAvailabilityNew>;
-def warn_partial_fwdclass_message : Warning<
- "%0 may be partial because the receiver type is unknown">,
- InGroup<UnguardedAvailability>, DefaultIgnore;
-def warn_partial_fwdclass_message_new :
- Warning<warn_partial_fwdclass_message.Text>,
- InGroup<UnguardedAvailabilityNew>;
def warn_at_available_unchecked_use : Warning<
"%select{@available|__builtin_available}0 does not guard availability here; "
"use if (%select{@available|__builtin_available}0) instead">,
@@ -3063,6 +3077,8 @@ def warn_impcast_vector_scalar : Warning<
def warn_impcast_complex_scalar : Warning<
"implicit conversion discards imaginary component: %0 to %1">,
InGroup<Conversion>, DefaultIgnore;
+def err_impcast_complex_scalar : Error<
+ "implicit conversion from %0 to %1 is not permitted in C++">;
def warn_impcast_float_precision : Warning<
"implicit conversion loses floating-point precision: %0 to %1">,
InGroup<Conversion>, DefaultIgnore;
@@ -3188,6 +3204,9 @@ def warn_int_to_void_pointer_cast : Warning<
"cast to %1 from smaller integer type %0">,
InGroup<IntToVoidPointerCast>;
+def warn_attribute_ignored_for_field_of_type : Warning<
+ "%0 attribute ignored for field of type %1">,
+ InGroup<IgnoredAttributes>;
def warn_no_underlying_type_specified_for_enum_bitfield : Warning<
"enums in the Microsoft ABI are signed integers by default; consider giving "
"the enum %0 an unsigned underlying type to make this code portable">,
@@ -3906,7 +3925,7 @@ def err_template_nontype_parm_bad_type : Error<
def warn_cxx14_compat_template_nontype_parm_auto_type : Warning<
"non-type template parameters declared with %0 are incompatible with C++ "
"standards before C++17">,
- DefaultIgnore, InGroup<CXXPre1zCompat>;
+ DefaultIgnore, InGroup<CXXPre17Compat>;
def err_template_param_default_arg_redefinition : Error<
"template parameter redefines default argument">;
def note_template_param_prev_default_arg : Note<
@@ -4080,6 +4099,13 @@ def err_pointer_to_member_call_drops_quals : Error<
def err_pointer_to_member_oper_value_classify: Error<
"pointer-to-member function type %0 can only be called on an "
"%select{rvalue|lvalue}1">;
+def ext_pointer_to_const_ref_member_on_rvalue : Extension<
+ "invoking a pointer to a 'const &' member function on an rvalue is a C++2a extension">,
+ InGroup<CXX2a>, SFINAEFailure;
+def warn_cxx17_compat_pointer_to_const_ref_member_on_rvalue : Warning<
+ "invoking a pointer to a 'const &' member function on an rvalue is "
+ "incompatible with C++ standards before C++2a">,
+ InGroup<CXXPre2aCompatPedantic>, DefaultIgnore;
def ext_ms_deref_template_argument: ExtWarn<
"non-type template argument containing a dereference operation is a "
"Microsoft extension">, InGroup<MicrosoftTemplate>;
@@ -4681,6 +4707,14 @@ def note_deleted_assign_field : Note<
def warn_undefined_internal : Warning<
"%select{function|variable}0 %q1 has internal linkage but is not defined">,
InGroup<DiagGroup<"undefined-internal">>;
+def err_undefined_internal_type : Error<
+ "%select{function|variable}0 %q1 is used but not defined in this "
+ "translation unit, and cannot be defined in any other translation unit "
+ "because its type does not have linkage">;
+def ext_undefined_internal_type : Extension<
+ "ISO C++ requires a definition in this translation unit for "
+ "%select{function|variable}0 %q1 because its type does not have linkage">,
+ InGroup<DiagGroup<"undefined-internal-type">>;
def warn_undefined_inline : Warning<"inline function %q0 is not defined">,
InGroup<DiagGroup<"undefined-inline">>;
def err_undefined_inline_var : Error<"inline variable %q0 is not defined">;
@@ -4746,6 +4780,9 @@ def err_thread_non_thread : Error<
def err_thread_thread_different_kind : Error<
"thread-local declaration of %0 with %select{static|dynamic}1 initialization "
"follows declaration with %select{dynamic|static}1 initialization">;
+def err_mismatched_owning_module : Error<
+ "declaration of %0 in %select{the global module|module %2}1 follows "
+ "declaration in %select{the global module|module %4}3">;
def err_redefinition_different_type : Error<
"redefinition of %0 with a different type%diff{: $ vs $|}1,2">;
def err_redefinition_different_kind : Error<
@@ -5164,6 +5201,28 @@ def ext_flexible_array_empty_aggregate_gnu : Extension<
def ext_flexible_array_union_gnu : Extension<
"flexible array member %0 in a union is a GNU extension">, InGroup<GNUFlexibleArrayUnionMember>;
+def err_flexible_array_not_at_end : Error<
+ "flexible array member %0 with type %1 is not at the end of"
+ " %select{struct|interface|union|class|enum}2">;
+def err_objc_variable_sized_type_not_at_end : Error<
+ "field %0 with variable sized type %1 is not at the end of class">;
+def note_next_field_declaration : Note<
+ "next field declaration is here">;
+def note_next_ivar_declaration : Note<
+ "next %select{instance variable declaration|synthesized instance variable}0"
+ " is here">;
+def err_synthesize_variable_sized_ivar : Error<
+ "synthesized property with variable size type %0"
+ " requires an existing instance variable">;
+def err_flexible_array_arc_retainable : Error<
+ "ARC forbids flexible array members with retainable object type">;
+def warn_variable_sized_ivar_visibility : Warning<
+ "field %0 with variable sized type %1 is not visible to subclasses and"
+ " can conflict with their instance variables">, InGroup<ObjCFlexibleArray>;
+def warn_superclass_variable_sized_type_not_at_end : Warning<
+ "field %0 can overwrite instance variable %1 with variable sized type %2"
+ " in superclass %3">, InGroup<ObjCFlexibleArray>;
+
let CategoryName = "ARC Semantic Issue" in {
// ARC-mode diagnostics.
@@ -5462,9 +5521,6 @@ def err_offsetof_incomplete_type : Error<
def err_offsetof_record_type : Error<
"offsetof requires struct, union, or class type, %0 invalid">;
def err_offsetof_array_type : Error<"offsetof requires array type, %0 invalid">;
-def ext_offsetof_extended_field_designator : Extension<
- "using extended field designator is an extension">,
- InGroup<DiagGroup<"extended-offsetof">>;
def ext_offsetof_non_pod_type : ExtWarn<"offset of on non-POD type %0">,
InGroup<InvalidOffsetof>;
def ext_offsetof_non_standardlayout_type : ExtWarn<
@@ -5475,6 +5531,12 @@ def err_offsetof_field_of_virtual_base : Error<
def warn_sub_ptr_zero_size_types : Warning<
"subtraction of pointers to type %0 of zero size has undefined behavior">,
InGroup<PointerArith>;
+def warn_pointer_arith_null_ptr : Warning<
+ "performing pointer arithmetic on a null pointer has undefined behavior%select{| if the offset is nonzero}0">,
+ InGroup<NullPointerArithmetic>, DefaultIgnore;
+def warn_gnu_null_ptr_arith : Warning<
+ "arithmetic on a null pointer treated as a cast from integer to pointer is a GNU extension">,
+ InGroup<NullPointerArithmetic>, DefaultIgnore;
def warn_floatingpoint_eq : Warning<
"comparing floating point with == or != is unsafe">,
@@ -5862,6 +5924,8 @@ def err_typecheck_assign_const : Error<
"cannot assign to %select{non-|}1static data member %2 "
"with const-qualified type %3|"
"cannot assign to non-static data member within const member function %1|"
+ "cannot assign to %select{variable %2|non-static data member %2|lvalue}1 "
+ "with %select{|nested }3const-qualified data member %4|"
"read-only variable is not assignable}0">;
def note_typecheck_assign_const : Note<
@@ -5869,25 +5933,39 @@ def note_typecheck_assign_const : Note<
"function %1 which returns const-qualified type %2 declared here|"
"variable %1 declared const here|"
"%select{non-|}1static data member %2 declared const here|"
- "member function %q1 is declared const here}0">;
+ "member function %q1 is declared const here|"
+ "%select{|nested }1data member %2 declared const here}0">;
+
+def warn_unsigned_always_true_comparison : Warning<
+ "result of comparison of %select{%3|unsigned expression}0 %2 "
+ "%select{unsigned expression|%3}0 is always %4">,
+ InGroup<TautologicalUnsignedZeroCompare>;
+def warn_unsigned_enum_always_true_comparison : Warning<
+ "result of comparison of %select{%3|unsigned enum expression}0 %2 "
+ "%select{unsigned enum expression|%3}0 is always %4">,
+ InGroup<TautologicalUnsignedEnumZeroCompare>;
+def warn_tautological_constant_compare : Warning<
+ "result of comparison %select{%3|%1}0 %2 "
+ "%select{%1|%3}0 is always %4">,
+ InGroup<TautologicalConstantCompare>;
def warn_mixed_sign_comparison : Warning<
"comparison of integers of different signs: %0 and %1">,
InGroup<SignCompare>, DefaultIgnore;
-def warn_lunsigned_always_true_comparison : Warning<
- "comparison of unsigned%select{| enum}2 expression %0 is always %1">,
- InGroup<TautologicalCompare>;
def warn_out_of_range_compare : Warning<
- "comparison of %select{constant %0|true|false}1 with "
- "%select{expression of type %2|boolean expression}3 is always "
- "%select{false|true}4">, InGroup<TautologicalOutOfRangeCompare>;
-def warn_runsigned_always_true_comparison : Warning<
- "comparison of %0 unsigned%select{| enum}2 expression is always %1">,
- InGroup<TautologicalCompare>;
+ "result of comparison of %select{constant %0|true|false}1 with "
+ "%select{expression of type %2|boolean expression}3 is always %4">,
+ InGroup<TautologicalOutOfRangeCompare>;
+def warn_tautological_bool_compare : Warning<warn_out_of_range_compare.Text>,
+ InGroup<TautologicalConstantCompare>;
def warn_comparison_of_mixed_enum_types : Warning<
"comparison of two values with different enumeration types"
"%diff{ ($ and $)|}0,1">,
- InGroup<DiagGroup<"enum-compare">>;
+ InGroup<EnumCompare>;
+def warn_comparison_of_mixed_enum_types_switch : Warning<
+ "comparison of two values with different enumeration types in switch statement"
+ "%diff{ ($ and $)|}0,1">,
+ InGroup<EnumCompareSwitch>;
def warn_null_in_arithmetic_operation : Warning<
"use of NULL in arithmetic operation">,
InGroup<NullArithmetic>;
@@ -6391,12 +6469,12 @@ def warn_non_virtual_dtor : Warning<
def warn_delete_non_virtual_dtor : Warning<
"%select{delete|destructor}0 called on non-final %1 that has "
"virtual functions but non-virtual destructor">,
- InGroup<DeleteNonVirtualDtor>, DefaultIgnore;
+ InGroup<DeleteNonVirtualDtor>, DefaultIgnore, ShowInSystemHeader;
def note_delete_non_virtual : Note<
"qualify call to silence this warning">;
def warn_delete_abstract_non_virtual_dtor : Warning<
"%select{delete|destructor}0 called on %1 that is abstract but has "
- "non-virtual destructor">, InGroup<DeleteNonVirtualDtor>;
+ "non-virtual destructor">, InGroup<DeleteNonVirtualDtor>, ShowInSystemHeader;
def warn_overloaded_virtual : Warning<
"%q0 hides overloaded virtual %select{function|functions}1">,
InGroup<OverloadedVirtual>, DefaultIgnore;
@@ -6420,8 +6498,8 @@ def warn_overaligned_type : Warning<
"guarantees %2 bytes">,
InGroup<OveralignedType>, DefaultIgnore;
def warn_aligned_allocation_unavailable :Warning<
- "aligned %select{allocation|deallocation}0 function of type '%1' possibly "
- "unavailable on %2">, InGroup<AlignedAllocationUnavailable>, DefaultError;
+ "aligned %select{allocation|deallocation}0 function of type '%1' is only "
+ "available on %2 %3 or newer">, InGroup<AlignedAllocationUnavailable>, DefaultError;
def note_silence_unligned_allocation_unavailable : Note<
"if you supply your own aligned allocation functions, use "
"-Wno-aligned-allocation-unavailable to silence this diagnostic">;
@@ -6458,8 +6536,6 @@ let CategoryName = "Lambda Issue" in {
"%0 can appear only once in a capture list">;
def err_reference_capture_with_reference_default : Error<
"'&' cannot precede a capture when the capture default is '&'">;
- def err_this_capture_with_copy_default : Error<
- "'this' cannot be explicitly captured when the capture default is '='">;
def err_copy_capture_with_copy_default : Error<
"'&' must precede a capture when the capture default is '='">;
def err_capture_does_not_name_variable : Error<
@@ -6526,12 +6602,20 @@ let CategoryName = "Lambda Issue" in {
def err_init_capture_deduction_failure_from_init_list : Error<
"cannot deduce type for lambda capture %0 from initializer list">;
- // C++1z '*this' captures.
+ // C++17 '*this' captures.
def warn_cxx14_compat_star_this_lambda_capture : Warning<
"by value capture of '*this' is incompatible with C++ standards before C++17">,
- InGroup<CXXPre1zCompat>, DefaultIgnore;
- def ext_star_this_lambda_capture_cxx1z : ExtWarn<
+ InGroup<CXXPre17Compat>, DefaultIgnore;
+ def ext_star_this_lambda_capture_cxx17 : ExtWarn<
"capture of '*this' by copy is a C++17 extension">, InGroup<CXX17>;
+
+ // C++2a [=, this] captures.
+ def warn_cxx17_compat_equals_this_lambda_capture : Warning<
+ "explicit capture of 'this' with a capture default of '=' is incompatible "
+ "with C++ standards before C++2a">, InGroup<CXXPre2aCompat>, DefaultIgnore;
+ def ext_equals_this_lambda_capture_cxx2a : ExtWarn<
+ "explicit capture of 'this' with a capture default of '=' "
+ "is a C++2a extension">, InGroup<CXX2a>;
}
def err_return_in_captured_stmt : Error<
@@ -6981,8 +7065,8 @@ def err_atomic_op_needs_atomic : Error<
"address argument to atomic operation must be a pointer to _Atomic "
"type (%0 invalid)">;
def err_atomic_op_needs_non_const_atomic : Error<
- "address argument to atomic operation must be a pointer to non-const _Atomic "
- "type (%0 invalid)">;
+ "address argument to atomic operation must be a pointer to non-%select{const|constant}0 _Atomic "
+ "type (%1 invalid)">;
def err_atomic_op_needs_non_const_pointer : Error<
"address argument to atomic operation must be a pointer to non-const "
"type (%0 invalid)">;
@@ -6998,6 +7082,8 @@ def err_atomic_op_bitwise_needs_atomic_int : Error<
def warn_atomic_op_has_invalid_memory_order : Warning<
"memory order argument to atomic operation is invalid">,
InGroup<DiagGroup<"atomic-memory-ordering">>;
+def err_atomic_op_has_invalid_synch_scope : Error<
+ "synchronization scope argument to atomic operation is invalid">;
def err_overflow_builtin_must_be_int : Error<
"operand argument to overflow builtin must be an integer (%0 invalid)">;
@@ -7199,11 +7285,11 @@ def warn_unused_volatile : Warning<
def ext_cxx14_attr : Extension<
"use of the %0 attribute is a C++14 extension">, InGroup<CXX14>;
-def ext_cxx1z_attr : Extension<
+def ext_cxx17_attr : Extension<
"use of the %0 attribute is a C++17 extension">, InGroup<CXX17>;
def warn_unused_comparison : Warning<
- "%select{%select{|in}1equality|relational}0 comparison result unused">,
+ "%select{equality|inequality|relational|three-way}0 comparison result unused">,
InGroup<UnusedComparison>;
def note_inequality_comparison_to_or_assign : Note<
"use '|=' to turn this inequality comparison into an or-assignment">;
@@ -7315,8 +7401,8 @@ def err_invalid_conversion_between_vector_and_integer : Error<
def err_opencl_function_pointer : Error<
"pointers to functions are not allowed">;
-def err_opencl_taking_function_address : Error<
- "taking address of function is not allowed">;
+def err_opencl_taking_address_capture : Error<
+ "taking address of a capture is not allowed">;
def err_invalid_conversion_between_vector_and_scalar : Error<
"invalid conversion between vector type %0 and scalar type %1">;
@@ -7457,6 +7543,9 @@ def err_ambiguous_derived_to_base_conv : Error<
def err_ambiguous_memptr_conv : Error<
"ambiguous conversion from pointer to member of %select{base|derived}0 "
"class %1 to pointer to member of %select{derived|base}0 class %2:%3">;
+def ext_ms_ambiguous_direct_base : ExtWarn<
+ "accessing inaccessible direct base %0 of %1 is a Microsoft extension">,
+ InGroup<MicrosoftInaccessibleBase>;
def err_memptr_conv_via_virtual : Error<
"conversion from pointer to member of class %0 to pointer to member "
@@ -7526,6 +7615,11 @@ def err_operator_delete_dependent_param_type : Error<
"%0 cannot take a dependent type as first parameter; use %1 instead">;
def err_operator_delete_param_type : Error<
"first parameter of %0 must have type %1">;
+def err_destroying_operator_delete_not_usual : Error<
+ "destroying operator delete can have only an optional size and optional "
+ "alignment parameter">;
+def note_implicit_delete_this_in_destructor_here : Note<
+ "while checking implicit 'delete this' for virtual destructor">;
// C++ literal operators
def err_literal_operator_outside_namespace : Error<
@@ -7831,6 +7925,8 @@ def err_type_tag_for_datatype_too_large : Error<
"'type_tag_for_datatype' attribute requires the initializer to be "
"an %select{integer|integral}0 constant expression "
"that can be represented by a 64 bit integer">;
+def err_tag_index_out_of_range : Error<
+ "%select{type tag|argument}0 index %1 is greater than the number of arguments specified">;
def warn_type_tag_for_datatype_wrong_kind : Warning<
"this type tag was not designed to be used with this function">,
InGroup<TypeSafety>;
@@ -7868,6 +7964,8 @@ def err_builtin_annotation_first_arg : Error<
"first argument to __builtin_annotation must be an integer">;
def err_builtin_annotation_second_arg : Error<
"second argument to __builtin_annotation must be a non-wide string constant">;
+def err_msvc_annotation_wide_str : Error<
+ "arguments to __annotation must be wide string constants">;
// CFString checking
def err_cfstring_literal_not_string_constant : Error<
@@ -8195,12 +8293,12 @@ def err_c99_array_usage_cxx : Error<
"feature, not permitted in C++">;
def err_type_unsupported : Error<
"%0 is not supported on this target">;
-def err_nsconsumed_attribute_mismatch : Error<
+def warn_nsconsumed_attribute_mismatch : Warning<
"overriding method has mismatched ns_consumed attribute on its"
- " parameter">;
-def err_nsreturns_retained_attribute_mismatch : Error<
+ " parameter">, InGroup<NSConsumedMismatch>;
+def warn_nsreturns_retained_attribute_mismatch : Warning<
"overriding method has mismatched ns_returns_%select{not_retained|retained}0"
- " attributes">;
+ " attributes">, InGroup<NSReturnsMismatch>;
def note_getter_unavailable : Note<
"or because setter is declared here, but no getter method %0 is found">;
@@ -8364,8 +8462,6 @@ def err_opencl_scalar_type_rank_greater_than_vector_type : Error<
"element. (%0 and %1)">;
def err_bad_kernel_param_type : Error<
"%0 cannot be used as the type of a kernel parameter">;
-def err_opencl_implicit_function_decl : Error<
- "implicit declaration of function %0 is invalid in OpenCL">;
def err_record_with_pointers_kernel_param : Error<
"%select{struct|union}0 kernel parameters may not contain pointers">;
def note_within_field_of_type : Note<
@@ -8518,6 +8614,8 @@ def err_omp_expected_var_name_member_expr : Error<
"expected variable name%select{| or data member of current class}0">;
def err_omp_expected_var_name_member_expr_or_array_item : Error<
"expected variable name%select{|, data member of current class}0, array element or array section">;
+def err_omp_expected_addressable_lvalue_or_array_item : Error<
+ "expected addressable lvalue expression, array element or array section">;
def err_omp_expected_named_var_member_or_array_expression: Error<
"expected expression containing only member accesses and/or array sections based on named variables">;
def err_omp_bit_fields_forbidden_in_clause : Error<
@@ -8525,7 +8623,7 @@ def err_omp_bit_fields_forbidden_in_clause : Error<
def err_array_section_does_not_specify_contiguous_storage : Error<
"array section does not specify contiguous storage">;
def err_omp_union_type_not_allowed : Error<
- "mapped storage cannot be derived from a union">;
+ "mapping of union members is not allowed">;
def err_omp_expected_access_to_data_field : Error<
"expected access to data field">;
def err_omp_multiple_array_items_in_map_clause : Error<
@@ -8612,6 +8710,8 @@ def err_omp_declare_target_to_and_link : Error<
def warn_omp_not_in_target_context : Warning<
"declaration is not declared in any declare target region">,
InGroup<OpenMPTarget>;
+def err_omp_function_in_link_clause : Error<
+ "function name is not allowed in 'link' clause">;
def err_omp_aligned_expected_array_or_ptr : Error<
"argument of aligned clause should be array"
"%select{ or pointer|, pointer, reference to array or reference to pointer}1"
@@ -8670,6 +8770,12 @@ def err_omp_reduction_in_task : Error<
"reduction variables may not be accessed in an explicit task">;
def err_omp_reduction_id_not_compatible : Error<
"list item of type %0 is not valid for specified reduction operation: unable to provide default initialization value">;
+def err_omp_in_reduction_not_task_reduction : Error<
+ "in_reduction variable must appear in a task_reduction clause">;
+def err_omp_reduction_identifier_mismatch : Error<
+ "in_reduction variable must have the same reduction operation as in a task_reduction clause">;
+def note_omp_previous_reduction_identifier : Note<
+ "previously marked as task_reduction with different reduction operation">;
def err_omp_prohibited_region : Error<
"region cannot be%select{| closely}0 nested inside '%1' region"
"%select{|; perhaps you forget to enclose 'omp %3' directive into a parallel region?|"
@@ -8746,9 +8852,9 @@ def err_omp_function_expected : Error<
def err_omp_wrong_cancel_region : Error<
"one of 'for', 'parallel', 'sections' or 'taskgroup' is expected">;
def err_omp_parent_cancel_region_nowait : Error<
- "parent region for 'omp %select{cancellation point/cancel}0' construct cannot be nowait">;
+ "parent region for 'omp %select{cancellation point|cancel}0' construct cannot be nowait">;
def err_omp_parent_cancel_region_ordered : Error<
- "parent region for 'omp %select{cancellation point/cancel}0' construct cannot be ordered">;
+ "parent region for 'omp %select{cancellation point|cancel}0' construct cannot be ordered">;
def err_omp_reduction_wrong_type : Error<"reduction type cannot be %select{qualified with 'const', 'volatile' or 'restrict'|a function|a reference|an array}0 type">;
def err_omp_wrong_var_in_declare_reduction : Error<"only %select{'omp_priv' or 'omp_orig'|'omp_in' or 'omp_out'}0 variables are allowed in %select{initializer|combiner}0 expression">;
def err_omp_declare_reduction_redefinition : Error<"redefinition of user-defined reduction for type %0">;
@@ -8793,16 +8899,10 @@ def err_omp_expected_base_var_name : Error<
"expected variable name as a base of the array %select{subscript|section}0">;
def err_omp_map_shared_storage : Error<
"variable already marked as mapped in current construct">;
-def err_omp_not_mappable_type : Error<
- "type %0 is not mappable to target">;
def err_omp_invalid_map_type_for_directive : Error<
"%select{map type '%1' is not allowed|map type must be specified}0 for '#pragma omp %2'">;
def err_omp_no_clause_for_directive : Error<
"expected at least one %0 clause for '#pragma omp %1'">;
-def note_omp_polymorphic_in_target : Note<
- "mappable type cannot be polymorphic">;
-def note_omp_static_member_in_target : Note<
- "mappable type cannot contain static members">;
def err_omp_threadprivate_in_clause : Error<
"threadprivate variables are not allowed in '%0' clause">;
def err_omp_wrong_ordered_loop_count : Error<
@@ -8821,12 +8921,6 @@ def note_omp_critical_hint_here : Note<
"%select{|previous }0'hint' clause with value '%1'">;
def note_omp_critical_no_hint : Note<
"%select{|previous }0directive with no 'hint' clause specified">;
-def err_omp_firstprivate_distribute_private_teams : Error<
- "private variable in '#pragma omp teams' cannot be firstprivate in '#pragma omp distribute'">;
-def err_omp_firstprivate_and_lastprivate_in_distribute : Error<
- "lastprivate variable cannot be firstprivate in '#pragma omp distribute'">;
-def err_omp_firstprivate_distribute_in_teams_reduction : Error<
- "reduction variable in '#pragma omp teams' cannot be firstprivate in '#pragma omp distribute'">;
def err_omp_depend_clause_thread_simd : Error<
"'depend' clauses cannot be mixed with '%0' clause">;
def err_omp_depend_sink_expected_loop_iteration : Error<
@@ -8871,6 +8965,10 @@ def err_omp_reduction_non_addressable_expression : Error<
"expected addressable reduction item for the task-based directives">;
def err_omp_reduction_with_nogroup : Error<
"'reduction' clause cannot be used with 'nogroup' clause">;
+def err_omp_reduction_vla_unsupported : Error<
+ "cannot generate code for reduction on %select{|array section, which requires a }0variable length array">;
+def err_omp_linear_distribute_var_non_loop_iteration : Error<
+ "only loop iteration variables are allowed in 'linear' clause in distribute directives">;
} // end of OpenMP category
let CategoryName = "Related Result Type Issue" in {
@@ -8912,6 +9010,14 @@ def err_module_redefinition : Error<
"redefinition of module '%0'">;
def note_prev_module_definition : Note<"previously defined here">;
def note_prev_module_definition_from_ast_file : Note<"module loaded from '%0'">;
+def err_module_not_defined : Error<
+ "definition of module '%0' is not available; use -fmodule-file= to specify "
+ "path to precompiled module interface">;
+def err_module_redeclaration : Error<
+ "translation unit contains multiple module declarations">;
+def note_prev_module_declaration : Note<"previous module declaration is here">;
+def err_module_declaration_missing : Error<
+ "missing 'export module' declaration in module interface unit">;
def err_module_private_specialization : Error<
"%select{template|partial|member}0 specialization cannot be "
"declared __module_private__">;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSerializationKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSerializationKinds.td
index 420ccebbfaf03..3949bc2146f6b 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSerializationKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSerializationKinds.td
@@ -77,6 +77,8 @@ def err_imported_module_not_found : Error<
"module '%0' in AST file '%1' (imported by AST file '%2') "
"is not defined in any loaded module map file; "
"maybe you need to load '%3'?">, DefaultFatal;
+def note_imported_by_pch_module_not_found : Note<
+ "consider adding '%0' to the header search path">;
def err_imported_module_modmap_changed : Error<
"module '%0' imported by AST file '%1' found in a different module map file"
" (%2) than when the importing AST file was built (%3)">, DefaultFatal;
@@ -122,6 +124,45 @@ def note_second_module_difference : Note<
def err_module_odr_violation_different_instantiations : Error<
"instantiation of %q0 is different in different modules">;
+def err_module_odr_violation_definition_data : Error <
+ "%q0 has different definitions in different modules; first difference is "
+ "%select{definition in module '%2'|defined here}1 found "
+ "%select{"
+ "%4 base %plural{1:class|:classes}4|"
+ "%4 virtual base %plural{1:class|:classes}4|"
+ "%ordinal4 base class with type %5|"
+ "%ordinal4 %select{non-virtual|virtual}5 base class %6|"
+ "%ordinal4 base class %5 with "
+ "%select{public|protected|private|no}6 access specifier}3">;
+
+def note_module_odr_violation_definition_data : Note <
+ "but in '%0' found "
+ "%select{"
+ "%2 base %plural{1:class|:classes}2|"
+ "%2 virtual base %plural{1:class|:classes}2|"
+ "%ordinal2 base class with different type %3|"
+ "%ordinal2 %select{non-virtual|virtual}3 base class %4|"
+ "%ordinal2 base class %3 with "
+ "%select{public|protected|private|no}4 access specifier}1">;
+
+def err_module_odr_violation_template_parameter : Error <
+ "%q0 has different definitions in different modules; first difference is "
+ "%select{definition in module '%2'|defined here}1 found "
+ "%select{"
+ "unnamed template parameter|"
+ "template parameter %4|"
+ "template parameter with %select{no |}4default argument|"
+ "template parameter with default argument}3">;
+
+
+def note_module_odr_violation_template_parameter : Note <
+ "but in '%0' found "
+ "%select{"
+ "unnamed template parameter %2|"
+ "template parameter %2|"
+ "template parameter with %select{no |}2default argument|"
+ "template parameter with different default argument}1">;
+
def err_module_odr_violation_mismatch_decl : Error<
"%q0 has different definitions in different modules; first difference is "
"%select{definition in module '%2'|defined here}1 found "
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h b/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h
index f94b2c9b2f420..8e3c15afbfcd4 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h
@@ -1,4 +1,4 @@
-//===--- IdentifierTable.h - Hash table for identifier lookup ---*- C++ -*-===//
+//===- IdentifierTable.h - Hash table for identifier lookup -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,11 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
/// \brief Defines the clang::IdentifierInfo, clang::IdentifierTable, and
/// clang::Selector interfaces.
-///
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_IDENTIFIERTABLE_H
@@ -18,35 +18,29 @@
#include "clang/Basic/LLVM.h"
#include "clang/Basic/TokenKinds.h"
+#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
+#include "llvm/Support/type_traits.h"
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <cstring>
-#include <new>
#include <string>
#include <utility>
-namespace llvm {
-
- template <typename T> struct DenseMapInfo;
-
-} // end namespace llvm
-
namespace clang {
- class LangOptions;
- class IdentifierInfo;
- class IdentifierTable;
- class SourceLocation;
- class MultiKeywordSelector; // private class used by Selector
- class DeclarationName; // AST class that stores declaration names
+class IdentifierInfo;
+class LangOptions;
+class MultiKeywordSelector;
+class SourceLocation;
- /// \brief A simple pair of identifier info and location.
- typedef std::pair<IdentifierInfo*, SourceLocation> IdentifierLocPair;
+/// \brief A simple pair of identifier info and location.
+using IdentifierLocPair = std::pair<IdentifierInfo *, SourceLocation>;
/// One of these records is kept for each identifier that
/// is lexed. This contains information about whether the token was \#define'd,
@@ -85,8 +79,10 @@ class IdentifierInfo {
// keyword.
// 29 bit left in 64-bit word.
- void *FETokenInfo; // Managed by the language front-end.
- llvm::StringMapEntry<IdentifierInfo*> *Entry;
+ // Managed by the language front-end.
+ void *FETokenInfo = nullptr;
+
+ llvm::StringMapEntry<IdentifierInfo *> *Entry = nullptr;
public:
IdentifierInfo();
@@ -104,7 +100,6 @@ public:
/// \brief Return the beginning of the actual null-terminated string for this
/// identifier.
- ///
const char *getNameStart() const {
if (Entry) return Entry->getKeyData();
// FIXME: This is gross. It would be best not to embed specific details
@@ -112,12 +107,12 @@ public:
// The 'this' pointer really points to a
// std::pair<IdentifierInfo, const char*>, where internal pointer
// points to the external string data.
- typedef std::pair<IdentifierInfo, const char*> actualtype;
+ using actualtype = std::pair<IdentifierInfo, const char *>;
+
return ((const actualtype*) this)->second;
}
/// \brief Efficiently return the length of this identifier info.
- ///
unsigned getLength() const {
if (Entry) return Entry->getKeyLength();
// FIXME: This is gross. It would be best not to embed specific details
@@ -125,7 +120,8 @@ public:
// The 'this' pointer really points to a
// std::pair<IdentifierInfo, const char*>, where internal pointer
// points to the external string data.
- typedef std::pair<IdentifierInfo, const char*> actualtype;
+ using actualtype = std::pair<IdentifierInfo, const char *>;
+
const char* p = ((const actualtype*) this)->second - 2;
return (((unsigned) p[0]) | (((unsigned) p[1]) << 8)) - 1;
}
@@ -465,7 +461,7 @@ public:
class IdentifierTable {
// Shark shows that using MallocAllocator is *much* slower than using this
// BumpPtrAllocator!
- typedef llvm::StringMap<IdentifierInfo*, llvm::BumpPtrAllocator> HashTableTy;
+ using HashTableTy = llvm::StringMap<IdentifierInfo *, llvm::BumpPtrAllocator>;
HashTableTy HashTable;
IdentifierInfoLookup* ExternalLookup;
@@ -551,8 +547,8 @@ public:
return *II;
}
- typedef HashTableTy::const_iterator iterator;
- typedef HashTableTy::const_iterator const_iterator;
+ using iterator = HashTableTy::const_iterator;
+ using const_iterator = HashTableTy::const_iterator;
iterator begin() const { return HashTable.begin(); }
iterator end() const { return HashTable.end(); }
@@ -654,7 +650,9 @@ class Selector {
MultiArg = 0x3,
ArgFlags = ZeroArg|OneArg
};
- uintptr_t InfoPtr; // a pointer to the MultiKeywordSelector or IdentifierInfo.
+
+ // a pointer to the MultiKeywordSelector or IdentifierInfo.
+ uintptr_t InfoPtr = 0;
Selector(IdentifierInfo *II, unsigned nArgs) {
InfoPtr = reinterpret_cast<uintptr_t>(II);
@@ -662,6 +660,7 @@ class Selector {
assert(nArgs < 2 && "nArgs not equal to 0/1");
InfoPtr |= nArgs+1;
}
+
Selector(MultiKeywordSelector *SI) {
InfoPtr = reinterpret_cast<uintptr_t>(SI);
assert((InfoPtr & ArgFlags) == 0 &&"Insufficiently aligned IdentifierInfo");
@@ -692,7 +691,7 @@ public:
/// The default ctor should only be used when creating data structures that
/// will contain selectors.
- Selector() : InfoPtr(0) {}
+ Selector() = default;
Selector(uintptr_t V) : InfoPtr(V) {}
/// operator==/!= - Indicate whether the specified selectors are identical.
@@ -776,7 +775,8 @@ public:
/// \brief This table allows us to fully hide how we implement
/// multi-keyword caching.
class SelectorTable {
- void *Impl; // Actually a SelectorTableImpl
+ // Actually a SelectorTableImpl
+ void *Impl;
public:
SelectorTable();
@@ -793,6 +793,7 @@ public:
Selector getUnarySelector(IdentifierInfo *ID) {
return Selector(ID, 1);
}
+
Selector getNullarySelector(IdentifierInfo *ID) {
return Selector(ID, 0);
}
@@ -848,7 +849,7 @@ public:
unsigned ExtraKindOrNumArgs;
};
-} // end namespace clang
+} // namespace clang
namespace llvm {
@@ -856,11 +857,11 @@ namespace llvm {
/// DenseSets.
template <>
struct DenseMapInfo<clang::Selector> {
- static inline clang::Selector getEmptyKey() {
+ static clang::Selector getEmptyKey() {
return clang::Selector::getEmptyMarker();
}
- static inline clang::Selector getTombstoneKey() {
+ static clang::Selector getTombstoneKey() {
return clang::Selector::getTombstoneMarker();
}
@@ -874,16 +875,13 @@ struct DenseMapInfo<clang::Selector> {
template <>
struct isPodLike<clang::Selector> { static const bool value = true; };
-template <typename T> class PointerLikeTypeTraits;
-
template<>
-class PointerLikeTypeTraits<clang::Selector> {
-public:
- static inline const void *getAsVoidPointer(clang::Selector P) {
+struct PointerLikeTypeTraits<clang::Selector> {
+ static const void *getAsVoidPointer(clang::Selector P) {
return P.getAsOpaquePtr();
}
- static inline clang::Selector getFromVoidPointer(const void *P) {
+ static clang::Selector getFromVoidPointer(const void *P) {
return clang::Selector(reinterpret_cast<uintptr_t>(P));
}
@@ -893,13 +891,12 @@ public:
// Provide PointerLikeTypeTraits for IdentifierInfo pointers, which
// are not guaranteed to be 8-byte aligned.
template<>
-class PointerLikeTypeTraits<clang::IdentifierInfo*> {
-public:
- static inline void *getAsVoidPointer(clang::IdentifierInfo* P) {
+struct PointerLikeTypeTraits<clang::IdentifierInfo*> {
+ static void *getAsVoidPointer(clang::IdentifierInfo* P) {
return P;
}
- static inline clang::IdentifierInfo *getFromVoidPointer(void *P) {
+ static clang::IdentifierInfo *getFromVoidPointer(void *P) {
return static_cast<clang::IdentifierInfo*>(P);
}
@@ -907,19 +904,18 @@ public:
};
template<>
-class PointerLikeTypeTraits<const clang::IdentifierInfo*> {
-public:
- static inline const void *getAsVoidPointer(const clang::IdentifierInfo* P) {
+struct PointerLikeTypeTraits<const clang::IdentifierInfo*> {
+ static const void *getAsVoidPointer(const clang::IdentifierInfo* P) {
return P;
}
- static inline const clang::IdentifierInfo *getFromVoidPointer(const void *P) {
+ static const clang::IdentifierInfo *getFromVoidPointer(const void *P) {
return static_cast<const clang::IdentifierInfo*>(P);
}
enum { NumLowBitsAvailable = 1 };
};
-} // end namespace llvm
+} // namespace llvm
#endif // LLVM_CLANG_BASIC_IDENTIFIERTABLE_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/LLVM.h b/contrib/llvm/tools/clang/include/clang/Basic/LLVM.h
index f32ab5e11bd4a..e60284d1b4459 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/LLVM.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/LLVM.h
@@ -35,6 +35,7 @@ namespace llvm {
template<typename T, unsigned N> class SmallVector;
template<typename T> class SmallVectorImpl;
template<typename T> class Optional;
+ template <class T> class Expected;
template<typename T>
struct SaveAndRestore;
@@ -71,6 +72,9 @@ namespace clang {
using llvm::SmallVectorImpl;
using llvm::SaveAndRestore;
+ // Error handling.
+ using llvm::Expected;
+
// Reference counting.
using llvm::IntrusiveRefCntPtr;
using llvm::IntrusiveRefCntPtrInfo;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.def b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.def
index c9230e0aaa6f3..ca3a0e349d62f 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.def
@@ -82,6 +82,7 @@
// FIXME: A lot of the BENIGN_ options should be COMPATIBLE_ instead.
LANGOPT(C99 , 1, 0, "C99")
LANGOPT(C11 , 1, 0, "C11")
+LANGOPT(C17 , 1, 0, "C17")
LANGOPT(MSVCCompat , 1, 0, "Microsoft Visual C++ full compatibility mode")
LANGOPT(MicrosoftExt , 1, 0, "Microsoft C++ extensions")
LANGOPT(AsmBlocks , 1, 0, "Microsoft inline asm blocks")
@@ -89,7 +90,7 @@ LANGOPT(Borland , 1, 0, "Borland extensions")
LANGOPT(CPlusPlus , 1, 0, "C++")
LANGOPT(CPlusPlus11 , 1, 0, "C++11")
LANGOPT(CPlusPlus14 , 1, 0, "C++14")
-LANGOPT(CPlusPlus1z , 1, 0, "C++1z")
+LANGOPT(CPlusPlus17 , 1, 0, "C++17")
LANGOPT(CPlusPlus2a , 1, 0, "C++2a")
LANGOPT(ObjC1 , 1, 0, "Objective-C 1")
LANGOPT(ObjC2 , 1, 0, "Objective-C 2")
@@ -124,7 +125,9 @@ LANGOPT(ZVector , 1, 0, "System z vector extensions")
LANGOPT(Exceptions , 1, 0, "exception handling")
LANGOPT(ObjCExceptions , 1, 0, "Objective-C exceptions")
LANGOPT(CXXExceptions , 1, 0, "C++ exceptions")
+LANGOPT(DWARFExceptions , 1, 0, "dwarf exception handling")
LANGOPT(SjLjExceptions , 1, 0, "setjmp-longjump exception handling")
+LANGOPT(SEHExceptions , 1, 0, "SEH .xdata exception handling")
LANGOPT(ExternCNoUnwind , 1, 0, "Assume extern C functions don't unwind")
LANGOPT(TraditionalCPP , 1, 0, "traditional CPP emulation")
LANGOPT(RTTI , 1, 1, "run-time type information")
@@ -137,6 +140,8 @@ LANGOPT(GNUAsm , 1, 1, "GNU-style inline assembly")
LANGOPT(CoroutinesTS , 1, 0, "C++ coroutines TS")
LANGOPT(RelaxedTemplateTemplateArgs, 1, 0, "C++17 relaxed matching of template template arguments")
+LANGOPT(DoubleSquareBracketAttributes, 1, 0, "'[[]]' attributes extension for all language standard modes")
+
BENIGN_LANGOPT(ThreadsafeStatics , 1, 1, "thread-safe static initializers")
LANGOPT(POSIXThreads , 1, 0, "POSIX thread support")
LANGOPT(Blocks , 1, 0, "blocks extension to C")
@@ -175,7 +180,8 @@ BENIGN_LANGOPT(ObjCGCBitmapPrint , 1, 0, "printing of GC's bitmap layout for __w
BENIGN_LANGOPT(AccessControl , 1, 1, "C++ access control")
LANGOPT(CharIsSigned , 1, 1, "signed char")
-LANGOPT(ShortWChar , 1, 0, "unsigned short wchar_t")
+LANGOPT(WCharSize , 4, 0, "width of wchar_t")
+LANGOPT(WCharIsSigned , 1, 0, "signed or unsigned wchar_t")
ENUM_LANGOPT(MSPointerToMemberRepresentationMethod, PragmaMSPointersToMembersKind, 2, PPTMK_BestCase, "member-pointer representation method")
ENUM_LANGOPT(DefaultCallingConv, DefaultCallingConvention, 3, DCC_None, "default calling convention")
@@ -267,6 +273,9 @@ LANGOPT(SanitizeAddressFieldPadding, 2, 0, "controls how aggressive is ASan "
"aggressive, 2: more aggressive)")
LANGOPT(XRayInstrument, 1, 0, "controls whether to do XRay instrumentation")
+LANGOPT(XRayAlwaysEmitCustomEvents, 1, 0,
+ "controls whether to always emit intrinsic calls to "
+ "__xray_customevent(...) builtin.")
BENIGN_LANGOPT(AllowEditorPlaceholders, 1, 0,
"allow editor placeholders in source")
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h
index 8488515d2b677..f7a43adefad0c 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h
@@ -77,7 +77,8 @@ public:
DCC_CDecl,
DCC_FastCall,
DCC_StdCall,
- DCC_VectorCall
+ DCC_VectorCall,
+ DCC_RegCall
};
enum AddrSpaceMapMangling { ASMM_Target, ASMM_On, ASMM_Off };
@@ -197,6 +198,10 @@ public:
bool allowsNonTrivialObjCLifetimeQualifiers() const {
return ObjCAutoRefCount || ObjCWeak;
}
+
+ bool assumeFunctionsAreConvergent() const {
+ return (CUDA && CUDAIsDevice) || OpenCL;
+ }
};
/// \brief Floating point control options
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Module.h b/contrib/llvm/tools/clang/include/clang/Basic/Module.h
index 177175eae9650..6631721e35314 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Module.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Module.h
@@ -1,4 +1,4 @@
-//===--- Module.h - Describe a module ---------------------------*- C++ -*-===//
+//===- Module.h - Describe a module -----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,12 +6,13 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
/// \brief Defines the clang::Module class, which describes a module in the
/// source code.
-///
+//
//===----------------------------------------------------------------------===//
+
#ifndef LLVM_CLANG_BASIC_MODULE_H
#define LLVM_CLANG_BASIC_MODULE_H
@@ -19,6 +20,7 @@
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SetVector.h"
@@ -26,22 +28,28 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include <array>
+#include <cassert>
+#include <cstdint>
+#include <ctime>
#include <string>
#include <utility>
#include <vector>
namespace llvm {
- class raw_ostream;
-}
+
+class raw_ostream;
+
+} // namespace llvm
namespace clang {
class LangOptions;
class TargetInfo;
-class IdentifierInfo;
-
+
/// \brief Describes the name of a module.
-typedef SmallVector<std::pair<std::string, SourceLocation>, 2> ModuleId;
+using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>;
/// The signature of a module, which is a hash of the AST content.
struct ASTFileSignature : std::array<uint32_t, 5> {
@@ -68,7 +76,11 @@ public:
ModuleMapModule,
/// \brief This is a C++ Modules TS module interface unit.
- ModuleInterfaceUnit
+ ModuleInterfaceUnit,
+
+ /// \brief This is a fragment of the global module within some C++ Modules
+ /// TS module.
+ GlobalModuleFragment,
};
/// \brief The kind of this module.
@@ -81,7 +93,7 @@ public:
/// \brief The build directory of this module. This is the directory in
/// which the module is notionally built, and relative to which its headers
/// are found.
- const DirectoryEntry *Directory;
+ const DirectoryEntry *Directory = nullptr;
/// \brief The presumed file name for the module map defining this module.
/// Only non-empty when building from preprocessed source.
@@ -95,6 +107,10 @@ public:
/// \brief The name of the umbrella entry, as written in the module map.
std::string UmbrellaAsWritten;
+
+ /// \brief The module through which entities defined in this module will
+ /// eventually be exposed, for use in "private" modules.
+ std::string ExportAsModule;
private:
/// \brief The submodules of this module, indexed by name.
@@ -106,7 +122,7 @@ private:
/// \brief The AST file if this is a top-level module which has a
/// corresponding serialized AST file, or null otherwise.
- const FileEntry *ASTFile;
+ const FileEntry *ASTFile = nullptr;
/// \brief The top-level headers associated with this module.
llvm::SmallSetVector<const FileEntry *, 2> TopHeaders;
@@ -173,7 +189,7 @@ public:
/// \brief An individual requirement: a feature name and a flag indicating
/// the required state of that feature.
- typedef std::pair<std::string, bool> Requirement;
+ using Requirement = std::pair<std::string, bool>;
/// \brief The set of language features required to use this module.
///
@@ -262,7 +278,7 @@ public:
///
/// The pointer is the module being re-exported, while the bit will be true
/// to indicate that this is a wildcard export.
- typedef llvm::PointerIntPair<Module *, 1, bool> ExportDecl;
+ using ExportDecl = llvm::PointerIntPair<Module *, 1, bool>;
/// \brief The set of export declarations.
SmallVector<ExportDecl, 2> Exports;
@@ -294,9 +310,9 @@ public:
/// \brief A library or framework to link against when an entity from this
/// module is used.
struct LinkLibrary {
- LinkLibrary() : IsFramework(false) { }
+ LinkLibrary() = default;
LinkLibrary(const std::string &Library, bool IsFramework)
- : Library(Library), IsFramework(IsFramework) { }
+ : Library(Library), IsFramework(IsFramework) {}
/// \brief The library to link against.
///
@@ -305,7 +321,7 @@ public:
std::string Library;
/// \brief Whether this is a framework rather than a library.
- bool IsFramework;
+ bool IsFramework = false;
};
/// \brief The set of libraries or frameworks to link against when
@@ -391,6 +407,15 @@ public:
return IsFramework && Parent && Parent->isPartOfFramework();
}
+ /// Set the parent of this module. This should only be used if the parent
+ /// could not be set during module creation.
+ void setParent(Module *M) {
+ assert(!Parent);
+ Parent = M;
+ Parent->SubModuleIndex[Name] = Parent->SubModules.size();
+ Parent->SubModules.push_back(this);
+ }
+
/// \brief Retrieve the full name of this module, including the path from
/// its top-level module.
/// \param AllowStringLiterals If \c true, components that might not be
@@ -415,7 +440,6 @@ public:
const Module *getTopLevelModule() const;
/// \brief Retrieve the name of the top-level module.
- ///
StringRef getTopLevelModuleName() const {
return getTopLevelModule()->Name;
}
@@ -508,8 +532,8 @@ public:
unsigned getVisibilityID() const { return VisibilityID; }
- typedef std::vector<Module *>::iterator submodule_iterator;
- typedef std::vector<Module *>::const_iterator submodule_const_iterator;
+ using submodule_iterator = std::vector<Module *>::iterator;
+ using submodule_const_iterator = std::vector<Module *>::const_iterator;
submodule_iterator submodule_begin() { return SubModules.begin(); }
submodule_const_iterator submodule_begin() const {return SubModules.begin();}
@@ -534,7 +558,6 @@ public:
}
/// \brief Print the module map for this module to the given stream.
- ///
void print(raw_ostream &OS, unsigned Indent = 0) const;
/// \brief Dump the contents of this module to the given output stream.
@@ -547,7 +570,7 @@ private:
/// \brief A set of visible modules.
class VisibleModuleSet {
public:
- VisibleModuleSet() : Generation(0) {}
+ VisibleModuleSet() = default;
VisibleModuleSet(VisibleModuleSet &&O)
: ImportLocs(std::move(O.ImportLocs)), Generation(O.Generation ? 1 : 0) {
O.ImportLocs.clear();
@@ -582,13 +605,15 @@ public:
/// \brief A callback to call when a module is made visible (directly or
/// indirectly) by a call to \ref setVisible.
- typedef llvm::function_ref<void(Module *M)> VisibleCallback;
+ using VisibleCallback = llvm::function_ref<void(Module *M)>;
+
/// \brief A callback to call when a module conflict is found. \p Path
/// consists of a sequence of modules from the conflicting module to the one
/// made visible, where each was exported by the next.
- typedef llvm::function_ref<void(ArrayRef<Module *> Path,
- Module *Conflict, StringRef Message)>
- ConflictCallback;
+ using ConflictCallback =
+ llvm::function_ref<void(ArrayRef<Module *> Path, Module *Conflict,
+ StringRef Message)>;
+
/// \brief Make a specific module visible.
void setVisible(Module *M, SourceLocation Loc,
VisibleCallback Vis = [](Module *) {},
@@ -599,11 +624,11 @@ private:
/// Import locations for each visible module. Indexed by the module's
/// VisibilityID.
std::vector<SourceLocation> ImportLocs;
+
/// Visibility generation, bumped every time the visibility state changes.
- unsigned Generation;
+ unsigned Generation = 0;
};
-} // end namespace clang
-
+} // namespace clang
#endif // LLVM_CLANG_BASIC_MODULE_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/OpenCLExtensions.def b/contrib/llvm/tools/clang/include/clang/Basic/OpenCLExtensions.def
index 360fec4281ac1..c3319d2d808b9 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/OpenCLExtensions.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/OpenCLExtensions.def
@@ -79,6 +79,10 @@ OPENCLEXT_INTERNAL(cl_clang_storage_class_specifiers, 100, ~0U)
OPENCLEXT_INTERNAL(cl_amd_media_ops, 100, ~0U)
OPENCLEXT_INTERNAL(cl_amd_media_ops2, 100, ~0U)
+// Intel OpenCL extensions
+OPENCLEXT_INTERNAL(cl_intel_subgroups, 120, ~0U)
+OPENCLEXT_INTERNAL(cl_intel_subgroups_short, 120, ~0U)
+
#undef OPENCLEXT_INTERNAL
#ifdef OPENCLEXT
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.def b/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.def
index 645ed52b59cab..6a0bed7ab15fc 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.def
@@ -274,6 +274,7 @@ OPENMP_CLAUSE(from, OMPFromClause)
OPENMP_CLAUSE(use_device_ptr, OMPUseDevicePtrClause)
OPENMP_CLAUSE(is_device_ptr, OMPIsDevicePtrClause)
OPENMP_CLAUSE(task_reduction, OMPTaskReductionClause)
+OPENMP_CLAUSE(in_reduction, OMPInReductionClause)
// Clauses allowed for OpenMP directive 'parallel'.
OPENMP_PARALLEL_CLAUSE(if)
@@ -434,6 +435,7 @@ OPENMP_TASK_CLAUSE(untied)
OPENMP_TASK_CLAUSE(mergeable)
OPENMP_TASK_CLAUSE(depend)
OPENMP_TASK_CLAUSE(priority)
+OPENMP_TASK_CLAUSE(in_reduction)
// Clauses allowed for OpenMP directive 'atomic'.
OPENMP_ATOMIC_CLAUSE(read)
@@ -452,6 +454,7 @@ OPENMP_TARGET_CLAUSE(depend)
OPENMP_TARGET_CLAUSE(defaultmap)
OPENMP_TARGET_CLAUSE(firstprivate)
OPENMP_TARGET_CLAUSE(is_device_ptr)
+OPENMP_TARGET_CLAUSE(reduction)
// Clauses allowed for OpenMP directive 'target data'.
OPENMP_TARGET_DATA_CLAUSE(if)
@@ -557,6 +560,7 @@ OPENMP_TASKLOOP_CLAUSE(grainsize)
OPENMP_TASKLOOP_CLAUSE(nogroup)
OPENMP_TASKLOOP_CLAUSE(num_tasks)
OPENMP_TASKLOOP_CLAUSE(reduction)
+OPENMP_TASKLOOP_CLAUSE(in_reduction)
// Clauses allowed for OpenMP directive 'taskloop simd'.
OPENMP_TASKLOOP_SIMD_CLAUSE(if)
@@ -578,6 +582,7 @@ OPENMP_TASKLOOP_SIMD_CLAUSE(grainsize)
OPENMP_TASKLOOP_SIMD_CLAUSE(nogroup)
OPENMP_TASKLOOP_SIMD_CLAUSE(num_tasks)
OPENMP_TASKLOOP_SIMD_CLAUSE(reduction)
+OPENMP_TASKLOOP_SIMD_CLAUSE(in_reduction)
// Clauses allowed for OpenMP directive 'critical'.
OPENMP_CRITICAL_CLAUSE(hint)
@@ -741,9 +746,9 @@ OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(private)
OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(shared)
OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(reduction)
OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(schedule)
-OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(linear)
OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(num_teams)
OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(thread_limit)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(copyin)
// Clauses allowed for OpenMP directive 'target teams'.
OPENMP_TARGET_TEAMS_CLAUSE(if)
@@ -801,7 +806,6 @@ OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(dist_schedule)
OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(num_threads)
OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(proc_bind)
OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(schedule)
-OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(linear)
// Clauses allowed for OpenMP directive
// 'target teams distribute parallel for simd'.
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.def b/contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.def
index 34ad7644cd2ba..d86294bac9020 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.def
@@ -89,6 +89,7 @@ OVERLOADED_OPERATOR(EqualEqual , "==" , equalequal , false, t
OVERLOADED_OPERATOR(ExclaimEqual , "!=" , exclaimequal , false, true , false)
OVERLOADED_OPERATOR(LessEqual , "<=" , lessequal , false, true , false)
OVERLOADED_OPERATOR(GreaterEqual , ">=" , greaterequal , false, true , false)
+OVERLOADED_OPERATOR(Spaceship , "<=>" , spaceship , false, true , false)
OVERLOADED_OPERATOR(AmpAmp , "&&" , ampamp , false, true , false)
OVERLOADED_OPERATOR(PipePipe , "||" , pipepipe , false, true , false)
OVERLOADED_OPERATOR(PlusPlus , "++" , plusplus , true , true , false)
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/OperatorPrecedence.h b/contrib/llvm/tools/clang/include/clang/Basic/OperatorPrecedence.h
index 640749fdd10d5..94978f81e543a 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/OperatorPrecedence.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/OperatorPrecedence.h
@@ -36,10 +36,11 @@ namespace prec {
And = 8, // &
Equality = 9, // ==, !=
Relational = 10, // >=, <=, >, <
- Shift = 11, // <<, >>
- Additive = 12, // -, +
- Multiplicative = 13, // *, /, %
- PointerToMember = 14 // .*, ->*
+ Spaceship = 11, // <=>
+ Shift = 12, // <<, >>
+ Additive = 13, // -, +
+ Multiplicative = 14, // *, /, %
+ PointerToMember = 15 // .*, ->*
};
}
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/SanitizerBlacklist.h b/contrib/llvm/tools/clang/include/clang/Basic/SanitizerBlacklist.h
index e651e18316833..1ae5c36eea99a 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/SanitizerBlacklist.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/SanitizerBlacklist.h
@@ -15,29 +15,30 @@
#define LLVM_CLANG_BASIC_SANITIZERBLACKLIST_H
#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SanitizerSpecialCaseList.h"
+#include "clang/Basic/Sanitizers.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/SpecialCaseList.h"
#include <memory>
namespace clang {
class SanitizerBlacklist {
- std::unique_ptr<llvm::SpecialCaseList> SCL;
+ std::unique_ptr<SanitizerSpecialCaseList> SSCL;
SourceManager &SM;
public:
SanitizerBlacklist(const std::vector<std::string> &BlacklistPaths,
SourceManager &SM);
- bool isBlacklistedGlobal(StringRef GlobalName,
+ bool isBlacklistedGlobal(SanitizerMask Mask, StringRef GlobalName,
StringRef Category = StringRef()) const;
- bool isBlacklistedType(StringRef MangledTypeName,
+ bool isBlacklistedType(SanitizerMask Mask, StringRef MangledTypeName,
StringRef Category = StringRef()) const;
- bool isBlacklistedFunction(StringRef FunctionName) const;
- bool isBlacklistedFile(StringRef FileName,
+ bool isBlacklistedFunction(SanitizerMask Mask, StringRef FunctionName) const;
+ bool isBlacklistedFile(SanitizerMask Mask, StringRef FileName,
StringRef Category = StringRef()) const;
- bool isBlacklistedLocation(SourceLocation Loc,
+ bool isBlacklistedLocation(SanitizerMask Mask, SourceLocation Loc,
StringRef Category = StringRef()) const;
};
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/SanitizerSpecialCaseList.h b/contrib/llvm/tools/clang/include/clang/Basic/SanitizerSpecialCaseList.h
new file mode 100644
index 0000000000000..e3252022a44f1
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/SanitizerSpecialCaseList.h
@@ -0,0 +1,54 @@
+//===--- SanitizerSpecialCaseList.h - SCL for sanitizers --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// An extension of SpecialCaseList to allowing querying sections by
+// SanitizerMask.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_BASIC_SANITIZERSPECIALCASELIST_H
+#define LLVM_CLANG_BASIC_SANITIZERSPECIALCASELIST_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/Sanitizers.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/SpecialCaseList.h"
+#include <memory>
+
+namespace clang {
+
+class SanitizerSpecialCaseList : public llvm::SpecialCaseList {
+public:
+ static std::unique_ptr<SanitizerSpecialCaseList>
+ create(const std::vector<std::string> &Paths, std::string &Error);
+
+ static std::unique_ptr<SanitizerSpecialCaseList>
+ createOrDie(const std::vector<std::string> &Paths);
+
+ // Query blacklisted entries if any bit in Mask matches the entry's section.
+ bool inSection(SanitizerMask Mask, StringRef Prefix, StringRef Query,
+ StringRef Category = StringRef()) const;
+
+protected:
+ // Initialize SanitizerSections.
+ void createSanitizerSections();
+
+ struct SanitizerSection {
+ SanitizerSection(SanitizerMask SM, SectionEntries &E)
+ : Mask(SM), Entries(E){};
+
+ SanitizerMask Mask;
+ SectionEntries &Entries;
+ };
+
+ std::vector<SanitizerSection> SanitizerSections;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.def b/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.def
index 71b11974dbfde..30d5cc8166dc6 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.def
@@ -44,12 +44,17 @@ SANITIZER("address", Address)
// Kernel AddressSanitizer (KASan)
SANITIZER("kernel-address", KernelAddress)
+SANITIZER("hwaddress", HWAddress)
+
// MemorySanitizer
SANITIZER("memory", Memory)
// libFuzzer
SANITIZER("fuzzer", Fuzzer)
+// libFuzzer-required instrumentation, no linking.
+SANITIZER("fuzzer-no-link", FuzzerNoLink)
+
// ThreadSanitizer
SANITIZER("thread", Thread)
@@ -60,6 +65,7 @@ SANITIZER("leak", Leak)
SANITIZER("alignment", Alignment)
SANITIZER("array-bounds", ArrayBounds)
SANITIZER("bool", Bool)
+SANITIZER("builtin", Builtin)
SANITIZER("enum", Enum)
SANITIZER("float-cast-overflow", FloatCastOverflow)
SANITIZER("float-divide-by-zero", FloatDivideByZero)
@@ -107,11 +113,12 @@ SANITIZER("safe-stack", SafeStack)
// -fsanitize=undefined includes all the sanitizers which have low overhead, no
// ABI or address space layout implications, and only catch undefined behavior.
SANITIZER_GROUP("undefined", Undefined,
- Alignment | Bool | ArrayBounds | Enum | FloatCastOverflow |
- FloatDivideByZero | IntegerDivideByZero | NonnullAttribute |
- Null | ObjectSize | PointerOverflow | Return |
- ReturnsNonnullAttribute | Shift | SignedIntegerOverflow |
- Unreachable | VLABound | Function | Vptr)
+ Alignment | Bool | Builtin | ArrayBounds | Enum |
+ FloatCastOverflow | FloatDivideByZero |
+ IntegerDivideByZero | NonnullAttribute | Null | ObjectSize |
+ PointerOverflow | Return | ReturnsNonnullAttribute | Shift |
+ SignedIntegerOverflow | Unreachable | VLABound | Function |
+ Vptr)
// -fsanitize=undefined-trap is an alias for -fsanitize=undefined.
SANITIZER_GROUP("undefined-trap", UndefinedTrap, Undefined)
@@ -130,6 +137,9 @@ SANITIZER("efficiency-working-set", EfficiencyWorkingSet)
SANITIZER_GROUP("efficiency-all", Efficiency,
EfficiencyCacheFrag | EfficiencyWorkingSet)
+// Scudo hardened allocator
+SANITIZER("scudo", Scudo)
+
// Magic group, containing all sanitizers. For example, "-fno-sanitize=all"
// can be used to disable all the sanitizers.
SANITIZER_GROUP("all", All, ~0ULL)
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.h b/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.h
index 5317720095e06..1b936c7d115cf 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.h
@@ -80,7 +80,7 @@ SanitizerMask parseSanitizerValue(StringRef Value, bool AllowGroups);
SanitizerMask expandSanitizerGroups(SanitizerMask Kinds);
/// Return the sanitizers which do not affect preprocessing.
-static inline SanitizerMask getPPTransparentSanitizers() {
+inline SanitizerMask getPPTransparentSanitizers() {
return SanitizerKind::CFI | SanitizerKind::Integer |
SanitizerKind::Nullability | SanitizerKind::Undefined;
}
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h b/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h
index 12aa0e4f57170..7418b50f9d83b 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h
@@ -39,10 +39,9 @@ class SourceManager;
class FileID {
/// \brief A mostly-opaque identifier, where 0 is "invalid", >0 is
/// this module, and <-1 is something loaded from another module.
- int ID;
-public:
- FileID() : ID(0) {}
+ int ID = 0;
+public:
bool isValid() const { return ID != 0; }
bool isInvalid() const { return ID == 0; }
@@ -86,17 +85,15 @@ private:
///
/// It is important that this type remains small. It is currently 32 bits wide.
class SourceLocation {
- unsigned ID;
+ unsigned ID = 0;
friend class SourceManager;
friend class ASTReader;
friend class ASTWriter;
enum : unsigned {
MacroIDBit = 1U << 31
};
-public:
-
- SourceLocation() : ID(0) {}
+public:
bool isFileID() const { return (ID & MacroIDBit) == 0; }
bool isMacroID() const { return (ID & MacroIDBit) != 0; }
@@ -172,6 +169,11 @@ public:
return getFromRawEncoding((unsigned)(uintptr_t)Encoding);
}
+ static bool isPairOfFileLocations(SourceLocation Start, SourceLocation End) {
+ return Start.isValid() && Start.isFileID() && End.isValid() &&
+ End.isFileID();
+ }
+
void print(raw_ostream &OS, const SourceManager &SM) const;
std::string printToString(const SourceManager &SM) const;
void dump(const SourceManager &SM) const;
@@ -193,8 +195,9 @@ inline bool operator<(const SourceLocation &LHS, const SourceLocation &RHS) {
class SourceRange {
SourceLocation B;
SourceLocation E;
+
public:
- SourceRange(): B(SourceLocation()), E(SourceLocation()) {}
+ SourceRange() = default;
SourceRange(SourceLocation loc) : B(loc), E(loc) {}
SourceRange(SourceLocation begin, SourceLocation end) : B(begin), E(end) {}
@@ -225,9 +228,10 @@ public:
/// range.
class CharSourceRange {
SourceRange Range;
- bool IsTokenRange;
+ bool IsTokenRange = false;
+
public:
- CharSourceRange() : IsTokenRange(false) {}
+ CharSourceRange() = default;
CharSourceRange(SourceRange R, bool ITR) : Range(R), IsTokenRange(ITR) {}
static CharSourceRange getTokenRange(SourceRange R) {
@@ -325,10 +329,11 @@ class FileEntry;
///
/// This is useful for argument passing to functions that expect both objects.
class FullSourceLoc : public SourceLocation {
- const SourceManager *SrcMgr;
+ const SourceManager *SrcMgr = nullptr;
+
public:
/// \brief Creates a FullSourceLoc where isValid() returns \c false.
- explicit FullSourceLoc() : SrcMgr(nullptr) {}
+ FullSourceLoc() = default;
explicit FullSourceLoc(SourceLocation Loc, const SourceManager &SM)
: SourceLocation(Loc), SrcMgr(&SM) {}
@@ -455,8 +460,7 @@ namespace llvm {
// Teach SmallPtrSet how to handle SourceLocation.
template<>
- class PointerLikeTypeTraits<clang::SourceLocation> {
- public:
+ struct PointerLikeTypeTraits<clang::SourceLocation> {
static inline void *getAsVoidPointer(clang::SourceLocation L) {
return L.getPtrEncoding();
}
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h b/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h
index ed3f8dfa86e74..397ad2e77fb5e 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h
@@ -1,4 +1,4 @@
-//===--- SourceManager.h - Track and cache source files ---------*- C++ -*-===//
+//===- SourceManager.h - Track and cache source files -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,7 +6,7 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
/// \brief Defines the SourceManager interface.
///
@@ -29,14 +29,13 @@
/// location in the source where the macro was originally defined,
/// and the presumed location is where the line directive states that
/// the line is 17, or any other line.
-///
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_SOURCEMANAGER_H
#define LLVM_CLANG_BASIC_SOURCEMANAGER_H
#include "clang/Basic/FileManager.h"
-#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
@@ -49,10 +48,8 @@
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MemoryBuffer.h"
-#include <algorithm>
#include <cassert>
#include <cstddef>
-#include <cstdint>
#include <map>
#include <memory>
#include <string>
@@ -69,7 +66,6 @@ class SourceManager;
/// \brief Public enums and private classes that are part of the
/// SourceManager implementation.
-///
namespace SrcMgr {
/// \brief Indicates whether a file or directory holds normal user code,
@@ -100,6 +96,7 @@ namespace SrcMgr {
enum CCFlags {
/// \brief Whether the buffer is invalid.
InvalidFlag = 0x01,
+
/// \brief Whether the buffer should not be freed on destruction.
DoNotFreeFlag = 0x02
};
@@ -130,12 +127,12 @@ namespace SrcMgr {
///
/// This is lazily computed. This is owned by the SourceManager
/// BumpPointerAllocator object.
- unsigned *SourceLineCache;
+ unsigned *SourceLineCache = nullptr;
/// \brief The number of lines in this ContentCache.
///
/// This is only valid if SourceLineCache is non-null.
- unsigned NumLines;
+ unsigned NumLines = 0;
/// \brief Indicates whether the buffer itself was provided to override
/// the actual file contents.
@@ -157,15 +154,14 @@ namespace SrcMgr {
ContentCache(const FileEntry *Ent, const FileEntry *contentEnt)
: Buffer(nullptr, false), OrigEntry(Ent), ContentsEntry(contentEnt),
- SourceLineCache(nullptr), NumLines(0), BufferOverridden(false),
- IsSystemFile(false), IsTransient(false) {}
+ BufferOverridden(false), IsSystemFile(false), IsTransient(false) {}
/// The copy ctor does not allow copies where source object has either
/// a non-NULL Buffer or SourceLineCache. Ownership of allocated memory
/// is not transferred, so this is a logical error.
ContentCache(const ContentCache &RHS)
- : Buffer(nullptr, false), SourceLineCache(nullptr),
- BufferOverridden(false), IsSystemFile(false), IsTransient(false) {
+ : Buffer(nullptr, false), BufferOverridden(false), IsSystemFile(false),
+ IsTransient(false) {
OrigEntry = RHS.OrigEntry;
ContentsEntry = RHS.ContentsEntry;
@@ -212,12 +208,6 @@ namespace SrcMgr {
/// this content cache. This is used for performance analysis.
llvm::MemoryBuffer::BufferKind getMemoryBufferKind() const;
- void setBuffer(std::unique_ptr<llvm::MemoryBuffer> B) {
- assert(!Buffer.getPointer() && "MemoryBuffer already set.");
- Buffer.setPointer(B.release());
- Buffer.setInt(0);
- }
-
/// \brief Get the underlying buffer, returning NULL if the buffer is not
/// yet available.
llvm::MemoryBuffer *getRawBuffer() const { return Buffer.getPointer(); }
@@ -252,6 +242,10 @@ namespace SrcMgr {
/// FileInfos contain a "ContentCache *", with the contents of the file.
///
class FileInfo {
+ friend class clang::SourceManager;
+ friend class clang::ASTWriter;
+ friend class clang::ASTReader;
+
/// \brief The location of the \#include that brought in this file.
///
/// This is an invalid SLOC for the main file (top of the \#include chain).
@@ -270,10 +264,6 @@ namespace SrcMgr {
llvm::PointerIntPair<const ContentCache*, 3, CharacteristicKind>
ContentAndKind;
- friend class clang::SourceManager;
- friend class clang::ASTWriter;
- friend class clang::ASTReader;
-
public:
/// \brief Return a FileInfo object.
static FileInfo get(SourceLocation IL, const ContentCache *Con,
@@ -454,7 +444,7 @@ namespace SrcMgr {
}
};
-} // end SrcMgr namespace.
+} // namespace SrcMgr
/// \brief External source of source location entries.
class ExternalSLocEntrySource {
@@ -552,7 +542,7 @@ public:
/// \brief The stack used when building modules on demand, which is used
/// to provide a link between the source managers of the different compiler
/// instances.
-typedef ArrayRef<std::pair<std::string, FullSourceLoc>> ModuleBuildStack;
+using ModuleBuildStack = ArrayRef<std::pair<std::string, FullSourceLoc>>;
/// \brief This class handles loading and caching of source files into memory.
///
@@ -584,7 +574,7 @@ class SourceManager : public RefCountedBase<SourceManager> {
/// \brief True if the ContentCache for files that are overridden by other
/// files, should report the original file name. Defaults to true.
- bool OverridenFilesKeepOriginalName;
+ bool OverridenFilesKeepOriginalName = true;
/// \brief True if non-system source files should be treated as volatile
/// (likely to change while trying to use them). Defaults to false.
@@ -593,12 +583,13 @@ class SourceManager : public RefCountedBase<SourceManager> {
/// \brief True if all files read during this compilation should be treated
/// as transient (may not be present in later compilations using a module
/// file created from this compilation). Defaults to false.
- bool FilesAreTransient;
+ bool FilesAreTransient = false;
struct OverriddenFilesInfoTy {
/// \brief Files that have been overridden with the contents from another
/// file.
llvm::DenseMap<const FileEntry *, const FileEntry *> OverriddenFiles;
+
/// \brief Files that were overridden with a memory buffer.
llvm::DenseSet<const FileEntry *> OverriddenFilesWithBuffer;
};
@@ -653,7 +644,7 @@ class SourceManager : public RefCountedBase<SourceManager> {
llvm::BitVector SLocEntryLoaded;
/// \brief An external source for source location entries.
- ExternalSLocEntrySource *ExternalSLocEntries;
+ ExternalSLocEntrySource *ExternalSLocEntries = nullptr;
/// \brief A one-entry cache to speed up getFileID.
///
@@ -664,7 +655,7 @@ class SourceManager : public RefCountedBase<SourceManager> {
/// \brief Holds information for \#line directives.
///
/// This is referenced by indices from SLocEntryTable.
- LineTableInfo *LineTable;
+ LineTableInfo *LineTable = nullptr;
/// \brief These ivars serve as a cache used in the getLineNumber
/// method which is used to speedup getLineNumber calls to nearby locations.
@@ -680,7 +671,8 @@ class SourceManager : public RefCountedBase<SourceManager> {
FileID PreambleFileID;
// Statistics for -print-stats.
- mutable unsigned NumLinearScans, NumBinaryProbes;
+ mutable unsigned NumLinearScans = 0;
+ mutable unsigned NumBinaryProbes = 0;
/// \brief Associates a FileID with its "included/expanded in" decomposed
/// location.
@@ -690,12 +682,12 @@ class SourceManager : public RefCountedBase<SourceManager> {
mutable llvm::DenseMap<FileID, std::pair<FileID, unsigned>> IncludedLocMap;
/// The key value into the IsBeforeInTUCache table.
- typedef std::pair<FileID, FileID> IsBeforeInTUCacheKey;
+ using IsBeforeInTUCacheKey = std::pair<FileID, FileID>;
/// The IsBeforeInTranslationUnitCache is a mapping from FileID pairs
/// to cache results.
- typedef llvm::DenseMap<IsBeforeInTUCacheKey, InBeforeInTUCacheEntry>
- InBeforeInTUCache;
+ using InBeforeInTUCache =
+ llvm::DenseMap<IsBeforeInTUCacheKey, InBeforeInTUCacheEntry>;
/// Cache results for the isBeforeInTranslationUnit method.
mutable InBeforeInTUCache IBTUCache;
@@ -712,7 +704,7 @@ class SourceManager : public RefCountedBase<SourceManager> {
/// \brief Lazily computed map of macro argument chunks to their expanded
/// source location.
- typedef std::map<unsigned, SourceLocation> MacroArgsMap;
+ using MacroArgsMap = std::map<unsigned, SourceLocation>;
mutable llvm::DenseMap<FileID, std::unique_ptr<MacroArgsMap>>
MacroArgsCacheMap;
@@ -816,7 +808,22 @@ public:
SrcMgr::CharacteristicKind FileCharacter = SrcMgr::C_User,
int LoadedID = 0, unsigned LoadedOffset = 0,
SourceLocation IncludeLoc = SourceLocation()) {
- return createFileID(createMemBufferContentCache(std::move(Buffer)),
+ return createFileID(
+ createMemBufferContentCache(Buffer.release(), /*DoNotFree*/ false),
+ IncludeLoc, FileCharacter, LoadedID, LoadedOffset);
+ }
+
+ enum UnownedTag { Unowned };
+
+ /// \brief Create a new FileID that represents the specified memory buffer.
+ ///
+ /// This does no caching of the buffer and takes ownership of the
+ /// MemoryBuffer, so only pass a MemoryBuffer to this once.
+ FileID createFileID(UnownedTag, llvm::MemoryBuffer *Buffer,
+ SrcMgr::CharacteristicKind FileCharacter = SrcMgr::C_User,
+ int LoadedID = 0, unsigned LoadedOffset = 0,
+ SourceLocation IncludeLoc = SourceLocation()) {
+ return createFileID(createMemBufferContentCache(Buffer, /*DoNotFree*/true),
IncludeLoc, FileCharacter, LoadedID, LoadedOffset);
}
@@ -1408,7 +1415,6 @@ public:
//===--------------------------------------------------------------------===//
/// \brief Return the uniqued ID for the specified filename.
- ///
unsigned getLineTableFilenameID(StringRef Str);
/// \brief Add a line note to the line table for the FileID and offset
@@ -1520,9 +1526,18 @@ public:
return LHSLoaded;
}
+ /// Return true if the Point is within Start and End.
+ bool isPointWithin(SourceLocation Location, SourceLocation Start,
+ SourceLocation End) const {
+ return Location == Start || Location == End ||
+ (isBeforeInTranslationUnit(Start, Location) &&
+ isBeforeInTranslationUnit(Location, End));
+ }
+
// Iterators over FileInfos.
- typedef llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*>
- ::const_iterator fileinfo_iterator;
+ using fileinfo_iterator =
+ llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*>::const_iterator;
+
fileinfo_iterator fileinfo_begin() const { return FileInfos.begin(); }
fileinfo_iterator fileinfo_end() const { return FileInfos.end(); }
bool hasFileInfo(const FileEntry *File) const {
@@ -1530,7 +1545,6 @@ public:
}
/// \brief Print statistics to stderr.
- ///
void PrintStats() const;
void dump() const;
@@ -1621,6 +1635,9 @@ public:
}
private:
+ friend class ASTReader;
+ friend class ASTWriter;
+
llvm::MemoryBuffer *getFakeBufferForRecovery() const;
const SrcMgr::ContentCache *getFakeContentCacheForRecovery() const;
@@ -1691,7 +1708,7 @@ private:
/// \brief Create a new ContentCache for the specified memory buffer.
const SrcMgr::ContentCache *
- createMemBufferContentCache(std::unique_ptr<llvm::MemoryBuffer> Buf);
+ createMemBufferContentCache(llvm::MemoryBuffer *Buf, bool DoNotFree);
FileID getFileIDSlow(unsigned SLocOffset) const;
FileID getFileIDLocal(unsigned SLocOffset) const;
@@ -1712,8 +1729,6 @@ private:
SourceLocation SpellLoc,
SourceLocation ExpansionLoc,
unsigned ExpansionLength) const;
- friend class ASTReader;
- friend class ASTWriter;
};
/// \brief Comparison function object.
@@ -1726,7 +1741,7 @@ class BeforeThanCompare<SourceLocation> {
SourceManager &SM;
public:
- explicit BeforeThanCompare(SourceManager &SM) : SM(SM) { }
+ explicit BeforeThanCompare(SourceManager &SM) : SM(SM) {}
bool operator()(SourceLocation LHS, SourceLocation RHS) const {
return SM.isBeforeInTranslationUnit(LHS, RHS);
@@ -1739,13 +1754,13 @@ class BeforeThanCompare<SourceRange> {
SourceManager &SM;
public:
- explicit BeforeThanCompare(SourceManager &SM) : SM(SM) { }
+ explicit BeforeThanCompare(SourceManager &SM) : SM(SM) {}
bool operator()(SourceRange LHS, SourceRange RHS) const {
return SM.isBeforeInTranslationUnit(LHS.getBegin(), RHS.getBegin());
}
};
-} // end namespace clang
+} // namespace clang
#endif // LLVM_CLANG_BASIC_SOURCEMANAGER_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/SourceManagerInternals.h b/contrib/llvm/tools/clang/include/clang/Basic/SourceManagerInternals.h
index 9403dea8889c2..edd910e704128 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/SourceManagerInternals.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/SourceManagerInternals.h
@@ -1,4 +1,4 @@
-//===--- SourceManagerInternals.h - SourceManager Internals -----*- C++ -*-===//
+//===- SourceManagerInternals.h - SourceManager Internals -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,10 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
/// \brief Defines implementation details of the clang::SourceManager class.
-///
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_SOURCEMANAGERINTERNALS_H
@@ -18,7 +18,11 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
+#include <cassert>
#include <map>
+#include <vector>
namespace clang {
@@ -86,7 +90,8 @@ class LineTableInfo {
/// \brief Map from FileIDs to a list of line entries (sorted by the offset
/// at which they occur in the file).
- std::map<FileID, std::vector<LineEntry> > LineEntries;
+ std::map<FileID, std::vector<LineEntry>> LineEntries;
+
public:
void clear() {
FilenameIDs.clear();
@@ -95,10 +100,12 @@ public:
}
unsigned getLineTableFilenameID(StringRef Str);
+
StringRef getFilename(unsigned ID) const {
assert(ID < FilenamesByID.size() && "Invalid FilenameID");
return FilenamesByID[ID]->getKey();
}
+
unsigned getNumFilenames() const { return FilenamesByID.size(); }
void AddLineNote(FileID FID, unsigned Offset,
@@ -112,7 +119,8 @@ public:
const LineEntry *FindNearestLineEntry(FileID FID, unsigned Offset);
// Low-level access
- typedef std::map<FileID, std::vector<LineEntry> >::iterator iterator;
+ using iterator = std::map<FileID, std::vector<LineEntry>>::iterator;
+
iterator begin() { return LineEntries.begin(); }
iterator end() { return LineEntries.end(); }
@@ -121,6 +129,6 @@ public:
void AddEntry(FileID FID, const std::vector<LineEntry> &Entries);
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_BASIC_SOURCEMANAGERINTERNALS_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h b/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h
index 50fb936e01d1f..377534baab06b 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h
@@ -52,6 +52,7 @@ namespace clang {
TST_int,
TST_int128,
TST_half, // OpenCL half, ARM NEON __fp16
+ TST_Float16, // C11 extension ISO/IEC TS 18661-3
TST_float,
TST_double,
TST_float128,
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/SyncScope.h b/contrib/llvm/tools/clang/include/clang/Basic/SyncScope.h
new file mode 100644
index 0000000000000..09ac0052185af
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/SyncScope.h
@@ -0,0 +1,154 @@
+//===--- SyncScope.h - Atomic synchronization scopes ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Provides definitions for the atomic synchronization scopes.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_SYNCSCOPE_H
+#define LLVM_CLANG_BASIC_SYNCSCOPE_H
+
+#include "clang/Basic/LangOptions.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include <memory>
+
+namespace clang {
+
+/// \brief Defines synch scope values used internally by clang.
+///
+/// The enum values start from 0 and are contiguous. They are mainly used for
+/// enumerating all supported synch scope values and mapping them to LLVM
+/// synch scopes. Their numerical values may be different from the corresponding
+/// synch scope enums used in source languages.
+///
+/// In atomic builtin and expressions, language-specific synch scope enums are
+/// used. Currently only OpenCL memory scope enums are supported and assumed
+/// to be used by all languages. However, in the future, other languages may
+/// define their own set of synch scope enums. The language-specific synch scope
+/// values are represented by class AtomicScopeModel and its derived classes.
+///
+/// To add a new enum value:
+/// Add the enum value to enum class SyncScope.
+/// Update enum value Last if necessary.
+/// Update getAsString.
+///
+enum class SyncScope {
+ OpenCLWorkGroup,
+ OpenCLDevice,
+ OpenCLAllSVMDevices,
+ OpenCLSubGroup,
+ Last = OpenCLSubGroup
+};
+
+inline llvm::StringRef getAsString(SyncScope S) {
+ switch (S) {
+ case SyncScope::OpenCLWorkGroup:
+ return "opencl_workgroup";
+ case SyncScope::OpenCLDevice:
+ return "opencl_device";
+ case SyncScope::OpenCLAllSVMDevices:
+ return "opencl_allsvmdevices";
+ case SyncScope::OpenCLSubGroup:
+ return "opencl_subgroup";
+ }
+ llvm_unreachable("Invalid synch scope");
+}
+
+/// \brief Defines the kind of atomic scope models.
+enum class AtomicScopeModelKind { None, OpenCL };
+
+/// \brief Defines the interface for synch scope model.
+class AtomicScopeModel {
+public:
+ virtual ~AtomicScopeModel() {}
+ /// \brief Maps language specific synch scope values to internal
+ /// SyncScope enum.
+ virtual SyncScope map(unsigned S) const = 0;
+
+ /// \brief Check if the compile-time constant synch scope value
+ /// is valid.
+ virtual bool isValid(unsigned S) const = 0;
+
+ /// \brief Get all possible synch scope values that might be
+ /// encountered at runtime for the current language.
+ virtual ArrayRef<unsigned> getRuntimeValues() const = 0;
+
+ /// \brief If atomic builtin function is called with invalid
+ /// synch scope value at runtime, it will fall back to a valid
+ /// synch scope value returned by this function.
+ virtual unsigned getFallBackValue() const = 0;
+
+ /// \brief Create an atomic scope model by AtomicScopeModelKind.
+ /// \return an empty std::unique_ptr for AtomicScopeModelKind::None.
+ static std::unique_ptr<AtomicScopeModel> create(AtomicScopeModelKind K);
+};
+
+/// \brief Defines the synch scope model for OpenCL.
+class AtomicScopeOpenCLModel : public AtomicScopeModel {
+public:
+ /// The enum values match the pre-defined macros
+ /// __OPENCL_MEMORY_SCOPE_*, which are used to define memory_scope_*
+ /// enums in opencl-c.h.
+ enum ID {
+ WorkGroup = 1,
+ Device = 2,
+ AllSVMDevices = 3,
+ SubGroup = 4,
+ Last = SubGroup
+ };
+
+ AtomicScopeOpenCLModel() {}
+
+ SyncScope map(unsigned S) const override {
+ switch (static_cast<ID>(S)) {
+ case WorkGroup:
+ return SyncScope::OpenCLWorkGroup;
+ case Device:
+ return SyncScope::OpenCLDevice;
+ case AllSVMDevices:
+ return SyncScope::OpenCLAllSVMDevices;
+ case SubGroup:
+ return SyncScope::OpenCLSubGroup;
+ }
+ llvm_unreachable("Invalid language synch scope value");
+ }
+
+ bool isValid(unsigned S) const override {
+ return S >= static_cast<unsigned>(WorkGroup) &&
+ S <= static_cast<unsigned>(Last);
+ }
+
+ ArrayRef<unsigned> getRuntimeValues() const override {
+ static_assert(Last == SubGroup, "Does not include all synch scopes");
+ static const unsigned Scopes[] = {
+ static_cast<unsigned>(WorkGroup), static_cast<unsigned>(Device),
+ static_cast<unsigned>(AllSVMDevices), static_cast<unsigned>(SubGroup)};
+ return llvm::makeArrayRef(Scopes);
+ }
+
+ unsigned getFallBackValue() const override {
+ return static_cast<unsigned>(AllSVMDevices);
+ }
+};
+
+inline std::unique_ptr<AtomicScopeModel>
+AtomicScopeModel::create(AtomicScopeModelKind K) {
+ switch (K) {
+ case AtomicScopeModelKind::None:
+ return std::unique_ptr<AtomicScopeModel>{};
+ case AtomicScopeModelKind::OpenCL:
+ return llvm::make_unique<AtomicScopeOpenCLModel>();
+ }
+ llvm_unreachable("Invalid atomic scope model kind");
+}
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h b/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h
index d1a9ea85dbe96..6ba58779114f5 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h
@@ -59,6 +59,7 @@ protected:
// values are specified by the TargetInfo constructor.
bool BigEndian;
bool TLSSupported;
+ bool VLASupported;
bool NoAsmVariants; // True if {|} are normal characters.
bool HasFloat128;
unsigned char PointerWidth, PointerAlign;
@@ -85,7 +86,7 @@ protected:
*LongDoubleFormat, *Float128Format;
unsigned char RegParmMax, SSERegParmMax;
TargetCXXABI TheCXXABI;
- const LangAS::Map *AddrSpaceMap;
+ const LangASMap *AddrSpaceMap;
mutable StringRef PlatformName;
mutable VersionTuple PlatformMinVersion;
@@ -247,6 +248,9 @@ public:
IntType getPtrDiffType(unsigned AddrSpace) const {
return AddrSpace == 0 ? PtrDiffType : getPtrDiffTypeV(AddrSpace);
}
+ IntType getUnsignedPtrDiffType(unsigned AddrSpace) const {
+ return getCorrespondingUnsignedType(getPtrDiffType(AddrSpace));
+ }
IntType getIntPtrType() const { return IntPtrType; }
IntType getUIntPtrType() const {
return getCorrespondingUnsignedType(IntPtrType);
@@ -318,9 +322,7 @@ public:
/// \brief Get integer value for null pointer.
/// \param AddrSpace address space of pointee in source language.
- virtual uint64_t getNullPointerValue(unsigned AddrSpace) const {
- return 0;
- }
+ virtual uint64_t getNullPointerValue(LangAS AddrSpace) const { return 0; }
/// \brief Return the size of '_Bool' and C++ 'bool' for this target, in bits.
unsigned getBoolWidth() const { return BoolWidth; }
@@ -447,6 +449,9 @@ public:
/// \brief Return the maximum width lock-free atomic operation which can be
/// inlined given the supported features of the given target.
unsigned getMaxAtomicInlineWidth() const { return MaxAtomicInlineWidth; }
+ /// \brief Set the maximum inline or promote width lock-free atomic operation
+ /// for the given target.
+ virtual void setMaxAtomicWidth() {}
/// \brief Returns true if the given target supports lock-free atomic
/// operations at the specified width and alignment.
virtual bool hasBuiltinAtomic(uint64_t AtomicSizeInBits,
@@ -464,21 +469,6 @@ public:
/// types for the given target.
unsigned getSimdDefaultAlign() const { return SimdDefaultAlign; }
- /// Return the alignment (in bits) of the thrown exception object. This is
- /// only meaningful for targets that allocate C++ exceptions in a system
- /// runtime, such as those using the Itanium C++ ABI.
- virtual unsigned getExnObjectAlignment() const {
- // Itanium says that an _Unwind_Exception has to be "double-word"
- // aligned (and thus the end of it is also so-aligned), meaning 16
- // bytes. Of course, that was written for the actual Itanium,
- // which is a 64-bit platform. Classically, the ABI doesn't really
- // specify the alignment on other platforms, but in practice
- // libUnwind declares the struct with __attribute__((aligned)), so
- // we assume that alignment here. (It's generally 16 bytes, but
- // some targets overwrite it.)
- return getDefaultAlignForAttributeAligned();
- }
-
/// \brief Return the size of intmax_t and uintmax_t for this target, in bits.
unsigned getIntMaxTWidth() const {
return getTypeWidth(IntMaxType);
@@ -569,6 +559,14 @@ public:
return ComplexLongDoubleUsesFP2Ret;
}
+ /// Check whether llvm intrinsics such as llvm.convert.to.fp16 should be used
+ /// to convert to and from __fp16.
+ /// FIXME: This function should be removed once all targets stop using the
+ /// conversion intrinsics.
+ virtual bool useFP16ConversionIntrinsics() const {
+ return true;
+ }
+
/// \brief Specify if mangling based on address space map should be used or
/// not for language specific address spaces
bool useAddressSpaceMapMangling() const {
@@ -869,6 +867,11 @@ public:
return false;
}
+ /// brief Determine whether this TargetInfo supports the given CPU name.
+ virtual bool isValidCPUName(StringRef Name) const {
+ return true;
+ }
+
/// \brief Use the specified ABI.
///
/// \return False on error (invalid ABI name).
@@ -891,6 +894,11 @@ public:
Features[Name] = Enabled;
}
+ /// \brief Determine whether this TargetInfo supports the given feature.
+ virtual bool isValidFeatureName(StringRef Feature) const {
+ return true;
+ }
+
/// \brief Perform initialization based on the user configured
/// set of features (e.g., +sse4).
///
@@ -916,6 +924,10 @@ public:
// argument.
virtual bool validateCpuSupports(StringRef Name) const { return false; }
+ // \brief Validate the contents of the __builtin_cpu_is(const char*)
+ // argument.
+ virtual bool validateCpuIs(StringRef Name) const { return false; }
+
// \brief Returns maximal number of args passed in registers.
unsigned getRegParmMax() const {
assert(RegParmMax < 7 && "RegParmMax value is larger than AST can handle");
@@ -935,6 +947,9 @@ public:
return MaxTLSAlign;
}
+ /// \brief Whether target supports variable-length arrays.
+ bool isVLASupported() const { return VLASupported; }
+
/// \brief Whether the target supports SEH __try.
bool isSEHTrySupported() const {
return getTriple().isOSWindows() &&
@@ -965,15 +980,13 @@ public:
return nullptr;
}
- const LangAS::Map &getAddressSpaceMap() const {
- return *AddrSpaceMap;
- }
+ const LangASMap &getAddressSpaceMap() const { return *AddrSpaceMap; }
/// \brief Return an AST address space which can be used opportunistically
/// for constant global memory. It must be possible to convert pointers into
/// this address space to LangAS::Default. If no such address space exists,
/// this may return None, and such optimizations will be disabled.
- virtual llvm::Optional<unsigned> getConstantAddressSpace() const {
+ virtual llvm::Optional<LangAS> getConstantAddressSpace() const {
return LangAS::Default;
}
@@ -1051,10 +1064,19 @@ public:
return getTargetOpts().SupportedOpenCLOptions;
}
- /// \brief Get OpenCL image type address space.
- virtual LangAS::ID getOpenCLImageAddrSpace() const {
- return LangAS::opencl_global;
- }
+ enum OpenCLTypeKind {
+ OCLTK_Default,
+ OCLTK_ClkEvent,
+ OCLTK_Event,
+ OCLTK_Image,
+ OCLTK_Pipe,
+ OCLTK_Queue,
+ OCLTK_ReserveID,
+ OCLTK_Sampler,
+ };
+
+ /// \brief Get address space for OpenCL type.
+ virtual LangAS getOpenCLTypeAddrSpace(OpenCLTypeKind TK) const;
/// \returns Target specific vtbl ptr address space.
virtual unsigned getVtblPtrAddressSpace() const {
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TargetOptions.h b/contrib/llvm/tools/clang/include/clang/Basic/TargetOptions.h
index 9bb19c7b79df0..60becfb8ee76e 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/TargetOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TargetOptions.h
@@ -54,8 +54,6 @@ public:
/// be a list of strings starting with by '+' or '-'.
std::vector<std::string> Features;
- std::vector<std::string> Reciprocals;
-
/// Supported OpenCL extensions and optional core features.
OpenCLOptions SupportedOpenCLOptions;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def b/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def
index be67663a1015c..6ae8821a834d0 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def
@@ -27,8 +27,11 @@
#ifndef CXX11_KEYWORD
#define CXX11_KEYWORD(X,Y) KEYWORD(X,KEYCXX11|(Y))
#endif
+#ifndef CXX2A_KEYWORD
+#define CXX2A_KEYWORD(X,Y) KEYWORD(X,KEYCXX2A|(Y))
+#endif
#ifndef CONCEPTS_KEYWORD
-#define CONCEPTS_KEYWORD(X) KEYWORD(X,KEYCONCEPTS)
+#define CONCEPTS_KEYWORD(X) CXX2A_KEYWORD(X,KEYCONCEPTS)
#endif
#ifndef MODULES_KEYWORD
#define MODULES_KEYWORD(X) KEYWORD(X,KEYMODULES)
@@ -142,7 +145,7 @@ TOK(numeric_constant) // 0x123
TOK(char_constant) // 'a'
TOK(wide_char_constant) // L'b'
-// C++1z Character Constants
+// C++17 Character Constants
TOK(utf8_char_constant) // u8'a'
// C++11 Character Constants
@@ -191,6 +194,7 @@ PUNCTUATOR(less, "<")
PUNCTUATOR(lessless, "<<")
PUNCTUATOR(lessequal, "<=")
PUNCTUATOR(lesslessequal, "<<=")
+PUNCTUATOR(spaceship, "<=>")
PUNCTUATOR(greater, ">")
PUNCTUATOR(greatergreater, ">>")
PUNCTUATOR(greaterequal, ">=")
@@ -236,6 +240,7 @@ PUNCTUATOR(caretcaret, "^^")
// implementation namespace
// KEYNOCXX - This is a keyword in every non-C++ dialect.
// KEYCXX11 - This is a C++ keyword introduced to C++ in C++11
+// KEYCXX2A - This is a C++ keyword introduced to C++ in C++2a
// KEYCONCEPTS - This is a keyword if the C++ extensions for concepts
// are enabled.
// KEYMODULES - This is a keyword if the C++ extensions for modules
@@ -362,7 +367,7 @@ CXX11_KEYWORD(nullptr , 0)
CXX11_KEYWORD(static_assert , 0)
CXX11_KEYWORD(thread_local , 0)
-// C++ concepts TS keywords
+// C++2a / concepts TS keywords
CONCEPTS_KEYWORD(concept)
CONCEPTS_KEYWORD(requires)
@@ -375,6 +380,9 @@ KEYWORD(co_yield , KEYCOROUTINES)
MODULES_KEYWORD(module)
MODULES_KEYWORD(import)
+// C11 Extension
+KEYWORD(_Float16 , KEYALL)
+
// GNU Extensions (in impl-reserved namespace)
KEYWORD(_Decimal32 , KEYALL)
KEYWORD(_Decimal64 , KEYALL)
@@ -390,6 +398,7 @@ TYPE_TRAIT_2(__builtin_types_compatible_p, TypeCompatible, KEYNOCXX)
KEYWORD(__builtin_va_arg , KEYALL)
KEYWORD(__extension__ , KEYALL)
KEYWORD(__float128 , KEYALL)
+ALIAS("_Float128", __float128 , KEYNOCXX)
KEYWORD(__imag , KEYALL)
KEYWORD(__int128 , KEYALL)
KEYWORD(__label__ , KEYALL)
@@ -448,6 +457,8 @@ TYPE_TRAIT_1(__is_pod, IsPOD, KEYCXX)
TYPE_TRAIT_1(__is_polymorphic, IsPolymorphic, KEYCXX)
TYPE_TRAIT_1(__is_trivial, IsTrivial, KEYCXX)
TYPE_TRAIT_1(__is_union, IsUnion, KEYCXX)
+TYPE_TRAIT_1(__has_unique_object_representations,
+ HasUniqueObjectRepresentations, KEYCXX)
// Clang-only C++ Type Traits
TYPE_TRAIT_N(__is_trivially_constructible, IsTriviallyConstructible, KEYCXX)
@@ -810,6 +821,7 @@ ANNOTATION(module_end)
#undef TYPE_TRAIT_1
#undef TYPE_TRAIT
#undef CONCEPTS_KEYWORD
+#undef CXX2A_KEYWORD
#undef CXX11_KEYWORD
#undef KEYWORD
#undef PUNCTUATOR
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h b/contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h
index 6aadf795d82e5..8ecd63f9c3cbb 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h
@@ -70,7 +70,8 @@ namespace clang {
UTT_IsUnsigned,
UTT_IsVoid,
UTT_IsVolatile,
- UTT_Last = UTT_IsVolatile,
+ UTT_HasUniqueObjectRepresentations,
+ UTT_Last = UTT_HasUniqueObjectRepresentations,
BTT_IsBaseOf,
BTT_IsConvertible,
BTT_IsConvertibleTo,
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/VirtualFileSystem.h b/contrib/llvm/tools/clang/include/clang/Basic/VirtualFileSystem.h
index e52b345e286c6..245452dd12b57 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/VirtualFileSystem.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/VirtualFileSystem.h
@@ -319,16 +319,30 @@ public:
explicit InMemoryFileSystem(bool UseNormalizedPaths = true);
~InMemoryFileSystem() override;
- /// Add a buffer to the VFS with a path. The VFS owns the buffer.
- /// \return true if the file was successfully added, false if the file already
- /// exists in the file system with different contents.
+ /// Add a file containing a buffer or a directory to the VFS with a
+ /// path. The VFS owns the buffer. If present, User, Group, Type
+ /// and Perms apply to the newly-created file or directory.
+ /// \return true if the file or directory was successfully added,
+ /// false if the file or directory already exists in the file system with
+ /// different contents.
bool addFile(const Twine &Path, time_t ModificationTime,
- std::unique_ptr<llvm::MemoryBuffer> Buffer);
+ std::unique_ptr<llvm::MemoryBuffer> Buffer,
+ Optional<uint32_t> User = None, Optional<uint32_t> Group = None,
+ Optional<llvm::sys::fs::file_type> Type = None,
+ Optional<llvm::sys::fs::perms> Perms = None);
/// Add a buffer to the VFS with a path. The VFS does not own the buffer.
- /// \return true if the file was successfully added, false if the file already
- /// exists in the file system with different contents.
+ /// If present, User, Group, Type and Perms apply to the newly-created file
+ /// or directory.
+ /// \return true if the file or directory was successfully added,
+ /// false if the file or directory already exists in the file system with
+ /// different contents.
bool addFileNoOwn(const Twine &Path, time_t ModificationTime,
- llvm::MemoryBuffer *Buffer);
+ llvm::MemoryBuffer *Buffer,
+ Optional<uint32_t> User = None,
+ Optional<uint32_t> Group = None,
+ Optional<llvm::sys::fs::file_type> Type = None,
+ Optional<llvm::sys::fs::perms> Perms = None);
+
std::string toString() const;
/// Return true if this file system normalizes . and .. in paths.
bool useNormalizedPaths() const { return UseNormalizedPaths; }
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/X86Target.def b/contrib/llvm/tools/clang/include/clang/Basic/X86Target.def
new file mode 100644
index 0000000000000..21550fe2dd55f
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/X86Target.def
@@ -0,0 +1,232 @@
+//===--- X86Target.def - X86 Feature/Processor Database ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the X86-specific Features and Processors, as used by
+// the X86 Targets.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef PROC
+#define PROC(ENUM, STRING, IS64BIT)
+#endif
+
+#ifndef PROC_ALIAS
+#define PROC_ALIAS(ENUM, ALIAS)
+#endif
+
+#define PROC_64_BIT true
+#define PROC_32_BIT false
+
+/// \name i386
+/// i386-generation processors.
+//@{
+PROC(i386, "i386", PROC_32_BIT)
+//@}
+
+/// \name i486
+/// i486-generation processors.
+//@{
+PROC(i486, "i486", PROC_32_BIT)
+PROC(WinChipC6, "winchip-c6", PROC_32_BIT)
+PROC(WinChip2, "winchip2", PROC_32_BIT)
+PROC(C3, "c3", PROC_32_BIT)
+//@}
+
+/// \name i586
+/// i586-generation processors, P5 microarchitecture based.
+//@{
+PROC(i586, "i586", PROC_32_BIT)
+PROC(Pentium, "pentium", PROC_32_BIT)
+PROC(PentiumMMX, "pentium-mmx", PROC_32_BIT)
+//@}
+
+/// \name i686
+/// i686-generation processors, P6 / Pentium M microarchitecture based.
+//@{
+PROC(PentiumPro, "pentiumpro", PROC_32_BIT)
+PROC_ALIAS(PentiumPro, "i686")
+PROC(Pentium2, "pentium2", PROC_32_BIT)
+PROC(Pentium3, "pentium3", PROC_32_BIT)
+PROC_ALIAS(Pentium3, "pentium3m")
+PROC(PentiumM, "pentium-m", PROC_32_BIT)
+PROC(C3_2, "c3-2", PROC_32_BIT)
+
+/// This enumerator is a bit odd, as GCC no longer accepts -march=yonah.
+/// Clang however has some logic to support this.
+// FIXME: Warn, deprecate, and potentially remove this.
+PROC(Yonah, "yonah", PROC_32_BIT)
+//@}
+
+/// \name Netburst
+/// Netburst microarchitecture based processors.
+//@{
+PROC(Pentium4, "pentium4", PROC_32_BIT)
+PROC_ALIAS(Pentium4, "pentium4m")
+
+PROC(Prescott, "prescott", PROC_32_BIT)
+PROC(Nocona, "nocona", PROC_64_BIT)
+//@}
+
+/// \name Core
+/// Core microarchitecture based processors.
+//@{
+PROC(Core2, "core2", PROC_64_BIT)
+
+/// This enumerator, like Yonah, is a bit odd. It is another
+/// codename which GCC no longer accepts as an option to -march, but Clang
+/// has some logic for recognizing it.
+// FIXME: Warn, deprecate, and potentially remove this.
+PROC(Penryn, "penryn", PROC_64_BIT)
+//@}
+
+/// \name Atom
+/// Atom processors
+//@{
+PROC(Bonnell, "bonnell", PROC_64_BIT)
+PROC_ALIAS(Bonnell, "atom")
+
+PROC(Silvermont, "silvermont", PROC_64_BIT)
+PROC_ALIAS(Silvermont, "slm")
+
+PROC(Goldmont, "goldmont", PROC_64_BIT)
+//@}
+
+/// \name Nehalem
+/// Nehalem microarchitecture based processors.
+PROC(Nehalem, "nehalem", PROC_64_BIT)
+PROC_ALIAS(Nehalem, "corei7")
+
+/// \name Westmere
+/// Westmere microarchitecture based processors.
+PROC(Westmere, "westmere", PROC_64_BIT)
+
+/// \name Sandy Bridge
+/// Sandy Bridge microarchitecture based processors.
+PROC(SandyBridge, "sandybridge", PROC_64_BIT)
+PROC_ALIAS(SandyBridge, "corei7-avx")
+
+/// \name Ivy Bridge
+/// Ivy Bridge microarchitecture based processors.
+PROC(IvyBridge, "ivybridge", PROC_64_BIT)
+PROC_ALIAS(IvyBridge, "core-avx-i")
+
+/// \name Haswell
+/// Haswell microarchitecture based processors.
+PROC(Haswell, "haswell", PROC_64_BIT)
+PROC_ALIAS(Haswell, "core-avx2")
+
+/// \name Broadwell
+/// Broadwell microarchitecture based processors.
+PROC(Broadwell, "broadwell", PROC_64_BIT)
+
+/// \name Skylake Client
+/// Skylake client microarchitecture based processors.
+PROC(SkylakeClient, "skylake", PROC_64_BIT)
+
+/// \name Skylake Server
+/// Skylake server microarchitecture based processors.
+PROC(SkylakeServer, "skylake-avx512", PROC_64_BIT)
+PROC_ALIAS(SkylakeServer, "skx")
+
+/// \name Cannonlake Client
+/// Cannonlake client microarchitecture based processors.
+PROC(Cannonlake, "cannonlake", PROC_64_BIT)
+
+/// \name Icelake Client
+/// Icelake client microarchitecture based processors.
+PROC(Icelake, "icelake", PROC_64_BIT)
+
+/// \name Knights Landing
+/// Knights Landing processor.
+PROC(KNL, "knl", PROC_64_BIT)
+
+/// \name Knights Mill
+/// Knights Mill processor.
+PROC(KNM, "knm", PROC_64_BIT)
+
+/// \name Lakemont
+/// Lakemont microarchitecture based processors.
+PROC(Lakemont, "lakemont", PROC_32_BIT)
+
+/// \name K6
+/// K6 architecture processors.
+//@{
+PROC(K6, "k6", PROC_32_BIT)
+PROC(K6_2, "k6-2", PROC_32_BIT)
+PROC(K6_3, "k6-3", PROC_32_BIT)
+//@}
+
+/// \name K7
+/// K7 architecture processors.
+//@{
+PROC(Athlon, "athlon", PROC_32_BIT)
+PROC_ALIAS(Athlon, "athlon-tbird")
+
+PROC(AthlonXP, "athlon-xp", PROC_32_BIT)
+PROC_ALIAS(AthlonXP, "athlon-mp")
+PROC_ALIAS(AthlonXP, "athlon-4")
+//@}
+
+/// \name K8
+/// K8 architecture processors.
+//@{
+PROC(K8, "k8", PROC_64_BIT)
+PROC_ALIAS(K8, "athlon64")
+PROC_ALIAS(K8, "athlon-fx")
+PROC_ALIAS(K8, "opteron")
+
+PROC(K8SSE3, "k8-sse3", PROC_64_BIT)
+PROC_ALIAS(K8SSE3, "athlon64-sse3")
+PROC_ALIAS(K8SSE3, "opteron-sse3")
+
+PROC(AMDFAM10, "amdfam10", PROC_64_BIT)
+PROC_ALIAS(AMDFAM10, "barcelona")
+//@}
+
+/// \name Bobcat
+/// Bobcat architecture processors.
+//@{
+PROC(BTVER1, "btver1", PROC_64_BIT)
+PROC(BTVER2, "btver2", PROC_64_BIT)
+//@}
+
+/// \name Bulldozer
+/// Bulldozer architecture processors.
+//@{
+PROC(BDVER1, "bdver1", PROC_64_BIT)
+PROC(BDVER2, "bdver2", PROC_64_BIT)
+PROC(BDVER3, "bdver3", PROC_64_BIT)
+PROC(BDVER4, "bdver4", PROC_64_BIT)
+//@}
+
+/// \name zen
+/// Zen architecture processors.
+//@{
+PROC(ZNVER1, "znver1", PROC_64_BIT)
+//@}
+
+/// This specification is deprecated and will be removed in the future.
+/// Users should prefer K8.
+// FIXME: Warn on this when the CPU is set to it.
+//@{
+PROC(x86_64, "x86-64", PROC_64_BIT)
+//@}
+
+/// \name Geode
+/// Geode processors.
+//@{
+PROC(Geode, "geode", PROC_32_BIT)
+//@}
+
+
+#undef PROC_64_BIT
+#undef PROC_32_BIT
+#undef PROC
+#undef PROC_ALIAS
diff --git a/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenABITypes.h b/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenABITypes.h
index 615e55c8b69f8..53619fa8ef65b 100644
--- a/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenABITypes.h
+++ b/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenABITypes.h
@@ -72,12 +72,19 @@ const CGFunctionInfo &arrangeFreeFunctionCall(CodeGenModule &CGM,
FunctionType::ExtInfo info,
RequiredArgs args);
-// Returns null if the function type is incomplete and can't be lowered.
+/// Returns null if the function type is incomplete and can't be lowered.
llvm::FunctionType *convertFreeFunctionType(CodeGenModule &CGM,
const FunctionDecl *FD);
llvm::Type *convertTypeForMemory(CodeGenModule &CGM, QualType T);
+/// Given a non-bitfield struct field, return its index within the elements of
+/// the struct's converted type. The returned index refers to a field number in
+/// the complete object type which is returned by convertTypeForMemory. FD must
+/// be a field in RD directly (i.e. not an inherited field).
+unsigned getLLVMFieldNumber(CodeGenModule &CGM,
+ const RecordDecl *RD, const FieldDecl *FD);
+
} // end namespace CodeGen
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/CodeGen/ConstantInitFuture.h b/contrib/llvm/tools/clang/include/clang/CodeGen/ConstantInitFuture.h
index ef1a5d2f49af7..f1a7e2264fc6b 100644
--- a/contrib/llvm/tools/clang/include/clang/CodeGen/ConstantInitFuture.h
+++ b/contrib/llvm/tools/clang/include/clang/CodeGen/ConstantInitFuture.h
@@ -31,8 +31,7 @@ class ConstantInitBuilderBase;
}
namespace llvm {
template <>
-class PointerLikeTypeTraits< ::clang::CodeGen::ConstantInitBuilderBase*> {
-public:
+struct PointerLikeTypeTraits< ::clang::CodeGen::ConstantInitBuilderBase*> {
using T = ::clang::CodeGen::ConstantInitBuilderBase*;
static inline void *getAsVoidPointer(T p) { return p; }
@@ -93,8 +92,7 @@ public:
namespace llvm {
template <>
-class PointerLikeTypeTraits< ::clang::CodeGen::ConstantInitFuture> {
-public:
+struct PointerLikeTypeTraits< ::clang::CodeGen::ConstantInitFuture> {
using T = ::clang::CodeGen::ConstantInitFuture;
static inline void *getAsVoidPointer(T future) {
diff --git a/contrib/llvm/tools/clang/include/clang/CodeGen/ModuleBuilder.h b/contrib/llvm/tools/clang/include/clang/CodeGen/ModuleBuilder.h
index 6f81ea9d6370b..e110f6fd30c1e 100644
--- a/contrib/llvm/tools/clang/include/clang/CodeGen/ModuleBuilder.h
+++ b/contrib/llvm/tools/clang/include/clang/CodeGen/ModuleBuilder.h
@@ -84,6 +84,10 @@ public:
/// code generator will schedule the entity for emission if a
/// definition has been registered with this code generator.
llvm::Constant *GetAddrOfGlobal(GlobalDecl decl, bool isForDefinition);
+
+ /// Create a new \c llvm::Module after calling HandleTranslationUnit. This
+ /// enable codegen in interactive processing environments.
+ llvm::Module* StartModule(llvm::StringRef ModuleName, llvm::LLVMContext &C);
};
/// CreateLLVMCodeGen - Create a CodeGenerator instance.
diff --git a/contrib/llvm/tools/clang/include/clang/CrossTU/CrossTUDiagnostic.h b/contrib/llvm/tools/clang/include/clang/CrossTU/CrossTUDiagnostic.h
new file mode 100644
index 0000000000000..dad38309fd1ad
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/CrossTU/CrossTUDiagnostic.h
@@ -0,0 +1,29 @@
+//===--- CrossTUDiagnostic.h - Diagnostics for Cross TU ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CROSSTU_CROSSTUDIAGNOSTIC_H
+#define LLVM_CLANG_CROSSTU_CROSSTUDIAGNOSTIC_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+namespace diag {
+enum {
+#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \
+ SHOWINSYSHEADER, CATEGORY) \
+ ENUM,
+#define CROSSTUSTART
+#include "clang/Basic/DiagnosticCrossTUKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_CROSSTU_DIAGNOSTICS
+};
+} // end namespace diag
+} // end namespace clang
+
+#endif // LLVM_CLANG_FRONTEND_FRONTENDDIAGNOSTIC_H
diff --git a/contrib/llvm/tools/clang/include/clang/CrossTU/CrossTranslationUnit.h b/contrib/llvm/tools/clang/include/clang/CrossTU/CrossTranslationUnit.h
new file mode 100644
index 0000000000000..f2a1690250090
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/CrossTU/CrossTranslationUnit.h
@@ -0,0 +1,159 @@
+//===--- CrossTranslationUnit.h - -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides an interface to load binary AST dumps on demand. This
+// feature can be utilized for tools that require cross translation unit
+// support.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_CROSSTU_CROSSTRANSLATIONUNIT_H
+#define LLVM_CLANG_CROSSTU_CROSSTRANSLATIONUNIT_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Error.h"
+
+namespace clang {
+class CompilerInstance;
+class ASTContext;
+class ASTImporter;
+class ASTUnit;
+class DeclContext;
+class FunctionDecl;
+class NamedDecl;
+class TranslationUnitDecl;
+
+namespace cross_tu {
+
+enum class index_error_code {
+ unspecified = 1,
+ missing_index_file,
+ invalid_index_format,
+ multiple_definitions,
+ missing_definition,
+ failed_import,
+ failed_to_get_external_ast,
+ failed_to_generate_usr
+};
+
+class IndexError : public llvm::ErrorInfo<IndexError> {
+public:
+ static char ID;
+ IndexError(index_error_code C) : Code(C), LineNo(0) {}
+ IndexError(index_error_code C, std::string FileName, int LineNo = 0)
+ : Code(C), FileName(std::move(FileName)), LineNo(LineNo) {}
+ void log(raw_ostream &OS) const override;
+ std::error_code convertToErrorCode() const override;
+ index_error_code getCode() const { return Code; }
+ int getLineNum() const { return LineNo; }
+ std::string getFileName() const { return FileName; }
+
+private:
+ index_error_code Code;
+ std::string FileName;
+ int LineNo;
+};
+
+/// \brief This function parses an index file that determines which
+/// translation unit contains which definition.
+///
+/// The index file format is the following:
+/// each line consists of an USR and a filepath separated by a space.
+///
+/// \return Returns a map where the USR is the key and the filepath is the value
+/// or an error.
+llvm::Expected<llvm::StringMap<std::string>>
+parseCrossTUIndex(StringRef IndexPath, StringRef CrossTUDir);
+
+std::string createCrossTUIndexString(const llvm::StringMap<std::string> &Index);
+
+/// \brief This class is used for tools that requires cross translation
+/// unit capability.
+///
+/// This class can load function definitions from external AST files.
+/// The loaded definition will be merged back to the original AST using the
+/// AST Importer.
+/// In order to use this class, an index file is required that describes
+/// the locations of the AST files for each function definition.
+///
+/// Note that this class also implements caching.
+class CrossTranslationUnitContext {
+public:
+ CrossTranslationUnitContext(CompilerInstance &CI);
+ ~CrossTranslationUnitContext();
+
+ /// \brief This function loads a function definition from an external AST
+ /// file and merge it into the original AST.
+ ///
+ /// This method should only be used on functions that have no definitions in
+ /// the current translation unit. A function definition with the same
+ /// declaration will be looked up in the index file which should be in the
+ /// \p CrossTUDir directory, called \p IndexName. In case the declaration is
+ /// found in the index the corresponding AST file will be loaded and the
+ /// definition of the function will be merged into the original AST using
+ /// the AST Importer.
+ ///
+ /// \return The declaration with the definition will be returned.
+ /// If no suitable definition is found in the index file or multiple
+ /// definitions found error will be returned.
+ ///
+ /// Note that the AST files should also be in the \p CrossTUDir.
+ llvm::Expected<const FunctionDecl *>
+ getCrossTUDefinition(const FunctionDecl *FD, StringRef CrossTUDir,
+ StringRef IndexName);
+
+ /// \brief This function loads a function definition from an external AST
+ /// file.
+ ///
+ /// A function definition with the same declaration will be looked up in the
+ /// index file which should be in the \p CrossTUDir directory, called
+ /// \p IndexName. In case the declaration is found in the index the
+ /// corresponding AST file will be loaded.
+ ///
+ /// \return Returns an ASTUnit that contains the definition of the looked up
+ /// function.
+ ///
+ /// Note that the AST files should also be in the \p CrossTUDir.
+ llvm::Expected<ASTUnit *> loadExternalAST(StringRef LookupName,
+ StringRef CrossTUDir,
+ StringRef IndexName);
+
+ /// \brief This function merges a definition from a separate AST Unit into
+ /// the current one which was created by the compiler instance that
+ /// was passed to the constructor.
+ ///
+ /// \return Returns the resulting definition or an error.
+ llvm::Expected<const FunctionDecl *> importDefinition(const FunctionDecl *FD);
+
+ /// \brief Get a name to identify a function.
+ static std::string getLookupName(const NamedDecl *ND);
+
+ /// \brief Emit diagnostics for the user for potential configuration errors.
+ void emitCrossTUDiagnostics(const IndexError &IE);
+
+private:
+ ASTImporter &getOrCreateASTImporter(ASTContext &From);
+ const FunctionDecl *findFunctionInDeclContext(const DeclContext *DC,
+ StringRef LookupFnName);
+
+ llvm::StringMap<std::unique_ptr<clang::ASTUnit>> FileASTUnitMap;
+ llvm::StringMap<clang::ASTUnit *> FunctionASTUnitMap;
+ llvm::StringMap<std::string> FunctionFileMap;
+ llvm::DenseMap<TranslationUnitDecl *, std::unique_ptr<ASTImporter>>
+ ASTUnitImporterMap;
+ CompilerInstance &CI;
+ ASTContext &Context;
+};
+
+} // namespace cross_tu
+} // namespace clang
+
+#endif // LLVM_CLANG_CROSSTU_CROSSTRANSLATIONUNIT_H
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td b/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td
index 205f36b723c87..7dea88b62cc19 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td
+++ b/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td
@@ -70,7 +70,7 @@ def analyzer_opt_analyze_nested_blocks : Flag<["-"], "analyzer-opt-analyze-neste
def analyzer_display_progress : Flag<["-"], "analyzer-display-progress">,
HelpText<"Emit verbose output about the analyzer's progress">;
def analyze_function : Separate<["-"], "analyze-function">,
- HelpText<"Run analysis on specific function">;
+ HelpText<"Run analysis on specific function (for C++ include parameters in name)">;
def analyze_function_EQ : Joined<["-"], "analyze-function=">, Alias<analyze_function>;
def analyzer_eagerly_assume : Flag<["-"], "analyzer-eagerly-assume">,
HelpText<"Eagerly assume the truth/falseness of some symbolic constraints">;
@@ -99,7 +99,19 @@ def analyzer_stats : Flag<["-"], "analyzer-stats">,
HelpText<"Print internal analyzer statistics.">;
def analyzer_checker : Separate<["-"], "analyzer-checker">,
- HelpText<"Choose analyzer checkers to enable">;
+ HelpText<"Choose analyzer checkers to enable">,
+ ValuesCode<[{
+ const char *Values =
+ #define GET_CHECKERS
+ #define CHECKER(FULLNAME, CLASS, DESCFILE, HT, G, H) FULLNAME ","
+ #include "clang/StaticAnalyzer/Checkers/Checkers.inc"
+ #undef GET_CHECKERS
+ #define GET_PACKAGES
+ #define PACKAGE(FULLNAME, G, D) FULLNAME ","
+ #include "clang/StaticAnalyzer/Checkers/Checkers.inc"
+ #undef GET_PACKAGES
+ ;
+ }]>;
def analyzer_checker_EQ : Joined<["-"], "analyzer-checker=">,
Alias<analyzer_checker>;
@@ -188,6 +200,12 @@ def arange_sections : Flag<["-"], "arange_sections">,
def dwarf_ext_refs : Flag<["-"], "dwarf-ext-refs">,
HelpText<"Generate debug info with external references to clang modules"
" or precompiled headers">;
+def dwarf_explicit_import : Flag<["-"], "dwarf-explicit-import">,
+ HelpText<"Generate explicit import from anonymous namespace to containing"
+ " scope">;
+def debug_forward_template_params : Flag<["-"], "debug-forward-template-params">,
+ HelpText<"Emit complete descriptions of template parameters in forward"
+ " declarations">;
def fforbid_guard_variables : Flag<["-"], "fforbid-guard-variables">,
HelpText<"Emit an error if a C++ static local initializer would need a guard variable">;
def no_implicit_float : Flag<["-"], "no-implicit-float">,
@@ -226,6 +244,8 @@ def relaxed_aliasing : Flag<["-"], "relaxed-aliasing">,
HelpText<"Turn off Type Based Alias Analysis">;
def no_struct_path_tbaa : Flag<["-"], "no-struct-path-tbaa">,
HelpText<"Turn off struct-path aware Type Based Alias Analysis">;
+def new_struct_path_tbaa : Flag<["-"], "new-struct-path-tbaa">,
+ HelpText<"Enable enhanced struct-path aware Type Based Alias Analysis">;
def masm_verbose : Flag<["-"], "masm-verbose">,
HelpText<"Generate verbose assembly output">;
def mcode_model : Separate<["-"], "mcode-model">,
@@ -243,8 +263,12 @@ def menable_no_nans : Flag<["-"], "menable-no-nans">,
def menable_unsafe_fp_math : Flag<["-"], "menable-unsafe-fp-math">,
HelpText<"Allow unsafe floating-point math optimizations which may decrease "
"precision">;
+def mreassociate : Flag<["-"], "mreassociate">,
+ HelpText<"Allow reassociation transformations for floating-point instructions">;
def mfloat_abi : Separate<["-"], "mfloat-abi">,
HelpText<"The float ABI to use">;
+def mtp : Separate<["-"], "mtp">,
+ HelpText<"Mode for reading thread pointer">;
def mlimit_float_precision : Separate<["-"], "mlimit-float-precision">,
HelpText<"Limit float precision to the given value">;
def split_stacks : Flag<["-"], "split-stacks">,
@@ -295,6 +319,9 @@ def fsanitize_coverage_8bit_counters
def fsanitize_coverage_inline_8bit_counters
: Flag<["-"], "fsanitize-coverage-inline-8bit-counters">,
HelpText<"Enable inline 8-bit counters in sanitizer coverage">;
+def fsanitize_coverage_pc_table
+ : Flag<["-"], "fsanitize-coverage-pc-table">,
+ HelpText<"Create a table of coverage-instrumented PCs">;
def fsanitize_coverage_trace_pc
: Flag<["-"], "fsanitize-coverage-trace-pc">,
HelpText<"Enable PC tracing in sanitizer coverage">;
@@ -304,6 +331,9 @@ def fsanitize_coverage_trace_pc_guard
def fsanitize_coverage_no_prune
: Flag<["-"], "fsanitize-coverage-no-prune">,
HelpText<"Disable coverage pruning (i.e. instrument all blocks/edges)">;
+def fsanitize_coverage_stack_depth
+ : Flag<["-"], "fsanitize-coverage-stack-depth">,
+ HelpText<"Enable max stack depth tracing">;
def fprofile_instrument_EQ : Joined<["-"], "fprofile-instrument=">,
HelpText<"Enable PGO instrumentation. The accepted value is clang, llvm, "
"or none">, Values<"none,clang,llvm">;
@@ -372,8 +402,12 @@ def fcaret_diagnostics_max_lines :
HelpText<"Set the maximum number of source lines to show in a caret diagnostic">;
def fmessage_length : Separate<["-"], "fmessage-length">, MetaVarName<"<N>">,
HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">;
+def verify_EQ : CommaJoined<["-"], "verify=">,
+ MetaVarName<"<prefixes>">,
+ HelpText<"Verify diagnostic output using comment directives that start with"
+ " prefixes in the comma-separated sequence <prefixes>">;
def verify : Flag<["-"], "verify">,
- HelpText<"Verify diagnostic output using comment directives">;
+ HelpText<"Equivalent to -verify=expected">;
def verify_ignore_unexpected : Flag<["-"], "verify-ignore-unexpected">,
HelpText<"Ignore unexpected diagnostic messages">;
def verify_ignore_unexpected_EQ : CommaJoined<["-"], "verify-ignore-unexpected=">,
@@ -409,6 +443,8 @@ def code_completion_patterns : Flag<["-"], "code-completion-patterns">,
HelpText<"Include code patterns in code-completion results">;
def no_code_completion_globals : Flag<["-"], "no-code-completion-globals">,
HelpText<"Do not include global declarations in code-completion results.">;
+def no_code_completion_ns_level_decls : Flag<["-"], "no-code-completion-ns-level-decls">,
+ HelpText<"Do not include declarations inside namespaces (incl. global namespace) in the code-completion results.">;
def code_completion_brief_comments : Flag<["-"], "code-completion-brief-comments">,
HelpText<"Include brief documentation comments in code-completion results.">;
def disable_free : Flag<["-"], "disable-free">,
@@ -678,11 +714,17 @@ def fnative_half_arguments_and_returns : Flag<["-"], "fnative-half-arguments-and
def fallow_half_arguments_and_returns : Flag<["-"], "fallow-half-arguments-and-returns">,
HelpText<"Allow function arguments and returns of type half">;
def fdefault_calling_conv_EQ : Joined<["-"], "fdefault-calling-conv=">,
- HelpText<"Set default MS calling convention">, Values<"cdecl,fastcall,stdcall,vectorcall">;
+ HelpText<"Set default calling convention">, Values<"cdecl,fastcall,stdcall,vectorcall,regcall">;
def finclude_default_header : Flag<["-"], "finclude-default-header">,
HelpText<"Include the default header file for OpenCL">;
def fpreserve_vec3_type : Flag<["-"], "fpreserve-vec3-type">,
HelpText<"Preserve 3-component vector type">;
+def fwchar_type_EQ : Joined<["-"], "fwchar-type=">,
+ HelpText<"Select underlying type for wchar_t">, Values<"char,short,int">;
+def fsigned_wchar : Flag<["-"], "fsigned-wchar">,
+ HelpText<"Use a signed type for wchar_t">;
+def fno_signed_wchar : Flag<["-"], "fno-signed-wchar">,
+ HelpText<"Use an unsigned type for wchar_t">;
// FIXME: Remove these entirely once functionality/tests have been excised.
def fobjc_gc_only : Flag<["-"], "fobjc-gc-only">, Group<f_Group>,
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/CLCompatOptions.td b/contrib/llvm/tools/clang/include/clang/Driver/CLCompatOptions.td
index aebb36ed0e2b6..c1f0a89b5dc8f 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/CLCompatOptions.td
+++ b/contrib/llvm/tools/clang/include/clang/Driver/CLCompatOptions.td
@@ -145,7 +145,8 @@ def _SLASH_W1 : CLFlag<"W1">, HelpText<"Enable -Wall">, Alias<Wall>;
def _SLASH_W2 : CLFlag<"W2">, HelpText<"Enable -Wall">, Alias<Wall>;
def _SLASH_W3 : CLFlag<"W3">, HelpText<"Enable -Wall">, Alias<Wall>;
def _SLASH_W4 : CLFlag<"W4">, HelpText<"Enable -Wall and -Wextra">, Alias<WCL4>;
-def _SLASH_Wall : CLFlag<"Wall">, HelpText<"Enable -Wall and -Wextra">, Alias<WCL4>;
+def _SLASH_Wall : CLFlag<"Wall">, HelpText<"Enable -Weverything">,
+ Alias<W_Joined>, AliasArgs<["everything"]>;
def _SLASH_WX : CLFlag<"WX">, HelpText<"Treat warnings as errors">,
Alias<W_Joined>, AliasArgs<["error"]>;
def _SLASH_WX_ : CLFlag<"WX-">, HelpText<"Do not treat warnings as errors">,
@@ -153,6 +154,8 @@ def _SLASH_WX_ : CLFlag<"WX-">, HelpText<"Do not treat warnings as errors">,
def _SLASH_w_flag : CLFlag<"w">, HelpText<"Disable all warnings">, Alias<w>;
def _SLASH_wd4005 : CLFlag<"wd4005">, Alias<W_Joined>,
AliasArgs<["no-macro-redefined"]>;
+def _SLASH_wd4018 : CLFlag<"wd4018">, Alias<W_Joined>,
+ AliasArgs<["no-sign-compare"]>;
def _SLASH_wd4100 : CLFlag<"wd4100">, Alias<W_Joined>,
AliasArgs<["no-unused-parameter"]>;
def _SLASH_wd4910 : CLFlag<"wd4910">, Alias<W_Joined>,
@@ -302,6 +305,8 @@ def _SLASH_Gz : CLFlag<"Gz">,
HelpText<"Set __stdcall as a default calling convention">;
def _SLASH_Gv : CLFlag<"Gv">,
HelpText<"Set __vectorcall as a default calling convention">;
+def _SLASH_Gregcall : CLFlag<"Gregcall">,
+ HelpText<"Set __regcall as a default calling convention">;
// Ignored:
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Compilation.h b/contrib/llvm/tools/clang/include/clang/Driver/Compilation.h
index 036b04605ac70..89c0def6c57a0 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/Compilation.h
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Compilation.h
@@ -99,8 +99,8 @@ class Compilation {
/// only be removed if we crash.
ArgStringMap FailureResultFiles;
- /// Redirection for stdout, stderr, etc.
- const StringRef **Redirects;
+ /// Optional redirection for stdin, stdout, stderr.
+ std::vector<Optional<StringRef>> Redirects;
/// Whether we're compiling for diagnostic purposes.
bool ForDiagnostics;
@@ -283,12 +283,10 @@ public:
/// Redirect - Redirect output of this compilation. Can only be done once.
///
- /// \param Redirects - array of pointers to paths. The array
- /// should have a size of three. The inferior process's
- /// stdin(0), stdout(1), and stderr(2) will be redirected to the
- /// corresponding paths. This compilation instance becomes
- /// the owner of Redirects and will delete the array and StringRef's.
- void Redirect(const StringRef** Redirects);
+ /// \param Redirects - array of optional paths. The array should have a size
+ /// of three. The inferior process's stdin(0), stdout(1), and stderr(2) will
+ /// be redirected to the corresponding paths, if provided (not llvm::None).
+ void Redirect(ArrayRef<Optional<StringRef>> Redirects);
};
} // end namespace driver
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Distro.h b/contrib/llvm/tools/clang/include/clang/Driver/Distro.h
index fab49862a442b..4ab4e2ae99370 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/Distro.h
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Distro.h
@@ -26,12 +26,14 @@ public:
// NB: Releases of a particular Linux distro should be kept together
// in this enum, because some tests are done by integer comparison against
// the first and last known member in the family, e.g. IsRedHat().
+ AlpineLinux,
ArchLinux,
DebianLenny,
DebianSqueeze,
DebianWheezy,
DebianJessie,
DebianStretch,
+ DebianBuster,
Exherbo,
RHEL5,
RHEL6,
@@ -58,6 +60,7 @@ public:
UbuntuYakkety,
UbuntuZesty,
UbuntuArtful,
+ UbuntuBionic,
UnknownDistro
};
@@ -107,11 +110,15 @@ public:
}
bool IsDebian() const {
- return DistroVal >= DebianLenny && DistroVal <= DebianStretch;
+ return DistroVal >= DebianLenny && DistroVal <= DebianBuster;
}
bool IsUbuntu() const {
- return DistroVal >= UbuntuHardy && DistroVal <= UbuntuArtful;
+ return DistroVal >= UbuntuHardy && DistroVal <= UbuntuBionic;
+ }
+
+ bool IsAlpineLinux() const {
+ return DistroVal == AlpineLinux;
}
/// @}
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Driver.h b/contrib/llvm/tools/clang/include/clang/Driver/Driver.h
index 5a087eea1b4ec..a3662872a9531 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/Driver.h
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Driver.h
@@ -129,6 +129,9 @@ public:
/// The original path to the clang executable.
std::string ClangExecutable;
+ /// Target and driver mode components extracted from clang executable name.
+ ParsedClangName ClangNameParts;
+
/// The path to the installed clang directory, if any.
std::string InstalledDir;
@@ -148,9 +151,6 @@ public:
/// Dynamic loader prefix, if present
std::string DyldPrefix;
- /// If the standard library is used
- bool UseStdLib;
-
/// Driver title to use with help.
std::string DriverTitle;
@@ -287,6 +287,8 @@ public:
void setCheckInputsExist(bool Value) { CheckInputsExist = Value; }
+ void setTargetAndMode(const ParsedClangName &TM) { ClangNameParts = TM; }
+
const std::string &getTitle() { return DriverTitle; }
void setTitle(std::string Value) { DriverTitle = std::move(Value); }
@@ -423,6 +425,10 @@ public:
// FIXME: This should be in CompilationInfo.
std::string GetProgramPath(StringRef Name, const ToolChain &TC) const;
+ /// handleAutocompletions - Handle --autocomplete by searching and printing
+ /// possible flags, descriptions, and its arguments.
+ void handleAutocompletions(StringRef PassedFlags) const;
+
/// HandleImmediateArgs - Handle any arguments which should be
/// treated before building actions or binding tools.
///
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Job.h b/contrib/llvm/tools/clang/include/clang/Driver/Job.h
index ff88256b8c0d6..b74b3b4b35e1b 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/Job.h
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Job.h
@@ -97,8 +97,8 @@ public:
virtual void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote,
CrashReportInfo *CrashInfo = nullptr) const;
- virtual int Execute(const StringRef **Redirects, std::string *ErrMsg,
- bool *ExecutionFailed) const;
+ virtual int Execute(ArrayRef<Optional<StringRef>> Redirects,
+ std::string *ErrMsg, bool *ExecutionFailed) const;
/// getSource - Return the Action which caused the creation of this job.
const Action &getSource() const { return Source; }
@@ -141,7 +141,7 @@ public:
void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote,
CrashReportInfo *CrashInfo = nullptr) const override;
- int Execute(const StringRef **Redirects, std::string *ErrMsg,
+ int Execute(ArrayRef<Optional<StringRef>> Redirects, std::string *ErrMsg,
bool *ExecutionFailed) const override;
private:
@@ -158,7 +158,7 @@ public:
void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote,
CrashReportInfo *CrashInfo = nullptr) const override;
- int Execute(const StringRef **Redirects, std::string *ErrMsg,
+ int Execute(ArrayRef<Optional<StringRef>> Redirects, std::string *ErrMsg,
bool *ExecutionFailed) const override;
};
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Options.td b/contrib/llvm/tools/clang/include/clang/Driver/Options.td
index 05dc9d7eb3ad9..d36e1a63220e9 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/Options.td
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Options.td
@@ -139,6 +139,10 @@ def m_arm_Features_Group : OptionGroup<"<arm features group>">,
Group<m_Group>, DocName<"ARM">;
def m_hexagon_Features_Group : OptionGroup<"<hexagon features group>">,
Group<m_Group>, DocName<"Hexagon">;
+// The features added by this group will not be added to target features.
+// These are explicitly handled.
+def m_hexagon_Features_HVX_Group : OptionGroup<"<hexagon features group>">,
+ Group<m_Group>, DocName<"Hexagon">;
def m_ppc_Features_Group : OptionGroup<"<ppc features group>">,
Group<m_Group>, DocName<"PowerPC">;
def m_wasm_Features_Group : OptionGroup<"<wasm features group>">,
@@ -459,6 +463,10 @@ def Xcuda_fatbinary : Separate<["-"], "Xcuda-fatbinary">,
HelpText<"Pass <arg> to fatbinary invocation">, MetaVarName<"<arg>">;
def Xcuda_ptxas : Separate<["-"], "Xcuda-ptxas">,
HelpText<"Pass <arg> to the ptxas assembler">, MetaVarName<"<arg>">;
+def Xopenmp_target : Separate<["-"], "Xopenmp-target">,
+ HelpText<"Pass <arg> to the target offloading toolchain.">, MetaVarName<"<arg>">;
+def Xopenmp_target_EQ : JoinedAndSeparate<["-"], "Xopenmp-target=">,
+ HelpText<"Pass <arg> to the specified target offloading toolchain. The triple that identifies the toolchain must be provided after the equals sign.">, MetaVarName<"<arg>">;
def z : Separate<["-"], "z">, Flags<[LinkerInput, RenderAsInput]>,
HelpText<"Pass -z <arg> to the linker">, MetaVarName<"<arg>">,
Group<Link_Group>;
@@ -511,7 +519,7 @@ def cl_fp32_correctly_rounded_divide_sqrt : Flag<["-"], "cl-fp32-correctly-round
def client__name : JoinedOrSeparate<["-"], "client_name">;
def combine : Flag<["-", "--"], "combine">, Flags<[DriverOption, Unsupported]>;
def compatibility__version : JoinedOrSeparate<["-"], "compatibility_version">;
-def coverage : Flag<["-", "--"], "coverage">;
+def coverage : Flag<["-", "--"], "coverage">, Flags<[CoreOption]>;
def cpp_precomp : Flag<["-"], "cpp-precomp">, Group<clang_ignored_f_Group>;
def current__version : JoinedOrSeparate<["-"], "current_version">;
def cxx_isystem : JoinedOrSeparate<["-"], "cxx-isystem">, Group<clang_i_Group>,
@@ -588,7 +596,9 @@ def fapple_kext : Flag<["-"], "fapple-kext">, Group<f_Group>, Flags<[CC1Option]>
HelpText<"Use Apple's kernel extensions ABI">;
def fapple_pragma_pack : Flag<["-"], "fapple-pragma-pack">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Enable Apple gcc-compatible #pragma pack handling">;
-def shared_libasan : Flag<["-"], "shared-libasan">;
+def shared_libsan : Flag<["-"], "shared-libsan">;
+def static_libsan : Flag<["-"], "static-libsan">;
+def : Flag<["-"], "shared-libasan">, Alias<shared_libsan>;
def fasm : Flag<["-"], "fasm">, Group<f_Group>;
def fasm_blocks : Flag<["-"], "fasm-blocks">, Group<f_Group>, Flags<[CC1Option]>;
@@ -600,6 +610,13 @@ def fastf : Flag<["-"], "fastf">, Group<f_Group>;
def fast : Flag<["-"], "fast">, Group<f_Group>;
def fasynchronous_unwind_tables : Flag<["-"], "fasynchronous-unwind-tables">, Group<f_Group>;
+def fdouble_square_bracket_attributes : Flag<[ "-" ], "fdouble-square-bracket-attributes">,
+ Group<f_Group>, Flags<[DriverOption, CC1Option]>,
+ HelpText<"Enable '[[]]' attributes in all C and C++ language modes">;
+def fno_double_square_bracket_attributes : Flag<[ "-" ], "fno-double-square-bracket-attributes">,
+ Group<f_Group>, Flags<[DriverOption, CC1Option]>,
+ HelpText<"Disable '[[]]' attributes in all C and C++ language modes">;
+
def fautolink : Flag <["-"], "fautolink">, Group<f_Group>;
def fno_autolink : Flag <["-"], "fno-autolink">, Group<f_Group>,
Flags<[DriverOption, CC1Option]>,
@@ -633,12 +650,25 @@ def fno_profile_sample_use : Flag<["-"], "fno-profile-sample-use">, Group<f_Grou
def fprofile_sample_use_EQ : Joined<["-"], "fprofile-sample-use=">,
Group<f_Group>, Flags<[DriverOption, CC1Option]>,
HelpText<"Enable sample-based profile guided optimizations">;
+def fprofile_sample_accurate : Flag<["-"], "fprofile-sample-accurate">,
+ Group<f_Group>, Flags<[DriverOption, CC1Option]>,
+ HelpText<"Specifies that the sample profile is accurate">,
+ DocBrief<[{Specifies that the sample profile is accurate. If the sample
+ profile is accurate, callsites without profile samples are marked
+ as cold. Otherwise, treat callsites without profile samples as if
+ we have no profile}]>;
+def fno_profile_sample_accurate : Flag<["-"], "fno-profile-sample-accurate">,
+ Group<f_Group>, Flags<[DriverOption]>;
def fauto_profile : Flag<["-"], "fauto-profile">, Group<f_Group>,
Alias<fprofile_sample_use>;
def fno_auto_profile : Flag<["-"], "fno-auto-profile">, Group<f_Group>,
Alias<fno_profile_sample_use>;
def fauto_profile_EQ : Joined<["-"], "fauto-profile=">,
Alias<fprofile_sample_use_EQ>;
+def fauto_profile_accurate : Flag<["-"], "fauto-profile-accurate">,
+ Group<f_Group>, Alias<fprofile_sample_accurate>;
+def fno_auto_profile_accurate : Flag<["-"], "fno-auto-profile-accurate">,
+ Group<f_Group>, Alias<fno_profile_sample_accurate>;
def fdebug_info_for_profiling : Flag<["-"], "fdebug-info-for-profiling">, Group<f_Group>,
Flags<[CC1Option]>,
HelpText<"Emit extra debug info to make sample profile more accurate.">;
@@ -770,8 +800,12 @@ def fencoding_EQ : Joined<["-"], "fencoding=">, Group<f_Group>;
def ferror_limit_EQ : Joined<["-"], "ferror-limit=">, Group<f_Group>, Flags<[CoreOption]>;
def fexceptions : Flag<["-"], "fexceptions">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Enable support for exception handling">;
+def fdwarf_exceptions : Flag<["-"], "fdwarf-exceptions">, Group<f_Group>,
+ Flags<[CC1Option]>, HelpText<"Use DWARF style exceptions">;
def fsjlj_exceptions : Flag<["-"], "fsjlj-exceptions">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Use SjLj style exceptions">;
+def fseh_exceptions : Flag<["-"], "fseh-exceptions">, Group<f_Group>,
+ Flags<[CC1Option]>, HelpText<"Use SEH style exceptions">;
def fexcess_precision_EQ : Joined<["-"], "fexcess-precision=">,
Group<clang_ignored_gcc_optimization_f_Group>;
def : Flag<["-"], "fexpensive-optimizations">, Group<clang_ignored_gcc_optimization_f_Group>;
@@ -834,6 +868,9 @@ def fno_sanitize_memory_track_origins : Flag<["-"], "fno-sanitize-memory-track-o
def fsanitize_memory_use_after_dtor : Flag<["-"], "fsanitize-memory-use-after-dtor">,
Group<f_clang_Group>,
HelpText<"Enable use-after-destroy detection in MemorySanitizer">;
+def fno_sanitize_memory_use_after_dtor : Flag<["-"], "fno-sanitize-memory-use-after-dtor">,
+ Group<f_clang_Group>,
+ HelpText<"Disable use-after-destroy detection in MemorySanitizer">;
def fsanitize_address_field_padding : Joined<["-"], "fsanitize-address-field-padding=">,
Group<f_clang_Group>,
HelpText<"Level of field padding for AddressSanitizer">;
@@ -868,6 +905,10 @@ def fsanitize_undefined_trap_on_error : Flag<["-"], "fsanitize-undefined-trap-on
Group<f_clang_Group>;
def fno_sanitize_undefined_trap_on_error : Flag<["-"], "fno-sanitize-undefined-trap-on-error">,
Group<f_clang_Group>;
+def fsanitize_minimal_runtime : Flag<["-"], "fsanitize-minimal-runtime">,
+ Group<f_clang_Group>;
+def fno_sanitize_minimal_runtime : Flag<["-"], "fno-sanitize-minimal-runtime">,
+ Group<f_clang_Group>;
def fsanitize_link_cxx_runtime : Flag<["-"], "fsanitize-link-c++-runtime">,
Group<f_clang_Group>;
def fsanitize_cfi_cross_dso : Flag<["-"], "fsanitize-cfi-cross-dso">,
@@ -877,6 +918,9 @@ def fno_sanitize_cfi_cross_dso : Flag<["-"], "fno-sanitize-cfi-cross-dso">,
Flags<[CoreOption, DriverOption]>,
Group<f_clang_Group>,
HelpText<"Disable control flow integrity (CFI) checks for cross-DSO calls.">;
+def fsanitize_cfi_icall_generalize_pointers : Flag<["-"], "fsanitize-cfi-icall-generalize-pointers">,
+ Group<f_clang_Group>,
+ HelpText<"Generalize pointers in CFI indirect call type signature checks">;
def fsanitize_stats : Flag<["-"], "fsanitize-stats">,
Group<f_clang_Group>,
HelpText<"Enable sanitizer statistics gathering.">;
@@ -988,6 +1032,10 @@ def finput_charset_EQ : Joined<["-"], "finput-charset=">, Group<f_Group>;
def fexec_charset_EQ : Joined<["-"], "fexec-charset=">, Group<f_Group>;
def finstrument_functions : Flag<["-"], "finstrument-functions">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Generate calls to instrument function entry and exit">;
+def finstrument_functions_after_inlining : Flag<["-"], "finstrument-functions-after-inlining">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Like -finstrument-functions, but insert the calls after inlining">;
+def finstrument_function_entry_bare : Flag<["-"], "finstrument-function-entry-bare">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Instrument function entry only, after inlining, without arguments to the instrumentation call">;
def fxray_instrument : Flag<["-"], "fxray-instrument">, Group<f_Group>,
Flags<[CC1Option]>,
@@ -1012,6 +1060,19 @@ def fxray_never_instrument :
Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Filename defining the whitelist for imbuing the 'never instrument' XRay attribute.">;
+def fxray_always_emit_customevents : Flag<["-"], "fxray-always-emit-customevents">, Group<f_Group>,
+ Flags<[CC1Option]>,
+ HelpText<"Determine whether to always emit __xray_customevent(...) calls even if the function it appears in is not always instrumented.">;
+def fnoxray_always_emit_customevents : Flag<["-"], "fno-xray-always-emit-customevents">, Group<f_Group>,
+ Flags<[CC1Option]>;
+
+def ffine_grained_bitfield_accesses : Flag<["-"],
+ "ffine-grained-bitfield-accesses">, Group<f_clang_Group>, Flags<[CC1Option]>,
+ HelpText<"Use separate accesses for bitfields with legal widths and alignments.">;
+def fno_fine_grained_bitfield_accesses : Flag<["-"],
+ "fno-fine-grained-bitfield-accesses">, Group<f_clang_Group>, Flags<[CC1Option]>,
+ HelpText<"Use large-integer access for consecutive bitfield runs.">;
+
def flat__namespace : Flag<["-"], "flat_namespace">;
def flax_vector_conversions : Flag<["-"], "flax-vector-conversions">, Group<f_Group>;
def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group<f_Group>;
@@ -1104,8 +1165,8 @@ def fmodule_map_file : Joined<["-"], "fmodule-map-file=">,
Group<f_Group>, Flags<[DriverOption,CC1Option]>, MetaVarName<"<file>">,
HelpText<"Load this module map file">;
def fmodule_file : Joined<["-"], "fmodule-file=">,
- Group<f_Group>, Flags<[DriverOption,CC1Option]>,
- HelpText<"Load this precompiled module file">, MetaVarName<"<file>">;
+ Group<i_Group>, Flags<[DriverOption,CC1Option]>, MetaVarName<"[<name>=]<file>">,
+ HelpText<"Specify the mapping of module name to precompiled module file, or load a module file if name is omitted.">;
def fmodules_ignore_macro : Joined<["-"], "fmodules-ignore-macro=">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Ignore the definition of the given macro when building and loading modules">;
def fmodules_decluse : Flag <["-"], "fmodules-decluse">, Group<f_Group>,
@@ -1310,6 +1371,10 @@ def fopenmp_targets_EQ : CommaJoined<["-"], "fopenmp-targets=">, Flags<[DriverOp
HelpText<"Specify comma-separated list of triples OpenMP offloading targets to be supported">;
def fopenmp_dump_offload_linker_script : Flag<["-"], "fopenmp-dump-offload-linker-script">, Group<f_Group>,
Flags<[NoArgumentUnused]>;
+def fopenmp_relocatable_target : Flag<["-"], "fopenmp-relocatable-target">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>,
+ HelpText<"OpenMP target code is compiled as relocatable using the -c flag. For OpenMP targets the code is relocatable by default.">;
+def fnoopenmp_relocatable_target : Flag<["-"], "fnoopenmp-relocatable-target">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>,
+ HelpText<"Do not compile OpenMP target code as relocatable.">;
def fno_optimize_sibling_calls : Flag<["-"], "fno-optimize-sibling-calls">, Group<f_Group>;
def foptimize_sibling_calls : Flag<["-"], "foptimize-sibling-calls">, Group<f_Group>;
def force__cpusubtype__ALL : Flag<["-"], "force_cpusubtype_ALL">;
@@ -1333,6 +1398,10 @@ def fpic : Flag<["-"], "fpic">, Group<f_Group>;
def fno_pic : Flag<["-"], "fno-pic">, Group<f_Group>;
def fpie : Flag<["-"], "fpie">, Group<f_Group>;
def fno_pie : Flag<["-"], "fno-pie">, Group<f_Group>;
+def fplt : Flag<["-"], "fplt">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Use the PLT to make function calls">;
+def fno_plt : Flag<["-"], "fno-plt">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Do not use the PLT to make function calls">;
def fropi : Flag<["-"], "fropi">, Group<f_Group>;
def fno_ropi : Flag<["-"], "fno-ropi">, Group<f_Group>;
def frwpi : Flag<["-"], "frwpi">, Group<f_Group>;
@@ -1352,9 +1421,9 @@ def frtti : Flag<["-"], "frtti">, Group<f_Group>;
def : Flag<["-"], "fsched-interblock">, Group<clang_ignored_f_Group>;
def fshort_enums : Flag<["-"], "fshort-enums">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Allocate to an enum type only as many bytes as it needs for the declared range of possible values">;
-def fshort_wchar : Flag<["-"], "fshort-wchar">, Group<f_Group>, Flags<[CC1Option]>,
+def fshort_wchar : Flag<["-"], "fshort-wchar">, Group<f_Group>,
HelpText<"Force wchar_t to be a short unsigned int">;
-def fno_short_wchar : Flag<["-"], "fno-short-wchar">, Group<f_Group>, Flags<[CC1Option]>,
+def fno_short_wchar : Flag<["-"], "fno-short-wchar">, Group<f_Group>,
HelpText<"Force wchar_t to be an unsigned int">;
def fshow_overloads_EQ : Joined<["-"], "fshow-overloads=">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Which overload candidates to show when overload resolution fails: "
@@ -1477,9 +1546,10 @@ def fvisibility_ms_compat : Flag<["-"], "fvisibility-ms-compat">, Group<f_Group>
HelpText<"Give global types 'default' visibility and global functions and "
"variables 'hidden' visibility by default">;
def fwhole_program_vtables : Flag<["-"], "fwhole-program-vtables">, Group<f_Group>,
- Flags<[CC1Option]>,
+ Flags<[CoreOption, CC1Option]>,
HelpText<"Enables whole-program vtable optimization. Requires -flto">;
-def fno_whole_program_vtables : Flag<["-"], "fno-whole-program-vtables">, Group<f_Group>;
+def fno_whole_program_vtables : Flag<["-"], "fno-whole-program-vtables">, Group<f_Group>,
+ Flags<[CoreOption]>;
def fwrapv : Flag<["-"], "fwrapv">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Treat signed integer overflow as two's complement">;
def fwritable_strings : Flag<["-"], "fwritable-strings">, Group<f_Group>, Flags<[CC1Option]>,
@@ -1571,7 +1641,7 @@ def gno_strict_dwarf : Flag<["-"], "gno-strict-dwarf">, Group<g_flags_Group>;
def gcolumn_info : Flag<["-"], "gcolumn-info">, Group<g_flags_Group>, Flags<[CoreOption]>;
def gno_column_info : Flag<["-"], "gno-column-info">, Group<g_flags_Group>, Flags<[CoreOption]>;
def gsplit_dwarf : Flag<["-"], "gsplit-dwarf">, Group<g_flags_Group>;
-def ggnu_pubnames : Flag<["-"], "ggnu-pubnames">, Group<g_flags_Group>;
+def ggnu_pubnames : Flag<["-"], "ggnu-pubnames">, Group<g_flags_Group>, Flags<[CC1Option]>;
def gdwarf_aranges : Flag<["-"], "gdwarf-aranges">, Group<g_flags_Group>;
def gmodules : Flag <["-"], "gmodules">, Group<gN_Group>,
HelpText<"Generate debug info with external references to clang modules"
@@ -1644,8 +1714,6 @@ def m16 : Flag<["-"], "m16">, Group<m_Group>, Flags<[DriverOption, CoreOption]>;
def m32 : Flag<["-"], "m32">, Group<m_Group>, Flags<[DriverOption, CoreOption]>;
def mqdsp6_compat : Flag<["-"], "mqdsp6-compat">, Group<m_Group>, Flags<[DriverOption,CC1Option]>,
HelpText<"Enable hexagon-qdsp6 backward compatibility">;
-def m3dnowa : Flag<["-"], "m3dnowa">, Group<m_x86_Features_Group>;
-def m3dnow : Flag<["-"], "m3dnow">, Group<m_x86_Features_Group>;
def m64 : Flag<["-"], "m64">, Group<m_Group>, Flags<[DriverOption, CoreOption]>;
def mx32 : Flag<["-"], "mx32">, Group<m_Group>, Flags<[DriverOption, CoreOption]>;
def mabi_EQ : Joined<["-"], "mabi=">, Group<m_Group>;
@@ -1664,6 +1732,8 @@ def mexecute_only : Flag<["-"], "mexecute-only">, Group<m_arm_Features_Group>,
HelpText<"Disallow generation of data access to code sections (ARM only)">;
def mno_execute_only : Flag<["-"], "mno-execute-only">, Group<m_arm_Features_Group>,
HelpText<"Allow generation of data access to code sections (ARM only)">;
+def mtp_mode_EQ : Joined<["-"], "mtp=">, Group<m_arm_Features_Group>, Values<"soft, cp15">,
+ HelpText<"Read thread pointer from coprocessor register (ARM only)">;
def mpure_code : Flag<["-"], "mpure-code">, Alias<mexecute_only>; // Alias for GCC compatibility
def mno_pure_code : Flag<["-"], "mno-pure-code">, Alias<mno_execute_only>;
def mtvos_version_min_EQ : Joined<["-"], "mtvos-version-min=">, Group<m_Group>;
@@ -1730,13 +1800,9 @@ def mthread_model : Separate<["-"], "mthread-model">, Group<m_Group>, Flags<[CC1
def meabi : Separate<["-"], "meabi">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Set EABI type, e.g. 4, 5 or gnu (default depends on triple)">, Values<"default,4,5,gnu">;
-def mmmx : Flag<["-"], "mmmx">, Group<m_x86_Features_Group>;
-def mno_3dnowa : Flag<["-"], "mno-3dnowa">, Group<m_x86_Features_Group>;
-def mno_3dnow : Flag<["-"], "mno-3dnow">, Group<m_x86_Features_Group>;
def mno_constant_cfstrings : Flag<["-"], "mno-constant-cfstrings">, Group<m_Group>;
def mno_global_merge : Flag<["-"], "mno-global-merge">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Disable merging of globals">;
-def mno_mmx : Flag<["-"], "mno-mmx">, Group<m_x86_Features_Group>;
def mno_pascal_strings : Flag<["-"], "mno-pascal-strings">,
Alias<fno_pascal_strings>;
def mno_red_zone : Flag<["-"], "mno-red-zone">, Group<m_Group>;
@@ -1744,65 +1810,6 @@ def mno_relax_all : Flag<["-"], "mno-relax-all">, Group<m_Group>;
def mno_rtd: Flag<["-"], "mno-rtd">, Group<m_Group>;
def mno_soft_float : Flag<["-"], "mno-soft-float">, Group<m_Group>;
def mno_stackrealign : Flag<["-"], "mno-stackrealign">, Group<m_Group>;
-def mno_x87 : Flag<["-"], "mno-x87">, Group<m_x86_Features_Group>;
-def mno_80387 : Flag<["-"], "mno-80387">, Alias<mno_x87>;
-def mno_sse2 : Flag<["-"], "mno-sse2">, Group<m_x86_Features_Group>;
-def mno_sse3 : Flag<["-"], "mno-sse3">, Group<m_x86_Features_Group>;
-def mno_sse4a : Flag<["-"], "mno-sse4a">, Group<m_x86_Features_Group>;
-def mno_sse4_1 : Flag<["-"], "mno-sse4.1">, Group<m_x86_Features_Group>;
-def mno_sse4_2 : Flag<["-"], "mno-sse4.2">, Group<m_x86_Features_Group>;
-// -mno-sse4 turns off sse4.1 which has the effect of turning off everything
-// later than 4.1. -msse4 turns on 4.2 which has the effect of turning on
-// everything earlier than 4.2.
-def mno_sse4 : Flag<["-"], "mno-sse4">, Alias<mno_sse4_1>;
-def mno_sse : Flag<["-"], "mno-sse">, Group<m_x86_Features_Group>;
-def mno_ssse3 : Flag<["-"], "mno-ssse3">, Group<m_x86_Features_Group>;
-def mno_aes : Flag<["-"], "mno-aes">, Group<m_x86_Features_Group>;
-def mno_avx : Flag<["-"], "mno-avx">, Group<m_x86_Features_Group>;
-def mno_avx2 : Flag<["-"], "mno-avx2">, Group<m_x86_Features_Group>;
-def mno_avx512f : Flag<["-"], "mno-avx512f">, Group<m_x86_Features_Group>;
-def mno_avx512cd : Flag<["-"], "mno-avx512cd">, Group<m_x86_Features_Group>;
-def mno_avx512vpopcntdq : Flag<["-"], "mno-avx512vpopcntdq">, Group<m_x86_Features_Group>;
-def mno_avx512er : Flag<["-"], "mno-avx512er">, Group<m_x86_Features_Group>;
-def mno_avx512pf : Flag<["-"], "mno-avx512pf">, Group<m_x86_Features_Group>;
-def mno_avx512dq : Flag<["-"], "mno-avx512dq">, Group<m_x86_Features_Group>;
-def mno_avx512bw : Flag<["-"], "mno-avx512bw">, Group<m_x86_Features_Group>;
-def mno_avx512vl : Flag<["-"], "mno-avx512vl">, Group<m_x86_Features_Group>;
-def mno_avx512vbmi : Flag<["-"], "mno-avx512vbmi">, Group<m_x86_Features_Group>;
-def mno_avx512ifma : Flag<["-"], "mno-avx512ifma">, Group<m_x86_Features_Group>;
-def mno_pclmul : Flag<["-"], "mno-pclmul">, Group<m_x86_Features_Group>;
-def mno_lzcnt : Flag<["-"], "mno-lzcnt">, Group<m_x86_Features_Group>;
-def mno_rdrnd : Flag<["-"], "mno-rdrnd">, Group<m_x86_Features_Group>;
-def mno_fsgsbase : Flag<["-"], "mno-fsgsbase">, Group<m_x86_Features_Group>;
-def mno_bmi : Flag<["-"], "mno-bmi">, Group<m_x86_Features_Group>;
-def mno_bmi2 : Flag<["-"], "mno-bmi2">, Group<m_x86_Features_Group>;
-def mno_popcnt : Flag<["-"], "mno-popcnt">, Group<m_x86_Features_Group>;
-def mno_tbm : Flag<["-"], "mno-tbm">, Group<m_x86_Features_Group>;
-def mno_lwp : Flag<["-"], "mno-lwp">, Group<m_x86_Features_Group>;
-def mno_fma4 : Flag<["-"], "mno-fma4">, Group<m_x86_Features_Group>;
-def mno_fma : Flag<["-"], "mno-fma">, Group<m_x86_Features_Group>;
-def mno_xop : Flag<["-"], "mno-xop">, Group<m_x86_Features_Group>;
-def mno_f16c : Flag<["-"], "mno-f16c">, Group<m_x86_Features_Group>;
-def mno_rtm : Flag<["-"], "mno-rtm">, Group<m_x86_Features_Group>;
-def mno_prfchw : Flag<["-"], "mno-prfchw">, Group<m_x86_Features_Group>;
-def mno_rdseed : Flag<["-"], "mno-rdseed">, Group<m_x86_Features_Group>;
-def mno_adx : Flag<["-"], "mno-adx">, Group<m_x86_Features_Group>;
-def mno_sha : Flag<["-"], "mno-sha">, Group<m_x86_Features_Group>;
-def mno_cx16 : Flag<["-"], "mno-cx16">, Group<m_x86_Features_Group>;
-def mno_fxsr : Flag<["-"], "mno-fxsr">, Group<m_x86_Features_Group>;
-def mno_xsave : Flag<["-"], "mno-xsave">, Group<m_x86_Features_Group>;
-def mno_xsaveopt : Flag<["-"], "mno-xsaveopt">, Group<m_x86_Features_Group>;
-def mno_xsavec : Flag<["-"], "mno-xsavec">, Group<m_x86_Features_Group>;
-def mno_xsaves : Flag<["-"], "mno-xsaves">, Group<m_x86_Features_Group>;
-def mno_mwaitx : Flag<["-"], "mno-mwaitx">, Group<m_x86_Features_Group>;
-def mno_clzero : Flag<["-"], "mno-clzero">, Group<m_x86_Features_Group>;
-def mno_pku : Flag<["-"], "mno-pku">, Group<m_x86_Features_Group>;
-def mno_clflushopt : Flag<["-"], "mno-clflushopt">, Group<m_x86_Features_Group>;
-def mno_clwb : Flag<["-"], "mno-clwb">, Group<m_x86_Features_Group>;
-def mno_movbe : Flag<["-"], "mno-movbe">, Group<m_x86_Features_Group>;
-def mno_mpx : Flag<["-"], "mno-mpx">, Group<m_x86_Features_Group>;
-def mno_sgx : Flag<["-"], "mno-sgx">, Group<m_x86_Features_Group>;
-def mno_prefetchwt1 : Flag<["-"], "mno-prefetchwt1">, Group<m_x86_Features_Group>;
def munaligned_access : Flag<["-"], "munaligned-access">, Group<m_arm_Features_Group>,
HelpText<"Allow memory accesses to be unaligned (AArch32/AArch64 only)">;
@@ -1829,7 +1836,6 @@ def mno_neg_immediates: Flag<["-"], "mno-neg-immediates">, Group<m_arm_Features_
def mgeneral_regs_only : Flag<["-"], "mgeneral-regs-only">, Group<m_aarch64_Features_Group>,
HelpText<"Generate code which only uses the general purpose registers (AArch64 only)">;
-
def mfix_cortex_a53_835769 : Flag<["-"], "mfix-cortex-a53-835769">,
Group<m_aarch64_Features_Group>,
HelpText<"Workaround Cortex-A53 erratum 835769 (AArch64 only)">;
@@ -1841,12 +1847,18 @@ def ffixed_x18 : Flag<["-"], "ffixed-x18">, Group<m_aarch64_Features_Group>,
def msimd128 : Flag<["-"], "msimd128">, Group<m_wasm_Features_Group>;
def mno_simd128 : Flag<["-"], "mno-simd128">, Group<m_wasm_Features_Group>;
+def mnontrapping_fptoint : Flag<["-"], "mnontrapping-fptoint">, Group<m_wasm_Features_Group>;
+def mno_nontrapping_fptoint : Flag<["-"], "mno-nontrapping-fptoint">, Group<m_wasm_Features_Group>;
def mamdgpu_debugger_abi : Joined<["-"], "mamdgpu-debugger-abi=">,
Flags<[HelpHidden]>,
Group<m_Group>,
HelpText<"Generate additional code for specified <version> of debugger ABI (AMDGPU only)">,
MetaVarName<"<version>">;
+def mxnack : Flag<["-"], "mxnack">, Group<m_amdgpu_Features_Group>,
+ HelpText<"Enable XNACK (AMDGPU only)">;
+def mno_xnack : Flag<["-"], "mno-xnack">, Group<m_amdgpu_Features_Group>,
+ HelpText<"Disable XNACK (AMDGPU only)">;
def faltivec : Flag<["-"], "faltivec">, Group<f_Group>, Flags<[DriverOption]>;
def fno_altivec : Flag<["-"], "fno-altivec">, Group<f_Group>, Flags<[DriverOption]>;
@@ -1942,68 +1954,14 @@ def mno_implicit_float : Flag<["-"], "mno-implicit-float">, Group<m_Group>,
def mimplicit_float : Flag<["-"], "mimplicit-float">, Group<m_Group>;
def mrecip : Flag<["-"], "mrecip">, Group<m_Group>;
def mrecip_EQ : CommaJoined<["-"], "mrecip=">, Group<m_Group>, Flags<[CC1Option]>;
+def mprefer_vector_width_EQ : Joined<["-"], "mprefer-vector-width=">, Group<m_Group>, Flags<[CC1Option]>,
+ HelpText<"Specifies preferred vector width for auto-vectorization. Defaults to 'none' which allows target specific decisions.">;
def mpie_copy_relocations : Flag<["-"], "mpie-copy-relocations">, Group<m_Group>,
Flags<[CC1Option]>,
HelpText<"Use copy relocations support for PIE builds">;
def mno_pie_copy_relocations : Flag<["-"], "mno-pie-copy-relocations">, Group<m_Group>;
def mfentry : Flag<["-"], "mfentry">, HelpText<"Insert calls to fentry at function entry (x86 only)">,
Flags<[CC1Option]>, Group<m_Group>;
-def mx87 : Flag<["-"], "mx87">, Group<m_x86_Features_Group>;
-def m80387 : Flag<["-"], "m80387">, Alias<mx87>;
-def msse2 : Flag<["-"], "msse2">, Group<m_x86_Features_Group>;
-def msse3 : Flag<["-"], "msse3">, Group<m_x86_Features_Group>;
-def msse4a : Flag<["-"], "msse4a">, Group<m_x86_Features_Group>;
-def msse4_1 : Flag<["-"], "msse4.1">, Group<m_x86_Features_Group>;
-def msse4_2 : Flag<["-"], "msse4.2">, Group<m_x86_Features_Group>;
-def msse4 : Flag<["-"], "msse4">, Alias<msse4_2>;
-def msse : Flag<["-"], "msse">, Group<m_x86_Features_Group>;
-def mssse3 : Flag<["-"], "mssse3">, Group<m_x86_Features_Group>;
-def maes : Flag<["-"], "maes">, Group<m_x86_Features_Group>;
-def mavx : Flag<["-"], "mavx">, Group<m_x86_Features_Group>;
-def mavx2 : Flag<["-"], "mavx2">, Group<m_x86_Features_Group>;
-def mavx512f : Flag<["-"], "mavx512f">, Group<m_x86_Features_Group>;
-def mavx512cd : Flag<["-"], "mavx512cd">, Group<m_x86_Features_Group>;
-def mavx512vpopcntdq : Flag<["-"], "mavx512vpopcntdq">, Group<m_x86_Features_Group>;
-def mavx512er : Flag<["-"], "mavx512er">, Group<m_x86_Features_Group>;
-def mavx512pf : Flag<["-"], "mavx512pf">, Group<m_x86_Features_Group>;
-def mavx512dq : Flag<["-"], "mavx512dq">, Group<m_x86_Features_Group>;
-def mavx512bw : Flag<["-"], "mavx512bw">, Group<m_x86_Features_Group>;
-def mavx512vl : Flag<["-"], "mavx512vl">, Group<m_x86_Features_Group>;
-def mavx512vbmi : Flag<["-"], "mavx512vbmi">, Group<m_x86_Features_Group>;
-def mavx512ifma : Flag<["-"], "mavx512ifma">, Group<m_x86_Features_Group>;
-def mpclmul : Flag<["-"], "mpclmul">, Group<m_x86_Features_Group>;
-def mlzcnt : Flag<["-"], "mlzcnt">, Group<m_x86_Features_Group>;
-def mrdrnd : Flag<["-"], "mrdrnd">, Group<m_x86_Features_Group>;
-def mfsgsbase : Flag<["-"], "mfsgsbase">, Group<m_x86_Features_Group>;
-def mbmi : Flag<["-"], "mbmi">, Group<m_x86_Features_Group>;
-def mbmi2 : Flag<["-"], "mbmi2">, Group<m_x86_Features_Group>;
-def mpopcnt : Flag<["-"], "mpopcnt">, Group<m_x86_Features_Group>;
-def mtbm : Flag<["-"], "mtbm">, Group<m_x86_Features_Group>;
-def mlwp : Flag<["-"], "mlwp">, Group<m_x86_Features_Group>;
-def mfma4 : Flag<["-"], "mfma4">, Group<m_x86_Features_Group>;
-def mfma : Flag<["-"], "mfma">, Group<m_x86_Features_Group>;
-def mxop : Flag<["-"], "mxop">, Group<m_x86_Features_Group>;
-def mf16c : Flag<["-"], "mf16c">, Group<m_x86_Features_Group>;
-def mrtm : Flag<["-"], "mrtm">, Group<m_x86_Features_Group>;
-def mprfchw : Flag<["-"], "mprfchw">, Group<m_x86_Features_Group>;
-def mrdseed : Flag<["-"], "mrdseed">, Group<m_x86_Features_Group>;
-def mpku : Flag<["-"], "mpku">, Group<m_x86_Features_Group>;
-def madx : Flag<["-"], "madx">, Group<m_x86_Features_Group>;
-def msha : Flag<["-"], "msha">, Group<m_x86_Features_Group>;
-def mcx16 : Flag<["-"], "mcx16">, Group<m_x86_Features_Group>;
-def mfxsr : Flag<["-"], "mfxsr">, Group<m_x86_Features_Group>;
-def mxsave : Flag<["-"], "mxsave">, Group<m_x86_Features_Group>;
-def mxsaveopt : Flag<["-"], "mxsaveopt">, Group<m_x86_Features_Group>;
-def mxsavec : Flag<["-"], "mxsavec">, Group<m_x86_Features_Group>;
-def mxsaves : Flag<["-"], "mxsaves">, Group<m_x86_Features_Group>;
-def mmwaitx : Flag<["-"], "mmwaitx">, Group<m_x86_Features_Group>;
-def mclzero : Flag<["-"], "mclzero">, Group<m_x86_Features_Group>;
-def mclflushopt : Flag<["-"], "mclflushopt">, Group<m_x86_Features_Group>;
-def mclwb : Flag<["-"], "mclwb">, Group<m_x86_Features_Group>;
-def mmovbe : Flag<["-"], "mmovbe">, Group<m_x86_Features_Group>;
-def mmpx : Flag<["-"], "mmpx">, Group<m_x86_Features_Group>;
-def msgx : Flag<["-"], "msgx">, Group<m_x86_Features_Group>;
-def mprefetchwt1 : Flag<["-"], "mprefetchwt1">, Group<m_x86_Features_Group>;
def mips16 : Flag<["-"], "mips16">, Group<m_Group>;
def mno_mips16 : Flag<["-"], "mno-mips16">, Group<m_Group>;
def mmicromips : Flag<["-"], "mmicromips">, Group<m_Group>;
@@ -2016,6 +1974,10 @@ def mcheck_zero_division : Flag<["-"], "mcheck-zero-division">, Group<m_Group>;
def mno_check_zero_division : Flag<["-"], "mno-check-zero-division">,
Group<m_Group>;
def mcompact_branches_EQ : Joined<["-"], "mcompact-branches=">, Group<m_Group>;
+def mbranch_likely : Flag<["-"], "mbranch-likely">, Group<m_Group>,
+ IgnoredGCCCompat;
+def mno_branch_likely : Flag<["-"], "mno-branch-likely">, Group<m_Group>,
+ IgnoredGCCCompat;
def mdsp : Flag<["-"], "mdsp">, Group<m_Group>;
def mno_dsp : Flag<["-"], "mno-dsp">, Group<m_Group>;
def mdspr2 : Flag<["-"], "mdspr2">, Group<m_Group>;
@@ -2038,7 +2000,30 @@ def mfp64 : Flag<["-"], "mfp64">, Group<m_Group>,
HelpText<"Use 64-bit floating point registers (MIPS only)">;
def mfp32 : Flag<["-"], "mfp32">, Group<m_Group>,
HelpText<"Use 32-bit floating point registers (MIPS only)">;
+def mgpopt : Flag<["-"], "mgpopt">, Group<m_Group>,
+ HelpText<"Use GP relative accesses for symbols known to be in a small"
+ " data section (MIPS)">;
+def mno_gpopt : Flag<["-"], "mno-gpopt">, Group<m_Group>,
+ HelpText<"Do not use GP relative accesses for symbols known to be in a small"
+ " data section (MIPS)">;
+def mlocal_sdata : Flag<["-"], "mlocal-sdata">, Group<m_Group>,
+ HelpText<"Extend the -G behaviour to object local data (MIPS)">;
+def mno_local_sdata : Flag<["-"], "mno-local-sdata">, Group<m_Group>,
+ HelpText<"Do not extend the -G behaviour to object local data (MIPS)">;
+def mextern_sdata : Flag<["-"], "mextern-sdata">, Group<m_Group>,
+ HelpText<"Assume that externally defined data is in the small data if it"
+ " meets the -G <size> threshold (MIPS)">;
+def mno_extern_sdata : Flag<["-"], "mno-extern-sdata">, Group<m_Group>,
+ HelpText<"Do not assume that externally defined data is in the small data if"
+ " it meets the -G <size> threshold (MIPS)">;
+def membedded_data : Flag<["-"], "membedded-data">, Group<m_Group>,
+ HelpText<"Place constants in the .rodata section instead of the .sdata "
+ "section even if they meet the -G <size> threshold (MIPS)">;
+def mno_embedded_data : Flag<["-"], "mno-embedded-data">, Group<m_Group>,
+ HelpText<"Do not place constants in the .rodata section instead of the "
+ ".sdata if they meet the -G <size> threshold (MIPS)">;
def mnan_EQ : Joined<["-"], "mnan=">, Group<m_Group>;
+def mabs_EQ : Joined<["-"], "mabs=">, Group<m_Group>;
def mabicalls : Flag<["-"], "mabicalls">, Group<m_Group>,
HelpText<"Enable SVR4-style position-independent code (Mips only)">;
def mno_abicalls : Flag<["-"], "mno-abicalls">, Group<m_Group>,
@@ -2131,6 +2116,7 @@ def nostdlibinc : Flag<["-"], "nostdlibinc">;
def nostdincxx : Flag<["-"], "nostdinc++">, Flags<[CC1Option]>,
HelpText<"Disable standard #include directories for the C++ standard library">;
def nostdlib : Flag<["-"], "nostdlib">;
+def nostdlibxx : Flag<["-"], "nostdlib++">;
def object : Flag<["-"], "object">;
def o : JoinedOrSeparate<["-"], "o">, Flags<[DriverOption, RenderAsInput, CC1Option, CC1AsOption]>,
HelpText<"Write output to <file>">, MetaVarName<"<file>">;
@@ -2225,7 +2211,14 @@ def static_libstdcxx : Flag<["-"], "static-libstdc++">;
def static : Flag<["-", "--"], "static">, Flags<[NoArgumentUnused]>;
def std_default_EQ : Joined<["-"], "std-default=">;
def std_EQ : Joined<["-", "--"], "std=">, Flags<[CC1Option]>,
- Group<CompileOnly_Group>, HelpText<"Language standard to compile for">;
+ Group<CompileOnly_Group>, HelpText<"Language standard to compile for">,
+ ValuesCode<[{
+ const char *Values =
+ #define LANGSTANDARD(id, name, lang, desc, features) name ","
+ #define LANGSTANDARD_ALIAS(id, alias) alias ","
+ #include "clang/Frontend/LangStandards.def"
+ ;
+ }]>;
def stdlib_EQ : Joined<["-", "--"], "stdlib=">, Flags<[CC1Option]>,
HelpText<"C++ standard library to use">, Values<"libc++,libstdc++,platform">;
def sub__library : JoinedOrSeparate<["-"], "sub_library">;
@@ -2383,7 +2376,8 @@ def _rtlib : Separate<["--"], "rtlib">, Alias<rtlib_EQ>;
def _serialize_diags : Separate<["-", "--"], "serialize-diagnostics">, Flags<[DriverOption]>,
HelpText<"Serialize compiler diagnostics to a file">;
// We give --version different semantics from -version.
-def _version : Flag<["--"], "version">, Flags<[CC1Option]>;
+def _version : Flag<["--"], "version">, Flags<[CoreOption, CC1Option]>,
+ HelpText<"Print version information">;
def _signed_char : Flag<["--"], "signed-char">, Alias<fsigned_char>;
def _std : Separate<["--"], "std">, Alias<std_EQ>;
def _stdlib : Separate<["--"], "stdlib">, Alias<stdlib_EQ>;
@@ -2413,14 +2407,156 @@ def mv60 : Flag<["-"], "mv60">, Group<m_hexagon_Features_Group>,
Alias<mcpu_EQ>, AliasArgs<["hexagonv60"]>;
def mv62 : Flag<["-"], "mv62">, Group<m_hexagon_Features_Group>,
Alias<mcpu_EQ>, AliasArgs<["hexagonv62"]>;
-def mhexagon_hvx : Flag<["-"], "mhvx">, Group<m_hexagon_Features_Group>,
- Flags<[CC1Option]>, HelpText<"Enable Hexagon Vector eXtensions">;
-def mno_hexagon_hvx : Flag<["-"], "mno-hvx">, Group<m_hexagon_Features_Group>,
- Flags<[CC1Option]>, HelpText<"Disable Hexagon Vector eXtensions">;
-def mhexagon_hvx_double : Flag<["-"], "mhvx-double">, Group<m_hexagon_Features_Group>,
- Flags<[CC1Option]>, HelpText<"Enable Hexagon Double Vector eXtensions">;
-def mno_hexagon_hvx_double : Flag<["-"], "mno-hvx-double">, Group<m_hexagon_Features_Group>,
- Flags<[CC1Option]>, HelpText<"Disable Hexagon Double Vector eXtensions">;
+def mv65 : Flag<["-"], "mv65">, Group<m_hexagon_Features_Group>,
+ Alias<mcpu_EQ>, AliasArgs<["hexagonv65"]>;
+def mhexagon_hvx : Flag<[ "-" ], "mhvx">,
+ Group<m_hexagon_Features_HVX_Group>,
+ HelpText<"Enable Hexagon Vector eXtensions">;
+def mhexagon_hvx_EQ : Joined<[ "-" ], "mhvx=">,
+ Group<m_hexagon_Features_HVX_Group>,
+ HelpText<"Enable Hexagon Vector eXtensions">;
+def mno_hexagon_hvx : Flag<[ "-" ], "mno-hvx">,
+ Group<m_hexagon_Features_HVX_Group>,
+ HelpText<"Disable Hexagon Vector eXtensions">;
+def mhexagon_hvx_length_EQ : Joined<[ "-" ], "mhvx-length=">,
+ Group<m_hexagon_Features_HVX_Group>,
+ HelpText<"Set Hexagon Vector Length">, Values<"64B,128B">;
+// hvx-double deprecrated flag.
+def mhexagon_hvx_double : Flag<[ "-" ], "mhvx-double">,
+ Group<m_hexagon_Features_HVX_Group>,
+ HelpText<"Enable Hexagon Double Vector eXtensions">;
+def mno_hexagon_hvx_double
+ : Flag<[ "-" ], "mno-hvx-double">,
+ Group<m_hexagon_Features_HVX_Group>,
+ HelpText<"Disable Hexagon Double Vector eXtensions">;
+
+
+// X86 feature flags
+def mx87 : Flag<["-"], "mx87">, Group<m_x86_Features_Group>;
+def mno_x87 : Flag<["-"], "mno-x87">, Group<m_x86_Features_Group>;
+def m80387 : Flag<["-"], "m80387">, Alias<mx87>;
+def mno_80387 : Flag<["-"], "mno-80387">, Alias<mno_x87>;
+def mmmx : Flag<["-"], "mmmx">, Group<m_x86_Features_Group>;
+def mno_mmx : Flag<["-"], "mno-mmx">, Group<m_x86_Features_Group>;
+def m3dnow : Flag<["-"], "m3dnow">, Group<m_x86_Features_Group>;
+def mno_3dnow : Flag<["-"], "mno-3dnow">, Group<m_x86_Features_Group>;
+def m3dnowa : Flag<["-"], "m3dnowa">, Group<m_x86_Features_Group>;
+def mno_3dnowa : Flag<["-"], "mno-3dnowa">, Group<m_x86_Features_Group>;
+def msse : Flag<["-"], "msse">, Group<m_x86_Features_Group>;
+def mno_sse : Flag<["-"], "mno-sse">, Group<m_x86_Features_Group>;
+def msse2 : Flag<["-"], "msse2">, Group<m_x86_Features_Group>;
+def mno_sse2 : Flag<["-"], "mno-sse2">, Group<m_x86_Features_Group>;
+def msse3 : Flag<["-"], "msse3">, Group<m_x86_Features_Group>;
+def mno_sse3 : Flag<["-"], "mno-sse3">, Group<m_x86_Features_Group>;
+def mssse3 : Flag<["-"], "mssse3">, Group<m_x86_Features_Group>;
+def mno_ssse3 : Flag<["-"], "mno-ssse3">, Group<m_x86_Features_Group>;
+def msse4_1 : Flag<["-"], "msse4.1">, Group<m_x86_Features_Group>;
+def mno_sse4_1 : Flag<["-"], "mno-sse4.1">, Group<m_x86_Features_Group>;
+def msse4_2 : Flag<["-"], "msse4.2">, Group<m_x86_Features_Group>;
+def mno_sse4_2 : Flag<["-"], "mno-sse4.2">, Group<m_x86_Features_Group>;
+def msse4 : Flag<["-"], "msse4">, Alias<msse4_2>;
+// -mno-sse4 turns off sse4.1 which has the effect of turning off everything
+// later than 4.1. -msse4 turns on 4.2 which has the effect of turning on
+// everything earlier than 4.2.
+def mno_sse4 : Flag<["-"], "mno-sse4">, Alias<mno_sse4_1>;
+def msse4a : Flag<["-"], "msse4a">, Group<m_x86_Features_Group>;
+def mno_sse4a : Flag<["-"], "mno-sse4a">, Group<m_x86_Features_Group>;
+def mavx : Flag<["-"], "mavx">, Group<m_x86_Features_Group>;
+def mno_avx : Flag<["-"], "mno-avx">, Group<m_x86_Features_Group>;
+def mavx2 : Flag<["-"], "mavx2">, Group<m_x86_Features_Group>;
+def mno_avx2 : Flag<["-"], "mno-avx2">, Group<m_x86_Features_Group>;
+def mavx512f : Flag<["-"], "mavx512f">, Group<m_x86_Features_Group>;
+def mno_avx512f : Flag<["-"], "mno-avx512f">, Group<m_x86_Features_Group>;
+def mavx512bw : Flag<["-"], "mavx512bw">, Group<m_x86_Features_Group>;
+def mno_avx512bw : Flag<["-"], "mno-avx512bw">, Group<m_x86_Features_Group>;
+def mavx512cd : Flag<["-"], "mavx512cd">, Group<m_x86_Features_Group>;
+def mno_avx512cd : Flag<["-"], "mno-avx512cd">, Group<m_x86_Features_Group>;
+def mavx512dq : Flag<["-"], "mavx512dq">, Group<m_x86_Features_Group>;
+def mno_avx512dq : Flag<["-"], "mno-avx512dq">, Group<m_x86_Features_Group>;
+def mavx512er : Flag<["-"], "mavx512er">, Group<m_x86_Features_Group>;
+def mno_avx512er : Flag<["-"], "mno-avx512er">, Group<m_x86_Features_Group>;
+def mavx512ifma : Flag<["-"], "mavx512ifma">, Group<m_x86_Features_Group>;
+def mno_avx512ifma : Flag<["-"], "mno-avx512ifma">, Group<m_x86_Features_Group>;
+def mavx512pf : Flag<["-"], "mavx512pf">, Group<m_x86_Features_Group>;
+def mno_avx512pf : Flag<["-"], "mno-avx512pf">, Group<m_x86_Features_Group>;
+def mavx512vbmi : Flag<["-"], "mavx512vbmi">, Group<m_x86_Features_Group>;
+def mno_avx512vbmi : Flag<["-"], "mno-avx512vbmi">, Group<m_x86_Features_Group>;
+def mavx512vl : Flag<["-"], "mavx512vl">, Group<m_x86_Features_Group>;
+def mno_avx512vl : Flag<["-"], "mno-avx512vl">, Group<m_x86_Features_Group>;
+def mavx512vpopcntdq : Flag<["-"], "mavx512vpopcntdq">, Group<m_x86_Features_Group>;
+def mno_avx512vpopcntdq : Flag<["-"], "mno-avx512vpopcntdq">, Group<m_x86_Features_Group>;
+def madx : Flag<["-"], "madx">, Group<m_x86_Features_Group>;
+def mno_adx : Flag<["-"], "mno-adx">, Group<m_x86_Features_Group>;
+def maes : Flag<["-"], "maes">, Group<m_x86_Features_Group>;
+def mno_aes : Flag<["-"], "mno-aes">, Group<m_x86_Features_Group>;
+def mbmi : Flag<["-"], "mbmi">, Group<m_x86_Features_Group>;
+def mno_bmi : Flag<["-"], "mno-bmi">, Group<m_x86_Features_Group>;
+def mbmi2 : Flag<["-"], "mbmi2">, Group<m_x86_Features_Group>;
+def mno_bmi2 : Flag<["-"], "mno-bmi2">, Group<m_x86_Features_Group>;
+def mclflushopt : Flag<["-"], "mclflushopt">, Group<m_x86_Features_Group>;
+def mno_clflushopt : Flag<["-"], "mno-clflushopt">, Group<m_x86_Features_Group>;
+def mclwb : Flag<["-"], "mclwb">, Group<m_x86_Features_Group>;
+def mno_clwb : Flag<["-"], "mno-clwb">, Group<m_x86_Features_Group>;
+def mclzero : Flag<["-"], "mclzero">, Group<m_x86_Features_Group>;
+def mno_clzero : Flag<["-"], "mno-clzero">, Group<m_x86_Features_Group>;
+def mcx16 : Flag<["-"], "mcx16">, Group<m_x86_Features_Group>;
+def mno_cx16 : Flag<["-"], "mno-cx16">, Group<m_x86_Features_Group>;
+def mf16c : Flag<["-"], "mf16c">, Group<m_x86_Features_Group>;
+def mno_f16c : Flag<["-"], "mno-f16c">, Group<m_x86_Features_Group>;
+def mfma : Flag<["-"], "mfma">, Group<m_x86_Features_Group>;
+def mno_fma : Flag<["-"], "mno-fma">, Group<m_x86_Features_Group>;
+def mfma4 : Flag<["-"], "mfma4">, Group<m_x86_Features_Group>;
+def mno_fma4 : Flag<["-"], "mno-fma4">, Group<m_x86_Features_Group>;
+def mfsgsbase : Flag<["-"], "mfsgsbase">, Group<m_x86_Features_Group>;
+def mno_fsgsbase : Flag<["-"], "mno-fsgsbase">, Group<m_x86_Features_Group>;
+def mfxsr : Flag<["-"], "mfxsr">, Group<m_x86_Features_Group>;
+def mno_fxsr : Flag<["-"], "mno-fxsr">, Group<m_x86_Features_Group>;
+def mlwp : Flag<["-"], "mlwp">, Group<m_x86_Features_Group>;
+def mno_lwp : Flag<["-"], "mno-lwp">, Group<m_x86_Features_Group>;
+def mlzcnt : Flag<["-"], "mlzcnt">, Group<m_x86_Features_Group>;
+def mno_lzcnt : Flag<["-"], "mno-lzcnt">, Group<m_x86_Features_Group>;
+def mmovbe : Flag<["-"], "mmovbe">, Group<m_x86_Features_Group>;
+def mno_movbe : Flag<["-"], "mno-movbe">, Group<m_x86_Features_Group>;
+def mmpx : Flag<["-"], "mmpx">, Group<m_x86_Features_Group>;
+def mno_mpx : Flag<["-"], "mno-mpx">, Group<m_x86_Features_Group>;
+def mmwaitx : Flag<["-"], "mmwaitx">, Group<m_x86_Features_Group>;
+def mno_mwaitx : Flag<["-"], "mno-mwaitx">, Group<m_x86_Features_Group>;
+def mpku : Flag<["-"], "mpku">, Group<m_x86_Features_Group>;
+def mno_pku : Flag<["-"], "mno-pku">, Group<m_x86_Features_Group>;
+def mpclmul : Flag<["-"], "mpclmul">, Group<m_x86_Features_Group>;
+def mno_pclmul : Flag<["-"], "mno-pclmul">, Group<m_x86_Features_Group>;
+def mpopcnt : Flag<["-"], "mpopcnt">, Group<m_x86_Features_Group>;
+def mno_popcnt : Flag<["-"], "mno-popcnt">, Group<m_x86_Features_Group>;
+def mprefetchwt1 : Flag<["-"], "mprefetchwt1">, Group<m_x86_Features_Group>;
+def mno_prefetchwt1 : Flag<["-"], "mno-prefetchwt1">, Group<m_x86_Features_Group>;
+def mprfchw : Flag<["-"], "mprfchw">, Group<m_x86_Features_Group>;
+def mno_prfchw : Flag<["-"], "mno-prfchw">, Group<m_x86_Features_Group>;
+def mrdrnd : Flag<["-"], "mrdrnd">, Group<m_x86_Features_Group>;
+def mno_rdrnd : Flag<["-"], "mno-rdrnd">, Group<m_x86_Features_Group>;
+def mrtm : Flag<["-"], "mrtm">, Group<m_x86_Features_Group>;
+def mno_rtm : Flag<["-"], "mno-rtm">, Group<m_x86_Features_Group>;
+def mrdseed : Flag<["-"], "mrdseed">, Group<m_x86_Features_Group>;
+def mno_rdseed : Flag<["-"], "mno-rdseed">, Group<m_x86_Features_Group>;
+def msgx : Flag<["-"], "msgx">, Group<m_x86_Features_Group>;
+def mno_sgx : Flag<["-"], "mno-sgx">, Group<m_x86_Features_Group>;
+def msha : Flag<["-"], "msha">, Group<m_x86_Features_Group>;
+def mno_sha : Flag<["-"], "mno-sha">, Group<m_x86_Features_Group>;
+def mtbm : Flag<["-"], "mtbm">, Group<m_x86_Features_Group>;
+def mno_tbm : Flag<["-"], "mno-tbm">, Group<m_x86_Features_Group>;
+def mxop : Flag<["-"], "mxop">, Group<m_x86_Features_Group>;
+def mno_xop : Flag<["-"], "mno-xop">, Group<m_x86_Features_Group>;
+def mxsave : Flag<["-"], "mxsave">, Group<m_x86_Features_Group>;
+def mno_xsave : Flag<["-"], "mno-xsave">, Group<m_x86_Features_Group>;
+def mxsavec : Flag<["-"], "mxsavec">, Group<m_x86_Features_Group>;
+def mno_xsavec : Flag<["-"], "mno-xsavec">, Group<m_x86_Features_Group>;
+def mxsaveopt : Flag<["-"], "mxsaveopt">, Group<m_x86_Features_Group>;
+def mno_xsaveopt : Flag<["-"], "mno-xsaveopt">, Group<m_x86_Features_Group>;
+def mxsaves : Flag<["-"], "mxsaves">, Group<m_x86_Features_Group>;
+def mno_xsaves : Flag<["-"], "mno-xsaves">, Group<m_x86_Features_Group>;
+def mshstk : Flag<["-"], "mshstk">, Group<m_x86_Features_Group>;
+def mno_shstk : Flag<["-"], "mno-shstk">, Group<m_x86_Features_Group>;
+def mibt : Flag<["-"], "mibt">, Group<m_x86_Features_Group>;
+def mno_ibt : Flag<["-"], "mno-ibt">, Group<m_x86_Features_Group>;
// These are legacy user-facing driver-level option spellings. They are always
// aliases for options that are spelled using the more common Unix / GNU flag
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/SanitizerArgs.h b/contrib/llvm/tools/clang/include/clang/Driver/SanitizerArgs.h
index a9645d463fa16..a31ac05afc1bb 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/SanitizerArgs.h
+++ b/contrib/llvm/tools/clang/include/clang/Driver/SanitizerArgs.h
@@ -32,41 +32,49 @@ class SanitizerArgs {
int MsanTrackOrigins = 0;
bool MsanUseAfterDtor = false;
bool CfiCrossDso = false;
+ bool CfiICallGeneralizePointers = false;
int AsanFieldPadding = 0;
- bool AsanSharedRuntime = false;
+ bool SharedRuntime = false;
bool AsanUseAfterScope = true;
bool AsanGlobalsDeadStripping = false;
bool LinkCXXRuntimes = false;
bool NeedPIE = false;
+ bool SafeStackRuntime = false;
bool Stats = false;
bool TsanMemoryAccess = true;
bool TsanFuncEntryExit = true;
bool TsanAtomics = true;
+ bool MinimalRuntime = false;
+ // True if cross-dso CFI support if provided by the system (i.e. Android).
+ bool ImplicitCfiRuntime = false;
public:
/// Parses the sanitizer arguments from an argument list.
SanitizerArgs(const ToolChain &TC, const llvm::opt::ArgList &Args);
+ bool needsSharedRt() const { return SharedRuntime; }
+
bool needsAsanRt() const { return Sanitizers.has(SanitizerKind::Address); }
- bool needsSharedAsanRt() const { return AsanSharedRuntime; }
+ bool needsHwasanRt() const { return Sanitizers.has(SanitizerKind::HWAddress); }
bool needsTsanRt() const { return Sanitizers.has(SanitizerKind::Thread); }
bool needsMsanRt() const { return Sanitizers.has(SanitizerKind::Memory); }
bool needsFuzzer() const { return Sanitizers.has(SanitizerKind::Fuzzer); }
bool needsLsanRt() const {
return Sanitizers.has(SanitizerKind::Leak) &&
- !Sanitizers.has(SanitizerKind::Address);
+ !Sanitizers.has(SanitizerKind::Address) &&
+ !Sanitizers.has(SanitizerKind::HWAddress);
}
bool needsUbsanRt() const;
+ bool requiresMinimalRuntime() const { return MinimalRuntime; }
bool needsDfsanRt() const { return Sanitizers.has(SanitizerKind::DataFlow); }
- bool needsSafeStackRt() const {
- return Sanitizers.has(SanitizerKind::SafeStack);
- }
+ bool needsSafeStackRt() const { return SafeStackRuntime; }
bool needsCfiRt() const;
bool needsCfiDiagRt() const;
bool needsStatsRt() const { return Stats; }
bool needsEsanRt() const {
return Sanitizers.hasOneOf(SanitizerKind::Efficiency);
}
+ bool needsScudoRt() const { return Sanitizers.has(SanitizerKind::Scudo); }
bool requiresPIE() const;
bool needsUnwindTables() const;
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h b/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h
index 6651491e5b27c..13f54d3718b4c 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h
+++ b/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h
@@ -40,12 +40,35 @@ namespace driver {
class Compilation;
class CudaInstallationDetector;
class Driver;
+ class InputInfo;
class JobAction;
class RegisterEffectiveTriple;
class SanitizerArgs;
class Tool;
class XRayArgs;
+/// Helper structure used to pass information extracted from clang executable
+/// name such as `i686-linux-android-g++`.
+///
+struct ParsedClangName {
+ /// Target part of the executable name, as `i686-linux-android`.
+ std::string TargetPrefix;
+ /// Driver mode part of the executable name, as `g++`.
+ std::string ModeSuffix;
+ /// Corresponding driver mode argument, as '--driver-mode=g++'
+ const char *DriverMode;
+ /// True if TargetPrefix is recognized as a registered target name.
+ bool TargetIsValid;
+
+ ParsedClangName() : DriverMode(nullptr), TargetIsValid(false) {}
+ ParsedClangName(std::string Suffix, const char *Mode)
+ : ModeSuffix(Suffix), DriverMode(Mode), TargetIsValid(false) {}
+ ParsedClangName(std::string Target, std::string Suffix, const char *Mode,
+ bool IsRegistered)
+ : TargetPrefix(Target), ModeSuffix(Suffix), DriverMode(Mode),
+ TargetIsValid(IsRegistered) {}
+};
+
/// ToolChain - Access to tools for a single platform.
class ToolChain {
public:
@@ -70,7 +93,7 @@ public:
private:
const Driver &D;
- const llvm::Triple Triple;
+ llvm::Triple Triple;
const llvm::opt::ArgList &Args;
// We need to initialize CachedRTTIArg before CachedRTTIMode
const llvm::opt::Arg *const CachedRTTIArg;
@@ -113,6 +136,8 @@ protected:
ToolChain(const Driver &D, const llvm::Triple &T,
const llvm::opt::ArgList &Args);
+ void setTripleEnvironment(llvm::Triple::EnvironmentType Env);
+
virtual Tool *buildAssembler() const;
virtual Tool *buildLinker() const;
virtual Tool *getTool(Action::ActionClass AC) const;
@@ -150,6 +175,11 @@ public:
/// while the aux triple is the host (CPU) toolchain, e.g. x86-linux-gnu.
virtual const llvm::Triple *getAuxTriple() const { return nullptr; }
+ /// Some toolchains need to modify the file name, for example to replace the
+ /// extension for object files with .cubin for OpenMP offloading to Nvidia
+ /// GPUs.
+ virtual std::string getInputFilename(const InputInfo &Input) const;
+
llvm::Triple::ArchType getArch() const { return Triple.getArch(); }
StringRef getArchName() const { return Triple.getArchName(); }
StringRef getPlatform() const { return Triple.getVendorName(); }
@@ -193,13 +223,16 @@ public:
/// For example, when called with i686-linux-android-g++, the first element
/// of the return value will be set to `"i686-linux-android"` and the second
/// will be set to "--driver-mode=g++"`.
+ /// It is OK if the target name is not registered. In this case the return
+ /// value contains false in the field TargetIsValid.
///
/// \pre `llvm::InitializeAllTargets()` has been called.
/// \param ProgName The name the Clang driver was invoked with (from,
- /// e.g., argv[0])
- /// \return A pair of (`target`, `mode-flag`), where one or both may be empty.
- static std::pair<std::string, std::string>
- getTargetAndModeFromProgramName(StringRef ProgName);
+ /// e.g., argv[0]).
+ /// \return A structure of type ParsedClangName that contains the executable
+ /// name parts.
+ ///
+ static ParsedClangName getTargetAndModeFromProgramName(StringRef ProgName);
// Tool access.
@@ -217,6 +250,13 @@ public:
return nullptr;
}
+ /// TranslateOpenMPTargetArgs - Create a new derived argument list for
+ /// that contains the OpenMP target specific flags passed via
+ /// -Xopenmp-target -opt=val OR -Xopenmp-target=<triple> -opt=val
+ virtual llvm::opt::DerivedArgList *TranslateOpenMPTargetArgs(
+ const llvm::opt::DerivedArgList &Args, bool SameTripleAsHost,
+ SmallVectorImpl<llvm::opt::Arg *> &AllocatedArgs) const;
+
/// Choose a tool to use to handle the action \p JA.
///
/// This can be overridden when a particular ToolChain needs to use
@@ -278,6 +318,9 @@ public:
/// mixed dispatch method be used?
virtual bool UseObjCMixedDispatch() const { return false; }
+ /// \brief Check whether to enable x86 relax relocations by default.
+ virtual bool useRelaxRelocations() const;
+
/// GetDefaultStackProtectorLevel - Get the default stack protector level for
/// this tool chain (0=off, 1=on, 2=strong, 3=all).
virtual unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const {
@@ -298,6 +341,8 @@ public:
return ToolChain::CST_Libstdcxx;
}
+ virtual std::string getCompilerRTPath() const;
+
virtual std::string getCompilerRT(const llvm::opt::ArgList &Args,
StringRef Component,
bool Shared = false) const;
@@ -332,9 +377,6 @@ public:
/// SupportsProfiling - Does this tool chain support -pg.
virtual bool SupportsProfiling() const { return true; }
- /// Does this tool chain support Objective-C garbage collection.
- virtual bool SupportsObjCGC() const { return true; }
-
/// Complain if this tool chain doesn't support Objective-C ARC.
virtual void CheckObjCARC() const {}
@@ -357,10 +399,9 @@ public:
return llvm::DebuggerKind::GDB;
}
- /// UseSjLjExceptions - Does this tool chain use SjLj exceptions.
- virtual bool UseSjLjExceptions(const llvm::opt::ArgList &Args) const {
- return false;
- }
+ /// GetExceptionModel - Return the tool chain exception model.
+ virtual llvm::ExceptionHandling
+ GetExceptionModel(const llvm::opt::ArgList &Args) const;
/// SupportsEmbeddedBitcode - Does this tool chain support embedded bitcode.
virtual bool SupportsEmbeddedBitcode() const {
@@ -432,6 +473,10 @@ public:
AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const;
+ /// Returns if the C++ standard library should be linked in.
+ /// Note that e.g. -lm should still be linked even if this returns false.
+ bool ShouldLinkCXXStdlib(const llvm::opt::ArgList &Args) const;
+
/// AddCXXStdlibLibArgs - Add the system specific linker arguments to use
/// for the given C++ standard library type.
virtual void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/XRayArgs.h b/contrib/llvm/tools/clang/include/clang/Driver/XRayArgs.h
index 83210d100a12c..e5b76162de8e2 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/XRayArgs.h
+++ b/contrib/llvm/tools/clang/include/clang/Driver/XRayArgs.h
@@ -24,6 +24,7 @@ class XRayArgs {
std::vector<std::string> ExtraDeps;
bool XRayInstrument = false;
int InstructionThreshold = 200;
+ bool XRayAlwaysEmitCustomEvents = false;
public:
/// Parses the XRay arguments from an argument list.
diff --git a/contrib/llvm/tools/clang/include/clang/Format/Format.h b/contrib/llvm/tools/clang/include/clang/Format/Format.h
index 99d54e55e8285..d27d934f76798 100644
--- a/contrib/llvm/tools/clang/include/clang/Format/Format.h
+++ b/contrib/llvm/tools/clang/include/clang/Format/Format.h
@@ -151,13 +151,20 @@ struct FormatStyle {
/// \endcode
bool AlignTrailingComments;
- /// \brief Allow putting all parameters of a function declaration onto
+ /// \brief If the function declaration doesn't fit on a line,
+ /// allow putting all parameters of a function declaration onto
/// the next line even if ``BinPackParameters`` is ``false``.
/// \code
- /// true: false:
- /// myFunction(foo, vs. myFunction(foo, bar, plop);
- /// bar,
- /// plop);
+ /// true:
+ /// void myFunction(
+ /// int a, int b, int c, int d, int e);
+ ///
+ /// false:
+ /// void myFunction(int a,
+ /// int b,
+ /// int c,
+ /// int d,
+ /// int e);
/// \endcode
bool AllowAllParametersOfDeclarationOnNextLine;
@@ -674,6 +681,20 @@ struct FormatStyle {
/// }
/// \endcode
bool AfterUnion;
+ /// \brief Wrap extern blocks.
+ /// \code
+ /// true:
+ /// extern "C"
+ /// {
+ /// int foo();
+ /// }
+ ///
+ /// false:
+ /// extern "C" {
+ /// int foo();
+ /// }
+ /// \endcode
+ bool AfterExternBlock;
/// \brief Wrap before ``catch``.
/// \code
/// true:
@@ -746,6 +767,14 @@ struct FormatStyle {
///
/// If ``BreakBeforeBraces`` is set to ``BS_Custom``, use this to specify how
/// each individual brace case should be handled. Otherwise, this is ignored.
+ /// \code{.yaml}
+ /// # Example of usage:
+ /// BreakBeforeBraces: Custom
+ /// BraceWrapping:
+ /// AfterEnum: true
+ /// AfterStruct: false
+ /// SplitEmptyFunction: false
+ /// \endcode
BraceWrappingFlags BraceWrapping;
/// \brief If ``true``, ternary operators will be placed after line breaks.
@@ -956,6 +985,40 @@ struct FormatStyle {
/// For example: BOOST_FOREACH.
std::vector<std::string> ForEachMacros;
+ /// \brief Styles for sorting multiple ``#include`` blocks.
+ enum IncludeBlocksStyle {
+ /// \brief Sort each ``#include`` block separately.
+ /// \code
+ /// #include "b.h" into #include "b.h"
+ ///
+ /// #include <lib/main.h> #include "a.h"
+ /// #include "a.h" #include <lib/main.h>
+ /// \endcode
+ IBS_Preserve,
+ /// \brief Merge multiple ``#include`` blocks together and sort as one.
+ /// \code
+ /// #include "b.h" into #include "a.h"
+ /// #include "b.h"
+ /// #include <lib/main.h> #include <lib/main.h>
+ /// #include "a.h"
+ /// \endcode
+ IBS_Merge,
+ /// \brief Merge multiple ``#include`` blocks together and sort as one.
+ /// Then split into groups based on category priority. See
+ /// ``IncludeCategories``.
+ /// \code
+ /// #include "b.h" into #include "a.h"
+ /// #include "b.h"
+ /// #include <lib/main.h>
+ /// #include "a.h" #include <lib/main.h>
+ /// \endcode
+ IBS_Regroup,
+ };
+
+ /// \brief Dependent on the value, multiple ``#include`` blocks can be sorted
+ /// as one and divided based on category.
+ IncludeBlocksStyle IncludeBlocks;
+
/// \brief See documentation of ``IncludeCategories``.
struct IncludeCategory {
/// \brief The regular expression that this category matches.
@@ -1024,6 +1087,31 @@ struct FormatStyle {
/// \endcode
bool IndentCaseLabels;
+ /// \brief Options for indenting preprocessor directives.
+ enum PPDirectiveIndentStyle {
+ /// Does not indent any directives.
+ /// \code
+ /// #if FOO
+ /// #if BAR
+ /// #include <foo>
+ /// #endif
+ /// #endif
+ /// \endcode
+ PPDIS_None,
+ /// Indents directives after the hash.
+ /// \code
+ /// #if FOO
+ /// # if BAR
+ /// # include <foo>
+ /// # endif
+ /// #endif
+ /// \endcode
+ PPDIS_AfterHash
+ };
+
+ /// \brief The preprocessor directive indenting style to use.
+ PPDirectiveIndentStyle IndentPPDirectives;
+
/// \brief The number of columns to use for indentation.
/// \code
/// IndentWidth: 3
@@ -1273,6 +1361,41 @@ struct FormatStyle {
/// \brief Pointer and reference alignment style.
PointerAlignmentStyle PointerAlignment;
+ /// See documentation of ``RawStringFormats``.
+ struct RawStringFormat {
+ /// \brief The delimiter that this raw string format matches.
+ std::string Delimiter;
+ /// \brief The language of this raw string.
+ LanguageKind Language;
+ /// \brief The style name on which this raw string format is based on.
+ /// If not specified, the raw string format is based on the style that this
+ /// format is based on.
+ std::string BasedOnStyle;
+ bool operator==(const RawStringFormat &Other) const {
+ return Delimiter == Other.Delimiter && Language == Other.Language &&
+ BasedOnStyle == Other.BasedOnStyle;
+ }
+ };
+
+ /// \brief Raw string delimiters denoting that the raw string contents are
+ /// code in a particular language and can be reformatted.
+ ///
+ /// A raw string with a matching delimiter will be reformatted assuming the
+ /// specified language based on a predefined style given by 'BasedOnStyle'.
+ /// If 'BasedOnStyle' is not found, the formatting is based on llvm style.
+ ///
+ /// To configure this in the .clang-format file, use:
+ /// \code{.yaml}
+ /// RawStringFormats:
+ /// - Delimiter: 'pb'
+ /// Language: TextProto
+ /// BasedOnStyle: llvm
+ /// - Delimiter: 'proto'
+ /// Language: TextProto
+ /// BasedOnStyle: google
+ /// \endcode
+ std::vector<RawStringFormat> RawStringFormats;
+
/// \brief If ``true``, clang-format will attempt to re-flow comments.
/// \code
/// false:
@@ -1296,6 +1419,14 @@ struct FormatStyle {
bool SortIncludes;
/// \brief If ``true``, clang-format will sort using declarations.
+ ///
+ /// The order of using declarations is defined as follows:
+ /// Split the strings by "::" and discard any initial empty strings. The last
+ /// element of each list is a non-namespace name; all others are namespace
+ /// names. Sort the lists of names lexicographically, where the sort order of
+ /// individual names is that all non-namespace names come before all namespace
+ /// names, and within those groups, names are in case-insensitive
+ /// lexicographic order.
/// \code
/// false: true:
/// using std::cout; vs. using std::cin;
@@ -1512,8 +1643,10 @@ struct FormatStyle {
R.ExperimentalAutoDetectBinPacking &&
FixNamespaceComments == R.FixNamespaceComments &&
ForEachMacros == R.ForEachMacros &&
+ IncludeBlocks == R.IncludeBlocks &&
IncludeCategories == R.IncludeCategories &&
IndentCaseLabels == R.IndentCaseLabels &&
+ IndentPPDirectives == R.IndentPPDirectives &&
IndentWidth == R.IndentWidth && Language == R.Language &&
IndentWrappedFunctionNames == R.IndentWrappedFunctionNames &&
JavaScriptQuotes == R.JavaScriptQuotes &&
@@ -1537,6 +1670,7 @@ struct FormatStyle {
PenaltyExcessCharacter == R.PenaltyExcessCharacter &&
PenaltyReturnTypeOnItsOwnLine == R.PenaltyReturnTypeOnItsOwnLine &&
PointerAlignment == R.PointerAlignment &&
+ RawStringFormats == R.RawStringFormats &&
SpaceAfterCStyleCast == R.SpaceAfterCStyleCast &&
SpaceAfterTemplateKeyword == R.SpaceAfterTemplateKeyword &&
SpaceBeforeAssignmentOperators == R.SpaceBeforeAssignmentOperators &&
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h b/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h
index 1ac4f07a3549a..5d04dcd19119a 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h
@@ -448,7 +448,7 @@ public:
IntrusiveRefCntPtr<ASTReader> getASTReader() const;
- StringRef getOriginalSourceFileName() {
+ StringRef getOriginalSourceFileName() const {
return OriginalSourceFile;
}
@@ -524,26 +524,26 @@ public:
/// \brief If \p Loc is a loaded location from the preamble, returns
/// the corresponding local location of the main file, otherwise it returns
/// \p Loc.
- SourceLocation mapLocationFromPreamble(SourceLocation Loc);
+ SourceLocation mapLocationFromPreamble(SourceLocation Loc) const;
/// \brief If \p Loc is a local location of the main file but inside the
/// preamble chunk, returns the corresponding loaded location from the
/// preamble, otherwise it returns \p Loc.
- SourceLocation mapLocationToPreamble(SourceLocation Loc);
+ SourceLocation mapLocationToPreamble(SourceLocation Loc) const;
- bool isInPreambleFileID(SourceLocation Loc);
- bool isInMainFileID(SourceLocation Loc);
- SourceLocation getStartOfMainFileID();
- SourceLocation getEndOfPreambleFileID();
+ bool isInPreambleFileID(SourceLocation Loc) const;
+ bool isInMainFileID(SourceLocation Loc) const;
+ SourceLocation getStartOfMainFileID() const;
+ SourceLocation getEndOfPreambleFileID() const;
/// \see mapLocationFromPreamble.
- SourceRange mapRangeFromPreamble(SourceRange R) {
+ SourceRange mapRangeFromPreamble(SourceRange R) const {
return SourceRange(mapLocationFromPreamble(R.getBegin()),
mapLocationFromPreamble(R.getEnd()));
}
/// \see mapLocationToPreamble.
- SourceRange mapRangeToPreamble(SourceRange R) {
+ SourceRange mapRangeToPreamble(SourceRange R) const {
return SourceRange(mapLocationToPreamble(R.getBegin()),
mapLocationToPreamble(R.getEnd()));
}
@@ -607,7 +607,7 @@ public:
/// \brief Returns true if the ASTUnit was constructed from a serialized
/// module file.
- bool isModuleFile();
+ bool isModuleFile() const;
std::unique_ptr<llvm::MemoryBuffer>
getBufferForFile(StringRef Filename, std::string *ErrorStr = nullptr);
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def b/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def
index 4002415adc459..bb91cf5f742b7 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def
@@ -76,10 +76,17 @@ CODEGENOPT(ForbidGuardVariables , 1, 0) ///< Issue errors if C++ guard variables
CODEGENOPT(FunctionSections , 1, 0) ///< Set when -ffunction-sections is enabled.
CODEGENOPT(InstrumentFunctions , 1, 0) ///< Set when -finstrument-functions is
///< enabled.
+CODEGENOPT(InstrumentFunctionsAfterInlining , 1, 0) ///< Set when
+ ///< -finstrument-functions-after-inlining is enabled.
+CODEGENOPT(InstrumentFunctionEntryBare , 1, 0) ///< Set when
+ ///< -finstrument-function-entry-bare is enabled.
CODEGENOPT(XRayInstrumentFunctions , 1, 0) ///< Set when -fxray-instrument is
///< enabled.
+///< Set when -fxray-always-emit-customevents is enabled.
+CODEGENOPT(XRayAlwaysEmitCustomEvents , 1, 0)
+
///< Set the minimum number of instructions in a function to determine selective
///< XRay instrumentation.
VALUE_CODEGENOPT(XRayInstructionThreshold , 32, 200)
@@ -110,6 +117,7 @@ CODEGENOPT(EnableSegmentedStacks , 1, 0) ///< Set when -fsplit-stack is enabled.
CODEGENOPT(NoImplicitFloat , 1, 0) ///< Set when -mno-implicit-float is enabled.
CODEGENOPT(NoInfsFPMath , 1, 0) ///< Assume FP arguments, results not +-Inf.
CODEGENOPT(NoSignedZeros , 1, 0) ///< Allow ignoring the signedness of FP zero
+CODEGENOPT(Reassociate , 1, 0) ///< Allow reassociation of FP math ops
CODEGENOPT(ReciprocalMath , 1, 0) ///< Allow FP divisions to be reassociated.
CODEGENOPT(NoTrappingMath , 1, 0) ///< Set when -fno-trapping-math is enabled.
CODEGENOPT(NoNaNsFPMath , 1, 0) ///< Assume FP arguments, results not NaN.
@@ -142,6 +150,7 @@ ENUM_CODEGENOPT(StructReturnConvention, StructReturnConventionKind, 2, SRCK_Defa
CODEGENOPT(RelaxAll , 1, 0) ///< Relax all machine code instructions.
CODEGENOPT(RelaxedAliasing , 1, 0) ///< Set when -fno-strict-aliasing is enabled.
CODEGENOPT(StructPathTBAA , 1, 0) ///< Whether or not to use struct-path TBAA.
+CODEGENOPT(NewStructPathTBAA , 1, 0) ///< Whether or not to use enhanced struct-path TBAA.
CODEGENOPT(SaveTempLabels , 1, 0) ///< Save temporary labels.
CODEGENOPT(SanitizeAddressUseAfterScope , 1, 0) ///< Enable use-after-scope detection
///< in AddressSanitizer
@@ -152,6 +161,10 @@ CODEGENOPT(SanitizeMemoryTrackOrigins, 2, 0) ///< Enable tracking origins in
CODEGENOPT(SanitizeMemoryUseAfterDtor, 1, 0) ///< Enable use-after-delete detection
///< in MemorySanitizer
CODEGENOPT(SanitizeCfiCrossDso, 1, 0) ///< Enable cross-dso support in CFI.
+CODEGENOPT(SanitizeMinimalRuntime, 1, 0) ///< Use "_minimal" sanitizer runtime for
+ ///< diagnostics.
+CODEGENOPT(SanitizeCfiICallGeneralizePointers, 1, 0) ///< Generalize pointer types in
+ ///< CFI icall function signatures
CODEGENOPT(SanitizeCoverageType, 2, 0) ///< Type of sanitizer coverage
///< instrumentation.
CODEGENOPT(SanitizeCoverageIndirectCalls, 1, 0) ///< Enable sanitizer coverage
@@ -171,10 +184,13 @@ CODEGENOPT(SanitizeCoverageTracePC, 1, 0) ///< Enable PC tracing
CODEGENOPT(SanitizeCoverageTracePCGuard, 1, 0) ///< Enable PC tracing with guard
///< in sanitizer coverage.
CODEGENOPT(SanitizeCoverageInline8bitCounters, 1, 0) ///< Use inline 8bit counters.
+CODEGENOPT(SanitizeCoveragePCTable, 1, 0) ///< Create a PC Table.
CODEGENOPT(SanitizeCoverageNoPrune, 1, 0) ///< Disable coverage pruning.
+CODEGENOPT(SanitizeCoverageStackDepth, 1, 0) ///< Enable max stack depth tracing
CODEGENOPT(SanitizeStats , 1, 0) ///< Collect statistics for sanitizers.
CODEGENOPT(SimplifyLibCalls , 1, 1) ///< Set when -fbuiltin is enabled.
CODEGENOPT(SoftFloat , 1, 0) ///< -soft-float.
+CODEGENOPT(FineGrainedBitfieldAccesses, 1, 0) ///< Enable fine-grained bitfield accesses.
CODEGENOPT(StrictEnums , 1, 0) ///< Optimize based on strict enum definition.
CODEGENOPT(StrictVTablePointers, 1, 0) ///< Optimize based on the strict vtable pointers
CODEGENOPT(TimePasses , 1, 0) ///< Set when -ftime-report is enabled.
@@ -185,6 +201,7 @@ CODEGENOPT(UnsafeFPMath , 1, 0) ///< Allow unsafe floating point optzns.
CODEGENOPT(UnwindTables , 1, 0) ///< Emit unwind tables.
CODEGENOPT(VectorizeLoop , 1, 0) ///< Run loop vectorizer.
CODEGENOPT(VectorizeSLP , 1, 0) ///< Run SLP vectorizer.
+CODEGENOPT(ProfileSampleAccurate, 1, 0) ///< Sample profile is accurate.
/// Attempt to use register sized accesses to bit-fields in structures, when
/// possible.
@@ -214,6 +231,10 @@ CODEGENOPT(EnableSplitDwarf, 1, 0) ///< Whether to enable split DWARF
CODEGENOPT(SplitDwarfInlining, 1, 1) ///< Whether to include inlining info in the
///< skeleton CU to allow for symbolication
///< of inline stack frames without .dwo files.
+CODEGENOPT(DebugFwdTemplateParams, 1, 0) ///< Whether to emit complete
+ ///< template parameter descriptions in
+ ///< forward declarations (versus just
+ ///< including them in the name).
CODEGENOPT(EmitLLVMUseLists, 1, 0) ///< Control whether to serialize use-lists.
@@ -282,6 +303,11 @@ CODEGENOPT(DebugInfoForProfiling, 1, 0)
/// Whether 3-component vector type is preserved.
CODEGENOPT(PreserveVec3Type, 1, 0)
+/// Whether to emit .debug_gnu_pubnames section instead of .debug_pubnames.
+CODEGENOPT(GnuPubnames, 1, 0)
+
+CODEGENOPT(NoPLT, 1, 0)
+
#undef CODEGENOPT
#undef ENUM_CODEGENOPT
#undef VALUE_CODEGENOPT
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h
index 71730a21dbe24..6b8d2b935fdd2 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h
@@ -251,6 +251,13 @@ public:
/// \brief A list of all -fno-builtin-* function names (e.g., memset).
std::vector<std::string> NoBuiltinFuncs;
+ std::vector<std::string> Reciprocals;
+
+ /// The preferred width for auto-vectorization transforms. This is intended to
+ /// override default transforms based on the width of the architected vector
+ /// registers.
+ std::string PreferVectorWidth;
+
public:
// Define accessors/mutators for code generation options of enumeration type.
#define CODEGENOPT(Name, Bits, Default)
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CommandLineSourceLoc.h b/contrib/llvm/tools/clang/include/clang/Frontend/CommandLineSourceLoc.h
index a78c96d23afa3..f5c1e1a8a67d0 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/CommandLineSourceLoc.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/CommandLineSourceLoc.h
@@ -51,6 +51,52 @@ public:
}
};
+/// A source range that has been parsed on the command line.
+struct ParsedSourceRange {
+ std::string FileName;
+ /// The starting location of the range. The first element is the line and
+ /// the second element is the column.
+ std::pair<unsigned, unsigned> Begin;
+ /// The ending location of the range. The first element is the line and the
+ /// second element is the column.
+ std::pair<unsigned, unsigned> End;
+
+ /// Returns a parsed source range from a string or None if the string is
+ /// invalid.
+ ///
+ /// These source string has the following format:
+ ///
+ /// file:start_line:start_column[-end_line:end_column]
+ ///
+ /// If the end line and column are omitted, the starting line and columns
+ /// are used as the end values.
+ static Optional<ParsedSourceRange> fromString(StringRef Str) {
+ std::pair<StringRef, StringRef> RangeSplit = Str.rsplit('-');
+ unsigned EndLine, EndColumn;
+ bool HasEndLoc = false;
+ if (!RangeSplit.second.empty()) {
+ std::pair<StringRef, StringRef> Split = RangeSplit.second.rsplit(':');
+ if (Split.first.getAsInteger(10, EndLine) ||
+ Split.second.getAsInteger(10, EndColumn)) {
+ // The string does not end in end_line:end_column, so the '-'
+ // probably belongs to the filename which menas the whole
+ // string should be parsed.
+ RangeSplit.first = Str;
+ } else
+ HasEndLoc = true;
+ }
+ auto Begin = ParsedSourceLocation::FromString(RangeSplit.first);
+ if (Begin.FileName.empty())
+ return None;
+ if (!HasEndLoc) {
+ EndLine = Begin.Line;
+ EndColumn = Begin.Column;
+ }
+ return ParsedSourceRange{std::move(Begin.FileName),
+ {Begin.Line, Begin.Column},
+ {EndLine, EndColumn}};
+ }
+};
}
namespace llvm {
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h
index 5b5c75298a313..90a9501475b52 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h
@@ -640,7 +640,9 @@ public:
const CodeGenOptions *CodeGenOpts = nullptr);
/// Create the file manager and replace any existing one with it.
- void createFileManager();
+ ///
+ /// \return The new file manager on success, or null on failure.
+ FileManager *createFileManager();
/// Create the source manager and replace any existing one with it.
void createSourceManager(FileManager &FileMgr);
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h
index c45aeaa208c8c..fa1529a3d65dc 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h
@@ -86,10 +86,15 @@ public:
/// \brief Compute the AST consumer arguments that will be used to
/// create the PCHGenerator instance returned by CreateASTConsumer.
///
- /// \returns true if an error occurred, false otherwise.
- static std::unique_ptr<raw_pwrite_stream>
- ComputeASTConsumerArguments(CompilerInstance &CI, StringRef InFile,
- std::string &Sysroot, std::string &OutputFile);
+ /// \returns false if an error occurred, true otherwise.
+ static bool ComputeASTConsumerArguments(CompilerInstance &CI,
+ std::string &Sysroot);
+
+ /// \brief Creates file to write the PCH into and returns a stream to write it
+ /// into. On error, returns null.
+ static std::unique_ptr<llvm::raw_pwrite_stream>
+ CreateOutputFile(CompilerInstance &CI, StringRef InFile,
+ std::string &OutputFile);
bool BeginSourceFileAction(CompilerInstance &CI) override;
};
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h
index e757a7e397e35..5192a3774cc1d 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h
@@ -128,21 +128,24 @@ class FrontendInputFile {
/// \brief The file name, or "-" to read from standard input.
std::string File;
- llvm::MemoryBuffer *Buffer;
+ /// The input, if it comes from a buffer rather than a file. This object
+ /// does not own the buffer, and the caller is responsible for ensuring
+ /// that it outlives any users.
+ llvm::MemoryBuffer *Buffer = nullptr;
/// \brief The kind of input, e.g., C source, AST file, LLVM IR.
InputKind Kind;
/// \brief Whether we're dealing with a 'system' input (vs. a 'user' input).
- bool IsSystem;
+ bool IsSystem = false;
public:
- FrontendInputFile() : Buffer(nullptr), Kind(), IsSystem(false) { }
+ FrontendInputFile() { }
FrontendInputFile(StringRef File, InputKind Kind, bool IsSystem = false)
- : File(File.str()), Buffer(nullptr), Kind(Kind), IsSystem(IsSystem) { }
- FrontendInputFile(llvm::MemoryBuffer *buffer, InputKind Kind,
+ : File(File.str()), Kind(Kind), IsSystem(IsSystem) { }
+ FrontendInputFile(llvm::MemoryBuffer *Buffer, InputKind Kind,
bool IsSystem = false)
- : Buffer(buffer), Kind(Kind), IsSystem(IsSystem) { }
+ : Buffer(Buffer), Kind(Kind), IsSystem(IsSystem) { }
InputKind getKind() const { return Kind; }
bool isSystem() const { return IsSystem; }
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/LangStandard.h b/contrib/llvm/tools/clang/include/clang/Frontend/LangStandard.h
index 6731e08bcae8f..83e452d884b62 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/LangStandard.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/LangStandard.h
@@ -22,16 +22,17 @@ enum LangFeatures {
LineComment = (1 << 0),
C99 = (1 << 1),
C11 = (1 << 2),
- CPlusPlus = (1 << 3),
- CPlusPlus11 = (1 << 4),
- CPlusPlus14 = (1 << 5),
- CPlusPlus1z = (1 << 6),
- CPlusPlus2a = (1 << 7),
- Digraphs = (1 << 8),
- GNUMode = (1 << 9),
- HexFloat = (1 << 10),
- ImplicitInt = (1 << 11),
- OpenCL = (1 << 12)
+ C17 = (1 << 3),
+ CPlusPlus = (1 << 4),
+ CPlusPlus11 = (1 << 5),
+ CPlusPlus14 = (1 << 6),
+ CPlusPlus17 = (1 << 7),
+ CPlusPlus2a = (1 << 8),
+ Digraphs = (1 << 9),
+ GNUMode = (1 << 10),
+ HexFloat = (1 << 11),
+ ImplicitInt = (1 << 12),
+ OpenCL = (1 << 13)
};
}
@@ -70,6 +71,9 @@ public:
/// isC11 - Language is a superset of C11.
bool isC11() const { return Flags & frontend::C11; }
+ /// isC17 - Language is a superset of C17.
+ bool isC17() const { return Flags & frontend::C17; }
+
/// isCPlusPlus - Language is a C++ variant.
bool isCPlusPlus() const { return Flags & frontend::CPlusPlus; }
@@ -79,8 +83,8 @@ public:
/// isCPlusPlus14 - Language is a C++14 variant (or later).
bool isCPlusPlus14() const { return Flags & frontend::CPlusPlus14; }
- /// isCPlusPlus1z - Language is a C++17 variant (or later).
- bool isCPlusPlus1z() const { return Flags & frontend::CPlusPlus1z; }
+ /// isCPlusPlus17 - Language is a C++17 variant (or later).
+ bool isCPlusPlus17() const { return Flags & frontend::CPlusPlus17; }
/// isCPlusPlus2a - Language is a post-C++17 variant (or later).
bool isCPlusPlus2a() const { return Flags & frontend::CPlusPlus2a; }
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def b/contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def
index a019d63922140..e7a081dc2aa76 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def
@@ -77,6 +77,15 @@ LANGSTANDARD(gnu11, "gnu11",
LineComment | C99 | C11 | Digraphs | GNUMode | HexFloat)
LANGSTANDARD_ALIAS_DEPR(gnu11, "gnu1x")
+// C17 modes
+LANGSTANDARD(c17, "c17",
+ C, "ISO C 2017",
+ LineComment | C99 | C11 | C17 | Digraphs | HexFloat)
+LANGSTANDARD_ALIAS(c17, "iso9899:2017")
+LANGSTANDARD(gnu17, "gnu17",
+ C, "ISO C 2017 with GNU extensions",
+ LineComment | C99 | C11 | C17 | Digraphs | GNUMode | HexFloat)
+
// C++ modes
LANGSTANDARD(cxx98, "c++98",
CXX, "ISO C++ 1998 with amendments",
@@ -111,24 +120,24 @@ LANGSTANDARD_ALIAS_DEPR(gnucxx14, "gnu++1y")
LANGSTANDARD(cxx17, "c++17",
CXX, "ISO C++ 2017 with amendments",
- LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus1z |
+ LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 |
Digraphs | HexFloat)
LANGSTANDARD_ALIAS_DEPR(cxx17, "c++1z")
LANGSTANDARD(gnucxx17, "gnu++17",
CXX, "ISO C++ 2017 with amendments and GNU extensions",
- LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus1z |
+ LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 |
Digraphs | HexFloat | GNUMode)
LANGSTANDARD_ALIAS_DEPR(gnucxx17, "gnu++1z")
LANGSTANDARD(cxx2a, "c++2a",
CXX, "Working draft for ISO C++ 2020",
- LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus1z |
+ LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 |
CPlusPlus2a | Digraphs | HexFloat)
LANGSTANDARD(gnucxx2a, "gnu++2a",
CXX, "Working draft for ISO C++ 2020 with GNU extensions",
- LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus1z |
+ LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 |
CPlusPlus2a | Digraphs | HexFloat | GNUMode)
// OpenCL
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/PrecompiledPreamble.h b/contrib/llvm/tools/clang/include/clang/Frontend/PrecompiledPreamble.h
index 8307392e7febd..64342b1dffa81 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/PrecompiledPreamble.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/PrecompiledPreamble.h
@@ -17,6 +17,7 @@
#include "clang/Lex/Lexer.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/Support/AlignOf.h"
#include "llvm/Support/MD5.h"
#include <memory>
#include <system_error>
@@ -36,21 +37,6 @@ class CompilerInvocation;
class DeclGroupRef;
class PCHContainerOperations;
-/// A size of the preamble and a flag required by
-/// PreprocessorOptions::PrecompiledPreambleBytes.
-struct PreambleBounds {
- PreambleBounds(unsigned Size, bool PreambleEndsAtStartOfLine)
- : Size(Size), PreambleEndsAtStartOfLine(PreambleEndsAtStartOfLine) {}
-
- /// \brief Size of the preamble in bytes.
- unsigned Size;
- /// \brief Whether the preamble ends at the start of a new line.
- ///
- /// Used to inform the lexer as to whether it's starting at the beginning of
- /// a line after skipping the preamble.
- bool PreambleEndsAtStartOfLine;
-};
-
/// \brief Runs lexer to compute suggested preamble bounds.
PreambleBounds ComputePreambleBounds(const LangOptions &LangOpts,
llvm::MemoryBuffer *Buffer,
@@ -62,7 +48,7 @@ class PreambleCallbacks;
/// reuse the PCH for the subsequent runs. Use BuildPreamble to create PCH and
/// CanReusePreamble + AddImplicitPreamble to make use of it.
class PrecompiledPreamble {
- class TempPCHFile;
+ class PCHStorage;
struct PreambleFileHash;
public:
@@ -85,6 +71,9 @@ public:
///
/// \param PCHContainerOps An instance of PCHContainerOperations.
///
+ /// \param StoreInMemory Store PCH in memory. If false, PCH will be stored in
+ /// a temporary file.
+ ///
/// \param Callbacks A set of callbacks to be executed when building
/// the preamble.
static llvm::ErrorOr<PrecompiledPreamble>
@@ -92,12 +81,12 @@ public:
const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds,
DiagnosticsEngine &Diagnostics, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
- PreambleCallbacks &Callbacks);
+ bool StoreInMemory, PreambleCallbacks &Callbacks);
PrecompiledPreamble(PrecompiledPreamble &&) = default;
PrecompiledPreamble &operator=(PrecompiledPreamble &&) = default;
- /// PreambleBounds used to build the preamble
+ /// PreambleBounds used to build the preamble.
PreambleBounds getBounds() const;
/// Check whether PrecompiledPreamble can be reused for the new contents(\p
@@ -107,12 +96,18 @@ public:
vfs::FileSystem *VFS) const;
/// Changes options inside \p CI to use PCH from this preamble. Also remaps
- /// main file to \p MainFileBuffer.
+ /// main file to \p MainFileBuffer and updates \p VFS to ensure the preamble
+ /// is accessible.
+ /// For in-memory preambles, PrecompiledPreamble instance continues to own
+ /// the MemoryBuffer with the Preamble after this method returns. The caller
+ /// is reponsible for making sure the PrecompiledPreamble instance outlives
+ /// the compiler run and the AST that will be using the PCH.
void AddImplicitPreamble(CompilerInvocation &CI,
+ IntrusiveRefCntPtr<vfs::FileSystem> &VFS,
llvm::MemoryBuffer *MainFileBuffer) const;
private:
- PrecompiledPreamble(TempPCHFile PCHFile, std::vector<char> PreambleBytes,
+ PrecompiledPreamble(PCHStorage Storage, std::vector<char> PreambleBytes,
bool PreambleEndsAtStartOfLine,
llvm::StringMap<PreambleFileHash> FilesInPreamble);
@@ -154,6 +149,44 @@ private:
llvm::Optional<std::string> FilePath;
};
+ class InMemoryPreamble {
+ public:
+ std::string Data;
+ };
+
+ class PCHStorage {
+ public:
+ enum class Kind { Empty, InMemory, TempFile };
+
+ PCHStorage() = default;
+ PCHStorage(TempPCHFile File);
+ PCHStorage(InMemoryPreamble Memory);
+
+ PCHStorage(const PCHStorage &) = delete;
+ PCHStorage &operator=(const PCHStorage &) = delete;
+
+ PCHStorage(PCHStorage &&Other);
+ PCHStorage &operator=(PCHStorage &&Other);
+
+ ~PCHStorage();
+
+ Kind getKind() const;
+
+ TempPCHFile &asFile();
+ const TempPCHFile &asFile() const;
+
+ InMemoryPreamble &asMemory();
+ const InMemoryPreamble &asMemory() const;
+
+ private:
+ void destroy();
+ void setEmpty();
+
+ private:
+ Kind StorageKind = Kind::Empty;
+ llvm::AlignedCharArrayUnion<TempPCHFile, InMemoryPreamble> Storage = {};
+ };
+
/// Data used to determine if a file used in the preamble has been changed.
struct PreambleFileHash {
/// All files have size set.
@@ -183,8 +216,15 @@ private:
}
};
- /// Manages the lifetime of temporary file that stores a PCH.
- TempPCHFile PCHFile;
+ /// Sets up the PreprocessorOptions and changes VFS, so that PCH stored in \p
+ /// Storage is accessible to clang. This method is an implementation detail of
+ /// AddImplicitPreamble.
+ static void setupPreambleStorage(const PCHStorage &Storage,
+ PreprocessorOptions &PreprocessorOpts,
+ IntrusiveRefCntPtr<vfs::FileSystem> &VFS);
+
+ /// Manages the memory buffer or temporary file that stores the PCH.
+ PCHStorage Storage;
/// Keeps track of the files that were used when computing the
/// preamble, with both their buffer size and their modification time.
///
@@ -215,11 +255,9 @@ public:
/// NOTE: To allow more flexibility a custom ASTConsumer could probably be
/// used instead, but having only this method allows a simpler API.
virtual void HandleTopLevelDecl(DeclGroupRef DG);
- /// Called for each macro defined in the Preamble.
- /// NOTE: To allow more flexibility a custom PPCallbacks could probably be
- /// used instead, but having only this method allows a simpler API.
- virtual void HandleMacroDefined(const Token &MacroNameTok,
- const MacroDirective *MD);
+ /// Creates wrapper class for PPCallbacks so we can also process information
+ /// about includes that are inside of a preamble
+ virtual std::unique_ptr<PPCallbacks> createPPCallbacks();
};
enum class BuildPreambleError {
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticBuffer.h b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticBuffer.h
index 3bcf824455e2d..23f168e2232df 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticBuffer.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticBuffer.h
@@ -29,6 +29,11 @@ public:
typedef DiagList::const_iterator const_iterator;
private:
DiagList Errors, Warnings, Remarks, Notes;
+ /// All - All diagnostics in the order in which they were generated. That
+ /// order likely doesn't correspond to user input order, but it at least
+ /// keeps notes in the right places. Each pair in the vector is a diagnostic
+ /// level and an index into the corresponding DiagList above.
+ std::vector<std::pair<DiagnosticsEngine::Level, size_t>> All;
public:
const_iterator err_begin() const { return Errors.begin(); }
const_iterator err_end() const { return Errors.end(); }
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h b/contrib/llvm/tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h
index 475f07f9dc06a..8d71fb98b0bb1 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h
@@ -176,7 +176,8 @@ public:
: DirectiveLoc(DirectiveLoc), DiagnosticLoc(DiagnosticLoc),
Text(Text), Min(Min), Max(Max), MatchAnyLine(MatchAnyLine) {
assert(!DirectiveLoc.isInvalid() && "DirectiveLoc is invalid!");
- assert(!DiagnosticLoc.isInvalid() && "DiagnosticLoc is invalid!");
+ assert((!DiagnosticLoc.isInvalid() || MatchAnyLine) &&
+ "DiagnosticLoc is invalid!");
}
private:
diff --git a/contrib/llvm/tools/clang/include/clang/Index/IndexDataConsumer.h b/contrib/llvm/tools/clang/include/clang/Index/IndexDataConsumer.h
index 315437048345b..080f4cb4d0978 100644
--- a/contrib/llvm/tools/clang/include/clang/Index/IndexDataConsumer.h
+++ b/contrib/llvm/tools/clang/include/clang/Index/IndexDataConsumer.h
@@ -11,6 +11,7 @@
#define LLVM_CLANG_INDEX_INDEXDATACONSUMER_H
#include "clang/Index/IndexSymbol.h"
+#include "clang/Lex/Preprocessor.h"
namespace clang {
class ASTContext;
@@ -36,6 +37,8 @@ public:
virtual void initialize(ASTContext &Ctx) {}
+ virtual void setPreprocessor(std::shared_ptr<Preprocessor> PP) {}
+
/// \returns true to continue indexing, or false to abort.
virtual bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles,
ArrayRef<SymbolRelation> Relations,
diff --git a/contrib/llvm/tools/clang/include/clang/Index/IndexSymbol.h b/contrib/llvm/tools/clang/include/clang/Index/IndexSymbol.h
index abb132f9e4ce8..ae591364f229e 100644
--- a/contrib/llvm/tools/clang/include/clang/Index/IndexSymbol.h
+++ b/contrib/llvm/tools/clang/include/clang/Index/IndexSymbol.h
@@ -53,6 +53,7 @@ enum class SymbolKind : uint8_t {
ConversionFunction,
Parameter,
+ Using,
};
enum class SymbolLanguage {
@@ -69,6 +70,8 @@ enum class SymbolSubKind {
CXXMoveConstructor,
AccessorGetter,
AccessorSetter,
+ UsingTypename,
+ UsingValue,
};
/// Set of properties that provide additional info about a symbol.
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h b/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h
index 1b7f80c87ff1d..6b9dbfcd1e934 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h
@@ -1,4 +1,4 @@
-//===--- HeaderSearch.h - Resolve Header File Locations ---------*- C++ -*-===//
+//===- HeaderSearch.h - Resolve Header File Locations -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,25 +14,37 @@
#ifndef LLVM_CLANG_LEX_HEADERSEARCH_H
#define LLVM_CLANG_LEX_HEADERSEARCH_H
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
#include "clang/Lex/DirectoryLookup.h"
#include "clang/Lex/ModuleMap.h"
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
+#include <cassert>
+#include <cstddef>
#include <memory>
+#include <string>
+#include <utility>
#include <vector>
namespace clang {
-
-class DiagnosticsEngine;
+
+class DiagnosticsEngine;
+class DirectoryEntry;
class ExternalPreprocessorSource;
class FileEntry;
class FileManager;
+class HeaderMap;
class HeaderSearchOptions;
class IdentifierInfo;
+class LangOptions;
+class Module;
class Preprocessor;
+class TargetInfo;
/// \brief The preprocessor keeps track of this information for each
/// file that is \#included.
@@ -76,14 +88,14 @@ struct HeaderFileInfo {
unsigned IsValid : 1;
/// \brief The number of times the file has been included already.
- unsigned short NumIncludes;
+ unsigned short NumIncludes = 0;
/// \brief The ID number of the controlling macro.
///
/// This ID number will be non-zero when there is a controlling
/// macro whose IdentifierInfo may not yet have been loaded from
/// external storage.
- unsigned ControllingMacroID;
+ unsigned ControllingMacroID = 0;
/// If this file has a \#ifndef XXX (or equivalent) guard that
/// protects the entire contents of the file, this is the identifier
@@ -93,17 +105,16 @@ struct HeaderFileInfo {
/// the controlling macro of this header, since
/// getControllingMacro() is able to load a controlling macro from
/// external storage.
- const IdentifierInfo *ControllingMacro;
+ const IdentifierInfo *ControllingMacro = nullptr;
/// \brief If this header came from a framework include, this is the name
/// of the framework.
StringRef Framework;
HeaderFileInfo()
- : isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User),
- External(false), isModuleHeader(false), isCompilingModuleHeader(false),
- Resolved(false), IndexHeaderMapHeader(false), IsValid(0),
- NumIncludes(0), ControllingMacroID(0), ControllingMacro(nullptr) {}
+ : isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User),
+ External(false), isModuleHeader(false), isCompilingModuleHeader(false),
+ Resolved(false), IndexHeaderMapHeader(false), IsValid(false) {}
/// \brief Retrieve the controlling macro for this header file, if
/// any.
@@ -135,6 +146,8 @@ public:
/// \brief Encapsulates the information needed to find the file referenced
/// by a \#include or \#include_next, (sub-)framework lookup, etc.
class HeaderSearch {
+ friend class DirectoryLookup;
+
/// This structure is used to record entries in our framework cache.
struct FrameworkCacheEntry {
/// The directory entry which should be used for the cached framework.
@@ -151,6 +164,7 @@ class HeaderSearch {
DiagnosticsEngine &Diags;
FileManager &FileMgr;
+
/// \#include search path information. Requests for \#include "x" search the
/// directory of the \#including file first, then each directory in SearchDirs
/// consecutively. Requests for <x> search the current dir first, then each
@@ -158,9 +172,9 @@ class HeaderSearch {
/// NoCurDirSearch is true, then the check for the file in the current
/// directory is suppressed.
std::vector<DirectoryLookup> SearchDirs;
- unsigned AngledDirIdx;
- unsigned SystemDirIdx;
- bool NoCurDirSearch;
+ unsigned AngledDirIdx = 0;
+ unsigned SystemDirIdx = 0;
+ bool NoCurDirSearch = false;
/// \brief \#include prefixes for which the 'system header' property is
/// overridden.
@@ -168,7 +182,7 @@ class HeaderSearch {
/// For a \#include "x" or \#include \<x> directive, the last string in this
/// list which is a prefix of 'x' determines whether the file is treated as
/// a system header.
- std::vector<std::pair<std::string, bool> > SystemHeaderPrefixes;
+ std::vector<std::pair<std::string, bool>> SystemHeaderPrefixes;
/// \brief The path to the module cache.
std::string ModuleCachePath;
@@ -182,15 +196,17 @@ class HeaderSearch {
/// Starting index in SearchDirs that the cached search was performed from.
/// If there is a hit and this value doesn't match the current query, the
/// cache has to be ignored.
- unsigned StartIdx;
+ unsigned StartIdx = 0;
+
/// The entry in SearchDirs that satisfied the query.
- unsigned HitIdx;
+ unsigned HitIdx = 0;
+
/// This is non-null if the original filename was mapped to a framework
/// include via a headermap.
- const char *MappedName;
+ const char *MappedName = nullptr;
/// Default constructor -- Initialize all members with zero.
- LookupFileCacheInfo(): StartIdx(0), HitIdx(0), MappedName(nullptr) {}
+ LookupFileCacheInfo() = default;
void reset(unsigned StartIdx) {
this->StartIdx = StartIdx;
@@ -206,13 +222,13 @@ class HeaderSearch {
/// IncludeAliases - maps include file names (including the quotes or
/// angle brackets) to other include file names. This is used to support the
/// include_alias pragma for Microsoft compatibility.
- typedef llvm::StringMap<std::string, llvm::BumpPtrAllocator>
- IncludeAliasMap;
+ using IncludeAliasMap =
+ llvm::StringMap<std::string, llvm::BumpPtrAllocator>;
std::unique_ptr<IncludeAliasMap> IncludeAliases;
/// HeaderMaps - This is a mapping from FileEntry -> HeaderMap, uniquing
/// headermaps. This vector owns the headermap.
- std::vector<std::pair<const FileEntry*, const HeaderMap*> > HeaderMaps;
+ std::vector<std::pair<const FileEntry *, const HeaderMap *>> HeaderMaps;
/// \brief The mapping between modules and headers.
mutable ModuleMap ModMap;
@@ -231,26 +247,23 @@ class HeaderSearch {
/// \brief Entity used to resolve the identifier IDs of controlling
/// macros into IdentifierInfo pointers, and keep the identifire up to date,
/// as needed.
- ExternalPreprocessorSource *ExternalLookup;
+ ExternalPreprocessorSource *ExternalLookup = nullptr;
/// \brief Entity used to look up stored header file information.
- ExternalHeaderFileInfoSource *ExternalSource;
+ ExternalHeaderFileInfoSource *ExternalSource = nullptr;
// Various statistics we track for performance analysis.
- unsigned NumIncluded;
- unsigned NumMultiIncludeFileOptzn;
- unsigned NumFrameworkLookups, NumSubFrameworkLookups;
+ unsigned NumIncluded = 0;
+ unsigned NumMultiIncludeFileOptzn = 0;
+ unsigned NumFrameworkLookups = 0;
+ unsigned NumSubFrameworkLookups = 0;
- // HeaderSearch doesn't support default or copy construction.
- HeaderSearch(const HeaderSearch&) = delete;
- void operator=(const HeaderSearch&) = delete;
-
- friend class DirectoryLookup;
-
public:
HeaderSearch(std::shared_ptr<HeaderSearchOptions> HSOpts,
SourceManager &SourceMgr, DiagnosticsEngine &Diags,
const LangOptions &LangOpts, const TargetInfo *Target);
+ HeaderSearch(const HeaderSearch &) = delete;
+ HeaderSearch &operator=(const HeaderSearch &) = delete;
~HeaderSearch();
/// \brief Retrieve the header-search options with which this header search
@@ -282,7 +295,7 @@ public:
}
/// \brief Set the list of system header prefixes.
- void SetSystemHeaderPrefixes(ArrayRef<std::pair<std::string, bool> > P) {
+ void SetSystemHeaderPrefixes(ArrayRef<std::pair<std::string, bool>> P) {
SystemHeaderPrefixes.assign(P.begin(), P.end());
}
@@ -310,7 +323,7 @@ public:
IncludeAliasMap::const_iterator Iter = IncludeAliases->find(Source);
if (Iter != IncludeAliases->end())
return Iter->second;
- return StringRef();
+ return {};
}
/// \brief Set the path to the module cache.
@@ -471,29 +484,40 @@ public:
/// \brief Get filenames for all registered header maps.
void getHeaderMapFileNames(SmallVectorImpl<std::string> &Names) const;
- /// \brief Retrieve the name of the module file that should be used to
- /// load the given module.
+ /// \brief Retrieve the name of the cached module file that should be used
+ /// to load the given module.
///
/// \param Module The module whose module file name will be returned.
///
/// \returns The name of the module file that corresponds to this module,
/// or an empty string if this module does not correspond to any module file.
- std::string getModuleFileName(Module *Module);
+ std::string getCachedModuleFileName(Module *Module);
+
+ /// \brief Retrieve the name of the prebuilt module file that should be used
+ /// to load a module with the given name.
+ ///
+ /// \param ModuleName The module whose module file name will be returned.
+ ///
+ /// \param FileMapOnly If true, then only look in the explicit module name
+ // to file name map and skip the directory search.
+ ///
+ /// \returns The name of the module file that corresponds to this module,
+ /// or an empty string if this module does not correspond to any module file.
+ std::string getPrebuiltModuleFileName(StringRef ModuleName,
+ bool FileMapOnly = false);
- /// \brief Retrieve the name of the module file that should be used to
- /// load a module with the given name.
+ /// \brief Retrieve the name of the (to-be-)cached module file that should
+ /// be used to load a module with the given name.
///
/// \param ModuleName The module whose module file name will be returned.
///
/// \param ModuleMapPath A path that when combined with \c ModuleName
/// uniquely identifies this module. See Module::ModuleMap.
///
- /// \param UsePrebuiltPath Whether we should use the prebuilt module path.
- ///
/// \returns The name of the module file that corresponds to this module,
/// or an empty string if this module does not correspond to any module file.
- std::string getModuleFileName(StringRef ModuleName, StringRef ModuleMapPath,
- bool UsePrebuiltPath);
+ std::string getCachedModuleFileName(StringRef ModuleName,
+ StringRef ModuleMapPath);
/// \brief Lookup a module Search for a module with the given name.
///
@@ -560,7 +584,6 @@ public:
void loadTopLevelSystemModules();
private:
-
/// \brief Lookup a module with the given module name and search-name.
///
/// \param ModuleName The name of the module we're looking for.
@@ -640,7 +663,8 @@ public:
bool WantExternal = true) const;
// Used by external tools
- typedef std::vector<DirectoryLookup>::const_iterator search_dir_iterator;
+ using search_dir_iterator = std::vector<DirectoryLookup>::const_iterator;
+
search_dir_iterator search_dir_begin() const { return SearchDirs.begin(); }
search_dir_iterator search_dir_end() const { return SearchDirs.end(); }
unsigned search_dir_size() const { return SearchDirs.size(); }
@@ -648,6 +672,7 @@ public:
search_dir_iterator quoted_dir_begin() const {
return SearchDirs.begin();
}
+
search_dir_iterator quoted_dir_end() const {
return SearchDirs.begin() + AngledDirIdx;
}
@@ -655,6 +680,7 @@ public:
search_dir_iterator angled_dir_begin() const {
return SearchDirs.begin() + AngledDirIdx;
}
+
search_dir_iterator angled_dir_end() const {
return SearchDirs.begin() + SystemDirIdx;
}
@@ -662,6 +688,7 @@ public:
search_dir_iterator system_dir_begin() const {
return SearchDirs.begin() + SystemDirIdx;
}
+
search_dir_iterator system_dir_end() const { return SearchDirs.end(); }
/// \brief Retrieve a uniqued framework name.
@@ -684,10 +711,13 @@ private:
enum LoadModuleMapResult {
/// \brief The module map file had already been loaded.
LMM_AlreadyLoaded,
+
/// \brief The module map file was loaded by this invocation.
LMM_NewlyLoaded,
+
/// \brief There is was directory with the given name.
LMM_NoDirectory,
+
/// \brief There was either no module map file or the module map file was
/// invalid.
LMM_InvalidModuleMap
@@ -723,6 +753,6 @@ private:
bool IsSystem, bool IsFramework);
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_LEX_HEADERSEARCH_H
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearchOptions.h b/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearchOptions.h
index ca3a84e75e181..937ad9863db37 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearchOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearchOptions.h
@@ -1,4 +1,4 @@
-//===--- HeaderSearchOptions.h ----------------------------------*- C++ -*-===//
+//===- HeaderSearchOptions.h ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,35 +12,55 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/CachedHashString.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/StringRef.h"
+#include <cstdint>
#include <string>
#include <vector>
+#include <map>
namespace clang {
namespace frontend {
- /// IncludeDirGroup - Identifies the group an include Entry belongs to,
- /// representing its relative positive in the search list.
- /// \#include directives whose paths are enclosed by string quotes ("")
- /// start searching at the Quoted group (specified by '-iquote'),
- /// then search the Angled group, then the System group, etc.
- enum IncludeDirGroup {
- Quoted = 0, ///< '\#include ""' paths, added by 'gcc -iquote'.
- Angled, ///< Paths for '\#include <>' added by '-I'.
- IndexHeaderMap, ///< Like Angled, but marks header maps used when
- /// building frameworks.
- System, ///< Like Angled, but marks system directories.
- ExternCSystem, ///< Like System, but headers are implicitly wrapped in
- /// extern "C".
- CSystem, ///< Like System, but only used for C.
- CXXSystem, ///< Like System, but only used for C++.
- ObjCSystem, ///< Like System, but only used for ObjC.
- ObjCXXSystem, ///< Like System, but only used for ObjC++.
- After ///< Like System, but searched after the system directories.
- };
-}
+
+/// IncludeDirGroup - Identifies the group an include Entry belongs to,
+/// representing its relative positive in the search list.
+/// \#include directives whose paths are enclosed by string quotes ("")
+/// start searching at the Quoted group (specified by '-iquote'),
+/// then search the Angled group, then the System group, etc.
+enum IncludeDirGroup {
+ /// '\#include ""' paths, added by 'gcc -iquote'.
+ Quoted = 0,
+
+ /// Paths for '\#include <>' added by '-I'.
+ Angled,
+
+ /// Like Angled, but marks header maps used when building frameworks.
+ IndexHeaderMap,
+
+ /// Like Angled, but marks system directories.
+ System,
+
+ /// Like System, but headers are implicitly wrapped in extern "C".
+ ExternCSystem,
+
+ /// Like System, but only used for C.
+ CSystem,
+
+ /// Like System, but only used for C++.
+ CXXSystem,
+
+ /// Like System, but only used for ObjC.
+ ObjCSystem,
+
+ /// Like System, but only used for ObjC++.
+ ObjCXXSystem,
+
+ /// Like System, but searched after the system directories.
+ After
+};
+
+} // namespace frontend
/// HeaderSearchOptions - Helper class for storing options related to the
/// initialization of the HeaderSearch object.
@@ -58,8 +78,8 @@ public:
Entry(StringRef path, frontend::IncludeDirGroup group, bool isFramework,
bool ignoreSysRoot)
- : Path(path), Group(group), IsFramework(isFramework),
- IgnoreSysRoot(ignoreSysRoot) {}
+ : Path(path), Group(group), IsFramework(isFramework),
+ IgnoreSysRoot(ignoreSysRoot) {}
};
struct SystemHeaderPrefix {
@@ -71,7 +91,7 @@ public:
bool IsSystemHeader;
SystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader)
- : Prefix(Prefix), IsSystemHeader(IsSystemHeader) {}
+ : Prefix(Prefix), IsSystemHeader(IsSystemHeader) {}
};
/// If non-empty, the directory to use as a "virtual system root" for include
@@ -94,6 +114,9 @@ public:
/// \brief The directory used for a user build.
std::string ModuleUserBuildPath;
+ /// \brief The mapping of module names to prebuilt module files.
+ std::map<std::string, std::string> PrebuiltModuleFiles;
+
/// \brief The directories used to load prebuilt module files.
std::vector<std::string> PrebuiltModulePaths;
@@ -126,7 +149,7 @@ public:
/// files.
///
/// The default value is large, e.g., the operation runs once a week.
- unsigned ModuleCachePruneInterval;
+ unsigned ModuleCachePruneInterval = 7 * 24 * 60 * 60;
/// \brief The time (in seconds) after which an unused module file will be
/// considered unused and will, therefore, be pruned.
@@ -135,13 +158,13 @@ public:
/// accessed in this many seconds will be removed. The default value is
/// large, e.g., a month, to avoid forcing infrequently-used modules to be
/// regenerated often.
- unsigned ModuleCachePruneAfter;
+ unsigned ModuleCachePruneAfter = 31 * 24 * 60 * 60;
/// \brief The time in seconds when the build session started.
///
/// This time is used by other optimizations in header search and module
/// loading.
- uint64_t BuildSessionTimestamp;
+ uint64_t BuildSessionTimestamp = 0;
/// \brief The set of macro names that should be ignored for the purposes
/// of computing the module hash.
@@ -181,10 +204,8 @@ public:
unsigned ModulesHashContent : 1;
HeaderSearchOptions(StringRef _Sysroot = "/")
- : Sysroot(_Sysroot), ModuleFormat("raw"), DisableModuleHash(0),
- ImplicitModuleMaps(0), ModuleMapFileHomeIsCwd(0),
- ModuleCachePruneInterval(7 * 24 * 60 * 60),
- ModuleCachePruneAfter(31 * 24 * 60 * 60), BuildSessionTimestamp(0),
+ : Sysroot(_Sysroot), ModuleFormat("raw"), DisableModuleHash(false),
+ ImplicitModuleMaps(false), ModuleMapFileHomeIsCwd(false),
UseBuiltinIncludes(true), UseStandardSystemIncludes(true),
UseStandardCXXIncludes(true), UseLibcxx(false), Verbose(false),
ModulesValidateOncePerBuildSession(false),
@@ -213,6 +234,6 @@ public:
}
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_LEX_HEADERSEARCHOPTIONS_H
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Lexer.h b/contrib/llvm/tools/clang/include/clang/Lex/Lexer.h
index 3be733167e5cf..d58849654cb83 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/Lexer.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/Lexer.h
@@ -1,4 +1,4 @@
-//===--- Lexer.h - C Language Family Lexer ----------------------*- C++ -*-===//
+//===- Lexer.h - C Language Family Lexer ------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,45 +15,88 @@
#define LLVM_CLANG_LEX_LEXER_H
#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/TokenKinds.h"
#include "clang/Lex/PreprocessorLexer.h"
+#include "clang/Lex/Token.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include <cassert>
+#include <cstdint>
#include <string>
+namespace llvm {
+
+class MemoryBuffer;
+
+} // namespace llvm
+
namespace clang {
-class DiagnosticsEngine;
-class SourceManager;
-class Preprocessor;
+
class DiagnosticBuilder;
+class Preprocessor;
+class SourceManager;
/// ConflictMarkerKind - Kinds of conflict marker which the lexer might be
/// recovering from.
enum ConflictMarkerKind {
/// Not within a conflict marker.
CMK_None,
+
/// A normal or diff3 conflict marker, initiated by at least 7 "<"s,
/// separated by at least 7 "="s or "|"s, and terminated by at least 7 ">"s.
CMK_Normal,
+
/// A Perforce-style conflict marker, initiated by 4 ">"s,
/// separated by 4 "="s, and terminated by 4 "<"s.
CMK_Perforce
};
+/// Describes the bounds (start, size) of the preamble and a flag required by
+/// PreprocessorOptions::PrecompiledPreambleBytes.
+/// The preamble includes the BOM, if any.
+struct PreambleBounds {
+ /// \brief Size of the preamble in bytes.
+ unsigned Size;
+
+ /// \brief Whether the preamble ends at the start of a new line.
+ ///
+ /// Used to inform the lexer as to whether it's starting at the beginning of
+ /// a line after skipping the preamble.
+ bool PreambleEndsAtStartOfLine;
+
+ PreambleBounds(unsigned Size, bool PreambleEndsAtStartOfLine)
+ : Size(Size), PreambleEndsAtStartOfLine(PreambleEndsAtStartOfLine) {}
+};
+
/// Lexer - This provides a simple interface that turns a text buffer into a
/// stream of tokens. This provides no support for file reading or buffering,
/// or buffering/seeking of tokens, only forward lexing is supported. It relies
/// on the specified Preprocessor object to handle preprocessor directives, etc.
class Lexer : public PreprocessorLexer {
+ friend class Preprocessor;
+
void anchor() override;
//===--------------------------------------------------------------------===//
// Constant configuration values for this lexer.
- const char *BufferStart; // Start of the buffer.
- const char *BufferEnd; // End of the buffer.
- SourceLocation FileLoc; // Location for start of file.
- LangOptions LangOpts; // LangOpts enabled by this language (cache).
- bool Is_PragmaLexer; // True if lexer for _Pragma handling.
-
+
+ // Start of the buffer.
+ const char *BufferStart;
+
+ // End of the buffer.
+ const char *BufferEnd;
+
+ // Location for start of file.
+ SourceLocation FileLoc;
+
+ // LangOpts enabled by this language (cache).
+ LangOptions LangOpts;
+
+ // True if lexer for _Pragma handling.
+ bool Is_PragmaLexer;
+
//===--------------------------------------------------------------------===//
// Context-specific lexing flags set by the preprocessor.
//
@@ -89,13 +132,9 @@ class Lexer : public PreprocessorLexer {
// CurrentConflictMarkerState - The kind of conflict marker we are handling.
ConflictMarkerKind CurrentConflictMarkerState;
- Lexer(const Lexer &) = delete;
- void operator=(const Lexer &) = delete;
- friend class Preprocessor;
-
void InitLexer(const char *BufStart, const char *BufPtr, const char *BufEnd);
-public:
+public:
/// Lexer constructor - Create a new lexer object for the specified buffer
/// with the specified preprocessor managing the lexing process. This lexer
/// assumes that the associated file buffer and Preprocessor objects will
@@ -114,6 +153,9 @@ public:
Lexer(FileID FID, const llvm::MemoryBuffer *InputBuffer,
const SourceManager &SM, const LangOptions &LangOpts);
+ Lexer(const Lexer &) = delete;
+ Lexer &operator=(const Lexer &) = delete;
+
/// Create_PragmaLexer: Lexer constructor - Create a new lexer object for
/// _Pragma expansion. This has a variety of magic semantics that this method
/// sets up. It returns a new'd Lexer that must be delete'd when done.
@@ -122,7 +164,6 @@ public:
SourceLocation ExpansionLocEnd,
unsigned TokLen, Preprocessor &PP);
-
/// getLangOpts - Return the language features currently enabled.
/// NOTE: this lexer modifies features as a file is parsed!
const LangOptions &getLangOpts() const { return LangOpts; }
@@ -224,17 +265,16 @@ public:
/// \brief Return the current location in the buffer.
const char *getBufferLocation() const { return BufferPtr; }
-
- /// Stringify - Convert the specified string into a C string by escaping '\'
- /// and " characters. This does not add surrounding ""'s to the string.
+
+ /// Stringify - Convert the specified string into a C string by i) escaping
+ /// '\\' and " characters and ii) replacing newline character(s) with "\\n".
/// If Charify is true, this escapes the ' character instead of ".
static std::string Stringify(StringRef Str, bool Charify = false);
- /// Stringify - Convert the specified string into a C string by escaping '\'
- /// and " characters. This does not add surrounding ""'s to the string.
+ /// Stringify - Convert the specified string into a C string by i) escaping
+ /// '\\' and " characters and ii) replacing newline character(s) with "\\n".
static void Stringify(SmallVectorImpl<char> &Str);
-
/// getSpelling - This method is used to get the spelling of a token into a
/// preallocated buffer, instead of as an std::string. The caller is required
/// to allocate enough space for the token, which is guaranteed to be at least
@@ -245,11 +285,11 @@ public:
/// to point to a constant buffer with the data already in it (avoiding a
/// copy). The caller is not allowed to modify the returned buffer pointer
/// if an internal buffer is returned.
- static unsigned getSpelling(const Token &Tok, const char *&Buffer,
+ static unsigned getSpelling(const Token &Tok, const char *&Buffer,
const SourceManager &SourceMgr,
const LangOptions &LangOpts,
bool *Invalid = nullptr);
-
+
/// getSpelling() - Return the 'spelling' of the Tok token. The spelling of a
/// token is the characters used to represent the token in the source file
/// after trigraph expansion and escaped-newline folding. In particular, this
@@ -257,7 +297,7 @@ public:
/// UCNs, etc.
static std::string getSpelling(const Token &Tok,
const SourceManager &SourceMgr,
- const LangOptions &LangOpts,
+ const LangOptions &LangOpts,
bool *Invalid = nullptr);
/// getSpelling - This method is used to get the spelling of the
@@ -273,7 +313,7 @@ public:
const SourceManager &SourceMgr,
const LangOptions &LangOpts,
bool *invalid = nullptr);
-
+
/// MeasureTokenLength - Relex the token at the specified location and return
/// its length in bytes in the input file. If the token needs cleaning (e.g.
/// includes a trigraph or an escaped newline) then this count includes bytes
@@ -295,7 +335,7 @@ public:
static SourceLocation GetBeginningOfToken(SourceLocation Loc,
const SourceManager &SM,
const LangOptions &LangOpts);
-
+
/// AdvanceToTokenCharacter - If the current SourceLocation specifies a
/// location at the start of a token, return a new location that specifies a
/// character within the token. This handles trigraphs and escaped newlines.
@@ -303,7 +343,7 @@ public:
unsigned Character,
const SourceManager &SM,
const LangOptions &LangOpts);
-
+
/// \brief Computes the source location just past the end of the
/// token at this source location.
///
@@ -443,11 +483,18 @@ public:
/// to fewer than this number of lines.
///
/// \returns The offset into the file where the preamble ends and the rest
- /// of the file begins along with a boolean value indicating whether
+ /// of the file begins along with a boolean value indicating whether
/// the preamble ends at the beginning of a new line.
- static std::pair<unsigned, bool> ComputePreamble(StringRef Buffer,
- const LangOptions &LangOpts,
- unsigned MaxLines = 0);
+ static PreambleBounds ComputePreamble(StringRef Buffer,
+ const LangOptions &LangOpts,
+ unsigned MaxLines = 0);
+
+ /// Finds the token that comes right after the given location.
+ ///
+ /// Returns the next token, or none if the location is inside a macro.
+ static Optional<Token> findNextToken(SourceLocation Loc,
+ const SourceManager &SM,
+ const LangOptions &LangOpts);
/// \brief Checks that the given token is the first token that occurs after
/// the given location (this excludes comments and whitespace). Returns the
@@ -463,6 +510,10 @@ public:
/// \brief Returns true if the given character could appear in an identifier.
static bool isIdentifierBodyChar(char c, const LangOptions &LangOpts);
+ /// \brief Checks whether new line pointed by Str is preceded by escape
+ /// sequence.
+ static bool isNewLineEscaped(const char *BufferStart, const char *Str);
+
/// getCharAndSizeNoWarn - Like the getCharAndSize method, but does not ever
/// emit a warning.
static inline char getCharAndSizeNoWarn(const char *Ptr, unsigned &Size,
@@ -483,9 +534,9 @@ public:
static StringRef getIndentationForLine(SourceLocation Loc,
const SourceManager &SM);
+private:
//===--------------------------------------------------------------------===//
// Internal implementation interfaces.
-private:
/// LexTokenInternal - Internal interface to lex a preprocessing token. Called
/// by Lex.
@@ -614,7 +665,7 @@ private:
//===--------------------------------------------------------------------===//
// Other lexer functions.
- void SkipBytes(unsigned Bytes, bool StartOfLine);
+ void SetByteOffset(unsigned Offset, bool StartOfLine);
void PropagateLineStartLeadingSpaceInfo(Token &Result);
@@ -639,7 +690,7 @@ private:
bool SkipBlockComment (Token &Result, const char *CurPtr,
bool &TokAtPhysicalStartOfLine);
bool SaveLineComment (Token &Result, const char *CurPtr);
-
+
bool IsStartOfConflictMarker(const char *CurPtr);
bool HandleEndOfConflictMarker(const char *CurPtr);
@@ -658,7 +709,7 @@ private:
/// valid), this parameter will be updated to point to the
/// character after the UCN.
/// \param SlashLoc The position in the source buffer of the '\'.
- /// \param Tok The token being formed. Pass \c NULL to suppress diagnostics
+ /// \param Tok The token being formed. Pass \c nullptr to suppress diagnostics
/// and handle token formation in the caller.
///
/// \return The Unicode codepoint specified by the UCN, or 0 if the UCN is
@@ -687,6 +738,6 @@ private:
bool tryConsumeIdentifierUTF8Char(const char *&CurPtr);
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_LEX_LEXER_H
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h b/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h
index b66581b428b1f..cc9223eb7dbb3 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h
@@ -65,6 +65,7 @@ public:
bool isHalf : 1; // 1.0h
bool isFloat : 1; // 1.0f
bool isImaginary : 1; // 1.0i
+ bool isFloat16 : 1; // 1.0f16
bool isFloat128 : 1; // 1.0q
uint8_t MicrosoftInteger; // Microsoft suffix extension i8, i16, i32, or i64.
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/MacroArgs.h b/contrib/llvm/tools/clang/include/clang/Lex/MacroArgs.h
index cfe46ceb09797..a202550da3b3c 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/MacroArgs.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/MacroArgs.h
@@ -17,6 +17,7 @@
#include "clang/Basic/LLVM.h"
#include "clang/Lex/Token.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/TrailingObjects.h"
#include <vector>
namespace clang {
@@ -26,7 +27,10 @@ namespace clang {
/// MacroArgs - An instance of this class captures information about
/// the formal arguments specified to a function-like macro invocation.
-class MacroArgs {
+class MacroArgs final
+ : private llvm::TrailingObjects<MacroArgs, Token> {
+
+ friend TrailingObjects;
/// NumUnexpArgTokens - The number of raw, unexpanded tokens for the
/// arguments. All of the actual argument tokens are allocated immediately
/// after the MacroArgs object in memory. This is all of the arguments
@@ -89,7 +93,7 @@ public:
/// getPreExpArgument - Return the pre-expanded form of the specified
/// argument.
const std::vector<Token> &
- getPreExpArgument(unsigned Arg, const MacroInfo *MI, Preprocessor &PP);
+ getPreExpArgument(unsigned Arg, Preprocessor &PP);
/// getStringifiedArgument - Compute, cache, and return the specified argument
/// that has been 'stringified' as required by the # operator.
@@ -108,6 +112,20 @@ public:
/// argument, this returns false.
bool isVarargsElidedUse() const { return VarargsElided; }
+ /// Returns true if the macro was defined with a variadic (ellipsis) parameter
+ /// AND was invoked with at least one token supplied as a variadic argument.
+ ///
+ /// \code
+ /// #define F(a) a
+ /// #define V(a, ...) __VA_OPT__(a)
+ /// F() <-- returns false on this invocation.
+ /// V(,a) <-- returns true on this invocation.
+ /// V(,) <-- returns false on this invocation.
+ /// \endcode
+ ///
+
+ bool invokedWithVariadicArgument(const MacroInfo *const MI) const;
+
/// StringifyArgument - Implement C99 6.10.3.2p2, converting a sequence of
/// tokens into the literal string token that should be produced by the C #
/// preprocessor operator. If Charify is true, then it should be turned into
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h b/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h
index d25431b55fdc3..3029294209ec5 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h
@@ -1,4 +1,4 @@
-//===--- MacroInfo.h - Information about #defined identifiers ---*- C++ -*-===//
+//===- MacroInfo.h - Information about #defined identifiers -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,27 +6,33 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
/// \brief Defines the clang::MacroInfo and clang::MacroDirective classes.
-///
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LEX_MACROINFO_H
#define LLVM_CLANG_LEX_MACROINFO_H
#include "clang/Lex/Token.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Allocator.h"
+#include <algorithm>
#include <cassert>
namespace clang {
+
+class DefMacroDirective;
+class IdentifierInfo;
class Module;
-class ModuleMacro;
class Preprocessor;
+class SourceManager;
/// \brief Encapsulates the data about a macro definition (e.g. its tokens).
///
@@ -37,6 +43,7 @@ class MacroInfo {
/// \brief The location the macro is defined.
SourceLocation Location;
+
/// \brief The location of the last token in the macro.
SourceLocation EndLocation;
@@ -46,10 +53,10 @@ class MacroInfo {
///
/// This can be empty, for, e.g. "#define X()". In a C99-style variadic
/// macro, this includes the \c __VA_ARGS__ identifier on the list.
- IdentifierInfo **ParameterList;
+ IdentifierInfo **ParameterList = nullptr;
/// \see ParameterList
- unsigned NumParameters;
+ unsigned NumParameters = 0;
/// \brief This is the list of tokens that the macro is defined to.
SmallVector<Token, 8> ReplacementTokens;
@@ -169,7 +176,7 @@ public:
/// Parameters - The list of parameters for a function-like macro. This can
/// be empty, for, e.g. "#define X()".
- typedef IdentifierInfo *const *param_iterator;
+ using param_iterator = IdentifierInfo *const *;
bool param_empty() const { return NumParameters == 0; }
param_iterator param_begin() const { return ParameterList; }
param_iterator param_end() const { return ParameterList + NumParameters; }
@@ -224,7 +231,6 @@ public:
bool isWarnIfUnused() const { return IsWarnIfUnused; }
/// \brief Return the number of tokens that this macro expands to.
- ///
unsigned getNumTokens() const { return ReplacementTokens.size(); }
const Token &getReplacementToken(unsigned Tok) const {
@@ -232,7 +238,8 @@ public:
return ReplacementTokens[Tok];
}
- typedef SmallVectorImpl<Token>::const_iterator tokens_iterator;
+ using tokens_iterator = SmallVectorImpl<Token>::const_iterator;
+
tokens_iterator tokens_begin() const { return ReplacementTokens.begin(); }
tokens_iterator tokens_end() const { return ReplacementTokens.end(); }
bool tokens_empty() const { return ReplacementTokens.empty(); }
@@ -269,12 +276,10 @@ public:
void dump() const;
private:
- unsigned getDefinitionLengthSlow(const SourceManager &SM) const;
-
friend class Preprocessor;
-};
-class DefMacroDirective;
+ unsigned getDefinitionLengthSlow(const SourceManager &SM) const;
+};
/// \brief Encapsulates changes to the "macros namespace" (the location where
/// the macro name became active, the location where it was undefined, etc.).
@@ -285,11 +290,15 @@ class DefMacroDirective;
/// create additional DefMacroDirectives for the same MacroInfo.
class MacroDirective {
public:
- enum Kind { MD_Define, MD_Undefine, MD_Visibility };
+ enum Kind {
+ MD_Define,
+ MD_Undefine,
+ MD_Visibility
+ };
protected:
- /// \brief Previous macro directive for the same identifier, or NULL.
- MacroDirective *Previous;
+ /// \brief Previous macro directive for the same identifier, or nullptr.
+ MacroDirective *Previous = nullptr;
SourceLocation Loc;
@@ -306,8 +315,7 @@ protected:
unsigned IsPublic : 1;
MacroDirective(Kind K, SourceLocation Loc)
- : Previous(nullptr), Loc(Loc), MDKind(K), IsFromPCH(false),
- IsPublic(true) {}
+ : Loc(Loc), MDKind(K), IsFromPCH(false), IsPublic(true) {}
public:
Kind getKind() const { return Kind(MDKind); }
@@ -329,13 +337,12 @@ public:
void setIsFromPCH() { IsFromPCH = true; }
class DefInfo {
- DefMacroDirective *DefDirective;
+ DefMacroDirective *DefDirective = nullptr;
SourceLocation UndefLoc;
- bool IsPublic;
+ bool IsPublic = true;
public:
- DefInfo() : DefDirective(nullptr), IsPublic(true) {}
-
+ DefInfo() = default;
DefInfo(DefMacroDirective *DefDirective, SourceLocation UndefLoc,
bool isPublic)
: DefDirective(DefDirective), UndefLoc(UndefLoc), IsPublic(isPublic) {}
@@ -345,6 +352,7 @@ public:
inline SourceLocation getLocation() const;
inline MacroInfo *getMacroInfo();
+
const MacroInfo *getMacroInfo() const {
return const_cast<DefInfo *>(this)->getMacroInfo();
}
@@ -360,6 +368,7 @@ public:
explicit operator bool() const { return isValid(); }
inline DefInfo getPreviousDefinition();
+
const DefInfo getPreviousDefinition() const {
return const_cast<DefInfo *>(this)->getPreviousDefinition();
}
@@ -412,6 +421,7 @@ public:
static bool classof(const MacroDirective *MD) {
return MD->getKind() == MD_Define;
}
+
static bool classof(const DefMacroDirective *) { return true; }
};
@@ -426,6 +436,7 @@ public:
static bool classof(const MacroDirective *MD) {
return MD->getKind() == MD_Undefine;
}
+
static bool classof(const UndefMacroDirective *) { return true; }
};
@@ -444,12 +455,13 @@ public:
static bool classof(const MacroDirective *MD) {
return MD->getKind() == MD_Visibility;
}
+
static bool classof(const VisibilityMacroDirective *) { return true; }
};
inline SourceLocation MacroDirective::DefInfo::getLocation() const {
if (isInvalid())
- return SourceLocation();
+ return {};
return DefDirective->getLocation();
}
@@ -462,7 +474,7 @@ inline MacroInfo *MacroDirective::DefInfo::getMacroInfo() {
inline MacroDirective::DefInfo
MacroDirective::DefInfo::getPreviousDefinition() {
if (isInvalid() || DefDirective->getPrevious() == nullptr)
- return DefInfo();
+ return {};
return DefDirective->getPrevious()->getDefinition();
}
@@ -474,23 +486,26 @@ MacroDirective::DefInfo::getPreviousDefinition() {
///
/// These are stored in a FoldingSet in the preprocessor.
class ModuleMacro : public llvm::FoldingSetNode {
+ friend class Preprocessor;
+
/// The name defined by the macro.
IdentifierInfo *II;
+
/// The body of the #define, or nullptr if this is a #undef.
MacroInfo *Macro;
+
/// The module that exports this macro.
Module *OwningModule;
+
/// The number of module macros that override this one.
- unsigned NumOverriddenBy;
+ unsigned NumOverriddenBy = 0;
+
/// The number of modules whose macros are directly overridden by this one.
unsigned NumOverrides;
- // ModuleMacro *OverriddenMacros[NumOverrides];
-
- friend class Preprocessor;
ModuleMacro(Module *OwningModule, IdentifierInfo *II, MacroInfo *Macro,
ArrayRef<ModuleMacro *> Overrides)
- : II(II), Macro(Macro), OwningModule(OwningModule), NumOverriddenBy(0),
+ : II(II), Macro(Macro), OwningModule(OwningModule),
NumOverrides(Overrides.size()) {
std::copy(Overrides.begin(), Overrides.end(),
reinterpret_cast<ModuleMacro **>(this + 1));
@@ -504,12 +519,16 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) const {
return Profile(ID, OwningModule, II);
}
+
static void Profile(llvm::FoldingSetNodeID &ID, Module *OwningModule,
IdentifierInfo *II) {
ID.AddPointer(OwningModule);
ID.AddPointer(II);
}
+ /// Get the name of the macro.
+ IdentifierInfo *getName() const { return II; }
+
/// Get the ID of the module that exports this macro.
Module *getOwningModule() const { return OwningModule; }
@@ -519,13 +538,16 @@ public:
/// Iterators over the overridden module IDs.
/// \{
- typedef ModuleMacro *const *overrides_iterator;
+ using overrides_iterator = ModuleMacro *const *;
+
overrides_iterator overrides_begin() const {
return reinterpret_cast<overrides_iterator>(this + 1);
}
+
overrides_iterator overrides_end() const {
return overrides_begin() + NumOverrides;
}
+
ArrayRef<ModuleMacro *> overrides() const {
return llvm::makeArrayRef(overrides_begin(), overrides_end());
}
@@ -544,7 +566,7 @@ class MacroDefinition {
ArrayRef<ModuleMacro *> ModuleMacros;
public:
- MacroDefinition() : LatestLocalAndAmbiguous(), ModuleMacros() {}
+ MacroDefinition() = default;
MacroDefinition(DefMacroDirective *MD, ArrayRef<ModuleMacro *> MMs,
bool IsAmbiguous)
: LatestLocalAndAmbiguous(MD, IsAmbiguous), ModuleMacros(MMs) {}
@@ -583,6 +605,6 @@ public:
}
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_LEX_MACROINFO_H
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/ModuleLoader.h b/contrib/llvm/tools/clang/include/clang/Lex/ModuleLoader.h
index ee0638b57f872..30ea583b71e0b 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/ModuleLoader.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/ModuleLoader.h
@@ -1,4 +1,4 @@
-//===--- ModuleLoader.h - Module Loader Interface ---------------*- C++ -*-===//
+//===- ModuleLoader.h - Module Loader Interface -----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,23 +11,26 @@
// loading named modules.
//
//===----------------------------------------------------------------------===//
+
#ifndef LLVM_CLANG_LEX_MODULELOADER_H
#define LLVM_CLANG_LEX_MODULELOADER_H
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/StringRef.h"
+#include <utility>
namespace clang {
class GlobalModuleIndex;
class IdentifierInfo;
-class Module;
/// \brief A sequence of identifier/location pairs used to describe a particular
/// module or submodule, e.g., std.vector.
-typedef ArrayRef<std::pair<IdentifierInfo *, SourceLocation> > ModuleIdPath;
+using ModuleIdPath = ArrayRef<std::pair<IdentifierInfo *, SourceLocation>>;
/// \brief Describes the result of attempting to load a module.
class ModuleLoadResult {
@@ -35,16 +38,18 @@ public:
enum LoadResultKind {
// We either succeeded or failed to load the named module.
Normal,
+
// The module exists, but does not actually contain the named submodule.
// This should only happen if the named submodule was inferred from an
// umbrella directory, but not actually part of the umbrella header.
MissingExpected,
+
// The module exists but cannot be imported due to a configuration mismatch.
ConfigMismatch
};
llvm::PointerIntPair<Module *, 2, LoadResultKind> Storage;
- ModuleLoadResult() : Storage() { }
+ ModuleLoadResult() = default;
ModuleLoadResult(Module *M) : Storage(M, Normal) {}
ModuleLoadResult(LoadResultKind Kind) : Storage(nullptr, Kind) {}
@@ -69,10 +74,10 @@ public:
class ModuleLoader {
// Building a module if true.
bool BuildingModule;
+
public:
- explicit ModuleLoader(bool BuildingModule = false) :
- BuildingModule(BuildingModule),
- HadFatalFailure(false) {}
+ explicit ModuleLoader(bool BuildingModule = false)
+ : BuildingModule(BuildingModule) {}
virtual ~ModuleLoader();
@@ -80,6 +85,7 @@ public:
bool buildingModule() const {
return BuildingModule;
}
+
/// \brief Flag indicating whether this instance is building a module.
void setBuildingModule(bool BuildingModuleFlag) {
BuildingModule = BuildingModuleFlag;
@@ -144,7 +150,7 @@ public:
virtual bool lookupMissingImports(StringRef Name,
SourceLocation TriggerLoc) = 0;
- bool HadFatalFailure;
+ bool HadFatalFailure = false;
};
/// A module loader that doesn't know how to load modules.
@@ -153,7 +159,7 @@ public:
ModuleLoadResult loadModule(SourceLocation ImportLoc, ModuleIdPath Path,
Module::NameVisibilityKind Visibility,
bool IsInclusionDirective) override {
- return ModuleLoadResult();
+ return {};
}
void loadModuleFromSource(SourceLocation ImportLoc, StringRef ModuleName,
@@ -165,12 +171,13 @@ public:
GlobalModuleIndex *loadGlobalModuleIndex(SourceLocation TriggerLoc) override {
return nullptr;
}
+
bool lookupMissingImports(StringRef Name,
SourceLocation TriggerLoc) override {
- return 0;
+ return false;
}
};
-}
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_LEX_MODULELOADER_H
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/ModuleMap.h b/contrib/llvm/tools/clang/include/clang/Lex/ModuleMap.h
index 11506939f9b18..41ed8e49b6c1d 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/ModuleMap.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/ModuleMap.h
@@ -1,4 +1,4 @@
-//===--- ModuleMap.h - Describe the layout of modules -----------*- C++ -*-===//
+//===- ModuleMap.h - Describe the layout of modules -------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -18,7 +18,6 @@
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceLocation.h"
-#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerIntPair.h"
@@ -28,20 +27,19 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/ADT/Twine.h"
-#include <algorithm>
+#include <ctime>
#include <memory>
#include <string>
#include <utility>
namespace clang {
+class DiagnosticsEngine;
class DirectoryEntry;
class FileEntry;
class FileManager;
-class DiagnosticConsumer;
-class DiagnosticsEngine;
class HeaderSearch;
-class ModuleMapParser;
+class SourceManager;
/// \brief A mechanism to observe the actions of the module map parser as it
/// reads module map files.
@@ -82,33 +80,40 @@ class ModuleMap {
/// \brief The directory used for Clang-supplied, builtin include headers,
/// such as "stdint.h".
- const DirectoryEntry *BuiltinIncludeDir;
+ const DirectoryEntry *BuiltinIncludeDir = nullptr;
/// \brief Language options used to parse the module map itself.
///
/// These are always simple C language options.
LangOptions MMapLangOpts;
- // The module that the main source file is associated with (the module
- // named LangOpts::CurrentModule, if we've loaded it).
- Module *SourceModule;
+ /// The module that the main source file is associated with (the module
+ /// named LangOpts::CurrentModule, if we've loaded it).
+ Module *SourceModule = nullptr;
+
+ /// The global module for the current TU, if we still own it. (Ownership is
+ /// transferred if/when we create an enclosing module.
+ std::unique_ptr<Module> PendingGlobalModule;
/// \brief The top-level modules that are known.
llvm::StringMap<Module *> Modules;
/// \brief The number of modules we have created in total.
- unsigned NumCreatedModules;
+ unsigned NumCreatedModules = 0;
public:
/// \brief Flags describing the role of a module header.
enum ModuleHeaderRole {
/// \brief This header is normally included in the module.
NormalHeader = 0x0,
+
/// \brief This header is included but private.
PrivateHeader = 0x1,
+
/// \brief This header is part of the module (for layering purposes) but
/// should be textually included.
TextualHeader = 0x2,
+
// Caution: Adding an enumerator needs other changes.
// Adjust the number of bits for KnownHeader::Storage.
// Adjust the bitfield HeaderFileInfo::HeaderRole size.
@@ -119,6 +124,7 @@ public:
/// Convert a header kind to a role. Requires Kind to not be HK_Excluded.
static ModuleHeaderRole headerKindToRole(Module::HeaderKind Kind);
+
/// Convert a header role to a kind.
static Module::HeaderKind headerRoleToKind(ModuleHeaderRole Role);
@@ -128,8 +134,8 @@ public:
llvm::PointerIntPair<Module *, 2, ModuleHeaderRole> Storage;
public:
- KnownHeader() : Storage(nullptr, NormalHeader) { }
- KnownHeader(Module *M, ModuleHeaderRole Role) : Storage(M, Role) { }
+ KnownHeader() : Storage(nullptr, NormalHeader) {}
+ KnownHeader(Module *M, ModuleHeaderRole Role) : Storage(M, Role) {}
friend bool operator==(const KnownHeader &A, const KnownHeader &B) {
return A.Storage == B.Storage;
@@ -162,11 +168,13 @@ public:
}
};
- typedef llvm::SmallPtrSet<const FileEntry *, 1> AdditionalModMapsSet;
+ using AdditionalModMapsSet = llvm::SmallPtrSet<const FileEntry *, 1>;
private:
- typedef llvm::DenseMap<const FileEntry *, SmallVector<KnownHeader, 1>>
- HeadersMap;
+ friend class ModuleMapParser;
+
+ using HeadersMap =
+ llvm::DenseMap<const FileEntry *, SmallVector<KnownHeader, 1>>;
/// \brief Mapping from each header to the module that owns the contents of
/// that header.
@@ -174,6 +182,7 @@ private:
/// Map from file sizes to modules with lazy header directives of that size.
mutable llvm::DenseMap<off_t, llvm::TinyPtrVector<Module*>> LazyHeadersBySize;
+
/// Map from mtimes to modules with lazy header directives with those mtimes.
mutable llvm::DenseMap<time_t, llvm::TinyPtrVector<Module*>>
LazyHeadersByModTime;
@@ -188,9 +197,6 @@ private:
/// \brief The set of attributes that can be attached to a module.
struct Attributes {
- Attributes()
- : IsSystem(), IsExternC(), IsExhaustive(), NoUndeclaredIncludes() {}
-
/// \brief Whether this is a system module.
unsigned IsSystem : 1;
@@ -203,12 +209,14 @@ private:
/// \brief Whether files in this module can only include non-modular headers
/// and headers from used modules.
unsigned NoUndeclaredIncludes : 1;
+
+ Attributes()
+ : IsSystem(false), IsExternC(false), IsExhaustive(false),
+ NoUndeclaredIncludes(false) {}
};
/// \brief A directory for which framework modules can be inferred.
struct InferredDirectory {
- InferredDirectory() : InferModules() {}
-
/// \brief Whether to infer modules from this directory.
unsigned InferModules : 1;
@@ -222,6 +230,8 @@ private:
/// \brief The names of modules that cannot be inferred within this
/// directory.
SmallVector<std::string, 2> ExcludedModules;
+
+ InferredDirectory() : InferModules(false) {}
};
/// \brief A mapping from directories to information about inferring
@@ -238,8 +248,6 @@ private:
/// map.
llvm::DenseMap<const FileEntry *, bool> ParsedModuleMap;
- friend class ModuleMapParser;
-
/// \brief Resolve the given export declaration into an actual export
/// declaration.
///
@@ -341,7 +349,6 @@ public:
HeaderSearch &HeaderInfo);
/// \brief Destroy the module map.
- ///
~ModuleMap();
/// \brief Set the target information.
@@ -460,7 +467,7 @@ public:
/// \param Name The name of the module to find or create.
///
/// \param Parent The module that will act as the parent of this submodule,
- /// or NULL to indicate that this is a top-level module.
+ /// or nullptr to indicate that this is a top-level module.
///
/// \param IsFramework Whether this is a framework module.
///
@@ -472,6 +479,14 @@ public:
bool IsFramework,
bool IsExplicit);
+ /// \brief Create a 'global module' for a C++ Modules TS module interface
+ /// unit.
+ ///
+ /// We model the global module as a submodule of the module interface unit.
+ /// Unfortunately, we can't create the module interface unit's Module until
+ /// later, because we don't know what it will be called.
+ Module *createGlobalModuleForInterfaceUnit(SourceLocation Loc);
+
/// \brief Create a new module for a C++ Modules TS module interface unit.
/// The module must not already exist, and will be configured for the current
/// compilation.
@@ -479,7 +494,8 @@ public:
/// Note that this also sets the current module to the newly-created module.
///
/// \returns The newly-created module.
- Module *createModuleForInterfaceUnit(SourceLocation Loc, StringRef Name);
+ Module *createModuleForInterfaceUnit(SourceLocation Loc, StringRef Name,
+ Module *GlobalModule);
/// \brief Infer the contents of a framework module map from the given
/// framework directory.
@@ -492,7 +508,7 @@ public:
/// \param Module The module whose module map file will be returned, if known.
///
/// \returns The file entry for the module map file containing the given
- /// module, or NULL if the module definition was inferred.
+ /// module, or nullptr if the module definition was inferred.
const FileEntry *getContainingModuleMapFile(const Module *Module) const;
/// \brief Get the module map file that (along with the module name) uniquely
@@ -599,11 +615,12 @@ public:
/// \brief Dump the contents of the module map, for debugging purposes.
void dump();
- typedef llvm::StringMap<Module *>::const_iterator module_iterator;
+ using module_iterator = llvm::StringMap<Module *>::const_iterator;
+
module_iterator module_begin() const { return Modules.begin(); }
module_iterator module_end() const { return Modules.end(); }
};
-} // end namespace clang
+} // namespace clang
#endif // LLVM_CLANG_LEX_MODULEMAP_H
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/MultipleIncludeOpt.h b/contrib/llvm/tools/clang/include/clang/Lex/MultipleIncludeOpt.h
index 83e6f99078dfd..3967f8688966f 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/MultipleIncludeOpt.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/MultipleIncludeOpt.h
@@ -92,7 +92,7 @@ public:
TheMacro = nullptr;
}
- /// getHasReadAnyTokensVal - This is used for the \#ifndef hande-shake at the
+ /// getHasReadAnyTokensVal - This is used for the \#ifndef handshake at the
/// top of the file when reading preprocessor directives. Otherwise, reading
/// the "ifndef x" would count as reading tokens.
bool getHasReadAnyTokensVal() const { return ReadAnyTokens; }
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h b/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h
index 81c3bd7d14ec5..19bce4dd32e88 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h
@@ -235,6 +235,14 @@ public:
virtual void PragmaWarningPop(SourceLocation Loc) {
}
+ /// \brief Callback invoked when a \#pragma clang assume_nonnull begin directive
+ /// is read.
+ virtual void PragmaAssumeNonNullBegin(SourceLocation Loc) {}
+
+ /// \brief Callback invoked when a \#pragma clang assume_nonnull end directive
+ /// is read.
+ virtual void PragmaAssumeNonNullEnd(SourceLocation Loc) {}
+
/// \brief Called by Preprocessor::HandleMacroExpandedIdentifier when a
/// macro invocation is found.
virtual void MacroExpands(const Token &MacroNameTok,
@@ -266,7 +274,10 @@ public:
/// \brief Hook called when a source range is skipped.
/// \param Range The SourceRange that was skipped. The range begins at the
/// \#if/\#else directive and ends after the \#endif/\#else directive.
- virtual void SourceRangeSkipped(SourceRange Range) {
+ /// \param EndifLoc The end location of the 'endif' token, which may precede
+ /// the range skipped by the directive (e.g excluding comments after an
+ /// 'endif').
+ virtual void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) {
}
enum ConditionValueKind {
@@ -381,6 +392,12 @@ public:
Second->Ident(Loc, str);
}
+ void PragmaDirective(SourceLocation Loc,
+ PragmaIntroducerKind Introducer) override {
+ First->PragmaDirective(Loc, Introducer);
+ Second->PragmaDirective(Loc, Introducer);
+ }
+
void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
StringRef Str) override {
First->PragmaComment(Loc, Kind, Str);
@@ -393,6 +410,11 @@ public:
Second->PragmaDetectMismatch(Loc, Name, Value);
}
+ void PragmaDebug(SourceLocation Loc, StringRef DebugType) override {
+ First->PragmaDebug(Loc, DebugType);
+ Second->PragmaDebug(Loc, DebugType);
+ }
+
void PragmaMessage(SourceLocation Loc, StringRef Namespace,
PragmaMessageKind Kind, StringRef Str) override {
First->PragmaMessage(Loc, Namespace, Kind, Str);
@@ -437,6 +459,16 @@ public:
Second->PragmaWarningPop(Loc);
}
+ void PragmaAssumeNonNullBegin(SourceLocation Loc) override {
+ First->PragmaAssumeNonNullBegin(Loc);
+ Second->PragmaAssumeNonNullBegin(Loc);
+ }
+
+ void PragmaAssumeNonNullEnd(SourceLocation Loc) override {
+ First->PragmaAssumeNonNullEnd(Loc);
+ Second->PragmaAssumeNonNullEnd(Loc);
+ }
+
void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
SourceRange Range, const MacroArgs *Args) override {
First->MacroExpands(MacroNameTok, MD, Range, Args);
@@ -462,9 +494,9 @@ public:
Second->Defined(MacroNameTok, MD, Range);
}
- void SourceRangeSkipped(SourceRange Range) override {
- First->SourceRangeSkipped(Range);
- Second->SourceRangeSkipped(Range);
+ void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override {
+ First->SourceRangeSkipped(Range, EndifLoc);
+ Second->SourceRangeSkipped(Range, EndifLoc);
}
/// \brief Hook called whenever an \#if is seen.
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PTHLexer.h b/contrib/llvm/tools/clang/include/clang/Lex/PTHLexer.h
index f96af665b1574..f122a008e4aa1 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/PTHLexer.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/PTHLexer.h
@@ -1,4 +1,4 @@
-//===--- PTHLexer.h - Lexer based on Pre-tokenized input --------*- C++ -*-===//
+//===- PTHLexer.h - Lexer based on Pre-tokenized input ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,12 +14,15 @@
#ifndef LLVM_CLANG_LEX_PTHLEXER_H
#define LLVM_CLANG_LEX_PTHLEXER_H
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/TokenKinds.h"
#include "clang/Lex/PreprocessorLexer.h"
+#include "clang/Lex/Token.h"
namespace clang {
+class Preprocessor;
class PTHManager;
-class PTHSpellingSearch;
class PTHLexer : public PreprocessorLexer {
SourceLocation FileStartLoc;
@@ -33,7 +36,7 @@ class PTHLexer : public PreprocessorLexer {
/// LastHashTokPtr - Pointer into TokBuf of the last processed '#'
/// token that appears at the start of a line.
- const unsigned char* LastHashTokPtr;
+ const unsigned char* LastHashTokPtr = nullptr;
/// PPCond - Pointer to a side table in the PTH file that provides a
/// a concise summary of the preprocessor conditional block structure.
@@ -44,11 +47,8 @@ class PTHLexer : public PreprocessorLexer {
/// to process when doing quick skipping of preprocessor blocks.
const unsigned char* CurPPCondPtr;
- PTHLexer(const PTHLexer &) = delete;
- void operator=(const PTHLexer &) = delete;
-
/// ReadToken - Used by PTHLexer to read tokens TokBuf.
- void ReadToken(Token& T);
+ void ReadToken(Token &T);
bool LexEndOfFile(Token &Result);
@@ -61,10 +61,13 @@ protected:
friend class PTHManager;
/// Create a PTHLexer for the specified token stream.
- PTHLexer(Preprocessor& pp, FileID FID, const unsigned char *D,
+ PTHLexer(Preprocessor &pp, FileID FID, const unsigned char *D,
const unsigned char* ppcond, PTHManager &PM);
+
public:
- ~PTHLexer() override {}
+ PTHLexer(const PTHLexer &) = delete;
+ PTHLexer &operator=(const PTHLexer &) = delete;
+ ~PTHLexer() override = default;
/// Lex - Return the next token.
bool Lex(Token &Tok);
@@ -99,6 +102,6 @@ public:
bool SkipBlock();
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_LEX_PTHLEXER_H
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PTHManager.h b/contrib/llvm/tools/clang/include/clang/Lex/PTHManager.h
index f4e4774429f94..483b69f23a9cc 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/PTHManager.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/PTHManager.h
@@ -1,4 +1,4 @@
-//===--- PTHManager.h - Manager object for PTH processing -------*- C++ -*-===//
+//===- PTHManager.h - Manager object for PTH processing ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,30 +17,33 @@
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/OnDiskHashTable.h"
+#include <memory>
namespace llvm {
- class MemoryBuffer;
-}
+
+class MemoryBuffer;
+
+} // namespace llvm
namespace clang {
-class FileEntry;
-class Preprocessor;
-class PTHLexer;
class DiagnosticsEngine;
class FileSystemStatCache;
+class Preprocessor;
+class PTHLexer;
class PTHManager : public IdentifierInfoLookup {
friend class PTHLexer;
-
friend class PTHStatCache;
- class PTHStringLookupTrait;
class PTHFileLookupTrait;
- typedef llvm::OnDiskChainedHashTable<PTHStringLookupTrait> PTHStringIdLookup;
- typedef llvm::OnDiskChainedHashTable<PTHFileLookupTrait> PTHFileLookup;
+ class PTHStringLookupTrait;
+
+ using PTHStringIdLookup = llvm::OnDiskChainedHashTable<PTHStringLookupTrait>;
+ using PTHFileLookup = llvm::OnDiskChainedHashTable<PTHFileLookupTrait>;
/// The memory mapped PTH file.
std::unique_ptr<const llvm::MemoryBuffer> Buf;
@@ -70,7 +73,7 @@ class PTHManager : public IdentifierInfoLookup {
/// PP - The Preprocessor object that will use this PTHManager to create
/// PTHLexer objects.
- Preprocessor* PP;
+ Preprocessor* PP = nullptr;
/// SpellingBase - The base offset within the PTH memory buffer that
/// contains the cached spellings for literals.
@@ -89,16 +92,13 @@ class PTHManager : public IdentifierInfoLookup {
std::unique_ptr<PTHStringIdLookup> stringIdLookup, unsigned numIds,
const unsigned char *spellingBase, const char *originalSourceFile);
- PTHManager(const PTHManager &) = delete;
- void operator=(const PTHManager &) = delete;
-
/// getSpellingAtPTHOffset - Used by PTHLexer classes to get the cached
/// spelling for a token.
unsigned getSpellingAtPTHOffset(unsigned PTHOffset, const char*& Buffer);
/// GetIdentifierInfo - Used to reconstruct IdentifierInfo objects from the
/// PTH file.
- inline IdentifierInfo* GetIdentifierInfo(unsigned PersistentID) {
+ IdentifierInfo *GetIdentifierInfo(unsigned PersistentID) {
// Check if the IdentifierInfo has already been resolved.
if (IdentifierInfo* II = PerIDCache[PersistentID])
return II;
@@ -110,6 +110,8 @@ public:
// The current PTH version.
enum { Version = 10 };
+ PTHManager(const PTHManager &) = delete;
+ PTHManager &operator=(const PTHManager &) = delete;
~PTHManager() override;
/// getOriginalSourceFile - Return the full path to the original header
@@ -120,18 +122,18 @@ public:
/// get - Return the identifier token info for the specified named identifier.
/// Unlike the version in IdentifierTable, this returns a pointer instead
- /// of a reference. If the pointer is NULL then the IdentifierInfo cannot
+ /// of a reference. If the pointer is nullptr then the IdentifierInfo cannot
/// be found.
IdentifierInfo *get(StringRef Name) override;
/// Create - This method creates PTHManager objects. The 'file' argument
- /// is the name of the PTH file. This method returns NULL upon failure.
+ /// is the name of the PTH file. This method returns nullptr upon failure.
static PTHManager *Create(StringRef file, DiagnosticsEngine &Diags);
void setPreprocessor(Preprocessor *pp) { PP = pp; }
/// CreateLexer - Return a PTHLexer that "lexes" the cached tokens for the
- /// specified file. This method returns NULL if no cached tokens exist.
+ /// specified file. This method returns nullptr if no cached tokens exist.
/// It is the responsibility of the caller to 'delete' the returned object.
PTHLexer *CreateLexer(FileID FID);
@@ -142,6 +144,6 @@ public:
std::unique_ptr<FileSystemStatCache> createStatCache();
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_LEX_PTHMANAGER_H
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Pragma.h b/contrib/llvm/tools/clang/include/clang/Lex/Pragma.h
index 274f0dad3dd00..090ae2a98236e 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/Pragma.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/Pragma.h
@@ -1,4 +1,4 @@
-//===--- Pragma.h - Pragma registration and handling ------------*- C++ -*-===//
+//===- Pragma.h - Pragma registration and handling --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,13 +17,13 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
-#include <cassert>
+#include <string>
namespace clang {
- class Preprocessor;
- class Token;
- class IdentifierInfo;
- class PragmaNamespace;
+
+class PragmaNamespace;
+class Preprocessor;
+class Token;
/**
* \brief Describes how the pragma was introduced, e.g., with \#pragma,
@@ -58,9 +58,10 @@ namespace clang {
/// pragmas.
class PragmaHandler {
std::string Name;
+
public:
+ PragmaHandler() = default;
explicit PragmaHandler(StringRef name) : Name(name) {}
- PragmaHandler() {}
virtual ~PragmaHandler();
StringRef getName() const { return Name; }
@@ -89,8 +90,8 @@ public:
class PragmaNamespace : public PragmaHandler {
/// Handlers - This is a map of the handlers in this namespace with their name
/// as key.
- ///
- llvm::StringMap<PragmaHandler*> Handlers;
+ llvm::StringMap<PragmaHandler *> Handlers;
+
public:
explicit PragmaNamespace(StringRef Name) : PragmaHandler(Name) {}
~PragmaNamespace() override;
@@ -103,16 +104,13 @@ public:
bool IgnoreNull = true) const;
/// AddPragma - Add a pragma to this namespace.
- ///
void AddPragma(PragmaHandler *Handler);
/// RemovePragmaHandler - Remove the given handler from the
/// namespace.
void RemovePragmaHandler(PragmaHandler *Handler);
- bool IsEmpty() {
- return Handlers.empty();
- }
+ bool IsEmpty() const { return Handlers.empty(); }
void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &FirstToken) override;
@@ -120,7 +118,6 @@ public:
PragmaNamespace *getIfNamespace() override { return this; }
};
+} // namespace clang
-} // end namespace clang
-
-#endif
+#endif // LLVM_CLANG_LEX_PRAGMA_H
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h
index fc2c507004001..5f7a6efcef107 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h
@@ -1,4 +1,4 @@
-//===--- PreprocessingRecord.h - Record of Preprocessing --------*- C++ -*-===//
+//===- PreprocessingRecord.h - Record of Preprocessing ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,24 +11,33 @@
// of what occurred during preprocessing.
//
//===----------------------------------------------------------------------===//
+
#ifndef LLVM_CLANG_LEX_PREPROCESSINGRECORD_H
#define LLVM_CLANG_LEX_PREPROCESSINGRECORD_H
-#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Lex/PPCallbacks.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Compiler.h"
+#include <cassert>
+#include <cstddef>
+#include <iterator>
+#include <utility>
#include <vector>
namespace clang {
- class IdentifierInfo;
- class MacroInfo;
- class PreprocessingRecord;
-}
+
+class PreprocessingRecord;
+
+} // namespace clang
/// \brief Allocates memory within a Clang preprocessing record.
void *operator new(size_t bytes, clang::PreprocessingRecord &PR,
@@ -39,8 +48,12 @@ void operator delete(void *ptr, clang::PreprocessingRecord &PR,
unsigned) noexcept;
namespace clang {
- class MacroDefinitionRecord;
- class FileEntry;
+
+class FileEntry;
+class IdentifierInfo;
+class MacroInfo;
+class SourceManager;
+class Token;
/// \brief Base class that describes a preprocessed entity, which may be a
/// preprocessor directive or macro expansion.
@@ -78,11 +91,11 @@ namespace clang {
SourceRange Range;
protected:
- PreprocessedEntity(EntityKind Kind, SourceRange Range)
- : Kind(Kind), Range(Range) { }
-
friend class PreprocessingRecord;
+ PreprocessedEntity(EntityKind Kind, SourceRange Range)
+ : Kind(Kind), Range(Range) {}
+
public:
/// \brief Retrieve the kind of preprocessed entity stored in this object.
EntityKind getKind() const { return Kind; }
@@ -122,7 +135,7 @@ namespace clang {
class PreprocessingDirective : public PreprocessedEntity {
public:
PreprocessingDirective(EntityKind Kind, SourceRange Range)
- : PreprocessedEntity(Kind, Range) { }
+ : PreprocessedEntity(Kind, Range) {}
// Implement isa/cast/dyncast/etc.
static bool classof(const PreprocessedEntity *PD) {
@@ -199,10 +212,13 @@ namespace clang {
enum InclusionKind {
/// \brief An \c \#include directive.
Include,
+
/// \brief An Objective-C \c \#import directive.
Import,
+
/// \brief A GNU \c \#include_next directive.
IncludeNext,
+
/// \brief A Clang \c \#__include_macros directive.
IncludeMacros
};
@@ -316,11 +332,14 @@ namespace clang {
/// value 1 corresponds to element 0 in the local entities vector,
/// value 2 corresponds to element 1 in the local entities vector, etc.
class PPEntityID {
- int ID;
- explicit PPEntityID(int ID) : ID(ID) {}
friend class PreprocessingRecord;
+
+ int ID = 0;
+
+ explicit PPEntityID(int ID) : ID(ID) {}
+
public:
- PPEntityID() : ID(0) {}
+ PPEntityID() = default;
};
static PPEntityID getPPEntityID(unsigned Index, bool isLoaded) {
@@ -331,7 +350,7 @@ namespace clang {
llvm::DenseMap<const MacroInfo *, MacroDefinitionRecord *> MacroDefinitions;
/// \brief External source of preprocessed entities.
- ExternalPreprocessingRecordSource *ExternalSource;
+ ExternalPreprocessingRecordSource *ExternalSource = nullptr;
/// \brief Retrieve the preprocessed entity at the given ID.
PreprocessedEntity *getPreprocessedEntity(PPEntityID PPID);
@@ -371,7 +390,7 @@ namespace clang {
}
/// \brief Deallocate memory in the preprocessing record.
- void Deallocate(void *Ptr) { }
+ void Deallocate(void *Ptr) {}
size_t getTotalMemory() const;
@@ -397,11 +416,12 @@ namespace clang {
iterator, int, std::random_access_iterator_tag,
PreprocessedEntity *, int, PreprocessedEntity *,
PreprocessedEntity *> {
+ friend class PreprocessingRecord;
+
PreprocessingRecord *Self;
iterator(PreprocessingRecord *Self, int Position)
: iterator::iterator_adaptor_base(Position), Self(Self) {}
- friend class PreprocessingRecord;
public:
iterator() : iterator(nullptr, 0) {}
@@ -451,7 +471,6 @@ namespace clang {
/// encompasses.
///
/// \param R the range to look for preprocessed entities.
- ///
llvm::iterator_range<iterator>
getPreprocessedEntitiesInRange(SourceRange R);
@@ -485,6 +504,9 @@ namespace clang {
}
private:
+ friend class ASTReader;
+ friend class ASTWriter;
+
void MacroExpands(const Token &Id, const MacroDefinition &MD,
SourceRange Range, const MacroArgs *Args) override;
void MacroDefined(const Token &Id, const MacroDirective *MD) override;
@@ -500,11 +522,13 @@ namespace clang {
const MacroDefinition &MD) override;
void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
const MacroDefinition &MD) override;
+
/// \brief Hook called whenever the 'defined' operator is seen.
void Defined(const Token &MacroNameTok, const MacroDefinition &MD,
SourceRange Range) override;
- void SourceRangeSkipped(SourceRange Range) override;
+ void SourceRangeSkipped(SourceRange Range,
+ SourceLocation EndifLoc) override;
void addMacroExpansion(const Token &Id, const MacroInfo *MI,
SourceRange Range);
@@ -517,11 +541,9 @@ namespace clang {
} CachedRangeQuery;
std::pair<int, int> getPreprocessedEntitiesInRangeSlow(SourceRange R);
-
- friend class ASTReader;
- friend class ASTWriter;
};
-} // end namespace clang
+
+} // namespace clang
inline void *operator new(size_t bytes, clang::PreprocessingRecord &PR,
unsigned alignment) noexcept {
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h b/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h
index dba4b80f60719..485600f122329 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h
@@ -1,4 +1,4 @@
-//===--- Preprocessor.h - C Language Family Preprocessor --------*- C++ -*-===//
+//===- Preprocessor.h - C Language Family Preprocessor ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,10 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
/// \brief Defines the clang::Preprocessor interface.
-///
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LEX_PREPROCESSOR_H
@@ -18,48 +18,70 @@
#include "clang/Basic/Builtins.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/Module.h"
#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TokenKinds.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/ModuleLoader.h"
#include "clang/Lex/ModuleMap.h"
#include "clang/Lex/PPCallbacks.h"
#include "clang/Lex/PTHLexer.h"
+#include "clang/Lex/Token.h"
#include "clang/Lex/TokenLexer.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/TinyPtrVector.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/Registry.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
#include <memory>
+#include <map>
+#include <string>
+#include <utility>
#include <vector>
namespace llvm {
- template<unsigned InternalLen> class SmallString;
-}
+
+template<unsigned InternalLen> class SmallString;
+
+} // namespace llvm
namespace clang {
-class SourceManager;
+class CodeCompletionHandler;
+class CommentHandler;
+class DirectoryEntry;
+class DirectoryLookup;
class ExternalPreprocessorSource;
-class FileManager;
class FileEntry;
+class FileManager;
class HeaderSearch;
+class MacroArgs;
class MemoryBufferCache;
-class PragmaNamespace;
class PragmaHandler;
-class CommentHandler;
-class ScratchBuffer;
-class TargetInfo;
-class PPCallbacks;
-class CodeCompletionHandler;
-class DirectoryLookup;
+class PragmaNamespace;
class PreprocessingRecord;
-class ModuleLoader;
-class PTHManager;
+class PreprocessorLexer;
class PreprocessorOptions;
+class PTHManager;
+class ScratchBuffer;
+class TargetInfo;
/// \brief Stores token information for comparing actual tokens with
/// predefined values. Only handles simple tokens and identifiers.
@@ -75,7 +97,9 @@ public:
assert(!tok::isLiteral(Kind) && "Literals are not supported.");
assert(!tok::isAnnotation(Kind) && "Annotations are not supported.");
}
+
TokenValue(IdentifierInfo *II) : Kind(tok::identifier), II(II) {}
+
bool operator==(const Token &Tok) const {
return Tok.getKind() == Kind &&
(!II || II == Tok.getIdentifierInfo());
@@ -84,9 +108,14 @@ public:
/// \brief Context in which macro name is used.
enum MacroUse {
- MU_Other = 0, // other than #define or #undef
- MU_Define = 1, // macro name specified in #define
- MU_Undef = 2 // macro name specified in #undef
+ // other than #define or #undef
+ MU_Other = 0,
+
+ // macro name specified in #define
+ MU_Define = 1,
+
+ // macro name specified in #undef
+ MU_Undef = 2
};
/// \brief Engages in a tight little dance with the lexer to efficiently
@@ -96,11 +125,14 @@ enum MacroUse {
/// know anything about preprocessor-level issues like the \#include stack,
/// token expansion, etc.
class Preprocessor {
+ friend class VAOptDefinitionContext;
+ friend class VariadicMacroScopeGuard;
+
std::shared_ptr<PreprocessorOptions> PPOpts;
DiagnosticsEngine *Diags;
LangOptions &LangOpts;
- const TargetInfo *Target;
- const TargetInfo *AuxTarget;
+ const TargetInfo *Target = nullptr;
+ const TargetInfo *AuxTarget = nullptr;
FileManager &FileMgr;
SourceManager &SourceMgr;
MemoryBufferCache &PCMCache;
@@ -111,7 +143,6 @@ class Preprocessor {
/// \brief External source of macros.
ExternalPreprocessorSource *ExternalSource;
-
/// An optional PTHManager object used for getting tokens from
/// a token cache rather than lexing the original source file.
std::unique_ptr<PTHManager> PTH;
@@ -130,6 +161,7 @@ class Preprocessor {
IdentifierInfo *Ident_Pragma, *Ident__pragma; // _Pragma, __pragma
IdentifierInfo *Ident__identifier; // __identifier
IdentifierInfo *Ident__VA_ARGS__; // __VA_ARGS__
+ IdentifierInfo *Ident__VA_OPT__; // __VA_OPT__
IdentifierInfo *Ident__has_feature; // __has_feature
IdentifierInfo *Ident__has_extension; // __has_extension
IdentifierInfo *Ident__has_builtin; // __has_builtin
@@ -141,10 +173,17 @@ class Preprocessor {
IdentifierInfo *Ident__building_module; // __building_module
IdentifierInfo *Ident__MODULE__; // __MODULE__
IdentifierInfo *Ident__has_cpp_attribute; // __has_cpp_attribute
+ IdentifierInfo *Ident__has_c_attribute; // __has_c_attribute
IdentifierInfo *Ident__has_declspec; // __has_declspec_attribute
+ IdentifierInfo *Ident__is_target_arch; // __is_target_arch
+ IdentifierInfo *Ident__is_target_vendor; // __is_target_vendor
+ IdentifierInfo *Ident__is_target_os; // __is_target_os
+ IdentifierInfo *Ident__is_target_environment; // __is_target_environment
SourceLocation DATELoc, TIMELoc;
- unsigned CounterValue; // Next __COUNTER__ value.
+
+ // Next __COUNTER__ value, starts at 0.
+ unsigned CounterValue = 0;
enum {
/// \brief Maximum depth of \#includes.
@@ -218,19 +257,19 @@ class Preprocessor {
/// \brief True if we want to ignore EOF token and continue later on (thus
/// avoid tearing the Lexer and etc. down).
- bool IncrementalProcessing;
+ bool IncrementalProcessing = false;
/// The kind of translation unit we are processing.
TranslationUnitKind TUKind;
/// \brief The code-completion handler.
- CodeCompletionHandler *CodeComplete;
+ CodeCompletionHandler *CodeComplete = nullptr;
/// \brief The file that we're performing code-completion for, if any.
- const FileEntry *CodeCompletionFile;
+ const FileEntry *CodeCompletionFile = nullptr;
/// \brief The offset in file for the code-completion point.
- unsigned CodeCompletionOffset;
+ unsigned CodeCompletionOffset = 0;
/// \brief The location for the code-completion point. This gets instantiated
/// when the CodeCompletionFile gets \#include'ed for preprocessing.
@@ -250,11 +289,11 @@ class Preprocessor {
SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> ModuleImportPath;
/// \brief Whether the last token we lexed was an '@'.
- bool LastTokenWasAt;
+ bool LastTokenWasAt = false;
/// \brief Whether the module import expects an identifier next. Otherwise,
/// it expects a '.' or ';'.
- bool ModuleImportExpectsIdentifier;
+ bool ModuleImportExpectsIdentifier = false;
/// \brief The source location of the currently-active
/// \#pragma clang arc_cf_code_audited begin.
@@ -265,16 +304,16 @@ class Preprocessor {
SourceLocation PragmaAssumeNonNullLoc;
/// \brief True if we hit the code-completion point.
- bool CodeCompletionReached;
+ bool CodeCompletionReached = false;
/// \brief The code completion token containing the information
/// on the stem that is to be code completed.
- IdentifierInfo *CodeCompletionII;
+ IdentifierInfo *CodeCompletionII = nullptr;
/// \brief The directory that the main file should be considered to occupy,
/// if it does not correspond to a real file (as happens when building a
/// module).
- const DirectoryEntry *MainFileDir;
+ const DirectoryEntry *MainFileDir = nullptr;
/// \brief The number of bytes that we will initially skip when entering the
/// main file, along with a flag that indicates whether skipping this number
@@ -283,6 +322,26 @@ class Preprocessor {
/// This is used when loading a precompiled preamble.
std::pair<int, bool> SkipMainFilePreamble;
+public:
+ struct PreambleSkipInfo {
+ SourceLocation HashTokenLoc;
+ SourceLocation IfTokenLoc;
+ bool FoundNonSkipPortion;
+ bool FoundElse;
+ SourceLocation ElseLoc;
+
+ PreambleSkipInfo(SourceLocation HashTokenLoc, SourceLocation IfTokenLoc,
+ bool FoundNonSkipPortion, bool FoundElse,
+ SourceLocation ElseLoc)
+ : HashTokenLoc(HashTokenLoc), IfTokenLoc(IfTokenLoc),
+ FoundNonSkipPortion(FoundNonSkipPortion), FoundElse(FoundElse),
+ ElseLoc(ElseLoc) {}
+ };
+
+private:
+ friend class ASTReader;
+ friend class MacroArgs;
+
class PreambleConditionalStackStore {
enum State {
Off = 0,
@@ -291,7 +350,7 @@ class Preprocessor {
};
public:
- PreambleConditionalStackStore() : ConditionalStackState(Off) {}
+ PreambleConditionalStackStore() = default;
void startRecording() { ConditionalStackState = Recording; }
void startReplaying() { ConditionalStackState = Replaying; }
@@ -316,9 +375,15 @@ class Preprocessor {
bool hasRecordedPreamble() const { return !ConditionalStack.empty(); }
+ bool reachedEOFWhileSkipping() const { return SkipInfo.hasValue(); }
+
+ void clearSkipInfo() { SkipInfo.reset(); }
+
+ llvm::Optional<PreambleSkipInfo> SkipInfo;
+
private:
SmallVector<PPConditionalInfo, 4> ConditionalStack;
- State ConditionalStackState;
+ State ConditionalStackState = Off;
} PreambleConditionalStack;
/// \brief The current top of the stack that we're lexing from if
@@ -337,14 +402,14 @@ class Preprocessor {
/// if not expanding a macro.
///
/// This is an alias for either CurLexer or CurPTHLexer.
- PreprocessorLexer *CurPPLexer;
+ PreprocessorLexer *CurPPLexer = nullptr;
/// \brief Used to find the current FileEntry, if CurLexer is non-null
/// and if applicable.
///
/// This allows us to implement \#include_next and find directory-specific
/// properties.
- const DirectoryLookup *CurDirLookup;
+ const DirectoryLookup *CurDirLookup = nullptr;
/// \brief The current macro we are expanding, if we are expanding a macro.
///
@@ -358,11 +423,11 @@ class Preprocessor {
CLK_TokenLexer,
CLK_CachingLexer,
CLK_LexAfterModuleImport
- } CurLexerKind;
+ } CurLexerKind = CLK_Lexer;
/// \brief If the current lexer is for a submodule that is being built, this
/// is that submodule.
- Module *CurLexerSubmodule;
+ Module *CurLexerSubmodule = nullptr;
/// \brief Keeps track of the stack of files currently
/// \#included, and macros currently being expanded from, not counting
@@ -401,27 +466,31 @@ class Preprocessor {
Token Tok;
MacroDefinition MD;
SourceRange Range;
+
MacroExpandsInfo(Token Tok, MacroDefinition MD, SourceRange Range)
- : Tok(Tok), MD(MD), Range(Range) { }
+ : Tok(Tok), MD(MD), Range(Range) {}
};
SmallVector<MacroExpandsInfo, 2> DelayedMacroExpandsCallbacks;
/// Information about a name that has been used to define a module macro.
struct ModuleMacroInfo {
- ModuleMacroInfo(MacroDirective *MD)
- : MD(MD), ActiveModuleMacrosGeneration(0), IsAmbiguous(false) {}
-
/// The most recent macro directive for this identifier.
MacroDirective *MD;
+
/// The active module macros for this identifier.
- llvm::TinyPtrVector<ModuleMacro*> ActiveModuleMacros;
+ llvm::TinyPtrVector<ModuleMacro *> ActiveModuleMacros;
+
/// The generation number at which we last updated ActiveModuleMacros.
/// \see Preprocessor::VisibleModules.
- unsigned ActiveModuleMacrosGeneration;
+ unsigned ActiveModuleMacrosGeneration = 0;
+
/// Whether this macro name is ambiguous.
- bool IsAmbiguous;
+ bool IsAmbiguous = false;
+
/// The module macros that are overridden by this macro.
- llvm::TinyPtrVector<ModuleMacro*> OverriddenMacros;
+ llvm::TinyPtrVector<ModuleMacro *> OverriddenMacros;
+
+ ModuleMacroInfo(MacroDirective *MD) : MD(MD) {}
};
/// The state of a macro for an identifier.
@@ -456,15 +525,18 @@ class Preprocessor {
public:
MacroState() : MacroState(nullptr) {}
MacroState(MacroDirective *MD) : State(MD) {}
+
MacroState(MacroState &&O) noexcept : State(O.State) {
O.State = (MacroDirective *)nullptr;
}
+
MacroState &operator=(MacroState &&O) noexcept {
auto S = O.State;
O.State = (MacroDirective *)nullptr;
State = S;
return *this;
}
+
~MacroState() {
if (auto *Info = State.dyn_cast<ModuleMacroInfo*>())
Info->~ModuleMacroInfo();
@@ -475,6 +547,7 @@ class Preprocessor {
return Info->MD;
return State.get<MacroDirective*>();
}
+
void setLatest(MacroDirective *MD) {
if (auto *Info = State.dyn_cast<ModuleMacroInfo*>())
Info->MD = MD;
@@ -486,6 +559,7 @@ class Preprocessor {
auto *Info = getModuleInfo(PP, II);
return Info ? Info->IsAmbiguous : false;
}
+
ArrayRef<ModuleMacro *>
getActiveModuleMacros(Preprocessor &PP, const IdentifierInfo *II) const {
if (auto *Info = getModuleInfo(PP, II))
@@ -498,7 +572,7 @@ class Preprocessor {
// FIXME: Incorporate module macros into the result of this.
if (auto *Latest = getLatest())
return Latest->findDirectiveAtLoc(Loc, SourceMgr);
- return MacroDirective::DefInfo();
+ return {};
}
void overrideActiveModuleMacros(Preprocessor &PP, IdentifierInfo *II) {
@@ -510,11 +584,13 @@ class Preprocessor {
Info->IsAmbiguous = false;
}
}
+
ArrayRef<ModuleMacro*> getOverriddenMacros() const {
if (auto *Info = State.dyn_cast<ModuleMacroInfo*>())
return Info->OverriddenMacros;
return None;
}
+
void setOverriddenMacros(Preprocessor &PP,
ArrayRef<ModuleMacro *> Overrides) {
auto *Info = State.dyn_cast<ModuleMacroInfo*>();
@@ -537,31 +613,33 @@ class Preprocessor {
/// the reverse order (the latest one is in the head of the list).
///
/// This mapping lives within the \p CurSubmoduleState.
- typedef llvm::DenseMap<const IdentifierInfo *, MacroState> MacroMap;
-
- friend class ASTReader;
+ using MacroMap = llvm::DenseMap<const IdentifierInfo *, MacroState>;
struct SubmoduleState;
/// \brief Information about a submodule that we're currently building.
struct BuildingSubmoduleInfo {
- BuildingSubmoduleInfo(Module *M, SourceLocation ImportLoc, bool IsPragma,
- SubmoduleState *OuterSubmoduleState,
- unsigned OuterPendingModuleMacroNames)
- : M(M), ImportLoc(ImportLoc), IsPragma(IsPragma),
- OuterSubmoduleState(OuterSubmoduleState),
- OuterPendingModuleMacroNames(OuterPendingModuleMacroNames) {}
-
/// The module that we are building.
Module *M;
+
/// The location at which the module was included.
SourceLocation ImportLoc;
+
/// Whether we entered this submodule via a pragma.
bool IsPragma;
+
/// The previous SubmoduleState.
SubmoduleState *OuterSubmoduleState;
+
/// The number of pending module macro names when we started building this.
unsigned OuterPendingModuleMacroNames;
+
+ BuildingSubmoduleInfo(Module *M, SourceLocation ImportLoc, bool IsPragma,
+ SubmoduleState *OuterSubmoduleState,
+ unsigned OuterPendingModuleMacroNames)
+ : M(M), ImportLoc(ImportLoc), IsPragma(IsPragma),
+ OuterSubmoduleState(OuterSubmoduleState),
+ OuterPendingModuleMacroNames(OuterPendingModuleMacroNames) {}
};
SmallVector<BuildingSubmoduleInfo, 8> BuildingSubmoduleStack;
@@ -569,12 +647,14 @@ class Preprocessor {
struct SubmoduleState {
/// The macros for the submodule.
MacroMap Macros;
+
/// The set of modules that are visible within the submodule.
VisibleModuleSet VisibleModules;
+
// FIXME: CounterValue?
// FIXME: PragmaPushMacroInfo?
};
- std::map<Module*, SubmoduleState> Submodules;
+ std::map<Module *, SubmoduleState> Submodules;
/// The preprocessor state for preprocessing outside of any submodule.
SubmoduleState NullSubmoduleState;
@@ -587,11 +667,11 @@ class Preprocessor {
llvm::FoldingSet<ModuleMacro> ModuleMacros;
/// The names of potential module macros that we've not yet processed.
- llvm::SmallVector<const IdentifierInfo*, 32> PendingModuleMacroNames;
+ llvm::SmallVector<const IdentifierInfo *, 32> PendingModuleMacroNames;
/// The list of module macros, for each identifier, that are not overridden by
/// any other module macro.
- llvm::DenseMap<const IdentifierInfo *, llvm::TinyPtrVector<ModuleMacro*>>
+ llvm::DenseMap<const IdentifierInfo *, llvm::TinyPtrVector<ModuleMacro *>>
LeafModuleMacros;
/// \brief Macros that we want to warn because they are not used at the end
@@ -603,25 +683,35 @@ class Preprocessor {
/// just so that we can report that they are unused, we just warn using
/// the SourceLocations of this set (that will be filled by the ASTReader).
/// We are using SmallPtrSet instead of a vector for faster removal.
- typedef llvm::SmallPtrSet<SourceLocation, 32> WarnUnusedMacroLocsTy;
+ using WarnUnusedMacroLocsTy = llvm::SmallPtrSet<SourceLocation, 32>;
WarnUnusedMacroLocsTy WarnUnusedMacroLocs;
/// \brief A "freelist" of MacroArg objects that can be
/// reused for quick allocation.
- MacroArgs *MacroArgCache;
- friend class MacroArgs;
+ MacroArgs *MacroArgCache = nullptr;
/// For each IdentifierInfo used in a \#pragma push_macro directive,
/// we keep a MacroInfo stack used to restore the previous macro value.
- llvm::DenseMap<IdentifierInfo*, std::vector<MacroInfo*> > PragmaPushMacroInfo;
+ llvm::DenseMap<IdentifierInfo *, std::vector<MacroInfo *>>
+ PragmaPushMacroInfo;
// Various statistics we track for performance analysis.
- unsigned NumDirectives, NumDefined, NumUndefined, NumPragma;
- unsigned NumIf, NumElse, NumEndif;
- unsigned NumEnteredSourceFiles, MaxIncludeStackDepth;
- unsigned NumMacroExpanded, NumFnMacroExpanded, NumBuiltinMacroExpanded;
- unsigned NumFastMacroExpanded, NumTokenPaste, NumFastTokenPaste;
- unsigned NumSkipped;
+ unsigned NumDirectives = 0;
+ unsigned NumDefined = 0;
+ unsigned NumUndefined = 0;
+ unsigned NumPragma = 0;
+ unsigned NumIf = 0;
+ unsigned NumElse = 0;
+ unsigned NumEndif = 0;
+ unsigned NumEnteredSourceFiles = 0;
+ unsigned MaxIncludeStackDepth = 0;
+ unsigned NumMacroExpanded = 0;
+ unsigned NumFnMacroExpanded = 0;
+ unsigned NumBuiltinMacroExpanded = 0;
+ unsigned NumFastMacroExpanded = 0;
+ unsigned NumTokenPaste = 0;
+ unsigned NumFastTokenPaste = 0;
+ unsigned NumSkipped = 0;
/// \brief The predefined macros that preprocessor should use from the
/// command line etc.
@@ -643,17 +733,17 @@ class Preprocessor {
/// going to lex in the cache and when it finishes the tokens are removed
/// from the end of the cache.
SmallVector<Token, 16> MacroExpandedTokens;
- std::vector<std::pair<TokenLexer *, size_t> > MacroExpandingLexersStack;
+ std::vector<std::pair<TokenLexer *, size_t>> MacroExpandingLexersStack;
/// \brief A record of the macro definitions and expansions that
/// occurred during preprocessing.
///
/// This is an optional side structure that can be enabled with
/// \c createPreprocessingRecord() prior to preprocessing.
- PreprocessingRecord *Record;
+ PreprocessingRecord *Record = nullptr;
/// Cached tokens state.
- typedef SmallVector<Token, 1> CachedTokensTy;
+ using CachedTokensTy = SmallVector<Token, 1>;
/// \brief Cached tokens are stored here when we do backtracking or
/// lookahead. They are "lexed" by the CachingLex() method.
@@ -664,7 +754,7 @@ class Preprocessor {
///
/// If it points beyond the CachedTokens vector, it means that a normal
/// Lex() should be invoked.
- CachedTokensTy::size_type CachedLexPos;
+ CachedTokensTy::size_type CachedLexPos = 0;
/// \brief Stack of backtrack positions, allowing nested backtracks.
///
@@ -680,7 +770,7 @@ class Preprocessor {
/// MacroInfos are managed as a chain for easy disposal. This is the head
/// of that list.
- MacroInfoChain *MIChainHead;
+ MacroInfoChain *MIChainHead = nullptr;
void updateOutOfDateIdentifier(IdentifierInfo &II) const;
@@ -853,7 +943,7 @@ public:
MacroDefinition getMacroDefinition(const IdentifierInfo *II) {
if (!II->hasMacroDefinition())
- return MacroDefinition();
+ return {};
MacroState &S = CurSubmoduleState->Macros[II];
auto *MD = S.getLatest();
@@ -867,7 +957,7 @@ public:
MacroDefinition getMacroDefinitionAtLoc(const IdentifierInfo *II,
SourceLocation Loc) {
if (!II->hadMacroDefinition())
- return MacroDefinition();
+ return {};
MacroState &S = CurSubmoduleState->Macros[II];
MacroDirective::DefInfo DI;
@@ -923,6 +1013,7 @@ public:
MacroInfo *MI) {
return appendDefMacroDirective(II, MI, MI->getDefinitionLoc());
}
+
/// \brief Set a MacroDirective that was loaded from a PCH file.
void setLoadedMacroDirective(IdentifierInfo *II, MacroDirective *ED,
MacroDirective *MD);
@@ -946,10 +1037,12 @@ public:
/// Iterators for the macro history table. Currently defined macros have
/// IdentifierInfo::hasMacroDefinition() set and an empty
/// MacroInfo::getUndefLoc() at the head of the list.
- typedef MacroMap::const_iterator macro_iterator;
+ using macro_iterator = MacroMap::const_iterator;
+
macro_iterator macro_begin(bool IncludeExternalMacros = true) const;
macro_iterator macro_end(bool IncludeExternalMacros = true) const;
llvm::iterator_range<macro_iterator>
+
macros(bool IncludeExternalMacros = true) const {
return llvm::make_range(macro_begin(IncludeExternalMacros),
macro_end(IncludeExternalMacros));
@@ -963,6 +1056,7 @@ public:
ArrayRef<TokenValue> Tokens) const;
const std::string &getPredefines() const { return Predefines; }
+
/// \brief Set the predefines for this Preprocessor.
///
/// These predefines are automatically injected when parsing the main file.
@@ -1087,6 +1181,7 @@ public:
bool DisableMacroExpansion) {
EnterTokenStream(Toks.release(), NumToks, DisableMacroExpansion, true);
}
+
void EnterTokenStream(ArrayRef<Token> Toks, bool DisableMacroExpansion) {
EnterTokenStream(Toks.data(), Toks.size(), DisableMacroExpansion, false);
}
@@ -1605,7 +1700,6 @@ private:
llvm::DenseMap<IdentifierInfo*,unsigned> PoisonReasons;
public:
-
/// \brief Specifies the reason for poisoning an identifier.
///
/// If that identifier is accessed while poisoned, then this reason will be
@@ -1655,7 +1749,6 @@ public:
/// lex again.
bool HandleIdentifier(Token &Identifier);
-
/// \brief Callback invoked when the lexer hits the end of the current file.
///
/// This either returns the EOF token and returns true, or
@@ -1760,6 +1853,8 @@ public:
Module *LeaveSubmodule(bool ForPragma);
private:
+ friend void TokenLexer::ExpandFunctionArguments();
+
void PushIncludeMacroStack() {
assert(CurLexerKind != CLK_CachingLexer && "cannot push a caching lexer");
IncludeMacroStack.emplace_back(CurLexerKind, CurLexerSubmodule,
@@ -1818,7 +1913,6 @@ private:
///
/// Either returns a pointer to a MacroInfo object OR emits a diagnostic and
/// returns a nullptr if an invalid sequence of tokens is encountered.
-
MacroInfo *ReadOptionalMacroParameterListAndBody(
const Token &MacroNameTok, bool ImmediatelyAfterHeaderGuard);
@@ -1836,7 +1930,8 @@ private:
/// \p FoundElse is false, then \#else directives are ok, if not, then we have
/// already seen one so a \#else directive is a duplicate. When this returns,
/// the caller can lex the first valid token.
- void SkipExcludedConditionalBlock(SourceLocation IfTokenLoc,
+ void SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
+ SourceLocation IfTokenLoc,
bool FoundNonSkipPortion, bool FoundElse,
SourceLocation ElseLoc = SourceLocation());
@@ -1848,6 +1943,7 @@ private:
struct DirectiveEvalResult {
/// Whether the expression was evaluated as true or not.
bool Conditional;
+
/// True if the expression contained identifiers that were undefined.
bool IncludedUndefinedIds;
};
@@ -1877,8 +1973,8 @@ private:
/// from the end of the cache.
Token *cacheMacroExpandedTokens(TokenLexer *tokLexer,
ArrayRef<Token> tokens);
+
void removeCachedMacroExpandedTokensOfLastLexer();
- friend void TokenLexer::ExpandFunctionArguments();
/// Determine whether the next preprocessor token to be
/// lexed is a '('. If so, consume the token and return true, if not, this
@@ -1934,17 +2030,21 @@ private:
//===--------------------------------------------------------------------===//
// Caching stuff.
void CachingLex(Token &Result);
+
bool InCachingLexMode() const {
// If the Lexer pointers are 0 and IncludeMacroStack is empty, it means
// that we are past EOF, not that we are in CachingLex mode.
return !CurPPLexer && !CurTokenLexer && !CurPTHLexer &&
!IncludeMacroStack.empty();
}
+
void EnterCachingLexMode();
+
void ExitCachingLexMode() {
if (InCachingLexMode())
RemoveTopOfLexerStack();
}
+
const Token &PeekAhead(unsigned N);
void AnnotatePreviousCachedTokens(const Token &Tok);
@@ -2015,9 +2115,15 @@ public:
PreambleConditionalStack.setStack(s);
}
- void setReplayablePreambleConditionalStack(ArrayRef<PPConditionalInfo> s) {
+ void setReplayablePreambleConditionalStack(ArrayRef<PPConditionalInfo> s,
+ llvm::Optional<PreambleSkipInfo> SkipInfo) {
PreambleConditionalStack.startReplaying();
PreambleConditionalStack.setStack(s);
+ PreambleConditionalStack.SkipInfo = SkipInfo;
+ }
+
+ llvm::Optional<PreambleSkipInfo> getPreambleSkipInfo() const {
+ return PreambleConditionalStack.SkipInfo;
}
private:
@@ -2030,16 +2136,18 @@ private:
void HandleUndefDirective();
// Conditional Inclusion.
- void HandleIfdefDirective(Token &Tok, bool isIfndef,
- bool ReadAnyTokensBeforeDirective);
- void HandleIfDirective(Token &Tok, bool ReadAnyTokensBeforeDirective);
+ void HandleIfdefDirective(Token &Tok, const Token &HashToken,
+ bool isIfndef, bool ReadAnyTokensBeforeDirective);
+ void HandleIfDirective(Token &Tok, const Token &HashToken,
+ bool ReadAnyTokensBeforeDirective);
void HandleEndifDirective(Token &Tok);
- void HandleElseDirective(Token &Tok);
- void HandleElifDirective(Token &Tok);
+ void HandleElseDirective(Token &Tok, const Token &HashToken);
+ void HandleElifDirective(Token &Tok, const Token &HashToken);
// Pragmas.
void HandlePragmaDirective(SourceLocation IntroducerLoc,
PragmaIntroducerKind Introducer);
+
public:
void HandlePragmaOnce(Token &OnceTok);
void HandlePragmaMark();
@@ -2073,8 +2181,8 @@ public:
};
/// \brief Registry of pragma handlers added by plugins
-typedef llvm::Registry<PragmaHandler> PragmaHandlerRegistry;
+using PragmaHandlerRegistry = llvm::Registry<PragmaHandler>;
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_LEX_PREPROCESSOR_H
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h
index 5c2e4d41454b6..ff71d11b4511b 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h
@@ -1,4 +1,4 @@
-//===--- PreprocessorLexer.h - C Language Family Lexer ----------*- C++ -*-===//
+//===- PreprocessorLexer.h - C Language Family Lexer ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,10 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
/// \brief Defines the PreprocessorLexer interface.
-///
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LEX_PREPROCESSORLEXER_H
@@ -17,8 +17,10 @@
#include "clang/Lex/MultipleIncludeOpt.h"
#include "clang/Lex/Token.h"
+#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
+#include <cassert>
namespace clang {
@@ -27,25 +29,29 @@ class Preprocessor;
class PreprocessorLexer {
virtual void anchor();
+
protected:
- Preprocessor *PP; // Preprocessor object controlling lexing.
+ friend class Preprocessor;
+
+ // Preprocessor object controlling lexing.
+ Preprocessor *PP = nullptr;
/// The SourceManager FileID corresponding to the file being lexed.
const FileID FID;
/// \brief Number of SLocEntries before lexing the file.
- unsigned InitialNumSLocEntries;
+ unsigned InitialNumSLocEntries = 0;
//===--------------------------------------------------------------------===//
// Context-specific lexing flags set by the preprocessor.
//===--------------------------------------------------------------------===//
/// \brief True when parsing \#XXX; turns '\\n' into a tok::eod token.
- bool ParsingPreprocessorDirective;
+ bool ParsingPreprocessorDirective = false;
/// \brief True after \#include; turns \<xx> into a tok::angle_string_literal
/// token.
- bool ParsingFilename;
+ bool ParsingFilename = false;
/// \brief True if in raw mode.
///
@@ -60,7 +66,7 @@ protected:
/// 5. No callbacks are made into the preprocessor.
///
/// Note that in raw mode that the PP pointer may be null.
- bool LexingRawMode;
+ bool LexingRawMode = false;
/// \brief A state machine that detects the \#ifndef-wrapping a file
/// idiom for the multiple-include optimization.
@@ -70,19 +76,9 @@ protected:
/// we are currently in.
SmallVector<PPConditionalInfo, 4> ConditionalStack;
- PreprocessorLexer(const PreprocessorLexer &) = delete;
- void operator=(const PreprocessorLexer &) = delete;
- friend class Preprocessor;
-
+ PreprocessorLexer() : FID() {}
PreprocessorLexer(Preprocessor *pp, FileID fid);
-
- PreprocessorLexer()
- : PP(nullptr), InitialNumSLocEntries(0),
- ParsingPreprocessorDirective(false),
- ParsingFilename(false),
- LexingRawMode(false) {}
-
- virtual ~PreprocessorLexer() {}
+ virtual ~PreprocessorLexer() = default;
virtual void IndirectLex(Token& Result) = 0;
@@ -128,6 +124,8 @@ protected:
unsigned getConditionalStackDepth() const { return ConditionalStack.size(); }
public:
+ PreprocessorLexer(const PreprocessorLexer &) = delete;
+ PreprocessorLexer &operator=(const PreprocessorLexer &) = delete;
//===--------------------------------------------------------------------===//
// Misc. lexing methods.
@@ -168,12 +166,13 @@ public:
/// \brief Iterator that traverses the current stack of preprocessor
/// conditional directives (\#if/\#ifdef/\#ifndef).
- typedef SmallVectorImpl<PPConditionalInfo>::const_iterator
- conditional_iterator;
+ using conditional_iterator =
+ SmallVectorImpl<PPConditionalInfo>::const_iterator;
conditional_iterator conditional_begin() const {
return ConditionalStack.begin();
}
+
conditional_iterator conditional_end() const {
return ConditionalStack.end();
}
@@ -184,6 +183,6 @@ public:
}
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_LEX_PREPROCESSORLEXER_H
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorOptions.h b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorOptions.h
index d91c665cf1dd5..55fc305dc2950 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorOptions.h
@@ -1,4 +1,4 @@
-//===--- PreprocessorOptions.h ----------------------------------*- C++ -*-===//
+//===- PreprocessorOptions.h ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,30 +10,30 @@
#ifndef LLVM_CLANG_LEX_PREPROCESSOROPTIONS_H_
#define LLVM_CLANG_LEX_PREPROCESSOROPTIONS_H_
-#include "clang/Basic/SourceLocation.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "clang/Basic/LLVM.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
-#include <cassert>
+#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>
namespace llvm {
- class MemoryBuffer;
-}
-namespace clang {
+class MemoryBuffer;
+
+} // namespace llvm
-class Preprocessor;
-class LangOptions;
+namespace clang {
/// \brief Enumerate the kinds of standard library that
enum ObjCXXARCStandardLibraryKind {
ARCXX_nolib,
+
/// \brief libc++
ARCXX_libcxx,
+
/// \brief libstdc++
ARCXX_libstdcxx
};
@@ -42,17 +42,17 @@ enum ObjCXXARCStandardLibraryKind {
/// used in preprocessor initialization to InitializePreprocessor().
class PreprocessorOptions {
public:
- std::vector<std::pair<std::string, bool/*isUndef*/> > Macros;
+ std::vector<std::pair<std::string, bool/*isUndef*/>> Macros;
std::vector<std::string> Includes;
std::vector<std::string> MacroIncludes;
/// \brief Initialize the preprocessor with the compiler and target specific
/// predefines.
- unsigned UsePredefines : 1;
+ bool UsePredefines = true;
/// \brief Whether we should maintain a detailed record of all macro
/// definitions and expansions.
- unsigned DetailedRecord : 1;
+ bool DetailedRecord = false;
/// The implicit PCH included at the start of the translation unit, or empty.
std::string ImplicitPCHInclude;
@@ -62,13 +62,13 @@ public:
/// \brief When true, disables most of the normal validation performed on
/// precompiled headers.
- bool DisablePCHValidation;
+ bool DisablePCHValidation = false;
/// \brief When true, a PCH with compiler errors will not be rejected.
- bool AllowPCHWithCompilerErrors;
+ bool AllowPCHWithCompilerErrors = false;
/// \brief Dump declarations that are deserialized from PCH, for testing.
- bool DumpDeserializedPCHDecls;
+ bool DumpDeserializedPCHDecls = false;
/// \brief This is a set of names for decls that we do not want to be
/// deserialized, and we emit an error if they are; for testing purposes.
@@ -86,7 +86,7 @@ public:
/// When the lexer is done, one of the things that need to be preserved is the
/// conditional #if stack, so the ASTWriter/ASTReader can save/restore it when
/// processing the rest of the file.
- bool GeneratePreamble;
+ bool GeneratePreamble = false;
/// The implicit PTH input included at the start of the translation unit, or
/// empty.
@@ -107,7 +107,7 @@ public:
/// \brief True if the SourceManager should report the original file name for
/// contents of files that were remapped to other files. Defaults to true.
- bool RemappedFilesKeepOriginalName;
+ bool RemappedFilesKeepOriginalName = true;
/// \brief The set of file remappings, which take existing files on
/// the system (the first part of each pair) and gives them the
@@ -126,12 +126,12 @@ public:
/// This flag defaults to false; it can be set true only through direct
/// manipulation of the compiler invocation object, in cases where the
/// compiler invocation and its buffers will be reused.
- bool RetainRemappedFileBuffers;
+ bool RetainRemappedFileBuffers = false;
/// \brief The Objective-C++ ARC standard library that we should support,
/// by providing appropriate definitions to retrofit the standard library
/// with support for lifetime-qualified pointers.
- ObjCXXARCStandardLibraryKind ObjCXXARCStandardLibrary;
+ ObjCXXARCStandardLibraryKind ObjCXXARCStandardLibrary = ARCXX_nolib;
/// \brief Records the set of modules
class FailedModulesSet {
@@ -156,18 +156,11 @@ public:
std::shared_ptr<FailedModulesSet> FailedModules;
public:
- PreprocessorOptions() : UsePredefines(true), DetailedRecord(false),
- DisablePCHValidation(false),
- AllowPCHWithCompilerErrors(false),
- DumpDeserializedPCHDecls(false),
- PrecompiledPreambleBytes(0, true),
- GeneratePreamble(false),
- RemappedFilesKeepOriginalName(true),
- RetainRemappedFileBuffers(false),
- ObjCXXARCStandardLibrary(ARCXX_nolib) { }
+ PreprocessorOptions() : PrecompiledPreambleBytes(0, false) {}
void addMacroDef(StringRef Name) { Macros.emplace_back(Name, false); }
void addMacroUndef(StringRef Name) { Macros.emplace_back(Name, true); }
+
void addRemappedFile(StringRef From, StringRef To) {
RemappedFiles.emplace_back(From, To);
}
@@ -195,10 +188,10 @@ public:
LexEditorPlaceholders = true;
RetainRemappedFileBuffers = true;
PrecompiledPreambleBytes.first = 0;
- PrecompiledPreambleBytes.second = 0;
+ PrecompiledPreambleBytes.second = false;
}
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_LEX_PREPROCESSOROPTIONS_H_
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h b/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h
index fdeed44d8f9b3..b8b0beabf2ba2 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h
@@ -1,4 +1,4 @@
-//===--- TokenLexer.h - Lex from a token buffer -----------------*- C++ -*-===//
+//===- TokenLexer.h - Lex from a token buffer -------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,29 +15,31 @@
#define LLVM_CLANG_LEX_TOKENLEXER_H
#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
namespace clang {
- class MacroInfo;
- class Preprocessor;
- class Token;
- class MacroArgs;
+
+class MacroArgs;
+class MacroInfo;
+class Preprocessor;
+class Token;
+class VAOptExpansionContext;
/// TokenLexer - This implements a lexer that returns tokens from a macro body
/// or token stream instead of lexing from a character buffer. This is used for
/// macro expansion and _Pragma handling, for example.
-///
class TokenLexer {
+ friend class Preprocessor;
+
/// Macro - The macro we are expanding from. This is null if expanding a
/// token stream.
- ///
- MacroInfo *Macro;
+ MacroInfo *Macro = nullptr;
/// ActualArgs - The actual arguments specified for a function-like macro, or
/// null. The TokenLexer owns the pointed-to object.
- MacroArgs *ActualArgs;
+ MacroArgs *ActualArgs = nullptr;
/// PP - The current preprocessor object we are expanding for.
- ///
Preprocessor &PP;
/// Tokens - This is the pointer to an array of tokens that the macro is
@@ -49,15 +51,12 @@ class TokenLexer {
/// Note that if it points into Preprocessor's cache buffer, the Preprocessor
/// may update the pointer as needed.
const Token *Tokens;
- friend class Preprocessor;
/// NumTokens - This is the length of the Tokens array.
- ///
unsigned NumTokens;
- /// CurToken - This is the next token that Lex will return.
- ///
- unsigned CurToken;
+ /// This is the index of the next token that Lex will return.
+ unsigned CurTokenIdx;
/// ExpandLocStart/End - The source location range where this macro was
/// expanded.
@@ -73,6 +72,7 @@ class TokenLexer {
/// \brief Location of the macro definition.
SourceLocation MacroDefStart;
+
/// \brief Length of the macro definition.
unsigned MacroDefLength;
@@ -99,8 +99,6 @@ class TokenLexer {
/// should not be subject to further macro expansion.
bool DisableMacroExpansion : 1;
- TokenLexer(const TokenLexer &) = delete;
- void operator=(const TokenLexer &) = delete;
public:
/// Create a TokenLexer for the specified macro with the specified actual
/// arguments. Note that this ctor takes ownership of the ActualArgs pointer.
@@ -108,26 +106,30 @@ public:
/// identifier for an object-like macro.
TokenLexer(Token &Tok, SourceLocation ILEnd, MacroInfo *MI,
MacroArgs *ActualArgs, Preprocessor &pp)
- : Macro(nullptr), ActualArgs(nullptr), PP(pp), OwnsTokens(false) {
+ : PP(pp), OwnsTokens(false) {
Init(Tok, ILEnd, MI, ActualArgs);
}
- /// Init - Initialize this TokenLexer to expand from the specified macro
- /// with the specified argument information. Note that this ctor takes
- /// ownership of the ActualArgs pointer. ILEnd specifies the location of the
- /// ')' for a function-like macro or the identifier for an object-like macro.
- void Init(Token &Tok, SourceLocation ILEnd, MacroInfo *MI,
- MacroArgs *ActualArgs);
-
/// Create a TokenLexer for the specified token stream. If 'OwnsTokens' is
/// specified, this takes ownership of the tokens and delete[]'s them when
/// the token lexer is empty.
TokenLexer(const Token *TokArray, unsigned NumToks, bool DisableExpansion,
bool ownsTokens, Preprocessor &pp)
- : Macro(nullptr), ActualArgs(nullptr), PP(pp), OwnsTokens(false) {
+ : PP(pp), OwnsTokens(false) {
Init(TokArray, NumToks, DisableExpansion, ownsTokens);
}
+ TokenLexer(const TokenLexer &) = delete;
+ TokenLexer &operator=(const TokenLexer &) = delete;
+ ~TokenLexer() { destroy(); }
+
+ /// Init - Initialize this TokenLexer to expand from the specified macro
+ /// with the specified argument information. Note that this ctor takes
+ /// ownership of the ActualArgs pointer. ILEnd specifies the location of the
+ /// ')' for a function-like macro or the identifier for an object-like macro.
+ void Init(Token &Tok, SourceLocation ILEnd, MacroInfo *MI,
+ MacroArgs *ActualArgs);
+
/// Init - Initialize this TokenLexer with the specified token stream.
/// This does not take ownership of the specified token vector.
///
@@ -136,8 +138,6 @@ public:
void Init(const Token *TokArray, unsigned NumToks,
bool DisableMacroExpansion, bool OwnsTokens);
- ~TokenLexer() { destroy(); }
-
/// isNextTokenLParen - If the next token lexed will pop this macro off the
/// expansion stack, return 2. If the next unexpanded token is a '(', return
/// 1, otherwise return 0.
@@ -156,15 +156,54 @@ private:
/// isAtEnd - Return true if the next lex call will pop this macro off the
/// include stack.
bool isAtEnd() const {
- return CurToken == NumTokens;
+ return CurTokenIdx == NumTokens;
}
- /// PasteTokens - Tok is the LHS of a ## operator, and CurToken is the ##
- /// operator. Read the ## and RHS, and paste the LHS/RHS together. If there
- /// are is another ## after it, chomp it iteratively. Return the result as
- /// Tok. If this returns true, the caller should immediately return the
+ /// Concatenates the next (sub-)sequence of \p Tokens separated by '##'
+ /// starting with LHSTok - stopping when we encounter a token that is neither
+ /// '##' nor preceded by '##'. Places the result back into \p LHSTok and sets
+ /// \p CurIdx to point to the token following the last one that was pasted.
+ ///
+ /// Also performs the MSVC extension wide-literal token pasting involved with:
+ /// \code L #macro-arg. \endcode
+ ///
+ /// \param[in,out] LHSTok - Contains the token to the left of '##' in \p
+ /// Tokens upon entry and will contain the resulting concatenated Token upon
+ /// exit.
+ ///
+ /// \param[in] TokenStream - The stream of Tokens we are lexing from.
+ ///
+ /// \param[in,out] CurIdx - Upon entry, \pTokens[\pCurIdx] must equal '##'
+ /// (with the exception of the MSVC extension mentioned above). Upon exit, it
+ /// is set to the index of the token following the last token that was
+ /// concatenated together.
+ ///
+ /// \returns If this returns true, the caller should immediately return the
/// token.
- bool PasteTokens(Token &Tok);
+ bool pasteTokens(Token &LHSTok, ArrayRef<Token> TokenStream,
+ unsigned int &CurIdx);
+
+ /// Calls pasteTokens above, passing in the '*this' object's Tokens and
+ /// CurTokenIdx data members.
+ bool pasteTokens(Token &Tok);
+
+
+ /// Takes the tail sequence of tokens within ReplacementToks that represent
+ /// the just expanded __VA_OPT__ tokens (possibly zero tokens) and transforms
+ /// them into a string. \p VCtx is used to determine which token represents
+ /// the first __VA_OPT__ replacement token.
+ ///
+ /// \param[in,out] ReplacementToks - Contains the current Replacement Tokens
+ /// (prior to rescanning and token pasting), the tail end of which represents
+ /// the tokens just expanded through __VA_OPT__ processing. These (sub)
+ /// sequence of tokens are folded into one stringified token.
+ ///
+ /// \param[in] VCtx - contains relevent contextual information about the
+ /// state of the tokens around and including the __VA_OPT__ token, necessary
+ /// for stringification.
+ void stringifyVAOPTContents(SmallVectorImpl<Token> &ReplacementToks,
+ const VAOptExpansionContext &VCtx,
+ SourceLocation VAOPTClosingParenLoc);
/// Expand the arguments of a function-like macro so that we can quickly
/// return preexpanded tokens from Tokens.
@@ -200,6 +239,6 @@ private:
void PropagateLineStartLeadingSpaceInfo(Token &Result);
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_LEX_TOKENLEXER_H
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/VariadicMacroSupport.h b/contrib/llvm/tools/clang/include/clang/Lex/VariadicMacroSupport.h
new file mode 100644
index 0000000000000..cebaf15187de0
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/VariadicMacroSupport.h
@@ -0,0 +1,226 @@
+//===- VariadicMacroSupport.h - state machines and scope guards -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines support types to help with preprocessing variadic macro
+// (i.e. macros that use: ellipses __VA_ARGS__ ) definitions and
+// expansions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_VARIADICMACROSUPPORT_H
+#define LLVM_CLANG_LEX_VARIADICMACROSUPPORT_H
+
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+ class Preprocessor;
+
+ /// An RAII class that tracks when the Preprocessor starts and stops lexing
+ /// the definition of a (ISO C/C++) variadic macro. As an example, this is
+ /// useful for unpoisoning and repoisoning certain identifiers (such as
+ /// __VA_ARGS__) that are only allowed in this context. Also, being a friend
+ /// of the Preprocessor class allows it to access PP's cached identifiers
+ /// directly (as opposed to performing a lookup each time).
+ class VariadicMacroScopeGuard {
+ const Preprocessor &PP;
+ IdentifierInfo *const Ident__VA_ARGS__;
+ IdentifierInfo *const Ident__VA_OPT__;
+
+ public:
+ VariadicMacroScopeGuard(const Preprocessor &P)
+ : PP(P), Ident__VA_ARGS__(PP.Ident__VA_ARGS__),
+ Ident__VA_OPT__(PP.Ident__VA_OPT__) {
+ assert(Ident__VA_ARGS__->isPoisoned() && "__VA_ARGS__ should be poisoned "
+ "outside an ISO C/C++ variadic "
+ "macro definition!");
+ assert(
+ !Ident__VA_OPT__ ||
+ (Ident__VA_OPT__->isPoisoned() && "__VA_OPT__ should be poisoned!"));
+ }
+
+ /// Client code should call this function just before the Preprocessor is
+ /// about to Lex tokens from the definition of a variadic (ISO C/C++) macro.
+ void enterScope() {
+ Ident__VA_ARGS__->setIsPoisoned(false);
+ if (Ident__VA_OPT__)
+ Ident__VA_OPT__->setIsPoisoned(false);
+ }
+
+ /// Client code should call this function as soon as the Preprocessor has
+ /// either completed lexing the macro's definition tokens, or an error
+ /// occured and the context is being exited. This function is idempotent
+ /// (might be explicitly called, and then reinvoked via the destructor).
+ void exitScope() {
+ Ident__VA_ARGS__->setIsPoisoned(true);
+ if (Ident__VA_OPT__)
+ Ident__VA_OPT__->setIsPoisoned(true);
+ }
+
+ ~VariadicMacroScopeGuard() { exitScope(); }
+ };
+
+ /// \brief A class for tracking whether we're inside a VA_OPT during a
+ /// traversal of the tokens of a variadic macro definition.
+ class VAOptDefinitionContext {
+ /// Contains all the locations of so far unmatched lparens.
+ SmallVector<SourceLocation, 8> UnmatchedOpeningParens;
+
+ const IdentifierInfo *const Ident__VA_OPT__;
+
+
+ public:
+ VAOptDefinitionContext(Preprocessor &PP)
+ : Ident__VA_OPT__(PP.Ident__VA_OPT__) {}
+
+ bool isVAOptToken(const Token &T) const {
+ return Ident__VA_OPT__ && T.getIdentifierInfo() == Ident__VA_OPT__;
+ }
+
+ /// Returns true if we have seen the __VA_OPT__ and '(' but before having
+ /// seen the matching ')'.
+ bool isInVAOpt() const { return UnmatchedOpeningParens.size(); }
+
+ /// Call this function as soon as you see __VA_OPT__ and '('.
+ void sawVAOptFollowedByOpeningParens(const SourceLocation LParenLoc) {
+ assert(!isInVAOpt() && "Must NOT be within VAOPT context to call this");
+ UnmatchedOpeningParens.push_back(LParenLoc);
+
+ }
+
+ SourceLocation getUnmatchedOpeningParenLoc() const {
+ assert(isInVAOpt() && "Must be within VAOPT context to call this");
+ return UnmatchedOpeningParens.back();
+ }
+
+ /// Call this function each time an rparen is seen. It returns true only if
+ /// the rparen that was just seen was the eventual (non-nested) closing
+ /// paren for VAOPT, and ejects us out of the VAOPT context.
+ bool sawClosingParen() {
+ assert(isInVAOpt() && "Must be within VAOPT context to call this");
+ UnmatchedOpeningParens.pop_back();
+ return !UnmatchedOpeningParens.size();
+ }
+
+ /// Call this function each time an lparen is seen.
+ void sawOpeningParen(SourceLocation LParenLoc) {
+ assert(isInVAOpt() && "Must be within VAOPT context to call this");
+ UnmatchedOpeningParens.push_back(LParenLoc);
+ }
+
+ };
+
+ /// \brief A class for tracking whether we're inside a VA_OPT during a
+ /// traversal of the tokens of a macro during macro expansion.
+ class VAOptExpansionContext : VAOptDefinitionContext {
+
+ Token SyntheticEOFToken;
+
+ // The (spelling) location of the current __VA_OPT__ in the replacement list
+ // of the function-like macro being expanded.
+ SourceLocation VAOptLoc;
+
+ // NumOfTokensPriorToVAOpt : when != -1, contains the index *of* the first
+ // token of the current VAOPT contents (so we know where to start eager
+ // token-pasting and stringification) *within* the substituted tokens of
+ // the function-like macro's new replacement list.
+ int NumOfTokensPriorToVAOpt = -1;
+
+ unsigned LeadingSpaceForStringifiedToken : 1;
+
+ unsigned StringifyBefore : 1;
+ unsigned CharifyBefore : 1;
+
+
+ bool hasStringifyBefore() const {
+ assert(!isReset() &&
+ "Must only be called if the state has not been reset");
+ return StringifyBefore;
+ }
+
+ bool isReset() const {
+ return NumOfTokensPriorToVAOpt == -1 ||
+ VAOptLoc.isInvalid();
+ }
+
+ public:
+ VAOptExpansionContext(Preprocessor &PP)
+ : VAOptDefinitionContext(PP), LeadingSpaceForStringifiedToken(false),
+ StringifyBefore(false), CharifyBefore(false) {
+ SyntheticEOFToken.startToken();
+ SyntheticEOFToken.setKind(tok::eof);
+ }
+
+ void reset() {
+ VAOptLoc = SourceLocation();
+ NumOfTokensPriorToVAOpt = -1;
+ LeadingSpaceForStringifiedToken = false;
+ StringifyBefore = false;
+ CharifyBefore = false;
+ }
+
+ const Token &getEOFTok() const { return SyntheticEOFToken; }
+
+ void sawHashOrHashAtBefore(const bool HasLeadingSpace,
+ const bool IsHashAt) {
+
+ StringifyBefore = !IsHashAt;
+ CharifyBefore = IsHashAt;
+ LeadingSpaceForStringifiedToken = HasLeadingSpace;
+ }
+
+
+
+ bool hasCharifyBefore() const {
+ assert(!isReset() &&
+ "Must only be called if the state has not been reset");
+ return CharifyBefore;
+ }
+ bool hasStringifyOrCharifyBefore() const {
+ return hasStringifyBefore() || hasCharifyBefore();
+ }
+
+ unsigned int getNumberOfTokensPriorToVAOpt() const {
+ assert(!isReset() &&
+ "Must only be called if the state has not been reset");
+ return NumOfTokensPriorToVAOpt;
+ }
+
+ bool getLeadingSpaceForStringifiedToken() const {
+ assert(hasStringifyBefore() &&
+ "Must only be called if this has been marked for stringification");
+ return LeadingSpaceForStringifiedToken;
+ }
+
+ void sawVAOptFollowedByOpeningParens(const SourceLocation VAOptLoc,
+ const unsigned int NumPriorTokens) {
+ assert(VAOptLoc.isFileID() && "Must not come from a macro expansion");
+ assert(isReset() && "Must only be called if the state has been reset");
+ VAOptDefinitionContext::sawVAOptFollowedByOpeningParens(SourceLocation());
+ this->VAOptLoc = VAOptLoc;
+ NumOfTokensPriorToVAOpt = NumPriorTokens;
+ assert(NumOfTokensPriorToVAOpt > -1 &&
+ "Too many prior tokens");
+ }
+
+ SourceLocation getVAOptLoc() const {
+ assert(!isReset() &&
+ "Must only be called if the state has not been reset");
+ assert(VAOptLoc.isValid() && "__VA_OPT__ location must be valid");
+ return VAOptLoc;
+ }
+ using VAOptDefinitionContext::isVAOptToken;
+ using VAOptDefinitionContext::isInVAOpt;
+ using VAOptDefinitionContext::sawClosingParen;
+ using VAOptDefinitionContext::sawOpeningParen;
+
+ };
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Parse/ParseAST.h b/contrib/llvm/tools/clang/include/clang/Parse/ParseAST.h
index 21f9701c3ed8b..34c96816ebdf6 100644
--- a/contrib/llvm/tools/clang/include/clang/Parse/ParseAST.h
+++ b/contrib/llvm/tools/clang/include/clang/Parse/ParseAST.h
@@ -29,10 +29,13 @@ namespace clang {
/// This operation inserts the parsed decls into the translation
/// unit held by Ctx.
///
+ /// \param PrintStats Whether to print LLVM statistics related to parsing.
/// \param TUKind The kind of translation unit being parsed.
- ///
/// \param CompletionConsumer If given, an object to consume code completion
/// results.
+ /// \param SkipFunctionBodies Whether to skip parsing of function bodies.
+ /// This option can be used, for example, to speed up searches for
+ /// declarations/definitions when indexing.
void ParseAST(Preprocessor &pp, ASTConsumer *C,
ASTContext &Ctx, bool PrintStats = false,
TranslationUnitKind TUKind = TU_Complete,
@@ -43,7 +46,7 @@ namespace clang {
/// abstract syntax tree.
void ParseAST(Sema &S, bool PrintStats = false,
bool SkipFunctionBodies = false);
-
+
} // end namespace clang
#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Parse/Parser.h b/contrib/llvm/tools/clang/include/clang/Parse/Parser.h
index 21d699ec402e5..396b5a9aa394d 100644
--- a/contrib/llvm/tools/clang/include/clang/Parse/Parser.h
+++ b/contrib/llvm/tools/clang/include/clang/Parse/Parser.h
@@ -253,6 +253,10 @@ class Parser : public CodeCompletionHandler {
/// be NULL.
bool ParsingInObjCContainer;
+ /// Whether to skip parsing of function bodies.
+ ///
+ /// This option can be used, for example, to speed up searches for
+ /// declarations/definitions when indexing.
bool SkipFunctionBodies;
/// The location of the expression statement that is being parsed right now.
@@ -334,6 +338,27 @@ public:
return true;
}
+ /// ConsumeAnyToken - Dispatch to the right Consume* method based on the
+ /// current token type. This should only be used in cases where the type of
+ /// the token really isn't known, e.g. in error recovery.
+ SourceLocation ConsumeAnyToken(bool ConsumeCodeCompletionTok = false) {
+ if (isTokenParen())
+ return ConsumeParen();
+ if (isTokenBracket())
+ return ConsumeBracket();
+ if (isTokenBrace())
+ return ConsumeBrace();
+ if (isTokenStringLiteral())
+ return ConsumeStringToken();
+ if (Tok.is(tok::code_completion))
+ return ConsumeCodeCompletionTok ? ConsumeCodeCompletionToken()
+ : handleUnexpectedCodeCompletionToken();
+ if (Tok.isAnnotation())
+ return ConsumeAnnotationToken();
+ return ConsumeToken();
+ }
+
+
SourceLocation getEndOfPreviousToken() {
return PP.getLocForEndOfToken(PrevTokLocation);
}
@@ -384,26 +409,6 @@ private:
PP.EnterToken(Next);
}
- /// ConsumeAnyToken - Dispatch to the right Consume* method based on the
- /// current token type. This should only be used in cases where the type of
- /// the token really isn't known, e.g. in error recovery.
- SourceLocation ConsumeAnyToken(bool ConsumeCodeCompletionTok = false) {
- if (isTokenParen())
- return ConsumeParen();
- if (isTokenBracket())
- return ConsumeBracket();
- if (isTokenBrace())
- return ConsumeBrace();
- if (isTokenStringLiteral())
- return ConsumeStringToken();
- if (Tok.is(tok::code_completion))
- return ConsumeCodeCompletionTok ? ConsumeCodeCompletionToken()
- : handleUnexpectedCodeCompletionToken();
- if (Tok.isAnnotation())
- return ConsumeAnnotationToken();
- return ConsumeToken();
- }
-
SourceLocation ConsumeAnnotationToken() {
assert(Tok.isAnnotation() && "wrong consume method");
SourceLocation Loc = Tok.getLocation();
@@ -501,6 +506,12 @@ private:
Kind == tok::annot_module_end || Kind == tok::annot_module_include;
}
+ /// \brief Checks if the \p Level is valid for use in a fold expression.
+ bool isFoldOperator(prec::Level Level) const;
+
+ /// \brief Checks if the \p Kind is a valid operator for fold expressions.
+ bool isFoldOperator(tok::TokenKind Kind) const;
+
/// \brief Initialize all pragma handlers.
void initializePragmaHandlers();
@@ -1470,7 +1481,6 @@ public:
ExprResult ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks,
unsigned &NumLineToksConsumed,
- void *Info,
bool IsUnevaluated);
private:
@@ -1517,9 +1527,10 @@ private:
typedef SmallVector<SourceLocation, 20> CommaLocsTy;
/// ParseExpressionList - Used for C/C++ (argument-)expression-list.
- bool ParseExpressionList(SmallVectorImpl<Expr *> &Exprs,
- SmallVectorImpl<SourceLocation> &CommaLocs,
- std::function<void()> Completer = nullptr);
+ bool ParseExpressionList(
+ SmallVectorImpl<Expr *> &Exprs,
+ SmallVectorImpl<SourceLocation> &CommaLocs,
+ llvm::function_ref<void()> Completer = llvm::function_ref<void()>());
/// ParseSimpleExpressionList - A simple comma-separated list of expressions,
/// used for misc language extensions.
@@ -2159,18 +2170,25 @@ public:
private:
void ParseBlockId(SourceLocation CaretLoc);
- // Check for the start of a C++11 attribute-specifier-seq in a context where
- // an attribute is not allowed.
+ /// Are [[]] attributes enabled?
+ bool standardAttributesAllowed() const {
+ const LangOptions &LO = getLangOpts();
+ return LO.DoubleSquareBracketAttributes;
+ }
+
+ // Check for the start of an attribute-specifier-seq in a context where an
+ // attribute is not allowed.
bool CheckProhibitedCXX11Attribute() {
assert(Tok.is(tok::l_square));
- if (!getLangOpts().CPlusPlus11 || NextToken().isNot(tok::l_square))
+ if (!standardAttributesAllowed() || NextToken().isNot(tok::l_square))
return false;
return DiagnoseProhibitedCXX11Attribute();
}
+
bool DiagnoseProhibitedCXX11Attribute();
void CheckMisplacedCXX11Attribute(ParsedAttributesWithRange &Attrs,
SourceLocation CorrectLocation) {
- if (!getLangOpts().CPlusPlus11)
+ if (!standardAttributesAllowed())
return;
if ((Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square)) &&
Tok.isNot(tok::kw_alignas))
@@ -2190,17 +2208,18 @@ private:
}
void DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs);
- // Forbid C++11 attributes that appear on certain syntactic
- // locations which standard permits but we don't supported yet,
- // for example, attributes appertain to decl specifiers.
+ // Forbid C++11 and C2x attributes that appear on certain syntactic locations
+ // which standard permits but we don't supported yet, for example, attributes
+ // appertain to decl specifiers.
void ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs,
unsigned DiagID);
- /// \brief Skip C++11 attributes and return the end location of the last one.
+ /// \brief Skip C++11 and C2x attributes and return the end location of the
+ /// last one.
/// \returns SourceLocation() if there are no attributes.
SourceLocation SkipCXX11Attributes();
- /// \brief Diagnose and skip C++11 attributes that appear in syntactic
+ /// \brief Diagnose and skip C++11 and C2x attributes that appear in syntactic
/// locations where attributes are not allowed.
void DiagnoseAndSkipCXX11Attributes();
@@ -2250,7 +2269,7 @@ private:
AttributeList::Syntax Syntax);
void MaybeParseCXX11Attributes(Declarator &D) {
- if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) {
+ if (standardAttributesAllowed() && isCXX11AttributeSpecifier()) {
ParsedAttributesWithRange attrs(AttrFactory);
SourceLocation endLoc;
ParseCXX11Attributes(attrs, &endLoc);
@@ -2259,7 +2278,7 @@ private:
}
void MaybeParseCXX11Attributes(ParsedAttributes &attrs,
SourceLocation *endLoc = nullptr) {
- if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) {
+ if (standardAttributesAllowed() && isCXX11AttributeSpecifier()) {
ParsedAttributesWithRange attrsWithRange(AttrFactory);
ParseCXX11Attributes(attrsWithRange, endLoc);
attrs.takeAllFrom(attrsWithRange);
@@ -2268,8 +2287,8 @@ private:
void MaybeParseCXX11Attributes(ParsedAttributesWithRange &attrs,
SourceLocation *endLoc = nullptr,
bool OuterMightBeMessageSend = false) {
- if (getLangOpts().CPlusPlus11 &&
- isCXX11AttributeSpecifier(false, OuterMightBeMessageSend))
+ if (standardAttributesAllowed() &&
+ isCXX11AttributeSpecifier(false, OuterMightBeMessageSend))
ParseCXX11Attributes(attrs, endLoc);
}
@@ -2277,8 +2296,8 @@ private:
SourceLocation *EndLoc = nullptr);
void ParseCXX11Attributes(ParsedAttributesWithRange &attrs,
SourceLocation *EndLoc = nullptr);
- /// \brief Parses a C++-style attribute argument list. Returns true if this
- /// results in adding an attribute to the ParsedAttributes list.
+ /// \brief Parses a C++11 (or C2x)-style attribute argument list. Returns true
+ /// if this results in adding an attribute to the ParsedAttributes list.
bool ParseCXX11AttributeArgs(IdentifierInfo *AttrName,
SourceLocation AttrNameLoc,
ParsedAttributes &Attrs, SourceLocation *EndLoc,
@@ -2608,6 +2627,9 @@ private:
Decl *TagDecl = nullptr);
/// \brief Parse 'omp declare reduction' construct.
DeclGroupPtrTy ParseOpenMPDeclareReductionDirective(AccessSpecifier AS);
+ /// Parses initializer for provided omp_priv declaration inside the reduction
+ /// initializer.
+ void ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm);
/// \brief Parses simple list of variables.
///
@@ -2720,11 +2742,11 @@ private:
AccessSpecifier AS=AS_none,
AttributeList *AccessAttrs = nullptr);
bool ParseTemplateParameters(unsigned Depth,
- SmallVectorImpl<Decl*> &TemplateParams,
+ SmallVectorImpl<NamedDecl *> &TemplateParams,
SourceLocation &LAngleLoc,
SourceLocation &RAngleLoc);
bool ParseTemplateParameterList(unsigned Depth,
- SmallVectorImpl<Decl*> &TemplateParams);
+ SmallVectorImpl<NamedDecl*> &TemplateParams);
bool isStartOfTemplateTypeParameter();
Decl *ParseTemplateParameter(unsigned Depth, unsigned Position);
Decl *ParseTypeParameter(unsigned Depth, unsigned Position);
@@ -2766,7 +2788,7 @@ private:
//===--------------------------------------------------------------------===//
// Modules
DeclGroupPtrTy ParseModuleDecl();
- DeclGroupPtrTy ParseModuleImport(SourceLocation AtLoc);
+ Decl *ParseModuleImport(SourceLocation AtLoc);
bool parseMisplacedModuleImport();
bool tryParseMisplacedModuleImport() {
tok::TokenKind Kind = Tok.getKind();
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h b/contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h
index 6bdd9d5fcdb6f..4e806116c4d9b 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h
@@ -100,16 +100,20 @@ public:
AS_GNU,
/// [[...]]
AS_CXX11,
+ /// [[...]]
+ AS_C2x,
/// __declspec(...)
AS_Declspec,
/// [uuid("...")] class Foo
AS_Microsoft,
/// __ptr16, alignas(...), etc.
AS_Keyword,
- /// Context-sensitive version of a keyword attribute.
- AS_ContextSensitiveKeyword,
/// #pragma ...
AS_Pragma,
+ // Note TableGen depends on the order above. Do not add or change the order
+ // without adding related code to TableGen/ClangAttrEmitter.cpp.
+ /// Context-sensitive version of a keyword attribute.
+ AS_ContextSensitiveKeyword,
};
private:
@@ -376,6 +380,9 @@ public:
bool isCXX11Attribute() const {
return SyntaxUsed == AS_CXX11 || isAlignasAttribute();
}
+ bool isC2xAttribute() const {
+ return SyntaxUsed == AS_C2x;
+ }
bool isKeywordAttribute() const {
return SyntaxUsed == AS_Keyword || SyntaxUsed == AS_ContextSensitiveKeyword;
}
@@ -893,50 +900,17 @@ enum AttributeDeclKind {
ExpectedFunction,
ExpectedUnion,
ExpectedVariableOrFunction,
- ExpectedFunctionOrGlobalVar,
- ExpectedFunctionVariableOrObjCInterface,
ExpectedFunctionOrMethod,
- ExpectedParameter,
ExpectedFunctionMethodOrBlock,
- ExpectedFunctionMethodOrClass,
ExpectedFunctionMethodOrParameter,
- ExpectedFunctionMethodOrGlobalVar,
- ExpectedClass,
- ExpectedEnum,
ExpectedVariable,
- ExpectedMethod,
- ExpectedFieldOrGlobalVar,
- ExpectedStruct,
- ExpectedParameterOrTypedef,
- ExpectedVariableOrTypedef,
- ExpectedTLSVar,
ExpectedVariableOrField,
ExpectedVariableFieldOrTag,
ExpectedTypeOrNamespace,
- ExpectedObjectiveCInterface,
- ExpectedMethodOrProperty,
- ExpectedFunctionOrMethodOrProperty,
- ExpectedStructOrUnion,
- ExpectedStructOrUnionOrClass,
- ExpectedType,
- ExpectedObjCInstanceMethod,
- ExpectedObjCInterfaceDeclInitMethod,
ExpectedFunctionVariableOrClass,
- ExpectedFunctionVariableClassOrObjCInterface,
- ExpectedObjectiveCProtocol,
- ExpectedStaticOrTLSVar,
- ExpectedFunctionGlobalVarMethodOrProperty,
- ExpectedStructOrUnionOrTypedef,
- ExpectedStructOrTypedef,
- ExpectedObjectiveCInterfaceOrProtocol,
ExpectedKernelFunction,
ExpectedFunctionWithProtoType,
- ExpectedVariableEnumFieldOrTypedef,
- ExpectedFunctionMethodEnumOrClass,
- ExpectedStructClassVariableFunctionOrInlineNamespace,
ExpectedForMaybeUnused,
- ExpectedEnumOrClass,
- ExpectedNamedDecl,
};
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteConsumer.h b/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteConsumer.h
index dee53dc14a8ca..5d280b5608e71 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteConsumer.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteConsumer.h
@@ -18,6 +18,7 @@
#include "clang/AST/DeclBase.h"
#include "clang/AST/Type.h"
#include "clang/Sema/CodeCompleteOptions.h"
+#include "clang/Sema/DeclSpec.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
@@ -280,6 +281,10 @@ private:
/// \brief The identifiers for Objective-C selector parts.
ArrayRef<IdentifierInfo *> SelIdents;
+ /// \brief The scope specifier that comes before the completion token e.g.
+ /// "a::b::"
+ llvm::Optional<CXXScopeSpec> ScopeSpecifier;
+
public:
/// \brief Construct a new code-completion context of the given kind.
CodeCompletionContext(enum Kind Kind) : Kind(Kind), SelIdents(None) { }
@@ -315,8 +320,20 @@ public:
/// \brief Determines whether we want C++ constructors as results within this
/// context.
bool wantConstructorResults() const;
-};
+ /// \brief Sets the scope specifier that comes before the completion token.
+ /// This is expected to be set in code completions on qualfied specifiers
+ /// (e.g. "a::b::").
+ void setCXXScopeSpecifier(CXXScopeSpec SS) {
+ this->ScopeSpecifier = std::move(SS);
+ }
+
+ llvm::Optional<const CXXScopeSpec *> getCXXScopeSpecifier() {
+ if (ScopeSpecifier)
+ return ScopeSpecifier.getPointer();
+ return llvm::None;
+ }
+};
/// \brief A "string" used to describe how code completion can
/// be performed for an entity.
@@ -777,6 +794,12 @@ public:
CodeCompletionTUInfo &CCTUInfo,
bool IncludeBriefComments);
+ /// \brief Retrieve the name that should be used to order a result.
+ ///
+ /// If the name needs to be constructed as a string, that string will be
+ /// saved into Saved and the returned StringRef will refer to it.
+ StringRef getOrderedName(std::string &Saved) const;
+
private:
void computeCursorKindAndAvailability(bool Accessible = true);
};
@@ -896,8 +919,13 @@ public:
}
/// \brief Whether to include global (top-level) declaration results.
- bool includeGlobals() const {
- return CodeCompleteOpts.IncludeGlobals;
+ bool includeGlobals() const { return CodeCompleteOpts.IncludeGlobals; }
+
+ /// \brief Whether to include declarations in namespace contexts (including
+ /// the global namespace). If this is false, `includeGlobals()` will be
+ /// ignored.
+ bool includeNamespaceLevelDecls() const {
+ return CodeCompleteOpts.IncludeNamespaceLevelDecls;
}
/// \brief Whether to include brief documentation comments within the set of
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteOptions.h b/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteOptions.h
index fc7713c795712..091d8ca60505e 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteOptions.h
@@ -24,15 +24,20 @@ public:
/// Show top-level decls in code completion results.
unsigned IncludeGlobals : 1;
+ /// Show decls in namespace (including the global namespace) in code
+ /// completion results. If this is 0, `IncludeGlobals` will be ignored.
+ ///
+ /// Currently, this only works when completing qualified IDs (i.e.
+ /// `Sema::CodeCompleteQualifiedId`).
+ /// FIXME: consider supporting more completion cases with this option.
+ unsigned IncludeNamespaceLevelDecls : 1;
+
/// Show brief documentation comments in code completion results.
unsigned IncludeBriefComments : 1;
- CodeCompleteOptions() :
- IncludeMacros(0),
- IncludeCodePatterns(0),
- IncludeGlobals(1),
- IncludeBriefComments(0)
- { }
+ CodeCompleteOptions()
+ : IncludeMacros(0), IncludeCodePatterns(0), IncludeGlobals(1),
+ IncludeNamespaceLevelDecls(1), IncludeBriefComments(0) {}
};
} // namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h b/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h
index bc817150ab82c..760a04d3c8d2e 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h
@@ -280,6 +280,7 @@ public:
static const TST TST_half = clang::TST_half;
static const TST TST_float = clang::TST_float;
static const TST TST_double = clang::TST_double;
+ static const TST TST_float16 = clang::TST_Float16;
static const TST TST_float128 = clang::TST_float128;
static const TST TST_bool = clang::TST_bool;
static const TST TST_decimal32 = clang::TST_decimal32;
@@ -360,9 +361,6 @@ private:
// constexpr-specifier
unsigned Constexpr_specified : 1;
- // concept-specifier
- unsigned Concept_specified : 1;
-
union {
UnionParsedType TypeRep;
Decl *DeclRep;
@@ -392,7 +390,7 @@ private:
TQ_unalignedLoc;
SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc, FS_noreturnLoc;
SourceLocation FS_forceinlineLoc;
- SourceLocation FriendLoc, ModulePrivateLoc, ConstexprLoc, ConceptLoc;
+ SourceLocation FriendLoc, ModulePrivateLoc, ConstexprLoc;
SourceLocation TQ_pipeLoc;
WrittenBuiltinSpecs writtenBS;
@@ -438,7 +436,6 @@ public:
FS_noreturn_specified(false),
Friend_specified(false),
Constexpr_specified(false),
- Concept_specified(false),
Attrs(attrFactory),
writtenBS(),
ObjCQualifiers(nullptr) {
@@ -696,8 +693,6 @@ public:
unsigned &DiagID);
bool SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec,
unsigned &DiagID);
- bool SetConceptSpec(SourceLocation Loc, const char *&PrevSpec,
- unsigned &DiagID);
bool isFriendSpecified() const { return Friend_specified; }
SourceLocation getFriendSpecLoc() const { return FriendLoc; }
@@ -708,19 +703,11 @@ public:
bool isConstexprSpecified() const { return Constexpr_specified; }
SourceLocation getConstexprSpecLoc() const { return ConstexprLoc; }
- bool isConceptSpecified() const { return Concept_specified; }
- SourceLocation getConceptSpecLoc() const { return ConceptLoc; }
-
void ClearConstexprSpec() {
Constexpr_specified = false;
ConstexprLoc = SourceLocation();
}
- void ClearConceptSpec() {
- Concept_specified = false;
- ConceptLoc = SourceLocation();
- }
-
AttributePool &getAttributePool() const {
return Attrs.getPool();
}
@@ -2008,9 +1995,9 @@ public:
case BlockContext:
case ForContext:
case InitStmtContext:
+ case ConditionContext:
return true;
- case ConditionContext:
case MemberContext:
case PrototypeContext:
case TemplateParamContext:
@@ -2300,6 +2287,42 @@ public:
}
llvm_unreachable("unknown context kind!");
}
+
+ /// Determine whether this declaration appears in a context where an
+ /// expression could appear.
+ bool isExpressionContext() const {
+ switch (Context) {
+ case FileContext:
+ case KNRTypeListContext:
+ case MemberContext:
+ case TypeNameContext: // FIXME: sizeof(...) permits an expression.
+ case FunctionalCastContext:
+ case AliasDeclContext:
+ case AliasTemplateContext:
+ case PrototypeContext:
+ case LambdaExprParameterContext:
+ case ObjCParameterContext:
+ case ObjCResultContext:
+ case TemplateParamContext:
+ case CXXNewContext:
+ case CXXCatchContext:
+ case ObjCCatchContext:
+ case BlockLiteralContext:
+ case LambdaExprContext:
+ case ConversionIdContext:
+ case TrailingReturnContext:
+ return false;
+
+ case BlockContext:
+ case ForContext:
+ case InitStmtContext:
+ case ConditionContext:
+ case TemplateTypeArgContext:
+ return true;
+ }
+
+ llvm_unreachable("unknown context kind!");
+ }
/// \brief Return true if a function declarator at this position would be a
/// function declaration.
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Lookup.h b/contrib/llvm/tools/clang/include/clang/Sema/Lookup.h
index ea32997d40667..546df8842a356 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/Lookup.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Lookup.h
@@ -139,6 +139,7 @@ public:
LookupKind(LookupKind),
IDNS(0),
Redecl(Redecl != Sema::NotForRedeclaration),
+ ExternalRedecl(Redecl == Sema::ForExternalRedeclaration),
HideTags(true),
Diagnose(Redecl == Sema::NotForRedeclaration),
AllowHidden(false),
@@ -161,6 +162,7 @@ public:
LookupKind(LookupKind),
IDNS(0),
Redecl(Redecl != Sema::NotForRedeclaration),
+ ExternalRedecl(Redecl == Sema::ForExternalRedeclaration),
HideTags(true),
Diagnose(Redecl == Sema::NotForRedeclaration),
AllowHidden(false),
@@ -181,6 +183,7 @@ public:
LookupKind(Other.LookupKind),
IDNS(Other.IDNS),
Redecl(Other.Redecl),
+ ExternalRedecl(Other.ExternalRedecl),
HideTags(Other.HideTags),
Diagnose(false),
AllowHidden(Other.AllowHidden),
@@ -201,7 +204,9 @@ public:
SemaPtr(std::move(Other.SemaPtr)), NameInfo(std::move(Other.NameInfo)),
NameContextRange(std::move(Other.NameContextRange)),
LookupKind(std::move(Other.LookupKind)), IDNS(std::move(Other.IDNS)),
- Redecl(std::move(Other.Redecl)), HideTags(std::move(Other.HideTags)),
+ Redecl(std::move(Other.Redecl)),
+ ExternalRedecl(std::move(Other.ExternalRedecl)),
+ HideTags(std::move(Other.HideTags)),
Diagnose(std::move(Other.Diagnose)),
AllowHidden(std::move(Other.AllowHidden)),
Shadowed(std::move(Other.Shadowed)) {
@@ -221,6 +226,7 @@ public:
LookupKind = std::move(Other.LookupKind);
IDNS = std::move(Other.IDNS);
Redecl = std::move(Other.Redecl);
+ ExternalRedecl = std::move(Other.ExternalRedecl);
HideTags = std::move(Other.HideTags);
Diagnose = std::move(Other.Diagnose);
AllowHidden = std::move(Other.AllowHidden);
@@ -265,6 +271,17 @@ public:
return Redecl;
}
+ /// True if this lookup is just looking for an existing declaration to link
+ /// against a declaration with external linkage.
+ bool isForExternalRedeclaration() const {
+ return ExternalRedecl;
+ }
+
+ Sema::RedeclarationKind redeclarationKind() const {
+ return ExternalRedecl ? Sema::ForExternalRedeclaration :
+ Redecl ? Sema::ForVisibleRedeclaration : Sema::NotForRedeclaration;
+ }
+
/// \brief Specify whether hidden declarations are visible, e.g.,
/// for recovery reasons.
void setAllowHidden(bool AH) {
@@ -275,7 +292,7 @@ public:
/// declarations, such as those in modules that have not yet been imported.
bool isHiddenDeclarationVisible(NamedDecl *ND) const {
return AllowHidden ||
- (isForRedeclaration() && ND->hasExternalFormalLinkage());
+ (isForExternalRedeclaration() && ND->isExternallyDeclarable());
}
/// Sets whether tag declarations should be hidden by non-tag
@@ -556,7 +573,8 @@ public:
/// \brief Change this lookup's redeclaration kind.
void setRedeclarationKind(Sema::RedeclarationKind RK) {
- Redecl = RK;
+ Redecl = (RK != Sema::NotForRedeclaration);
+ ExternalRedecl = (RK == Sema::ForExternalRedeclaration);
configure();
}
@@ -719,6 +737,7 @@ private:
unsigned IDNS; // set by configure()
bool Redecl;
+ bool ExternalRedecl;
/// \brief True if tag declarations should be hidden if non-tags
/// are present
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Overload.h b/contrib/llvm/tools/clang/include/clang/Sema/Overload.h
index ffdf011d1dcbc..05cfe53666ca9 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/Overload.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Overload.h
@@ -726,11 +726,20 @@ namespace clang {
enum CandidateSetKind {
/// Normal lookup.
CSK_Normal,
- /// Lookup for candidates for a call using operator syntax. Candidates
- /// that have no parameters of class type will be skipped unless there
- /// is a parameter of (reference to) enum type and the corresponding
- /// argument is of the same enum type.
- CSK_Operator
+ /// C++ [over.match.oper]:
+ /// Lookup of operator function candidates in a call using operator
+ /// syntax. Candidates that have no parameters of class type will be
+ /// skipped unless there is a parameter of (reference to) enum type and
+ /// the corresponding argument is of the same enum type.
+ CSK_Operator,
+ /// C++ [over.match.copy]:
+ /// Copy-initialization of an object of class type by user-defined
+ /// conversion.
+ CSK_InitByUserDefinedConversion,
+ /// C++ [over.match.ctor], [over.match.list]
+ /// Initialization of an object of class type by constructor,
+ /// using either a parenthesized or braced list of arguments.
+ CSK_InitByConstructor,
};
private:
@@ -795,7 +804,7 @@ namespace clang {
}
/// \brief Clear out all of the candidates.
- void clear();
+ void clear(CandidateSetKind CSK);
typedef SmallVectorImpl<OverloadCandidate>::iterator iterator;
iterator begin() { return Candidates.begin(); }
@@ -835,8 +844,7 @@ namespace clang {
/// Find the best viable function on this overload set, if it exists.
OverloadingResult BestViableFunction(Sema &S, SourceLocation Loc,
- OverloadCandidateSet::iterator& Best,
- bool UserDefinedConversion = false);
+ OverloadCandidateSet::iterator& Best);
void NoteCandidates(Sema &S,
OverloadCandidateDisplayKind OCD,
@@ -848,10 +856,10 @@ namespace clang {
};
bool isBetterOverloadCandidate(Sema &S,
- const OverloadCandidate& Cand1,
- const OverloadCandidate& Cand2,
+ const OverloadCandidate &Cand1,
+ const OverloadCandidate &Cand2,
SourceLocation Loc,
- bool UserDefinedConversion = false);
+ OverloadCandidateSet::CandidateSetKind Kind);
struct ConstructorInfo {
DeclAccessPair FoundDecl;
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Ownership.h b/contrib/llvm/tools/clang/include/clang/Sema/Ownership.h
index 848837a1deccd..1e35316fd5dd5 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/Ownership.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Ownership.h
@@ -107,8 +107,7 @@ namespace clang {
namespace llvm {
template <class T>
- class PointerLikeTypeTraits<clang::OpaquePtr<T> > {
- public:
+ struct PointerLikeTypeTraits<clang::OpaquePtr<T> > {
static inline void *getAsVoidPointer(clang::OpaquePtr<T> P) {
// FIXME: Doesn't work? return P.getAs< void >();
return P.getAsOpaquePtr();
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Scope.h b/contrib/llvm/tools/clang/include/clang/Sema/Scope.h
index d0b006b82ec6e..cd58a9910f98e 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/Scope.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Scope.h
@@ -124,6 +124,12 @@ public:
/// We are currently in the filter expression of an SEH except block.
SEHFilterScope = 0x200000,
+
+ /// This is a compound statement scope.
+ CompoundStmtScope = 0x400000,
+
+ /// We are between inheritance colon and the real class/struct definition scope.
+ ClassInheritanceScope = 0x800000,
};
private:
/// The parent scope for this scope. This is null for the translation-unit
@@ -429,6 +435,11 @@ public:
/// \brief Determine whether this scope is a SEH '__except' block.
bool isSEHExceptScope() const { return getFlags() & Scope::SEHExceptScope; }
+ /// \brief Determine whether this scope is a compound statement scope.
+ bool isCompoundStmtScope() const {
+ return getFlags() & Scope::CompoundStmtScope;
+ }
+
/// \brief Returns if rhs has a higher scope depth than this.
///
/// The caller is responsible for calling this only if one of the two scopes
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h b/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h
index 215f30a8d2838..c707a3e8ef074 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h
@@ -834,6 +834,12 @@ public:
return FSI->Kind == SK_Lambda;
}
+ /// Is this scope known to be for a generic lambda? (This will be false until
+ /// we parse the first 'auto'-typed parameter.
+ bool isGenericLambda() const {
+ return !AutoTemplateParams.empty() || GLTemplateParameterList;
+ }
+
///
/// \brief Add a variable that might potentially be captured by the
/// lambda and therefore the enclosing lambdas.
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Sema.h b/contrib/llvm/tools/clang/include/clang/Sema/Sema.h
index 5a708545705c0..47cea3029bd9f 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/Sema.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Sema.h
@@ -64,7 +64,7 @@ namespace llvm {
template <typename ValueT> struct DenseMapInfo;
template <typename ValueT, typename ValueInfoT> class DenseSet;
class SmallBitVector;
- class InlineAsmIdentifierInfo;
+ struct InlineAsmIdentifierInfo;
}
namespace clang {
@@ -208,6 +208,7 @@ namespace sema {
class FunctionScopeInfo;
class LambdaScopeInfo;
class PossiblyUnreachableDiag;
+ class SemaPPCallbacks;
class TemplateDeductionInfo;
}
@@ -228,6 +229,10 @@ struct FileNullability {
/// not have a corresponding nullability annotation.
SourceLocation PointerLoc;
+ /// The end location for the first pointer declarator in the file. Used for
+ /// placing fix-its.
+ SourceLocation PointerEndLoc;
+
/// Which kind of pointer declarator we saw.
uint8_t PointerKind;
@@ -280,15 +285,21 @@ class Sema {
bool isVisibleSlow(const NamedDecl *D);
+ /// Determine whether two declarations should be linked together, given that
+ /// the old declaration might not be visible and the new declaration might
+ /// not have external linkage.
bool shouldLinkPossiblyHiddenDecl(const NamedDecl *Old,
const NamedDecl *New) {
- // We are about to link these. It is now safe to compute the linkage of
- // the new decl. If the new decl has external linkage, we will
- // link it with the hidden decl (which also has external linkage) and
- // it will keep having external linkage. If it has internal linkage, we
- // will not link it. Since it has no previous decls, it will remain
- // with internal linkage.
- return isVisible(Old) || New->isExternallyVisible();
+ if (isVisible(Old))
+ return true;
+ // See comment in below overload for why it's safe to compute the linkage
+ // of the new declaration here.
+ if (New->isExternallyDeclarable()) {
+ assert(Old->isExternallyDeclarable() &&
+ "should not have found a non-externally-declarable previous decl");
+ return true;
+ }
+ return false;
}
bool shouldLinkPossiblyHiddenDecl(LookupResult &Old, const NamedDecl *New);
@@ -381,11 +392,12 @@ public:
llvm::StringRef StackSlotLabel;
ValueType Value;
SourceLocation PragmaLocation;
- Slot(llvm::StringRef StackSlotLabel,
- ValueType Value,
- SourceLocation PragmaLocation)
- : StackSlotLabel(StackSlotLabel), Value(Value),
- PragmaLocation(PragmaLocation) {}
+ SourceLocation PragmaPushLocation;
+ Slot(llvm::StringRef StackSlotLabel, ValueType Value,
+ SourceLocation PragmaLocation, SourceLocation PragmaPushLocation)
+ : StackSlotLabel(StackSlotLabel), Value(Value),
+ PragmaLocation(PragmaLocation),
+ PragmaPushLocation(PragmaPushLocation) {}
};
void Act(SourceLocation PragmaLocation,
PragmaMsStackAction Action,
@@ -416,6 +428,8 @@ public:
explicit PragmaStack(const ValueType &Default)
: DefaultValue(Default), CurrentValue(Default) {}
+ bool hasValue() const { return CurrentValue != DefaultValue; }
+
SmallVector<Slot, 2> Stack;
ValueType DefaultValue; // Value used for PSK_Reset action.
ValueType CurrentValue;
@@ -437,6 +451,13 @@ public:
// Sentinel to represent when the stack is set to mac68k alignment.
static const unsigned kMac68kAlignmentSentinel = ~0U;
PragmaStack<unsigned> PackStack;
+ // The current #pragma pack values and locations at each #include.
+ struct PackIncludeState {
+ unsigned CurrentValue;
+ SourceLocation CurrentPragmaLocation;
+ bool HasNonDefaultValue, ShouldWarnOnInclude;
+ };
+ SmallVector<PackIncludeState, 8> PackIncludeStack;
// Segment #pragmas.
PragmaStack<StringLiteral *> DataSegStack;
PragmaStack<StringLiteral *> BSSSegStack;
@@ -1075,6 +1096,11 @@ public:
/// definition in this translation unit.
llvm::MapVector<NamedDecl *, SourceLocation> UndefinedButUsed;
+ /// Determine if VD, which must be a variable or function, is an external
+ /// symbol that nonetheless can't be referenced from outside this translation
+ /// unit because its type has no linkage and it's not extern "C".
+ bool isExternalWithNoLinkageType(ValueDecl *VD);
+
/// Obtain a sorted list of functions that are undefined but ODR-used.
void getUndefinedButUsed(
SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> > &Undefined);
@@ -1110,12 +1136,13 @@ public:
CXXInvalid
};
- typedef std::pair<CXXRecordDecl*, CXXSpecialMember> SpecialMemberDecl;
+ typedef llvm::PointerIntPair<CXXRecordDecl *, 3, CXXSpecialMember>
+ SpecialMemberDecl;
/// The C++ special members which we are currently in the process of
/// declaring. If this process recursively triggers the declaration of the
/// same special member, we should act as if it is not yet declared.
- llvm::SmallSet<SpecialMemberDecl, 4> SpecialMembersBeingDeclared;
+ llvm::SmallPtrSet<SpecialMemberDecl, 4> SpecialMembersBeingDeclared;
/// The function definitions which were renamed as part of typo-correction
/// to match their respective declarations. We want to keep track of them
@@ -1357,6 +1384,8 @@ public:
SourceRange Brackets, DeclarationName Entity);
QualType BuildExtVectorType(QualType T, Expr *ArraySize,
SourceLocation AttrLoc);
+ QualType BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace,
+ SourceLocation AttrLoc);
bool CheckFunctionReturnType(QualType T, SourceLocation Loc);
@@ -1504,7 +1533,8 @@ private:
TypeDiagnoser *Diagnoser);
struct ModuleScope {
- clang::Module *Module;
+ clang::Module *Module = nullptr;
+ bool ModuleInterface = false;
VisibleModuleSet OuterVisibleModules;
};
/// The modules we're currently parsing.
@@ -1525,7 +1555,7 @@ public:
/// visible at the specified location.
void makeMergedDefinitionVisible(NamedDecl *ND);
- bool isModuleVisible(Module *M) { return VisibleModules.isVisible(M); }
+ bool isModuleVisible(const Module *M) { return VisibleModules.isVisible(M); }
/// Determine whether a declaration is visible to name lookup.
bool isVisible(const NamedDecl *D) {
@@ -1694,7 +1724,6 @@ public:
ExprResult Expr;
TemplateName Template;
ParsedType Type;
- const IdentifierInfo *Keyword;
explicit NameClassification(NameClassificationKind Kind) : Kind(Kind) {}
@@ -1703,8 +1732,7 @@ public:
NameClassification(ParsedType Type) : Kind(NC_Type), Type(Type) {}
- NameClassification(const IdentifierInfo *Keyword)
- : Kind(NC_Keyword), Keyword(Keyword) { }
+ NameClassification(const IdentifierInfo *Keyword) : Kind(NC_Keyword) {}
static NameClassification Error() {
return NameClassification(NC_Error);
@@ -2022,9 +2050,9 @@ public:
SourceLocation SemiLoc);
enum class ModuleDeclKind {
- Module, ///< 'module X;'
+ Interface, ///< 'export module X;'
+ Implementation, ///< 'module X;'
Partition, ///< 'module partition X;'
- Implementation, ///< 'module implementation X;'
};
/// The parser has processed a module-declaration that begins the definition
@@ -2677,7 +2705,8 @@ public:
OverloadCandidateSet &CandidateSet,
TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr,
bool SuppressUserConversions = false,
- bool PartialOverloading = false);
+ bool PartialOverloading = false,
+ bool FirstArgumentIsBase = false);
void AddMethodCandidate(DeclAccessPair FoundDecl,
QualType ObjectType,
Expr::Classification ObjectClassification,
@@ -2725,13 +2754,15 @@ public:
CXXRecordDecl *ActingContext,
Expr *From, QualType ToType,
OverloadCandidateSet& CandidateSet,
- bool AllowObjCConversionOnExplicit);
+ bool AllowObjCConversionOnExplicit,
+ bool AllowResultConversion = true);
void AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext,
Expr *From, QualType ToType,
OverloadCandidateSet &CandidateSet,
- bool AllowObjCConversionOnExplicit);
+ bool AllowObjCConversionOnExplicit,
+ bool AllowResultConversion = true);
void AddSurrogateCandidate(CXXConversionDecl *Conversion,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext,
@@ -2771,6 +2802,14 @@ public:
EnableIfAttr *CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
bool MissingImplicitThis = false);
+ /// Find the failed Boolean condition within a given Boolean
+ /// constant expression, and describe it with a string.
+ ///
+ /// \param AllowTopLevelCond Whether to allow the result to be the
+ /// complete top-level condition.
+ std::pair<Expr *, std::string>
+ findFailedBooleanCondition(Expr *Cond, bool AllowTopLevelCond);
+
/// Emit diagnostics for the diagnose_if attributes on Function, ignoring any
/// non-ArgDependent DiagnoseIfAttrs.
///
@@ -2881,12 +2920,13 @@ public:
ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc,
UnaryOperatorKind Opc,
const UnresolvedSetImpl &Fns,
- Expr *input);
+ Expr *input, bool RequiresADL = true);
ExprResult CreateOverloadedBinOp(SourceLocation OpLoc,
BinaryOperatorKind Opc,
const UnresolvedSetImpl &Fns,
- Expr *LHS, Expr *RHS);
+ Expr *LHS, Expr *RHS,
+ bool RequiresADL = true);
ExprResult CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
SourceLocation RLoc,
@@ -3001,14 +3041,31 @@ public:
/// purpose of redeclaring the name.
NotForRedeclaration = 0,
/// \brief The lookup results will be used for redeclaration of a name,
- /// if an entity by that name already exists.
- ForRedeclaration
+ /// if an entity by that name already exists and is visible.
+ ForVisibleRedeclaration,
+ /// \brief The lookup results will be used for redeclaration of a name
+ /// with external linkage; non-visible lookup results with external linkage
+ /// may also be found.
+ ForExternalRedeclaration
};
+ RedeclarationKind forRedeclarationInCurContext() {
+ // A declaration with an owning module for linkage can never link against
+ // anything that is not visible. We don't need to check linkage here; if
+ // the context has internal linkage, redeclaration lookup won't find things
+ // from other TUs, and we can't safely compute linkage yet in general.
+ if (cast<Decl>(CurContext)
+ ->getOwningModuleForLinkage(/*IgnoreLinkage*/true))
+ return ForVisibleRedeclaration;
+ return ForExternalRedeclaration;
+ }
+
/// \brief The possible outcomes of name lookup for a literal operator.
enum LiteralOperatorLookupResult {
/// \brief The lookup resulted in an error.
LOLR_Error,
+ /// \brief The lookup found no match but no diagnostic was issued.
+ LOLR_ErrorNoDiagnostic,
/// \brief The lookup found a single 'cooked' literal operator, which
/// expects a normal literal to be built and passed to it.
LOLR_Cooked,
@@ -3133,7 +3190,8 @@ public:
ArrayRef<QualType> ArgTys,
bool AllowRaw,
bool AllowTemplate,
- bool AllowStringTemplate);
+ bool AllowStringTemplate,
+ bool DiagnoseMissing);
bool isKnownName(StringRef name);
void ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
@@ -3229,6 +3287,8 @@ public:
void FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S,
bool ConsiderLinkage, bool AllowInlineNamespace);
+ bool CheckRedeclarationModuleOwnership(NamedDecl *New, NamedDecl *Old);
+
void DiagnoseAmbiguousLookup(LookupResult &Result);
//@}
@@ -3271,7 +3331,7 @@ public:
unsigned ArgNum, StringRef &Str,
SourceLocation *ArgLocation = nullptr);
bool checkSectionName(SourceLocation LiteralLoc, StringRef Str);
- void checkTargetAttr(SourceLocation LiteralLoc, StringRef Str);
+ bool checkTargetAttr(SourceLocation LiteralLoc, StringRef Str);
bool checkMSInheritanceAttrOnDefinition(
CXXRecordDecl *RD, SourceRange Range, bool BestCase,
MSInheritanceAttr::Spelling SemanticSpelling);
@@ -3754,15 +3814,15 @@ public:
Expr *AsmString, MultiExprArg Clobbers,
SourceLocation RParenLoc);
+ void FillInlineAsmIdentifierInfo(Expr *Res,
+ llvm::InlineAsmIdentifierInfo &Info);
ExprResult LookupInlineAsmIdentifier(CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
UnqualifiedId &Id,
- llvm::InlineAsmIdentifierInfo &Info,
bool IsUnevaluatedContext);
bool LookupInlineAsmField(StringRef Base, StringRef Member,
unsigned &Offset, SourceLocation AsmLoc);
ExprResult LookupInlineAsmVarDeclField(Expr *RefExpr, StringRef Member,
- llvm::InlineAsmIdentifierInfo &Info,
SourceLocation AsmLoc);
StmtResult ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
ArrayRef<Token> AsmToks,
@@ -6038,7 +6098,7 @@ public:
SourceLocation ExportLoc,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
- ArrayRef<Decl *> Params,
+ ArrayRef<NamedDecl *> Params,
SourceLocation RAngleLoc,
Expr *RequiresClause);
@@ -7368,13 +7428,16 @@ public:
unsigned PrevSFINAEErrors;
bool PrevInNonInstantiationSFINAEContext;
bool PrevAccessCheckingSFINAE;
+ bool PrevLastDiagnosticIgnored;
public:
explicit SFINAETrap(Sema &SemaRef, bool AccessCheckingSFINAE = false)
: SemaRef(SemaRef), PrevSFINAEErrors(SemaRef.NumSFINAEErrors),
PrevInNonInstantiationSFINAEContext(
SemaRef.InNonInstantiationSFINAEContext),
- PrevAccessCheckingSFINAE(SemaRef.AccessCheckingSFINAE)
+ PrevAccessCheckingSFINAE(SemaRef.AccessCheckingSFINAE),
+ PrevLastDiagnosticIgnored(
+ SemaRef.getDiagnostics().isLastDiagnosticIgnored())
{
if (!SemaRef.isSFINAEContext())
SemaRef.InNonInstantiationSFINAEContext = true;
@@ -7386,6 +7449,8 @@ public:
SemaRef.InNonInstantiationSFINAEContext
= PrevInNonInstantiationSFINAEContext;
SemaRef.AccessCheckingSFINAE = PrevAccessCheckingSFINAE;
+ SemaRef.getDiagnostics().setLastDiagnosticIgnored(
+ PrevLastDiagnosticIgnored);
}
/// \brief Determine whether any SFINAE errors have been trapped.
@@ -7725,11 +7790,6 @@ public:
VarDecl *Var, bool Recursive = false,
bool DefinitionRequired = false,
bool AtEndOfTU = false);
- void InstantiateStaticDataMemberDefinition(
- SourceLocation PointOfInstantiation,
- VarDecl *Var,
- bool Recursive = false,
- bool DefinitionRequired = false);
void InstantiateMemInitializers(CXXConstructorDecl *New,
const CXXConstructorDecl *Tmpl,
@@ -8182,6 +8242,15 @@ public:
void ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action,
StringRef SlotLabel, Expr *Alignment);
+ enum class PragmaPackDiagnoseKind {
+ NonDefaultStateAtInclude,
+ ChangedStateAtExit
+ };
+
+ void DiagnoseNonDefaultPragmaPack(PragmaPackDiagnoseKind Kind,
+ SourceLocation IncludeLoc);
+ void DiagnoseUnterminatedPragmaPack();
+
/// ActOnPragmaMSStruct - Called on well formed \#pragma ms_struct [on|off].
void ActOnPragmaMSStruct(PragmaMSStructKind Kind);
@@ -8467,6 +8536,10 @@ private:
/// Returns OpenMP nesting level for current directive.
unsigned getOpenMPNestingLevel() const;
+ /// Adjusts the function scopes index for the target-based regions.
+ void adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
+ unsigned Level) const;
+
/// Push new OpenMP function region for non-capturing function.
void pushOpenMPFunctionRegion();
@@ -8507,6 +8580,11 @@ public:
/// is performed.
bool isOpenMPPrivateDecl(ValueDecl *D, unsigned Level);
+ /// Sets OpenMP capture kind (OMPC_private, OMPC_firstprivate, OMPC_map etc.)
+ /// for \p FD based on DSA for the provided corresponding captured declaration
+ /// \p D.
+ void setOpenMPCaptureKind(FieldDecl *FD, ValueDecl *D, unsigned Level);
+
/// \brief Check if the specified variable is captured by 'target' directive.
/// \param Level Relative level of nested OpenMP construct for that the check
/// is performed.
@@ -8559,9 +8637,11 @@ public:
/// \brief Finish current declare reduction construct initializer.
void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner);
/// \brief Initialize declare reduction construct initializer.
- void ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D);
+ /// \return omp_priv variable.
+ VarDecl *ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D);
/// \brief Finish current declare reduction construct initializer.
- void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer);
+ void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer,
+ VarDecl *OmpPrivParm);
/// \brief Called at the end of '#pragma omp declare reduction'.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveEnd(
Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid);
@@ -8576,11 +8656,20 @@ public:
OMPDeclareTargetDeclAttr::MapTypeTy MT,
NamedDeclSetType &SameDirectiveDecls);
/// Check declaration inside target region.
- void checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D);
- /// Return true inside OpenMP target region.
+ void checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
+ SourceLocation IdLoc = SourceLocation());
+ /// Return true inside OpenMP declare target region.
bool isInOpenMPDeclareTargetContext() const {
return IsInOpenMPDeclareTargetContext;
}
+ /// Return true inside OpenMP target region.
+ bool isInOpenMPTargetExecutionDirective() const;
+ /// Return true if (un)supported features for the current target should be
+ /// diagnosed if OpenMP (offloading) is enabled.
+ bool shouldDiagnoseTargetSupportFromOpenMP() const {
+ return !getLangOpts().OpenMPIsDevice || isInOpenMPDeclareTargetContext() ||
+ isInOpenMPTargetExecutionDirective();
+ }
/// Return the number of captured regions created for an OpenMP directive.
static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind);
@@ -8710,12 +8799,14 @@ public:
/// parsing of the associated statement.
StmtResult ActOnOpenMPTargetEnterDataDirective(ArrayRef<OMPClause *> Clauses,
SourceLocation StartLoc,
- SourceLocation EndLoc);
+ SourceLocation EndLoc,
+ Stmt *AStmt);
/// \brief Called on well-formed '\#pragma omp target exit data' after
/// parsing of the associated statement.
StmtResult ActOnOpenMPTargetExitDataDirective(ArrayRef<OMPClause *> Clauses,
SourceLocation StartLoc,
- SourceLocation EndLoc);
+ SourceLocation EndLoc,
+ Stmt *AStmt);
/// \brief Called on well-formed '\#pragma omp target parallel' after
/// parsing of the associated statement.
StmtResult ActOnOpenMPTargetParallelDirective(ArrayRef<OMPClause *> Clauses,
@@ -8764,7 +8855,8 @@ public:
/// \brief Called on well-formed '\#pragma omp target update'.
StmtResult ActOnOpenMPTargetUpdateDirective(ArrayRef<OMPClause *> Clauses,
SourceLocation StartLoc,
- SourceLocation EndLoc);
+ SourceLocation EndLoc,
+ Stmt *AStmt);
/// \brief Called on well-formed '\#pragma omp distribute parallel for' after
/// parsing of the associated statement.
StmtResult ActOnOpenMPDistributeParallelForDirective(
@@ -9029,6 +9121,13 @@ public:
CXXScopeSpec &ReductionIdScopeSpec,
const DeclarationNameInfo &ReductionId,
ArrayRef<Expr *> UnresolvedReductions = llvm::None);
+ /// Called on well-formed 'in_reduction' clause.
+ OMPClause *ActOnOpenMPInReductionClause(
+ ArrayRef<Expr *> VarList, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
+ CXXScopeSpec &ReductionIdScopeSpec,
+ const DeclarationNameInfo &ReductionId,
+ ArrayRef<Expr *> UnresolvedReductions = llvm::None);
/// \brief Called on well-formed 'linear' clause.
OMPClause *
ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
@@ -10126,8 +10225,7 @@ public:
void CodeCompleteObjCPropertyDefinition(Scope *S);
void CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
IdentifierInfo *PropertyName);
- void CodeCompleteObjCMethodDecl(Scope *S,
- bool IsInstanceMethod,
+ void CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
ParsedType ReturnType);
void CodeCompleteObjCMethodDeclSelector(Scope *S,
bool IsInstanceMethod,
@@ -10211,7 +10309,7 @@ private:
bool CheckPPCBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool SemaBuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall);
- bool SemaBuiltinVAStartARM(CallExpr *Call);
+ bool SemaBuiltinVAStartARMMicrosoft(CallExpr *Call);
bool SemaBuiltinUnorderedCompare(CallExpr *TheCall);
bool SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs);
bool SemaBuiltinVSX(CallExpr *TheCall);
@@ -10362,7 +10460,8 @@ private:
/// \brief Peform checks on a call of a function with argument_with_type_tag
/// or pointer_with_type_tag attributes.
void CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr,
- const Expr * const *ExprArgs);
+ const ArrayRef<const Expr *> ExprArgs,
+ SourceLocation CallSiteLoc);
/// \brief Check if we are taking the address of a packed field
/// as this may be a problem if the pointer value is dereferenced.
@@ -10383,6 +10482,12 @@ private:
IdentifierInfo *Ident_NSError = nullptr;
+ /// \brief The handler for the FileChanged preprocessor events.
+ ///
+ /// Used for diagnostics that implement custom semantic analysis for #include
+ /// directives, like -Wpragma-pack.
+ sema::SemaPPCallbacks *SemaPPCallbackHandler;
+
protected:
friend class Parser;
friend class InitializationSequence;
@@ -10446,6 +10551,36 @@ public:
SmallVector<CXXRecordDecl*, 4> DelayedDllExportClasses;
private:
+ class SavePendingParsedClassStateRAII {
+ public:
+ SavePendingParsedClassStateRAII(Sema &S) : S(S) { swapSavedState(); }
+
+ ~SavePendingParsedClassStateRAII() {
+ assert(S.DelayedExceptionSpecChecks.empty() &&
+ "there shouldn't be any pending delayed exception spec checks");
+ assert(S.DelayedDefaultedMemberExceptionSpecs.empty() &&
+ "there shouldn't be any pending delayed defaulted member "
+ "exception specs");
+ assert(S.DelayedDllExportClasses.empty() &&
+ "there shouldn't be any pending delayed DLL export classes");
+ swapSavedState();
+ }
+
+ private:
+ Sema &S;
+ decltype(DelayedExceptionSpecChecks) SavedExceptionSpecChecks;
+ decltype(DelayedDefaultedMemberExceptionSpecs)
+ SavedDefaultedMemberExceptionSpecs;
+ decltype(DelayedDllExportClasses) SavedDllExportClasses;
+
+ void swapSavedState() {
+ SavedExceptionSpecChecks.swap(S.DelayedExceptionSpecChecks);
+ SavedDefaultedMemberExceptionSpecs.swap(
+ S.DelayedDefaultedMemberExceptionSpecs);
+ SavedDllExportClasses.swap(S.DelayedDllExportClasses);
+ }
+ };
+
/// \brief Helper class that collects misaligned member designations and
/// their location info for delayed diagnostics.
struct MisalignedMember {
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/SemaInternal.h b/contrib/llvm/tools/clang/include/clang/Sema/SemaInternal.h
index a01e8d639f603..4dc215ba21cb7 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/SemaInternal.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/SemaInternal.h
@@ -73,7 +73,8 @@ inline void MarkVarDeclODRUsed(VarDecl *Var,
// Keep track of used but undefined variables.
// FIXME: We shouldn't suppress this warning for static data members.
if (Var->hasDefinition(SemaRef.Context) == VarDecl::DeclarationOnly &&
- (!Var->isExternallyVisible() || Var->isInline()) &&
+ (!Var->isExternallyVisible() || Var->isInline() ||
+ SemaRef.isExternalWithNoLinkageType(Var)) &&
!(Var->isStaticDataMember() && Var->hasInit())) {
SourceLocation &old = SemaRef.UndefinedButUsed[Var->getCanonicalDecl()];
if (old.isInvalid())
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h
index 9227b33d2c53c..34a7bb330174b 100644
--- a/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h
@@ -14,17 +14,23 @@
// respective lists.
//
//===----------------------------------------------------------------------===//
+
#ifndef LLVM_CLANG_SERIALIZATION_ASTBITCODES_H
#define LLVM_CLANG_SERIALIZATION_ASTBITCODES_H
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Type.h"
-#include "llvm/ADT/DenseMap.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/OperatorKinds.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/Bitcode/BitCodes.h"
-#include "llvm/Support/DataTypes.h"
+#include <cassert>
+#include <cstdint>
namespace clang {
- namespace serialization {
+namespace serialization {
+
/// \brief AST file major version number supported by this version of
/// Clang.
///
@@ -52,7 +58,7 @@ namespace clang {
///
/// The ID numbers of identifiers are consecutive (in order of discovery)
/// and start at 1. 0 is reserved for NULL.
- typedef uint32_t IdentifierID;
+ using IdentifierID = uint32_t;
/// \brief An ID number that refers to a declaration in an AST file.
///
@@ -60,12 +66,12 @@ namespace clang {
/// discovery), with values below NUM_PREDEF_DECL_IDS being reserved.
/// At the start of a chain of precompiled headers, declaration ID 1 is
/// used for the translation unit declaration.
- typedef uint32_t DeclID;
+ using DeclID = uint32_t;
// FIXME: Turn these into classes so we can have some type safety when
// we go from local ID to global and vice-versa.
- typedef DeclID LocalDeclID;
- typedef DeclID GlobalDeclID;
+ using LocalDeclID = DeclID;
+ using GlobalDeclID = DeclID;
/// \brief An ID number that refers to a type in an AST file.
///
@@ -77,22 +83,25 @@ namespace clang {
/// IDs (based on the PREDEF_TYPE_*_ID constants), with 0 as a
/// placeholder for "no type". Values from NUM_PREDEF_TYPE_IDs are
/// other types that have serialized representations.
- typedef uint32_t TypeID;
+ using TypeID = uint32_t;
/// \brief A type index; the type ID with the qualifier bits removed.
class TypeIdx {
- uint32_t Idx;
+ uint32_t Idx = 0;
+
public:
- TypeIdx() : Idx(0) { }
- explicit TypeIdx(uint32_t index) : Idx(index) { }
+ TypeIdx() = default;
+ explicit TypeIdx(uint32_t index) : Idx(index) {}
uint32_t getIndex() const { return Idx; }
+
TypeID asTypeID(unsigned FastQuals) const {
if (Idx == uint32_t(-1))
return TypeID(-1);
return (Idx << Qualifiers::FastWidth) | FastQuals;
}
+
static TypeIdx fromTypeID(TypeID ID) {
if (ID == TypeID(-1))
return TypeIdx(-1);
@@ -104,14 +113,17 @@ namespace clang {
/// A structure for putting "fast"-unqualified QualTypes into a
/// DenseMap. This uses the standard pointer hash function.
struct UnsafeQualTypeDenseMapInfo {
- static inline bool isEqual(QualType A, QualType B) { return A == B; }
- static inline QualType getEmptyKey() {
+ static bool isEqual(QualType A, QualType B) { return A == B; }
+
+ static QualType getEmptyKey() {
return QualType::getFromOpaquePtr((void*) 1);
}
- static inline QualType getTombstoneKey() {
+
+ static QualType getTombstoneKey() {
return QualType::getFromOpaquePtr((void*) 2);
}
- static inline unsigned getHashValue(QualType T) {
+
+ static unsigned getHashValue(QualType T) {
assert(!T.getLocalFastQualifiers() &&
"hash invalid for types with fast quals");
uintptr_t v = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
@@ -120,44 +132,44 @@ namespace clang {
};
/// \brief An ID number that refers to an identifier in an AST file.
- typedef uint32_t IdentID;
+ using IdentID = uint32_t;
/// \brief The number of predefined identifier IDs.
const unsigned int NUM_PREDEF_IDENT_IDS = 1;
/// \brief An ID number that refers to a macro in an AST file.
- typedef uint32_t MacroID;
+ using MacroID = uint32_t;
/// \brief A global ID number that refers to a macro in an AST file.
- typedef uint32_t GlobalMacroID;
+ using GlobalMacroID = uint32_t;
/// \brief A local to a module ID number that refers to a macro in an
/// AST file.
- typedef uint32_t LocalMacroID;
+ using LocalMacroID = uint32_t;
/// \brief The number of predefined macro IDs.
const unsigned int NUM_PREDEF_MACRO_IDS = 1;
/// \brief An ID number that refers to an ObjC selector in an AST file.
- typedef uint32_t SelectorID;
+ using SelectorID = uint32_t;
/// \brief The number of predefined selector IDs.
const unsigned int NUM_PREDEF_SELECTOR_IDS = 1;
/// \brief An ID number that refers to a set of CXXBaseSpecifiers in an
/// AST file.
- typedef uint32_t CXXBaseSpecifiersID;
+ using CXXBaseSpecifiersID = uint32_t;
/// \brief An ID number that refers to a list of CXXCtorInitializers in an
/// AST file.
- typedef uint32_t CXXCtorInitializersID;
+ using CXXCtorInitializersID = uint32_t;
/// \brief An ID number that refers to an entity in the detailed
/// preprocessing record.
- typedef uint32_t PreprocessedEntityID;
+ using PreprocessedEntityID = uint32_t;
/// \brief An ID number that refers to a submodule in a module file.
- typedef uint32_t SubmoduleID;
+ using SubmoduleID = uint32_t;
/// \brief The number of predefined submodule IDs.
const unsigned int NUM_PREDEF_SUBMODULE_IDS = 1;
@@ -166,18 +178,21 @@ namespace clang {
struct PPEntityOffset {
/// \brief Raw source location of beginning of range.
unsigned Begin;
+
/// \brief Raw source location of end of range.
unsigned End;
+
/// \brief Offset in the AST file.
uint32_t BitOffset;
PPEntityOffset(SourceRange R, uint32_t BitOffset)
: Begin(R.getBegin().getRawEncoding()),
- End(R.getEnd().getRawEncoding()),
- BitOffset(BitOffset) { }
+ End(R.getEnd().getRawEncoding()), BitOffset(BitOffset) {}
+
SourceLocation getBegin() const {
return SourceLocation::getFromRawEncoding(Begin);
}
+
SourceLocation getEnd() const {
return SourceLocation::getFromRawEncoding(End);
}
@@ -186,17 +201,19 @@ namespace clang {
/// \brief Source range/offset of a preprocessed entity.
struct DeclOffset {
/// \brief Raw source location.
- unsigned Loc;
+ unsigned Loc = 0;
+
/// \brief Offset in the AST file.
- uint32_t BitOffset;
+ uint32_t BitOffset = 0;
- DeclOffset() : Loc(0), BitOffset(0) { }
+ DeclOffset() = default;
DeclOffset(SourceLocation Loc, uint32_t BitOffset)
- : Loc(Loc.getRawEncoding()),
- BitOffset(BitOffset) { }
+ : Loc(Loc.getRawEncoding()), BitOffset(BitOffset) {}
+
void setLocation(SourceLocation L) {
Loc = L.getRawEncoding();
}
+
SourceLocation getLocation() const {
return SourceLocation::getFromRawEncoding(Loc);
}
@@ -617,17 +634,21 @@ namespace clang {
/// \brief Describes a source location entry (SLocEntry) for a
/// file.
SM_SLOC_FILE_ENTRY = 1,
+
/// \brief Describes a source location entry (SLocEntry) for a
/// buffer.
SM_SLOC_BUFFER_ENTRY = 2,
+
/// \brief Describes a blob that contains the data for a buffer
/// entry. This kind of record always directly follows a
/// SM_SLOC_BUFFER_ENTRY record or a SM_SLOC_FILE_ENTRY with an
/// overridden buffer.
SM_SLOC_BUFFER_BLOB = 3,
+
/// \brief Describes a zlib-compressed blob that contains the data for
/// a buffer entry.
SM_SLOC_BUFFER_BLOB_COMPRESSED = 4,
+
/// \brief Describes a source location entry (SLocEntry) for a
/// macro expansion.
SM_SLOC_EXPANSION_ENTRY = 5
@@ -676,46 +697,66 @@ namespace clang {
enum SubmoduleRecordTypes {
/// \brief Metadata for submodules as a whole.
SUBMODULE_METADATA = 0,
+
/// \brief Defines the major attributes of a submodule, including its
/// name and parent.
SUBMODULE_DEFINITION = 1,
+
/// \brief Specifies the umbrella header used to create this module,
/// if any.
SUBMODULE_UMBRELLA_HEADER = 2,
+
/// \brief Specifies a header that falls into this (sub)module.
SUBMODULE_HEADER = 3,
+
/// \brief Specifies a top-level header that falls into this (sub)module.
SUBMODULE_TOPHEADER = 4,
+
/// \brief Specifies an umbrella directory.
SUBMODULE_UMBRELLA_DIR = 5,
+
/// \brief Specifies the submodules that are imported by this
/// submodule.
SUBMODULE_IMPORTS = 6,
+
/// \brief Specifies the submodules that are re-exported from this
/// submodule.
SUBMODULE_EXPORTS = 7,
+
/// \brief Specifies a required feature.
SUBMODULE_REQUIRES = 8,
+
/// \brief Specifies a header that has been explicitly excluded
/// from this submodule.
SUBMODULE_EXCLUDED_HEADER = 9,
+
/// \brief Specifies a library or framework to link against.
SUBMODULE_LINK_LIBRARY = 10,
+
/// \brief Specifies a configuration macro for this module.
SUBMODULE_CONFIG_MACRO = 11,
+
/// \brief Specifies a conflict with another module.
SUBMODULE_CONFLICT = 12,
+
/// \brief Specifies a header that is private to this submodule.
SUBMODULE_PRIVATE_HEADER = 13,
+
/// \brief Specifies a header that is part of the module but must be
/// textually included.
SUBMODULE_TEXTUAL_HEADER = 14,
+
/// \brief Specifies a header that is private to this submodule but
/// must be textually included.
SUBMODULE_PRIVATE_TEXTUAL_HEADER = 15,
+
/// \brief Specifies some declarations with initializers that must be
/// emitted to initialize the module.
SUBMODULE_INITIALIZERS = 16,
+
+ /// \brief Specifies the name of the module that will eventually
+ /// re-export the entities in this module.
+ SUBMODULE_EXPORT_AS = 17,
};
/// \brief Record types used within a comments block.
@@ -740,92 +781,139 @@ namespace clang {
enum PredefinedTypeIDs {
/// \brief The NULL type.
PREDEF_TYPE_NULL_ID = 0,
+
/// \brief The void type.
PREDEF_TYPE_VOID_ID = 1,
+
/// \brief The 'bool' or '_Bool' type.
PREDEF_TYPE_BOOL_ID = 2,
+
/// \brief The 'char' type, when it is unsigned.
PREDEF_TYPE_CHAR_U_ID = 3,
+
/// \brief The 'unsigned char' type.
PREDEF_TYPE_UCHAR_ID = 4,
+
/// \brief The 'unsigned short' type.
PREDEF_TYPE_USHORT_ID = 5,
+
/// \brief The 'unsigned int' type.
PREDEF_TYPE_UINT_ID = 6,
+
/// \brief The 'unsigned long' type.
PREDEF_TYPE_ULONG_ID = 7,
+
/// \brief The 'unsigned long long' type.
PREDEF_TYPE_ULONGLONG_ID = 8,
+
/// \brief The 'char' type, when it is signed.
PREDEF_TYPE_CHAR_S_ID = 9,
+
/// \brief The 'signed char' type.
PREDEF_TYPE_SCHAR_ID = 10,
+
/// \brief The C++ 'wchar_t' type.
PREDEF_TYPE_WCHAR_ID = 11,
+
/// \brief The (signed) 'short' type.
PREDEF_TYPE_SHORT_ID = 12,
+
/// \brief The (signed) 'int' type.
PREDEF_TYPE_INT_ID = 13,
+
/// \brief The (signed) 'long' type.
PREDEF_TYPE_LONG_ID = 14,
+
/// \brief The (signed) 'long long' type.
PREDEF_TYPE_LONGLONG_ID = 15,
+
/// \brief The 'float' type.
PREDEF_TYPE_FLOAT_ID = 16,
+
/// \brief The 'double' type.
PREDEF_TYPE_DOUBLE_ID = 17,
+
/// \brief The 'long double' type.
PREDEF_TYPE_LONGDOUBLE_ID = 18,
+
/// \brief The placeholder type for overloaded function sets.
PREDEF_TYPE_OVERLOAD_ID = 19,
+
/// \brief The placeholder type for dependent types.
PREDEF_TYPE_DEPENDENT_ID = 20,
+
/// \brief The '__uint128_t' type.
PREDEF_TYPE_UINT128_ID = 21,
+
/// \brief The '__int128_t' type.
PREDEF_TYPE_INT128_ID = 22,
+
/// \brief The type of 'nullptr'.
PREDEF_TYPE_NULLPTR_ID = 23,
+
/// \brief The C++ 'char16_t' type.
PREDEF_TYPE_CHAR16_ID = 24,
+
/// \brief The C++ 'char32_t' type.
PREDEF_TYPE_CHAR32_ID = 25,
+
/// \brief The ObjC 'id' type.
PREDEF_TYPE_OBJC_ID = 26,
+
/// \brief The ObjC 'Class' type.
PREDEF_TYPE_OBJC_CLASS = 27,
+
/// \brief The ObjC 'SEL' type.
PREDEF_TYPE_OBJC_SEL = 28,
+
/// \brief The 'unknown any' placeholder type.
PREDEF_TYPE_UNKNOWN_ANY = 29,
+
/// \brief The placeholder type for bound member functions.
PREDEF_TYPE_BOUND_MEMBER = 30,
+
/// \brief The "auto" deduction type.
PREDEF_TYPE_AUTO_DEDUCT = 31,
+
/// \brief The "auto &&" deduction type.
PREDEF_TYPE_AUTO_RREF_DEDUCT = 32,
+
/// \brief The OpenCL 'half' / ARM NEON __fp16 type.
PREDEF_TYPE_HALF_ID = 33,
+
/// \brief ARC's unbridged-cast placeholder type.
PREDEF_TYPE_ARC_UNBRIDGED_CAST = 34,
+
/// \brief The pseudo-object placeholder type.
PREDEF_TYPE_PSEUDO_OBJECT = 35,
+
/// \brief The placeholder type for builtin functions.
PREDEF_TYPE_BUILTIN_FN = 36,
+
/// \brief OpenCL event type.
PREDEF_TYPE_EVENT_ID = 37,
+
/// \brief OpenCL clk event type.
PREDEF_TYPE_CLK_EVENT_ID = 38,
+
/// \brief OpenCL sampler type.
PREDEF_TYPE_SAMPLER_ID = 39,
+
/// \brief OpenCL queue type.
PREDEF_TYPE_QUEUE_ID = 40,
+
/// \brief OpenCL reserve_id type.
PREDEF_TYPE_RESERVE_ID_ID = 41,
+
/// \brief The placeholder type for OpenMP array section.
PREDEF_TYPE_OMP_ARRAY_SECTION = 42,
+
/// \brief The '__float128' type
PREDEF_TYPE_FLOAT128_ID = 43,
+
+ /// \brief The '_Float16' type
+ PREDEF_TYPE_FLOAT16_ID = 44,
+
/// \brief OpenCL image types with auto numeration
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
PREDEF_TYPE_##Id##_ID,
@@ -848,94 +936,141 @@ namespace clang {
enum TypeCode {
/// \brief An ExtQualType record.
TYPE_EXT_QUAL = 1,
+
/// \brief A ComplexType record.
TYPE_COMPLEX = 3,
+
/// \brief A PointerType record.
TYPE_POINTER = 4,
+
/// \brief A BlockPointerType record.
TYPE_BLOCK_POINTER = 5,
+
/// \brief An LValueReferenceType record.
TYPE_LVALUE_REFERENCE = 6,
+
/// \brief An RValueReferenceType record.
TYPE_RVALUE_REFERENCE = 7,
+
/// \brief A MemberPointerType record.
TYPE_MEMBER_POINTER = 8,
+
/// \brief A ConstantArrayType record.
TYPE_CONSTANT_ARRAY = 9,
+
/// \brief An IncompleteArrayType record.
TYPE_INCOMPLETE_ARRAY = 10,
+
/// \brief A VariableArrayType record.
TYPE_VARIABLE_ARRAY = 11,
+
/// \brief A VectorType record.
TYPE_VECTOR = 12,
+
/// \brief An ExtVectorType record.
TYPE_EXT_VECTOR = 13,
+
/// \brief A FunctionNoProtoType record.
TYPE_FUNCTION_NO_PROTO = 14,
+
/// \brief A FunctionProtoType record.
TYPE_FUNCTION_PROTO = 15,
+
/// \brief A TypedefType record.
TYPE_TYPEDEF = 16,
+
/// \brief A TypeOfExprType record.
TYPE_TYPEOF_EXPR = 17,
+
/// \brief A TypeOfType record.
TYPE_TYPEOF = 18,
+
/// \brief A RecordType record.
TYPE_RECORD = 19,
+
/// \brief An EnumType record.
TYPE_ENUM = 20,
+
/// \brief An ObjCInterfaceType record.
TYPE_OBJC_INTERFACE = 21,
+
/// \brief An ObjCObjectPointerType record.
TYPE_OBJC_OBJECT_POINTER = 22,
+
/// \brief a DecltypeType record.
TYPE_DECLTYPE = 23,
+
/// \brief An ElaboratedType record.
TYPE_ELABORATED = 24,
+
/// \brief A SubstTemplateTypeParmType record.
TYPE_SUBST_TEMPLATE_TYPE_PARM = 25,
+
/// \brief An UnresolvedUsingType record.
TYPE_UNRESOLVED_USING = 26,
+
/// \brief An InjectedClassNameType record.
TYPE_INJECTED_CLASS_NAME = 27,
+
/// \brief An ObjCObjectType record.
TYPE_OBJC_OBJECT = 28,
+
/// \brief An TemplateTypeParmType record.
TYPE_TEMPLATE_TYPE_PARM = 29,
+
/// \brief An TemplateSpecializationType record.
TYPE_TEMPLATE_SPECIALIZATION = 30,
+
/// \brief A DependentNameType record.
TYPE_DEPENDENT_NAME = 31,
+
/// \brief A DependentTemplateSpecializationType record.
TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION = 32,
+
/// \brief A DependentSizedArrayType record.
TYPE_DEPENDENT_SIZED_ARRAY = 33,
+
/// \brief A ParenType record.
TYPE_PAREN = 34,
+
/// \brief A PackExpansionType record.
TYPE_PACK_EXPANSION = 35,
+
/// \brief An AttributedType record.
TYPE_ATTRIBUTED = 36,
+
/// \brief A SubstTemplateTypeParmPackType record.
TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK = 37,
+
/// \brief A AutoType record.
TYPE_AUTO = 38,
+
/// \brief A UnaryTransformType record.
TYPE_UNARY_TRANSFORM = 39,
+
/// \brief An AtomicType record.
TYPE_ATOMIC = 40,
+
/// \brief A DecayedType record.
TYPE_DECAYED = 41,
+
/// \brief An AdjustedType record.
TYPE_ADJUSTED = 42,
+
/// \brief A PipeType record.
TYPE_PIPE = 43,
+
/// \brief An ObjCTypeParamType record.
TYPE_OBJC_TYPE_PARAM = 44,
+
/// \brief A DeducedTemplateSpecializationType record.
TYPE_DEDUCED_TEMPLATE_SPECIALIZATION = 45,
+
/// \brief A DependentSizedExtVectorType record.
- TYPE_DEPENDENT_SIZED_EXT_VECTOR = 46
+ TYPE_DEPENDENT_SIZED_EXT_VECTOR = 46,
+
+ /// \brief A DependentAddressSpaceType record.
+ TYPE_DEPENDENT_ADDRESS_SPACE = 47
};
/// \brief The type IDs for special types constructed by semantic
@@ -946,18 +1081,25 @@ namespace clang {
enum SpecialTypeIDs {
/// \brief CFConstantString type
SPECIAL_TYPE_CF_CONSTANT_STRING = 0,
+
/// \brief C FILE typedef type
SPECIAL_TYPE_FILE = 1,
+
/// \brief C jmp_buf typedef type
SPECIAL_TYPE_JMP_BUF = 2,
+
/// \brief C sigjmp_buf typedef type
SPECIAL_TYPE_SIGJMP_BUF = 3,
+
/// \brief Objective-C "id" redefinition type
SPECIAL_TYPE_OBJC_ID_REDEFINITION = 4,
+
/// \brief Objective-C "Class" redefinition type
SPECIAL_TYPE_OBJC_CLASS_REDEFINITION = 5,
+
/// \brief Objective-C "SEL" redefinition type
SPECIAL_TYPE_OBJC_SEL_REDEFINITION = 6,
+
/// \brief C ucontext_t typedef type
SPECIAL_TYPE_UCONTEXT_T = 7
};
@@ -1048,57 +1190,84 @@ namespace clang {
/// \brief A TypedefDecl record.
DECL_TYPEDEF = 51,
/// \brief A TypeAliasDecl record.
+
DECL_TYPEALIAS,
+
/// \brief An EnumDecl record.
DECL_ENUM,
+
/// \brief A RecordDecl record.
DECL_RECORD,
+
/// \brief An EnumConstantDecl record.
DECL_ENUM_CONSTANT,
+
/// \brief A FunctionDecl record.
DECL_FUNCTION,
+
/// \brief A ObjCMethodDecl record.
DECL_OBJC_METHOD,
+
/// \brief A ObjCInterfaceDecl record.
DECL_OBJC_INTERFACE,
+
/// \brief A ObjCProtocolDecl record.
DECL_OBJC_PROTOCOL,
+
/// \brief A ObjCIvarDecl record.
DECL_OBJC_IVAR,
+
/// \brief A ObjCAtDefsFieldDecl record.
DECL_OBJC_AT_DEFS_FIELD,
+
/// \brief A ObjCCategoryDecl record.
DECL_OBJC_CATEGORY,
+
/// \brief A ObjCCategoryImplDecl record.
DECL_OBJC_CATEGORY_IMPL,
+
/// \brief A ObjCImplementationDecl record.
DECL_OBJC_IMPLEMENTATION,
+
/// \brief A ObjCCompatibleAliasDecl record.
DECL_OBJC_COMPATIBLE_ALIAS,
+
/// \brief A ObjCPropertyDecl record.
DECL_OBJC_PROPERTY,
+
/// \brief A ObjCPropertyImplDecl record.
DECL_OBJC_PROPERTY_IMPL,
+
/// \brief A FieldDecl record.
DECL_FIELD,
+
/// \brief A MSPropertyDecl record.
DECL_MS_PROPERTY,
+
/// \brief A VarDecl record.
DECL_VAR,
+
/// \brief An ImplicitParamDecl record.
DECL_IMPLICIT_PARAM,
+
/// \brief A ParmVarDecl record.
DECL_PARM_VAR,
+
/// \brief A DecompositionDecl record.
DECL_DECOMPOSITION,
+
/// \brief A BindingDecl record.
DECL_BINDING,
+
/// \brief A FileScopeAsmDecl record.
DECL_FILE_SCOPE_ASM,
+
/// \brief A BlockDecl record.
DECL_BLOCK,
+
/// \brief A CapturedDecl record.
DECL_CAPTURED,
+
/// \brief A record that stores the set of declarations that are
/// lexically stored within a given DeclContext.
///
@@ -1108,6 +1277,7 @@ namespace clang {
/// the contents of a DeclContext, e.g., via
/// DeclContext::decls_begin() and DeclContext::decls_end().
DECL_CONTEXT_LEXICAL,
+
/// \brief A record that stores the set of declarations that are
/// visible from a given DeclContext.
///
@@ -1116,104 +1286,151 @@ namespace clang {
/// IDs. This data is used when performing qualified name lookup
/// into a DeclContext via DeclContext::lookup.
DECL_CONTEXT_VISIBLE,
+
/// \brief A LabelDecl record.
DECL_LABEL,
+
/// \brief A NamespaceDecl record.
DECL_NAMESPACE,
+
/// \brief A NamespaceAliasDecl record.
DECL_NAMESPACE_ALIAS,
+
/// \brief A UsingDecl record.
DECL_USING,
+
/// \brief A UsingPackDecl record.
DECL_USING_PACK,
+
/// \brief A UsingShadowDecl record.
DECL_USING_SHADOW,
+
/// \brief A ConstructorUsingShadowDecl record.
DECL_CONSTRUCTOR_USING_SHADOW,
+
/// \brief A UsingDirecitveDecl record.
DECL_USING_DIRECTIVE,
+
/// \brief An UnresolvedUsingValueDecl record.
DECL_UNRESOLVED_USING_VALUE,
+
/// \brief An UnresolvedUsingTypenameDecl record.
DECL_UNRESOLVED_USING_TYPENAME,
+
/// \brief A LinkageSpecDecl record.
DECL_LINKAGE_SPEC,
+
/// \brief An ExportDecl record.
DECL_EXPORT,
+
/// \brief A CXXRecordDecl record.
DECL_CXX_RECORD,
+
/// \brief A CXXDeductionGuideDecl record.
DECL_CXX_DEDUCTION_GUIDE,
+
/// \brief A CXXMethodDecl record.
DECL_CXX_METHOD,
+
/// \brief A CXXConstructorDecl record.
DECL_CXX_CONSTRUCTOR,
+
/// \brief A CXXConstructorDecl record for an inherited constructor.
DECL_CXX_INHERITED_CONSTRUCTOR,
+
/// \brief A CXXDestructorDecl record.
DECL_CXX_DESTRUCTOR,
+
/// \brief A CXXConversionDecl record.
DECL_CXX_CONVERSION,
+
/// \brief An AccessSpecDecl record.
DECL_ACCESS_SPEC,
/// \brief A FriendDecl record.
DECL_FRIEND,
+
/// \brief A FriendTemplateDecl record.
DECL_FRIEND_TEMPLATE,
+
/// \brief A ClassTemplateDecl record.
DECL_CLASS_TEMPLATE,
+
/// \brief A ClassTemplateSpecializationDecl record.
DECL_CLASS_TEMPLATE_SPECIALIZATION,
+
/// \brief A ClassTemplatePartialSpecializationDecl record.
DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION,
+
/// \brief A VarTemplateDecl record.
DECL_VAR_TEMPLATE,
+
/// \brief A VarTemplateSpecializationDecl record.
DECL_VAR_TEMPLATE_SPECIALIZATION,
+
/// \brief A VarTemplatePartialSpecializationDecl record.
DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION,
+
/// \brief A FunctionTemplateDecl record.
DECL_FUNCTION_TEMPLATE,
+
/// \brief A TemplateTypeParmDecl record.
DECL_TEMPLATE_TYPE_PARM,
+
/// \brief A NonTypeTemplateParmDecl record.
DECL_NON_TYPE_TEMPLATE_PARM,
+
/// \brief A TemplateTemplateParmDecl record.
DECL_TEMPLATE_TEMPLATE_PARM,
+
/// \brief A TypeAliasTemplateDecl record.
DECL_TYPE_ALIAS_TEMPLATE,
+
/// \brief A StaticAssertDecl record.
DECL_STATIC_ASSERT,
+
/// \brief A record containing CXXBaseSpecifiers.
DECL_CXX_BASE_SPECIFIERS,
+
/// \brief A record containing CXXCtorInitializers.
DECL_CXX_CTOR_INITIALIZERS,
+
/// \brief A IndirectFieldDecl record.
DECL_INDIRECTFIELD,
+
/// \brief A NonTypeTemplateParmDecl record that stores an expanded
/// non-type template parameter pack.
DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK,
+
/// \brief A TemplateTemplateParmDecl record that stores an expanded
/// template template parameter pack.
DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK,
+
/// \brief A ClassScopeFunctionSpecializationDecl record a class scope
/// function specialization. (Microsoft extension).
DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION,
+
/// \brief An ImportDecl recording a module import.
DECL_IMPORT,
+
/// \brief An OMPThreadPrivateDecl record.
DECL_OMP_THREADPRIVATE,
+
/// \brief An EmptyDecl record.
DECL_EMPTY,
+
/// \brief An ObjCTypeParamDecl record.
DECL_OBJC_TYPE_PARAM,
+
/// \brief An OMPCapturedExprDecl record.
DECL_OMP_CAPTUREDEXPR,
+
/// \brief A PragmaCommentDecl record.
DECL_PRAGMA_COMMENT,
+
/// \brief A PragmaDetectMismatchDecl record.
DECL_PRAGMA_DETECT_MISMATCH,
+
/// \brief An OMPDeclareReductionDecl record.
DECL_OMP_DECLARE_REDUCTION,
};
@@ -1229,128 +1446,190 @@ namespace clang {
/// \brief A marker record that indicates that we are at the end
/// of an expression.
STMT_STOP = 128,
+
/// \brief A NULL expression.
STMT_NULL_PTR,
+
/// \brief A reference to a previously [de]serialized Stmt record.
STMT_REF_PTR,
+
/// \brief A NullStmt record.
STMT_NULL,
+
/// \brief A CompoundStmt record.
STMT_COMPOUND,
+
/// \brief A CaseStmt record.
STMT_CASE,
+
/// \brief A DefaultStmt record.
STMT_DEFAULT,
+
/// \brief A LabelStmt record.
STMT_LABEL,
+
/// \brief An AttributedStmt record.
STMT_ATTRIBUTED,
+
/// \brief An IfStmt record.
STMT_IF,
+
/// \brief A SwitchStmt record.
STMT_SWITCH,
+
/// \brief A WhileStmt record.
STMT_WHILE,
+
/// \brief A DoStmt record.
STMT_DO,
+
/// \brief A ForStmt record.
STMT_FOR,
+
/// \brief A GotoStmt record.
STMT_GOTO,
+
/// \brief An IndirectGotoStmt record.
STMT_INDIRECT_GOTO,
+
/// \brief A ContinueStmt record.
STMT_CONTINUE,
+
/// \brief A BreakStmt record.
STMT_BREAK,
+
/// \brief A ReturnStmt record.
STMT_RETURN,
+
/// \brief A DeclStmt record.
STMT_DECL,
+
/// \brief A CapturedStmt record.
STMT_CAPTURED,
+
/// \brief A GCC-style AsmStmt record.
STMT_GCCASM,
+
/// \brief A MS-style AsmStmt record.
STMT_MSASM,
+
/// \brief A PredefinedExpr record.
EXPR_PREDEFINED,
+
/// \brief A DeclRefExpr record.
EXPR_DECL_REF,
+
/// \brief An IntegerLiteral record.
EXPR_INTEGER_LITERAL,
+
/// \brief A FloatingLiteral record.
EXPR_FLOATING_LITERAL,
+
/// \brief An ImaginaryLiteral record.
EXPR_IMAGINARY_LITERAL,
+
/// \brief A StringLiteral record.
EXPR_STRING_LITERAL,
+
/// \brief A CharacterLiteral record.
EXPR_CHARACTER_LITERAL,
+
/// \brief A ParenExpr record.
EXPR_PAREN,
+
/// \brief A ParenListExpr record.
EXPR_PAREN_LIST,
+
/// \brief A UnaryOperator record.
EXPR_UNARY_OPERATOR,
+
/// \brief An OffsetOfExpr record.
EXPR_OFFSETOF,
+
/// \brief A SizefAlignOfExpr record.
EXPR_SIZEOF_ALIGN_OF,
+
/// \brief An ArraySubscriptExpr record.
EXPR_ARRAY_SUBSCRIPT,
+
/// \brief A CallExpr record.
EXPR_CALL,
+
/// \brief A MemberExpr record.
EXPR_MEMBER,
+
/// \brief A BinaryOperator record.
EXPR_BINARY_OPERATOR,
+
/// \brief A CompoundAssignOperator record.
EXPR_COMPOUND_ASSIGN_OPERATOR,
+
/// \brief A ConditionOperator record.
EXPR_CONDITIONAL_OPERATOR,
+
/// \brief An ImplicitCastExpr record.
EXPR_IMPLICIT_CAST,
+
/// \brief A CStyleCastExpr record.
EXPR_CSTYLE_CAST,
+
/// \brief A CompoundLiteralExpr record.
EXPR_COMPOUND_LITERAL,
+
/// \brief An ExtVectorElementExpr record.
EXPR_EXT_VECTOR_ELEMENT,
+
/// \brief An InitListExpr record.
EXPR_INIT_LIST,
+
/// \brief A DesignatedInitExpr record.
EXPR_DESIGNATED_INIT,
+
/// \brief A DesignatedInitUpdateExpr record.
EXPR_DESIGNATED_INIT_UPDATE,
+
/// \brief An NoInitExpr record.
EXPR_NO_INIT,
+
/// \brief An ArrayInitLoopExpr record.
EXPR_ARRAY_INIT_LOOP,
+
/// \brief An ArrayInitIndexExpr record.
EXPR_ARRAY_INIT_INDEX,
+
/// \brief An ImplicitValueInitExpr record.
EXPR_IMPLICIT_VALUE_INIT,
+
/// \brief A VAArgExpr record.
EXPR_VA_ARG,
+
/// \brief An AddrLabelExpr record.
EXPR_ADDR_LABEL,
+
/// \brief A StmtExpr record.
EXPR_STMT,
+
/// \brief A ChooseExpr record.
EXPR_CHOOSE,
+
/// \brief A GNUNullExpr record.
EXPR_GNU_NULL,
+
/// \brief A ShuffleVectorExpr record.
EXPR_SHUFFLE_VECTOR,
+
/// \brief A ConvertVectorExpr record.
EXPR_CONVERT_VECTOR,
+
/// \brief BlockExpr
EXPR_BLOCK,
+
/// \brief A GenericSelectionExpr record.
EXPR_GENERIC_SELECTION,
+
/// \brief A PseudoObjectExpr record.
EXPR_PSEUDO_OBJECT,
+
/// \brief An AtomicExpr record.
EXPR_ATOMIC,
@@ -1362,45 +1641,61 @@ namespace clang {
EXPR_OBJC_BOXED_EXPRESSION,
EXPR_OBJC_ARRAY_LITERAL,
EXPR_OBJC_DICTIONARY_LITERAL,
-
-
+
/// \brief An ObjCEncodeExpr record.
EXPR_OBJC_ENCODE,
+
/// \brief An ObjCSelectorExpr record.
EXPR_OBJC_SELECTOR_EXPR,
+
/// \brief An ObjCProtocolExpr record.
EXPR_OBJC_PROTOCOL_EXPR,
+
/// \brief An ObjCIvarRefExpr record.
EXPR_OBJC_IVAR_REF_EXPR,
+
/// \brief An ObjCPropertyRefExpr record.
EXPR_OBJC_PROPERTY_REF_EXPR,
+
/// \brief An ObjCSubscriptRefExpr record.
EXPR_OBJC_SUBSCRIPT_REF_EXPR,
+
/// \brief UNUSED
EXPR_OBJC_KVC_REF_EXPR,
+
/// \brief An ObjCMessageExpr record.
EXPR_OBJC_MESSAGE_EXPR,
+
/// \brief An ObjCIsa Expr record.
EXPR_OBJC_ISA,
+
/// \brief An ObjCIndirectCopyRestoreExpr record.
EXPR_OBJC_INDIRECT_COPY_RESTORE,
/// \brief An ObjCForCollectionStmt record.
STMT_OBJC_FOR_COLLECTION,
+
/// \brief An ObjCAtCatchStmt record.
STMT_OBJC_CATCH,
+
/// \brief An ObjCAtFinallyStmt record.
STMT_OBJC_FINALLY,
+
/// \brief An ObjCAtTryStmt record.
STMT_OBJC_AT_TRY,
+
/// \brief An ObjCAtSynchronizedStmt record.
STMT_OBJC_AT_SYNCHRONIZED,
+
/// \brief An ObjCAtThrowStmt record.
STMT_OBJC_AT_THROW,
+
/// \brief An ObjCAutoreleasePoolStmt record.
STMT_OBJC_AUTORELEASE_POOL,
+
/// \brief An ObjCBoolLiteralExpr record.
EXPR_OBJC_BOOL_LITERAL,
+
/// \brief An ObjCAvailabilityCheckExpr record.
EXPR_OBJC_AVAILABILITY_CHECK,
@@ -1408,37 +1703,52 @@ namespace clang {
/// \brief A CXXCatchStmt record.
STMT_CXX_CATCH,
+
/// \brief A CXXTryStmt record.
STMT_CXX_TRY,
/// \brief A CXXForRangeStmt record.
+
STMT_CXX_FOR_RANGE,
/// \brief A CXXOperatorCallExpr record.
EXPR_CXX_OPERATOR_CALL,
+
/// \brief A CXXMemberCallExpr record.
EXPR_CXX_MEMBER_CALL,
+
/// \brief A CXXConstructExpr record.
EXPR_CXX_CONSTRUCT,
+
/// \brief A CXXInheritedCtorInitExpr record.
EXPR_CXX_INHERITED_CTOR_INIT,
+
/// \brief A CXXTemporaryObjectExpr record.
EXPR_CXX_TEMPORARY_OBJECT,
+
/// \brief A CXXStaticCastExpr record.
EXPR_CXX_STATIC_CAST,
+
/// \brief A CXXDynamicCastExpr record.
EXPR_CXX_DYNAMIC_CAST,
+
/// \brief A CXXReinterpretCastExpr record.
EXPR_CXX_REINTERPRET_CAST,
+
/// \brief A CXXConstCastExpr record.
EXPR_CXX_CONST_CAST,
+
/// \brief A CXXFunctionalCastExpr record.
EXPR_CXX_FUNCTIONAL_CAST,
+
/// \brief A UserDefinedLiteral record.
EXPR_USER_DEFINED_LITERAL,
+
/// \brief A CXXStdInitializerListExpr record.
EXPR_CXX_STD_INITIALIZER_LIST,
+
/// \brief A CXXBoolLiteralExpr record.
EXPR_CXX_BOOL_LITERAL,
+
EXPR_CXX_NULL_PTR_LITERAL, // CXXNullPtrLiteralExpr
EXPR_CXX_TYPEID_EXPR, // CXXTypeidExpr (of expr).
EXPR_CXX_TYPEID_TYPE, // CXXTypeidExpr (of type).
@@ -1560,11 +1870,14 @@ namespace clang {
enum DesignatorTypes {
/// \brief Field designator where only the field name is known.
DESIG_FIELD_NAME = 0,
+
/// \brief Field designator where the field has been resolved to
/// a declaration.
DESIG_FIELD_DECL = 1,
+
/// \brief Array designator.
DESIG_ARRAY = 2,
+
/// \brief GNU array range designator.
DESIG_ARRAY_RANGE = 3
};
@@ -1580,8 +1893,11 @@ namespace clang {
/// \brief Describes the redeclarations of a declaration.
struct LocalRedeclarationsInfo {
- DeclID FirstID; // The ID of the first declaration
- unsigned Offset; // Offset into the array of redeclaration chains.
+ // The ID of the first declaration
+ DeclID FirstID;
+
+ // Offset into the array of redeclaration chains.
+ unsigned Offset;
friend bool operator<(const LocalRedeclarationsInfo &X,
const LocalRedeclarationsInfo &Y) {
@@ -1606,8 +1922,11 @@ namespace clang {
/// \brief Describes the categories of an Objective-C class.
struct ObjCCategoriesInfo {
- DeclID DefinitionID; // The ID of the definition
- unsigned Offset; // Offset into the array of category lists.
+ // The ID of the definition
+ DeclID DefinitionID;
+
+ // Offset into the array of category lists.
+ unsigned Offset;
friend bool operator<(const ObjCCategoriesInfo &X,
const ObjCCategoriesInfo &Y) {
@@ -1636,15 +1955,14 @@ namespace clang {
/// same key can occasionally represent multiple names (for names that
/// contain types, in particular).
class DeclarationNameKey {
- typedef unsigned NameKind;
+ using NameKind = unsigned;
- NameKind Kind;
- uint64_t Data;
+ NameKind Kind = 0;
+ uint64_t Data = 0;
public:
- DeclarationNameKey() : Kind(), Data() {}
+ DeclarationNameKey() = default;
DeclarationNameKey(DeclarationName Name);
-
DeclarationNameKey(NameKind Kind, uint64_t Data)
: Kind(Kind), Data(Data) {}
@@ -1656,12 +1974,14 @@ namespace clang {
Kind == DeclarationName::CXXDeductionGuideName);
return (IdentifierInfo *)Data;
}
+
Selector getSelector() const {
assert(Kind == DeclarationName::ObjCZeroArgSelector ||
Kind == DeclarationName::ObjCOneArgSelector ||
Kind == DeclarationName::ObjCMultiArgSelector);
return Selector(Data);
}
+
OverloadedOperatorKind getOperatorKind() const {
assert(Kind == DeclarationName::CXXOperatorName);
return (OverloadedOperatorKind)Data;
@@ -1677,26 +1997,32 @@ namespace clang {
};
/// @}
- }
-} // end namespace clang
+
+} // namespace serialization
+} // namespace clang
namespace llvm {
+
template <> struct DenseMapInfo<clang::serialization::DeclarationNameKey> {
static clang::serialization::DeclarationNameKey getEmptyKey() {
return clang::serialization::DeclarationNameKey(-1, 1);
}
+
static clang::serialization::DeclarationNameKey getTombstoneKey() {
return clang::serialization::DeclarationNameKey(-1, 2);
}
+
static unsigned
getHashValue(const clang::serialization::DeclarationNameKey &Key) {
return Key.getHash();
}
+
static bool isEqual(const clang::serialization::DeclarationNameKey &L,
const clang::serialization::DeclarationNameKey &R) {
return L == R;
}
};
-}
-#endif
+} // namespace llvm
+
+#endif // LLVM_CLANG_SERIALIZATION_ASTBITCODES_H
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h
index eafa051758325..7b71fee95de27 100644
--- a/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h
@@ -1,4 +1,4 @@
-//===--- ASTReader.h - AST File Reader --------------------------*- C++ -*-===//
+//===- ASTReader.h - AST File Reader ----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,13 +17,21 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/TemplateBase.h"
+#include "clang/AST/TemplateName.h"
+#include "clang/AST/Type.h"
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileSystemOptions.h"
#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/Module.h"
+#include "clang/Basic/OpenCLOptions.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Version.h"
+#include "clang/Basic/VersionTuple.h"
#include "clang/Lex/ExternalPreprocessorSource.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/PreprocessingRecord.h"
+#include "clang/Lex/Token.h"
#include "clang/Sema/ExternalSemaSource.h"
#include "clang/Sema/IdentifierResolver.h"
#include "clang/Serialization/ASTBitCodes.h"
@@ -31,70 +39,86 @@
#include "clang/Serialization/Module.h"
#include "clang/Serialization/ModuleFileExtension.h"
#include "clang/Serialization/ModuleManager.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/TinyPtrVector.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Timer.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <ctime>
#include <deque>
#include <memory>
+#include <set>
#include <string>
#include <utility>
#include <vector>
-namespace llvm {
- class BitstreamCursor;
- class MemoryBuffer;
- class APInt;
- class APSInt;
- class APFloat;
-}
-
namespace clang {
-class SourceManager;
-class HeaderSearchOptions;
-class FileManager;
-class AddrLabelExpr;
class ASTConsumer;
class ASTContext;
-class ASTIdentifierIterator;
-class ASTUnit; // FIXME: Layering violation and egregious hack.
-class Attr;
-class Decl;
-class DeclContext;
-class DefMacroDirective;
-class DiagnosticOptions;
-class NestedNameSpecifier;
+class ASTDeserializationListener;
+class ASTReader;
+class ASTRecordReader;
class CXXBaseSpecifier;
class CXXConstructorDecl;
class CXXCtorInitializer;
+class CXXTemporary;
+class Decl;
+class DeclaratorDecl;
+class DeclContext;
+class EnumDecl;
+class Expr;
+class FieldDecl;
+class FileEntry;
+class FileManager;
+class FileSystemOptions;
+class FunctionDecl;
class GlobalModuleIndex;
-class GotoStmt;
-class MacroDefinition;
-class MacroDirective;
-class ModuleMacro;
+struct HeaderFileInfo;
+class HeaderSearchOptions;
+class LangOptions;
+class LazyASTUnresolvedSet;
+class MacroInfo;
+class MemoryBufferCache;
class NamedDecl;
-class OpaqueValueExpr;
+class NamespaceDecl;
+class NestedNameSpecifier;
+class ObjCCategoryDecl;
+class ObjCInterfaceDecl;
+class PCHContainerReader;
class Preprocessor;
class PreprocessorOptions;
+struct QualifierInfo;
class Sema;
+class SourceManager;
+class Stmt;
class SwitchCase;
-class ASTDeserializationListener;
-class ASTWriter;
-class ASTReader;
-class ASTDeclReader;
-class ASTStmtReader;
-class ASTRecordReader;
-class TypeLocReader;
-struct HeaderFileInfo;
-class VersionTuple;
class TargetOptions;
-class LazyASTUnresolvedSet;
+class TemplateParameterList;
+class TypedefNameDecl;
+class TypeSourceInfo;
+class ValueDecl;
+class VarDecl;
/// \brief Abstract interface for callback invocations by the ASTReader.
///
@@ -189,9 +213,11 @@ public:
/// \brief Returns true if this \c ASTReaderListener wants to receive the
/// input files of the AST file via \c visitInputFile, false otherwise.
virtual bool needsInputFileVisitation() { return false; }
+
/// \brief Returns true if this \c ASTReaderListener wants to receive the
/// system input files of the AST file via \c visitInputFile, false otherwise.
virtual bool needsSystemInputFileVisitation() { return false; }
+
/// \brief if \c needsInputFileVisitation returns true, this is called for
/// each non-system input file of the AST File. If
/// \c needsSystemInputFileVisitation is true, then it is called for all
@@ -206,6 +232,7 @@ public:
/// \brief Returns true if this \c ASTReaderListener wants to receive the
/// imports of the AST file via \c visitImport, false otherwise.
virtual bool needsImportVisitation() const { return false; }
+
/// \brief If needsImportVisitation returns \c true, this is called for each
/// AST file imported by this AST file.
virtual void visitImport(StringRef Filename) {}
@@ -306,12 +333,15 @@ namespace serialization {
class ReadMethodPoolVisitor;
namespace reader {
- class ASTIdentifierLookupTrait;
- /// \brief The on-disk hash table(s) used for DeclContext name lookup.
- struct DeclContextLookupTable;
-}
-} // end namespace serialization
+class ASTIdentifierLookupTrait;
+
+/// \brief The on-disk hash table(s) used for DeclContext name lookup.
+struct DeclContextLookupTable;
+
+} // namespace reader
+
+} // namespace serialization
/// \brief Reads an AST files chain containing the contents of a translation
/// unit.
@@ -334,8 +364,20 @@ class ASTReader
public ExternalSLocEntrySource
{
public:
- typedef SmallVector<uint64_t, 64> RecordData;
- typedef SmallVectorImpl<uint64_t> RecordDataImpl;
+ /// \brief Types of AST files.
+ friend class ASTDeclReader;
+ friend class ASTIdentifierIterator;
+ friend class ASTRecordReader;
+ friend class ASTStmtReader;
+ friend class ASTUnit; // ASTUnit needs to remap source locations.
+ friend class ASTWriter;
+ friend class PCHValidator;
+ friend class serialization::reader::ASTIdentifierLookupTrait;
+ friend class serialization::ReadMethodPoolVisitor;
+ friend class TypeLocReader;
+
+ using RecordData = SmallVector<uint64_t, 64>;
+ using RecordDataImpl = SmallVectorImpl<uint64_t>;
/// \brief The result of reading the control block of an AST file, which
/// can fail for various reasons.
@@ -343,41 +385,34 @@ public:
/// \brief The control block was read successfully. Aside from failures,
/// the AST file is safe to read into the current context.
Success,
+
/// \brief The AST file itself appears corrupted.
Failure,
+
/// \brief The AST file was missing.
Missing,
+
/// \brief The AST file is out-of-date relative to its input files,
/// and needs to be regenerated.
OutOfDate,
+
/// \brief The AST file was written by a different version of Clang.
VersionMismatch,
+
/// \brief The AST file was writtten with a different language/target
/// configuration.
ConfigurationMismatch,
+
/// \brief The AST file has errors.
HadErrors
};
- /// \brief Types of AST files.
- friend class PCHValidator;
- friend class ASTDeclReader;
- friend class ASTStmtReader;
- friend class ASTIdentifierIterator;
- friend class serialization::reader::ASTIdentifierLookupTrait;
- friend class TypeLocReader;
- friend class ASTRecordReader;
- friend class ASTWriter;
- friend class ASTUnit; // ASTUnit needs to remap source locations.
- friend class serialization::ReadMethodPoolVisitor;
-
- typedef serialization::ModuleFile ModuleFile;
- typedef serialization::ModuleKind ModuleKind;
- typedef serialization::ModuleManager ModuleManager;
-
- typedef ModuleManager::ModuleIterator ModuleIterator;
- typedef ModuleManager::ModuleConstIterator ModuleConstIterator;
- typedef ModuleManager::ModuleReverseIterator ModuleReverseIterator;
+ using ModuleFile = serialization::ModuleFile;
+ using ModuleKind = serialization::ModuleKind;
+ using ModuleManager = serialization::ModuleManager;
+ using ModuleIterator = ModuleManager::ModuleIterator;
+ using ModuleConstIterator = ModuleManager::ModuleConstIterator;
+ using ModuleReverseIterator = ModuleManager::ModuleReverseIterator;
private:
/// \brief The receiver of some callbacks invoked by ASTReader.
@@ -385,6 +420,7 @@ private:
/// \brief The receiver of deserialization events.
ASTDeserializationListener *DeserializationListener = nullptr;
+
bool OwnsDeserializationListener = false;
SourceManager &SourceMgr;
@@ -436,7 +472,8 @@ private:
/// \brief A map of negated SLocEntryIDs to the modules containing them.
ContinuousRangeMap<unsigned, ModuleFile*, 64> GlobalSLocEntryMap;
- typedef ContinuousRangeMap<unsigned, ModuleFile*, 64> GlobalSLocOffsetMapType;
+ using GlobalSLocOffsetMapType =
+ ContinuousRangeMap<unsigned, ModuleFile *, 64>;
/// \brief A map of reversed (SourceManager::MaxLoadedOffset - SLocOffset)
/// SourceLocation offsets to the modules containing them.
@@ -448,8 +485,8 @@ private:
/// ID = (I + 1) << FastQual::Width has already been loaded
std::vector<QualType> TypesLoaded;
- typedef ContinuousRangeMap<serialization::TypeID, ModuleFile *, 4>
- GlobalTypeMapType;
+ using GlobalTypeMapType =
+ ContinuousRangeMap<serialization::TypeID, ModuleFile *, 4>;
/// \brief Mapping from global type IDs to the module in which the
/// type resides along with the offset that should be added to the
@@ -462,17 +499,17 @@ private:
/// = I + 1 has already been loaded.
std::vector<Decl *> DeclsLoaded;
- typedef ContinuousRangeMap<serialization::DeclID, ModuleFile *, 4>
- GlobalDeclMapType;
+ using GlobalDeclMapType =
+ ContinuousRangeMap<serialization::DeclID, ModuleFile *, 4>;
/// \brief Mapping from global declaration IDs to the module in which the
/// declaration resides.
GlobalDeclMapType GlobalDeclMap;
- typedef std::pair<ModuleFile *, uint64_t> FileOffset;
- typedef SmallVector<FileOffset, 2> FileOffsetsTy;
- typedef llvm::DenseMap<serialization::DeclID, FileOffsetsTy>
- DeclUpdateOffsetsMap;
+ using FileOffset = std::pair<ModuleFile *, uint64_t>;
+ using FileOffsetsTy = SmallVector<FileOffset, 2>;
+ using DeclUpdateOffsetsMap =
+ llvm::DenseMap<serialization::DeclID, FileOffsetsTy>;
/// \brief Declarations that have modifications residing in a later file
/// in the chain.
@@ -481,12 +518,15 @@ private:
struct PendingUpdateRecord {
Decl *D;
serialization::GlobalDeclID ID;
+
// Whether the declaration was just deserialized.
bool JustLoaded;
+
PendingUpdateRecord(serialization::GlobalDeclID ID, Decl *D,
bool JustLoaded)
: D(D), ID(ID), JustLoaded(JustLoaded) {}
};
+
/// \brief Declaration updates for already-loaded declarations that we need
/// to apply once we finish processing an import.
llvm::SmallVector<PendingUpdateRecord, 16> PendingUpdateRecords;
@@ -505,7 +545,7 @@ private:
/// \brief Declarations that have been imported and have typedef names for
/// linkage purposes.
- llvm::DenseMap<std::pair<DeclContext*, IdentifierInfo*>, NamedDecl*>
+ llvm::DenseMap<std::pair<DeclContext *, IdentifierInfo *>, NamedDecl *>
ImportedTypedefNamesForLinkage;
/// \brief Mergeable declaration contexts that have anonymous declarations
@@ -514,10 +554,10 @@ private:
AnonymousDeclarationsForMerging;
struct FileDeclsInfo {
- ModuleFile *Mod;
+ ModuleFile *Mod = nullptr;
ArrayRef<serialization::LocalDeclID> Decls;
- FileDeclsInfo() : Mod(nullptr) {}
+ FileDeclsInfo() = default;
FileDeclsInfo(ModuleFile *Mod, ArrayRef<serialization::LocalDeclID> Decls)
: Mod(Mod), Decls(Decls) {}
};
@@ -527,7 +567,7 @@ private:
/// \brief An array of lexical contents of a declaration context, as a sequence of
/// Decl::Kind, DeclID pairs.
- typedef ArrayRef<llvm::support::unaligned_uint32_t> LexicalContents;
+ using LexicalContents = ArrayRef<llvm::support::unaligned_uint32_t>;
/// \brief Map from a DeclContext to its lexical contents.
llvm::DenseMap<const DeclContext*, std::pair<ModuleFile*, LexicalContents>>
@@ -548,7 +588,7 @@ private:
ModuleFile *Mod;
const unsigned char *Data;
};
- typedef SmallVector<PendingVisibleUpdate, 1> DeclContextVisibleUpdates;
+ using DeclContextVisibleUpdates = SmallVector<PendingVisibleUpdate, 1>;
/// \brief Updates to the visible declarations of declaration contexts that
/// haven't been loaded yet.
@@ -559,22 +599,23 @@ private:
/// declarations that have not yet been linked to their definitions.
llvm::SmallPtrSet<Decl *, 4> PendingDefinitions;
- typedef llvm::MapVector<Decl *, uint64_t,
- llvm::SmallDenseMap<Decl *, unsigned, 4>,
- SmallVector<std::pair<Decl *, uint64_t>, 4> >
- PendingBodiesMap;
+ using PendingBodiesMap =
+ llvm::MapVector<Decl *, uint64_t,
+ llvm::SmallDenseMap<Decl *, unsigned, 4>,
+ SmallVector<std::pair<Decl *, uint64_t>, 4>>;
/// \brief Functions or methods that have bodies that will be attached.
PendingBodiesMap PendingBodies;
/// \brief Definitions for which we have added merged definitions but not yet
/// performed deduplication.
- llvm::SetVector<NamedDecl*> PendingMergedDefinitionsToDeduplicate;
+ llvm::SetVector<NamedDecl *> PendingMergedDefinitionsToDeduplicate;
/// \brief Read the record that describes the lexical contents of a DC.
bool ReadLexicalDeclContextStorage(ModuleFile &M,
llvm::BitstreamCursor &Cursor,
uint64_t Offset, DeclContext *DC);
+
/// \brief Read the record that describes the visible contents of a DC.
bool ReadVisibleDeclContextStorage(ModuleFile &M,
llvm::BitstreamCursor &Cursor,
@@ -588,8 +629,8 @@ private:
/// been loaded.
std::vector<IdentifierInfo *> IdentifiersLoaded;
- typedef ContinuousRangeMap<serialization::IdentID, ModuleFile *, 4>
- GlobalIdentifierMapType;
+ using GlobalIdentifierMapType =
+ ContinuousRangeMap<serialization::IdentID, ModuleFile *, 4>;
/// \brief Mapping from global identifier IDs to the module in which the
/// identifier resides along with the offset that should be added to the
@@ -604,16 +645,16 @@ private:
/// been loaded.
std::vector<MacroInfo *> MacrosLoaded;
- typedef std::pair<IdentifierInfo *, serialization::SubmoduleID>
- LoadedMacroInfo;
+ using LoadedMacroInfo =
+ std::pair<IdentifierInfo *, serialization::SubmoduleID>;
/// \brief A set of #undef directives that we have loaded; used to
/// deduplicate the same #undef information coming from multiple module
/// files.
llvm::DenseSet<LoadedMacroInfo> LoadedUndefs;
- typedef ContinuousRangeMap<serialization::MacroID, ModuleFile *, 4>
- GlobalMacroMapType;
+ using GlobalMacroMapType =
+ ContinuousRangeMap<serialization::MacroID, ModuleFile *, 4>;
/// \brief Mapping from global macro IDs to the module in which the
/// macro resides along with the offset that should be added to the
@@ -626,8 +667,8 @@ private:
/// indicate that the particular submodule ID has not yet been loaded.
SmallVector<Module *, 2> SubmodulesLoaded;
- typedef ContinuousRangeMap<serialization::SubmoduleID, ModuleFile *, 4>
- GlobalSubmoduleMapType;
+ using GlobalSubmoduleMapType =
+ ContinuousRangeMap<serialization::SubmoduleID, ModuleFile *, 4>;
/// \brief Mapping from global submodule IDs to the module file in which the
/// submodule resides along with the offset that should be added to the
@@ -635,14 +676,13 @@ private:
GlobalSubmoduleMapType GlobalSubmoduleMap;
/// \brief A set of hidden declarations.
- typedef SmallVector<Decl*, 2> HiddenNames;
- typedef llvm::DenseMap<Module *, HiddenNames> HiddenNamesMapType;
+ using HiddenNames = SmallVector<Decl *, 2>;
+ using HiddenNamesMapType = llvm::DenseMap<Module *, HiddenNames>;
/// \brief A mapping from each of the hidden submodules to the deserialized
/// declarations in that submodule that could be made visible.
HiddenNamesMapType HiddenNamesMap;
-
/// \brief A module import, export, or conflict that hasn't yet been resolved.
struct UnresolvedModuleRef {
/// \brief The file in which this module resides.
@@ -675,11 +715,10 @@ private:
/// been loaded.
SmallVector<Selector, 16> SelectorsLoaded;
- typedef ContinuousRangeMap<serialization::SelectorID, ModuleFile *, 4>
- GlobalSelectorMapType;
+ using GlobalSelectorMapType =
+ ContinuousRangeMap<serialization::SelectorID, ModuleFile *, 4>;
/// \brief Mapping from global selector IDs to the module in which the
-
/// global selector ID to produce a local ID.
GlobalSelectorMapType GlobalSelectorMap;
@@ -699,15 +738,15 @@ private:
: M(M), MacroDirectivesOffset(MacroDirectivesOffset) {}
};
- typedef llvm::MapVector<IdentifierInfo *, SmallVector<PendingMacroInfo, 2> >
- PendingMacroIDsMap;
+ using PendingMacroIDsMap =
+ llvm::MapVector<IdentifierInfo *, SmallVector<PendingMacroInfo, 2>>;
/// \brief Mapping from identifiers that have a macro history to the global
/// IDs have not yet been deserialized to the global IDs of those macros.
PendingMacroIDsMap PendingMacroIDs;
- typedef ContinuousRangeMap<unsigned, ModuleFile *, 4>
- GlobalPreprocessedEntityMapType;
+ using GlobalPreprocessedEntityMapType =
+ ContinuousRangeMap<unsigned, ModuleFile *, 4>;
/// \brief Mapping from global preprocessing entity IDs to the module in
/// which the preprocessed entity resides along with the offset that should be
@@ -825,6 +864,7 @@ private:
struct PragmaPackStackEntry {
unsigned Value;
SourceLocation Location;
+ SourceLocation PushLocation;
StringRef SlotLabel;
};
llvm::SmallVector<PragmaPackStackEntry, 2> PragmaPackStack;
@@ -867,9 +907,6 @@ private:
SmallVector<ImportedSubmodule, 2> ImportedModules;
//@}
- /// \brief The directory that the PCH we are reading is stored in.
- std::string CurrentDir;
-
/// \brief The system include root to be used when loading the
/// precompiled header.
std::string isysroot;
@@ -897,7 +934,8 @@ private:
///\brief Whether we are currently processing update records.
bool ProcessingUpdateRecords = false;
- typedef llvm::DenseMap<unsigned, SwitchCase *> SwitchCaseMapTy;
+ using SwitchCaseMapTy = llvm::DenseMap<unsigned, SwitchCase *>;
+
/// \brief Mapping from switch-case IDs in the chain to switch-case statements
///
/// Statements usually don't have IDs, but switch cases need them, so that the
@@ -981,7 +1019,7 @@ private:
///
/// The declarations on the identifier chain for these identifiers will be
/// loaded once the recursive loading has completed.
- llvm::MapVector<IdentifierInfo *, SmallVector<uint32_t, 4> >
+ llvm::MapVector<IdentifierInfo *, SmallVector<uint32_t, 4>>
PendingIdentifierInfos;
/// \brief The set of lookup results that we have faked in order to support
@@ -1000,7 +1038,9 @@ private:
public:
InterestingDecl(Decl *D, bool HasBody)
: D(D), DeclHasPendingBody(HasBody) {}
+
Decl *getDecl() { return D; }
+
/// Whether the declaration has a pending body.
bool hasPendingBody() { return DeclHasPendingBody; }
};
@@ -1045,8 +1085,11 @@ private:
/// once recursing loading has been completed.
llvm::SmallVector<NamedDecl *, 16> PendingOdrMergeChecks;
+ using DataPointers =
+ std::pair<CXXRecordDecl *, struct CXXRecordDecl::DefinitionData *>;
+
/// \brief Record definitions in which we found an ODR violation.
- llvm::SmallDenseMap<CXXRecordDecl *, llvm::TinyPtrVector<CXXRecordDecl *>, 2>
+ llvm::SmallDenseMap<CXXRecordDecl *, llvm::SmallVector<DataPointers, 2>, 2>
PendingOdrMergeFailures;
/// \brief DeclContexts in which we have diagnosed an ODR violation.
@@ -1061,8 +1104,8 @@ private:
/// module is loaded.
SmallVector<ObjCInterfaceDecl *, 16> ObjCClassesLoaded;
- typedef llvm::DenseMap<Decl *, SmallVector<serialization::DeclID, 2> >
- KeyDeclsMap;
+ using KeyDeclsMap =
+ llvm::DenseMap<Decl *, SmallVector<serialization::DeclID, 2>>;
/// \brief A mapping from canonical declarations to the set of global
/// declaration IDs for key declaration that have been merged with that
@@ -1096,15 +1139,14 @@ private:
ASTReader &Reader;
enum ReadingKind PrevKind;
- ReadingKindTracker(const ReadingKindTracker &) = delete;
- void operator=(const ReadingKindTracker &) = delete;
-
public:
ReadingKindTracker(enum ReadingKind newKind, ASTReader &reader)
: Reader(reader), PrevKind(Reader.ReadingKind) {
Reader.ReadingKind = newKind;
}
+ ReadingKindTracker(const ReadingKindTracker &) = delete;
+ ReadingKindTracker &operator=(const ReadingKindTracker &) = delete;
~ReadingKindTracker() { Reader.ReadingKind = PrevKind; }
};
@@ -1113,15 +1155,15 @@ private:
ASTReader &Reader;
bool PrevState;
- ProcessingUpdatesRAIIObj(const ProcessingUpdatesRAIIObj &) = delete;
- void operator=(const ProcessingUpdatesRAIIObj &) = delete;
-
public:
ProcessingUpdatesRAIIObj(ASTReader &reader)
: Reader(reader), PrevState(Reader.ProcessingUpdateRecords) {
Reader.ProcessingUpdateRecords = true;
}
+ ProcessingUpdatesRAIIObj(const ProcessingUpdatesRAIIObj &) = delete;
+ ProcessingUpdatesRAIIObj &
+ operator=(const ProcessingUpdatesRAIIObj &) = delete;
~ProcessingUpdatesRAIIObj() { Reader.ProcessingUpdateRecords = PrevState; }
};
@@ -1135,7 +1177,7 @@ private:
/// predefines buffer may contain additional definitions.
std::string SuggestedPredefines;
- llvm::DenseMap<const Decl *, bool> BodySource;
+ llvm::DenseMap<const Decl *, bool> DefinitionSource;
/// \brief Reads a statement from the specified cursor.
Stmt *ReadStmtFromStream(ModuleFile &F);
@@ -1204,7 +1246,7 @@ private:
ImportedModule(ModuleFile *Mod,
ModuleFile *ImportedBy,
SourceLocation ImportLoc)
- : Mod(Mod), ImportedBy(ImportedBy), ImportLoc(ImportLoc) { }
+ : Mod(Mod), ImportedBy(ImportedBy), ImportLoc(ImportLoc) {}
};
ASTReadResult ReadASTCore(StringRef FileName, ModuleKind Type,
@@ -1265,10 +1307,11 @@ private:
std::string &SuggestedPredefines);
struct RecordLocation {
- RecordLocation(ModuleFile *M, uint64_t O)
- : F(M), Offset(O) {}
ModuleFile *F;
uint64_t Offset;
+
+ RecordLocation(ModuleFile *M, uint64_t O)
+ : F(M), Offset(O) {}
};
QualType readTypeRecord(unsigned Index);
@@ -1327,12 +1370,11 @@ public:
ModuleDeclIterator, const serialization::LocalDeclID *,
std::random_access_iterator_tag, const Decl *, ptrdiff_t,
const Decl *, const Decl *> {
- ASTReader *Reader;
- ModuleFile *Mod;
+ ASTReader *Reader = nullptr;
+ ModuleFile *Mod = nullptr;
public:
- ModuleDeclIterator()
- : iterator_adaptor_base(nullptr), Reader(nullptr), Mod(nullptr) {}
+ ModuleDeclIterator() : iterator_adaptor_base(nullptr) {}
ModuleDeclIterator(ASTReader *Reader, ModuleFile *Mod,
const serialization::LocalDeclID *Pos)
@@ -1341,6 +1383,7 @@ public:
value_type operator*() const {
return Reader->GetDecl(Reader->getGlobalDeclID(*Mod, *I));
}
+
value_type operator->() const { return **this; }
bool operator==(const ModuleDeclIterator &RHS) const {
@@ -1377,8 +1420,6 @@ private:
void Error(unsigned DiagID, StringRef Arg1 = StringRef(),
StringRef Arg2 = StringRef()) const;
- ASTReader(const ASTReader &) = delete;
- void operator=(const ASTReader &) = delete;
public:
/// \brief Load the AST file and validate its contents against the given
/// Preprocessor.
@@ -1427,7 +1468,8 @@ public:
bool AllowConfigurationMismatch = false,
bool ValidateSystemInputs = false, bool UseGlobalIndex = true,
std::unique_ptr<llvm::Timer> ReadTimer = {});
-
+ ASTReader(const ASTReader &) = delete;
+ ASTReader &operator=(const ASTReader &) = delete;
~ASTReader() override;
SourceManager &getSourceManager() const { return SourceMgr; }
@@ -1442,15 +1484,19 @@ public:
enum LoadFailureCapabilities {
/// \brief The client can't handle any AST loading failures.
ARR_None = 0,
+
/// \brief The client can handle an AST file that cannot load because it
/// is missing.
ARR_Missing = 0x1,
+
/// \brief The client can handle an AST file that cannot load because it
/// is out-of-date relative to its input files.
ARR_OutOfDate = 0x2,
+
/// \brief The client can handle an AST file that cannot load because it
/// was built with a different version of Clang.
ARR_VersionMismatch = 0x4,
+
/// \brief The client can handle an AST file that cannot load because it's
/// compiled configuration doesn't match that of the context it was
/// loaded into.
@@ -1521,11 +1567,11 @@ public:
/// RAII object to temporarily add an AST callback listener.
class ListenerScope {
ASTReader &Reader;
- bool Chained;
+ bool Chained = false;
public:
ListenerScope(ASTReader &Reader, std::unique_ptr<ASTReaderListener> L)
- : Reader(Reader), Chained(false) {
+ : Reader(Reader) {
auto Old = Reader.takeListener();
if (Old) {
Chained = true;
@@ -1534,6 +1580,7 @@ public:
}
Reader.setListener(std::move(L));
}
+
~ListenerScope() {
auto New = Reader.takeListener();
if (Chained)
@@ -1932,16 +1979,16 @@ public:
llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) override;
void ReadReferencedSelectors(
- SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels) override;
+ SmallVectorImpl<std::pair<Selector, SourceLocation>> &Sels) override;
void ReadWeakUndeclaredIdentifiers(
- SmallVectorImpl<std::pair<IdentifierInfo *, WeakInfo> > &WI) override;
+ SmallVectorImpl<std::pair<IdentifierInfo *, WeakInfo>> &WI) override;
void ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables) override;
void ReadPendingInstantiations(
- SmallVectorImpl<std::pair<ValueDecl *,
- SourceLocation> > &Pending) override;
+ SmallVectorImpl<std::pair<ValueDecl *,
+ SourceLocation>> &Pending) override;
void ReadLateParsedTemplates(
llvm::MapVector<const FunctionDecl *, std::unique_ptr<LateParsedTemplate>>
@@ -2144,9 +2191,19 @@ public:
// \brief Read a string
static std::string ReadString(const RecordData &Record, unsigned &Idx);
+ // \brief Skip a string
+ static void SkipString(const RecordData &Record, unsigned &Idx) {
+ Idx += Record[Idx] + 1;
+ }
+
// \brief Read a path
std::string ReadPath(ModuleFile &F, const RecordData &Record, unsigned &Idx);
+ // \brief Skip a path
+ static void SkipPath(const RecordData &Record, unsigned &Idx) {
+ SkipString(Record, Idx);
+ }
+
/// \brief Read a version tuple.
static VersionTuple ReadVersionTuple(const RecordData &Record, unsigned &Idx);
@@ -2264,20 +2321,19 @@ public:
/// \brief An object for streaming information from a record.
class ASTRecordReader {
- typedef serialization::ModuleFile ModuleFile;
+ using ModuleFile = serialization::ModuleFile;
ASTReader *Reader;
ModuleFile *F;
unsigned Idx = 0;
ASTReader::RecordData Record;
- typedef ASTReader::RecordData RecordData;
- typedef ASTReader::RecordDataImpl RecordDataImpl;
+ using RecordData = ASTReader::RecordData;
+ using RecordDataImpl = ASTReader::RecordDataImpl;
public:
/// Construct an ASTRecordReader that uses the default encoding scheme.
- ASTRecordReader(ASTReader &Reader, ModuleFile &F)
- : Reader(&Reader), F(&F) {}
+ ASTRecordReader(ASTReader &Reader, ModuleFile &F) : Reader(&Reader), F(&F) {}
/// \brief Reads a record with id AbbrevID from Cursor, resetting the
/// internal state.
@@ -2291,17 +2347,20 @@ public:
/// \brief The current position in this record.
unsigned getIdx() const { return Idx; }
+
/// \brief The length of this record.
size_t size() const { return Record.size(); }
/// \brief An arbitrary index in this record.
const uint64_t &operator[](size_t N) { return Record[N]; }
+
/// \brief The last element in this record.
const uint64_t &back() const { return Record.back(); }
/// \brief Returns the current value in this record, and advances to the
/// next value.
const uint64_t &readInt() { return Record[Idx++]; }
+
/// \brief Returns the current value in this record, without advancing.
const uint64_t &peekInt() { return Record[Idx]; }
@@ -2555,7 +2614,7 @@ public:
/// then restores it when destroyed.
struct SavedStreamPosition {
explicit SavedStreamPosition(llvm::BitstreamCursor &Cursor)
- : Cursor(Cursor), Offset(Cursor.GetCurrentBitNo()) { }
+ : Cursor(Cursor), Offset(Cursor.GetCurrentBitNo()) {}
~SavedStreamPosition() {
Cursor.JumpToBit(Offset);
@@ -2570,6 +2629,6 @@ inline void PCHValidator::Error(const char *Msg) {
Reader.Error(Msg);
}
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_SERIALIZATION_ASTREADER_H
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h
index f14dfc73baa98..9437bf7f2c9f1 100644
--- a/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h
@@ -1,4 +1,4 @@
-//===--- ASTWriter.h - AST File Writer --------------------------*- C++ -*-===//
+//===- ASTWriter.h - AST File Writer ----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,67 +11,89 @@
// containing a serialized representation of a translation unit.
//
//===----------------------------------------------------------------------===//
+
#ifndef LLVM_CLANG_SERIALIZATION_ASTWRITER_H
#define LLVM_CLANG_SERIALIZATION_ASTWRITER_H
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TemplateBase.h"
+#include "clang/AST/TemplateName.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/Sema/SemaConsumer.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Serialization/ASTDeserializationListener.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Bitcode/BitstreamWriter.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <ctime>
+#include <memory>
#include <queue>
+#include <string>
+#include <utility>
#include <vector>
namespace llvm {
- class APFloat;
- class APInt;
-}
+
+class APFloat;
+class APInt;
+class APSInt;
+
+} // namespace llvm
namespace clang {
-class DeclarationName;
class ASTContext;
+class ASTReader;
+class ASTUnresolvedSet;
class Attr;
-class NestedNameSpecifier;
class CXXBaseSpecifier;
class CXXCtorInitializer;
+class CXXRecordDecl;
+class CXXTemporary;
class FileEntry;
class FPOptions;
+class FunctionDecl;
class HeaderSearch;
class HeaderSearchOptions;
class IdentifierResolver;
+class LangOptions;
class MacroDefinitionRecord;
-class MacroDirective;
class MacroInfo;
-class OpaqueValueExpr;
-class OpenCLOptions;
-class ASTReader;
class MemoryBufferCache;
class Module;
class ModuleFileExtension;
class ModuleFileExtensionWriter;
-class PreprocessedEntity;
+class NamedDecl;
+class NestedNameSpecifier;
+class ObjCInterfaceDecl;
class PreprocessingRecord;
class Preprocessor;
+struct QualifierInfo;
class RecordDecl;
class Sema;
class SourceManager;
+class Stmt;
struct StoredDeclsList;
class SwitchCase;
-class TargetInfo;
+class TemplateParameterList;
class Token;
+class TypeSourceInfo;
class VersionTuple;
-class ASTUnresolvedSet;
-
-namespace SrcMgr { class SLocEntry; }
/// \brief Writes an AST file containing the contents of a translation unit.
///
@@ -82,14 +104,15 @@ namespace SrcMgr { class SLocEntry; }
class ASTWriter : public ASTDeserializationListener,
public ASTMutationListener {
public:
- typedef SmallVector<uint64_t, 64> RecordData;
- typedef SmallVectorImpl<uint64_t> RecordDataImpl;
- typedef ArrayRef<uint64_t> RecordDataRef;
-
friend class ASTDeclWriter;
+ friend class ASTRecordWriter;
friend class ASTStmtWriter;
friend class ASTTypeWriter;
- friend class ASTRecordWriter;
+
+ using RecordData = SmallVector<uint64_t, 64>;
+ using RecordDataImpl = SmallVectorImpl<uint64_t>;
+ using RecordDataRef = ArrayRef<uint64_t>;
+
private:
/// \brief Map that provides the ID numbers of each type within the
/// output stream, plus those deserialized from a chained PCH.
@@ -100,9 +123,8 @@ private:
/// allow for the const/volatile qualifiers.
///
/// Keys in the map never have const/volatile qualifiers.
- typedef llvm::DenseMap<QualType, serialization::TypeIdx,
- serialization::UnsafeQualTypeDenseMapInfo>
- TypeIdxMap;
+ using TypeIdxMap = llvm::DenseMap<QualType, serialization::TypeIdx,
+ serialization::UnsafeQualTypeDenseMapInfo>;
/// \brief The bitstream writer used to emit this precompiled header.
llvm::BitstreamWriter &Stream;
@@ -152,8 +174,8 @@ private:
/// \brief Stores a declaration or a type to be written to the AST file.
class DeclOrType {
public:
- DeclOrType(Decl *D) : Stored(D), IsType(false) { }
- DeclOrType(QualType T) : Stored(T.getAsOpaquePtr()), IsType(true) { }
+ DeclOrType(Decl *D) : Stored(D), IsType(false) {}
+ DeclOrType(QualType T) : Stored(T.getAsOpaquePtr()), IsType(true) {}
bool isType() const { return IsType; }
bool isDecl() const { return !IsType; }
@@ -195,15 +217,16 @@ private:
std::vector<serialization::DeclOffset> DeclOffsets;
/// \brief Sorted (by file offset) vector of pairs of file offset/DeclID.
- typedef SmallVector<std::pair<unsigned, serialization::DeclID>, 64>
- LocDeclIDsTy;
+ using LocDeclIDsTy =
+ SmallVector<std::pair<unsigned, serialization::DeclID>, 64>;
struct DeclIDInFileInfo {
LocDeclIDsTy DeclIDs;
+
/// \brief Set when the DeclIDs vectors from all files are joined, this
/// indicates the index that this particular vector has in the global one.
unsigned FirstDeclIndex;
};
- typedef llvm::DenseMap<FileID, DeclIDInFileInfo *> FileDeclIDsTy;
+ using FileDeclIDsTy = llvm::DenseMap<FileID, DeclIDInFileInfo *>;
/// \brief Map from file SLocEntries to info about the file-level declarations
/// that it contains.
@@ -260,6 +283,7 @@ private:
MacroInfo *MI;
serialization::MacroID ID;
};
+
/// \brief The macro infos to emit.
std::vector<MacroInfoToEmitData> MacroInfosToEmit;
@@ -331,31 +355,33 @@ private:
: Kind(Kind), Type(Type.getAsOpaquePtr()) {}
DeclUpdate(unsigned Kind, SourceLocation Loc)
: Kind(Kind), Loc(Loc.getRawEncoding()) {}
- DeclUpdate(unsigned Kind, unsigned Val)
- : Kind(Kind), Val(Val) {}
- DeclUpdate(unsigned Kind, Module *M)
- : Kind(Kind), Mod(M) {}
+ DeclUpdate(unsigned Kind, unsigned Val) : Kind(Kind), Val(Val) {}
+ DeclUpdate(unsigned Kind, Module *M) : Kind(Kind), Mod(M) {}
DeclUpdate(unsigned Kind, const Attr *Attribute)
: Kind(Kind), Attribute(Attribute) {}
unsigned getKind() const { return Kind; }
const Decl *getDecl() const { return Dcl; }
QualType getType() const { return QualType::getFromOpaquePtr(Type); }
+
SourceLocation getLoc() const {
return SourceLocation::getFromRawEncoding(Loc);
}
+
unsigned getNumber() const { return Val; }
Module *getModule() const { return Mod; }
const Attr *getAttr() const { return Attribute; }
};
- typedef SmallVector<DeclUpdate, 1> UpdateRecord;
- typedef llvm::MapVector<const Decl *, UpdateRecord> DeclUpdateMap;
+ using UpdateRecord = SmallVector<DeclUpdate, 1>;
+ using DeclUpdateMap = llvm::MapVector<const Decl *, UpdateRecord>;
+
/// \brief Mapping from declarations that came from a chained PCH to the
/// record containing modifications to them.
DeclUpdateMap DeclUpdates;
- typedef llvm::DenseMap<Decl *, Decl *> FirstLatestDeclMap;
+ using FirstLatestDeclMap = llvm::DenseMap<Decl *, Decl *>;
+
/// \brief Map of first declarations from a chained PCH that point to the
/// most recent declarations in another PCH.
FirstLatestDeclMap FirstLatestDecls;
@@ -600,7 +626,6 @@ public:
/// \brief Emit a reference to a declaration.
void AddDeclRef(const Decl *D, RecordDataImpl &Record);
-
/// \brief Force a declaration to be emitted and get its ID.
serialization::DeclID GetDeclRef(const Decl *D);
@@ -651,6 +676,7 @@ public:
unsigned getTypeExtQualAbbrev() const {
return TypeExtQualAbbrev;
}
+
unsigned getTypeFunctionProtoAbbrev() const {
return TypeFunctionProtoAbbrev;
}
@@ -698,12 +724,14 @@ private:
void ResolvedExceptionSpec(const FunctionDecl *FD) override;
void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) override;
void ResolvedOperatorDelete(const CXXDestructorDecl *DD,
- const FunctionDecl *Delete) override;
+ const FunctionDecl *Delete,
+ Expr *ThisArg) override;
void CompletedImplicitDefinition(const FunctionDecl *D) override;
- void StaticDataMemberInstantiated(const VarDecl *D) override;
+ void InstantiationRequested(const ValueDecl *D) override;
+ void VariableDefinitionInstantiated(const VarDecl *D) override;
+ void FunctionDefinitionInstantiated(const FunctionDecl *D) override;
void DefaultArgumentInstantiated(const ParmVarDecl *D) override;
void DefaultMemberInitializerInstantiated(const FieldDecl *D) override;
- void FunctionDefinitionInstantiated(const FunctionDecl *D) override;
void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
const ObjCInterfaceDecl *IFD) override;
void DeclarationMarkedUsed(const Decl *D) override;
@@ -756,8 +784,8 @@ public:
: Writer(Parent.Writer), Record(&Record) {}
/// Copying an ASTRecordWriter is almost certainly a bug.
- ASTRecordWriter(const ASTRecordWriter&) = delete;
- void operator=(const ASTRecordWriter&) = delete;
+ ASTRecordWriter(const ASTRecordWriter &) = delete;
+ ASTRecordWriter &operator=(const ASTRecordWriter &) = delete;
/// \brief Extract the underlying record storage.
ASTWriter::RecordDataImpl &getRecordData() const { return *Record; }
@@ -909,7 +937,7 @@ public:
void AddUnresolvedSet(const ASTUnresolvedSet &Set);
/// \brief Emit a CXXCtorInitializer array.
- void AddCXXCtorInitializers(ArrayRef<CXXCtorInitializer*> CtorInits);
+ void AddCXXCtorInitializers(ArrayRef<CXXCtorInitializer *> CtorInits);
void AddCXXDefinitionData(const CXXRecordDecl *D);
@@ -955,6 +983,7 @@ public:
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
bool AllowASTWithErrors = false, bool IncludeTimestamps = true);
~PCHGenerator() override;
+
void InitializeSema(Sema &S) override { SemaPtr = &S; }
void HandleTranslationUnit(ASTContext &Ctx) override;
ASTMutationListener *GetASTMutationListener() override;
@@ -962,6 +991,6 @@ public:
bool hasEmittedPCH() const { return Buffer->IsComplete; }
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_SERIALIZATION_ASTWRITER_H
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ContinuousRangeMap.h b/contrib/llvm/tools/clang/include/clang/Serialization/ContinuousRangeMap.h
index 244b01b22aa18..24bfadd0f8677 100644
--- a/contrib/llvm/tools/clang/include/clang/Serialization/ContinuousRangeMap.h
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ContinuousRangeMap.h
@@ -1,4 +1,4 @@
-//===--- ContinuousRangeMap.h - Map with int range as key -------*- C++ -*-===//
+//===- ContinuousRangeMap.h - Map with int range as key ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -18,6 +18,7 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/SmallVector.h"
#include <algorithm>
+#include <cassert>
#include <utility>
namespace clang {
@@ -35,14 +36,15 @@ namespace clang {
template <typename Int, typename V, unsigned InitialCapacity>
class ContinuousRangeMap {
public:
- typedef std::pair<Int, V> value_type;
- typedef value_type &reference;
- typedef const value_type &const_reference;
- typedef value_type *pointer;
- typedef const value_type *const_pointer;
+ using value_type = std::pair<Int, V>;
+ using reference = value_type &;
+ using const_reference = const value_type &;
+ using pointer = value_type *;
+ using const_pointer = const value_type *;
private:
- typedef SmallVector<value_type, InitialCapacity> Representation;
+ using Representation = SmallVector<value_type, InitialCapacity>;
+
Representation Rep;
struct Compare {
@@ -52,7 +54,7 @@ private:
bool operator ()(Int L, const_reference R) const {
return L < R.first;
}
- bool operator ()(Int L, Int R) const {
+ bool operator ()(Int L, Int R) const {
return L < R;
}
bool operator ()(const_reference L, const_reference R) const {
@@ -80,8 +82,8 @@ public:
Rep.insert(I, Val);
}
- typedef typename Representation::iterator iterator;
- typedef typename Representation::const_iterator const_iterator;
+ using iterator = typename Representation::iterator;
+ using const_iterator = typename Representation::const_iterator;
iterator begin() { return Rep.begin(); }
iterator end() { return Rep.end(); }
@@ -108,13 +110,12 @@ public:
/// from a set of values.
class Builder {
ContinuousRangeMap &Self;
-
+
+ public:
+ explicit Builder(ContinuousRangeMap &Self) : Self(Self) {}
Builder(const Builder&) = delete;
Builder &operator=(const Builder&) = delete;
- public:
- explicit Builder(ContinuousRangeMap &Self) : Self(Self) { }
-
~Builder() {
std::sort(Self.Rep.begin(), Self.Rep.end(), Compare());
std::unique(Self.Rep.begin(), Self.Rep.end(),
@@ -131,9 +132,10 @@ public:
Self.Rep.push_back(Val);
}
};
+
friend class Builder;
};
-}
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_SERIALIZATION_CONTINUOUSRANGEMAP_H
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ModuleManager.h b/contrib/llvm/tools/clang/include/clang/Serialization/ModuleManager.h
index fae387cac7e21..147a6910aa295 100644
--- a/contrib/llvm/tools/clang/include/clang/Serialization/ModuleManager.h
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ModuleManager.h
@@ -1,4 +1,4 @@
-//===--- ModuleManager.cpp - Module Manager ---------------------*- C++ -*-===//
+//===- ModuleManager.cpp - Module Manager -----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,15 +15,30 @@
#ifndef LLVM_CLANG_SERIALIZATION_MODULEMANAGER_H
#define LLVM_CLANG_SERIALIZATION_MODULEMANAGER_H
-#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/Module.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Serialization/Module.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/iterator_range.h"
+#include <cstdint>
+#include <ctime>
+#include <memory>
+#include <string>
+#include <utility>
-namespace clang {
+namespace clang {
+class FileEntry;
+class FileManager;
class GlobalModuleIndex;
+class HeaderSearch;
class MemoryBufferCache;
class ModuleMap;
class PCHContainerReader;
@@ -58,6 +73,9 @@ class ModuleManager {
/// \brief Knows how to unwrap module containers.
const PCHContainerReader &PCHContainerRdr;
+ /// \brief Preprocessor's HeaderSearchInfo containing the module map.
+ const HeaderSearch &HeaderSearchInfo;
+
/// \brief A lookup of in-memory (virtual file) buffers
llvm::DenseMap<const FileEntry *, std::unique_ptr<llvm::MemoryBuffer>>
InMemoryBuffers;
@@ -79,14 +97,12 @@ class ModuleManager {
///
/// The global module index will actually be owned by the ASTReader; this is
/// just an non-owning pointer.
- GlobalModuleIndex *GlobalIndex;
+ GlobalModuleIndex *GlobalIndex = nullptr;
/// \brief State used by the "visit" operation to avoid malloc traffic in
/// calls to visit().
struct VisitState {
- explicit VisitState(unsigned N)
- : VisitNumber(N, 0), NextVisitNumber(1), NextState(nullptr)
- {
+ explicit VisitState(unsigned N) : VisitNumber(N, 0) {
Stack.reserve(N);
}
@@ -103,46 +119,47 @@ class ModuleManager {
SmallVector<unsigned, 4> VisitNumber;
/// \brief The next visit number to use to mark visited module files.
- unsigned NextVisitNumber;
+ unsigned NextVisitNumber = 1;
/// \brief The next visit state.
- VisitState *NextState;
+ VisitState *NextState = nullptr;
};
/// \brief The first visit() state in the chain.
- VisitState *FirstVisitState;
+ VisitState *FirstVisitState = nullptr;
VisitState *allocateVisitState();
void returnVisitState(VisitState *State);
public:
- typedef llvm::pointee_iterator<
- SmallVectorImpl<std::unique_ptr<ModuleFile>>::iterator>
- ModuleIterator;
- typedef llvm::pointee_iterator<
- SmallVectorImpl<std::unique_ptr<ModuleFile>>::const_iterator>
- ModuleConstIterator;
- typedef llvm::pointee_iterator<
- SmallVectorImpl<std::unique_ptr<ModuleFile>>::reverse_iterator>
- ModuleReverseIterator;
- typedef std::pair<uint32_t, StringRef> ModuleOffset;
+ using ModuleIterator = llvm::pointee_iterator<
+ SmallVectorImpl<std::unique_ptr<ModuleFile>>::iterator>;
+ using ModuleConstIterator = llvm::pointee_iterator<
+ SmallVectorImpl<std::unique_ptr<ModuleFile>>::const_iterator>;
+ using ModuleReverseIterator = llvm::pointee_iterator<
+ SmallVectorImpl<std::unique_ptr<ModuleFile>>::reverse_iterator>;
+ using ModuleOffset = std::pair<uint32_t, StringRef>;
explicit ModuleManager(FileManager &FileMgr, MemoryBufferCache &PCMCache,
- const PCHContainerReader &PCHContainerRdr);
+ const PCHContainerReader &PCHContainerRdr,
+ const HeaderSearch &HeaderSearchInfo);
~ModuleManager();
/// \brief Forward iterator to traverse all loaded modules.
ModuleIterator begin() { return Chain.begin(); }
+
/// \brief Forward iterator end-point to traverse all loaded modules
ModuleIterator end() { return Chain.end(); }
/// \brief Const forward iterator to traverse all loaded modules.
ModuleConstIterator begin() const { return Chain.begin(); }
+
/// \brief Const forward iterator end-point to traverse all loaded modules
ModuleConstIterator end() const { return Chain.end(); }
/// \brief Reverse iterator to traverse all loaded modules.
ModuleReverseIterator rbegin() { return Chain.rbegin(); }
+
/// \brief Reverse iterator end-point to traverse all loaded modules.
ModuleReverseIterator rend() { return Chain.rend(); }
@@ -163,8 +180,11 @@ public:
/// \brief Returns the module associated with the given index
ModuleFile &operator[](unsigned Index) const { return *Chain[Index]; }
- /// \brief Returns the module associated with the given name
- ModuleFile *lookup(StringRef Name) const;
+ /// \brief Returns the module associated with the given file name.
+ ModuleFile *lookupByFileName(StringRef FileName) const;
+
+ /// \brief Returns the module associated with the given module name.
+ ModuleFile *lookupByModuleName(StringRef ModName) const;
/// \brief Returns the module associated with the given module file.
ModuleFile *lookup(const FileEntry *File) const;
@@ -179,15 +199,18 @@ public:
enum AddModuleResult {
/// \brief The module file had already been loaded.
AlreadyLoaded,
+
/// \brief The module file was just loaded in response to this call.
NewlyLoaded,
+
/// \brief The module file is missing.
Missing,
+
/// \brief The module file is out-of-date.
OutOfDate
};
- typedef ASTFileSignature(*ASTFileSignatureReader)(StringRef);
+ using ASTFileSignatureReader = ASTFileSignature (*)(StringRef);
/// \brief Attempts to create a new module and add it to the list of known
/// modules.
@@ -298,6 +321,8 @@ public:
MemoryBufferCache &getPCMCache() const { return *PCMCache; }
};
-} } // end namespace clang::serialization
+} // namespace serialization
+
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_SERIALIZATION_MODULEMANAGER_H
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index 82ab720af8dc7..e510e84e938af 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -132,6 +132,10 @@ def DynamicTypePropagation : Checker<"DynamicTypePropagation">,
HelpText<"Generate dynamic type information">,
DescFile<"DynamicTypePropagation.cpp">;
+def NonnullGlobalConstantsChecker: Checker<"NonnilStringConstants">,
+ HelpText<"Assume that const string-like globals are non-null">,
+ DescFile<"NonilStringConstantsChecker.cpp">;
+
} // end "core"
let ParentPackage = CoreAlpha in {
@@ -184,6 +188,10 @@ def DynamicTypeChecker : Checker<"DynamicTypeChecker">,
HelpText<"Check for cases where the dynamic and the static type of an object are unrelated.">,
DescFile<"DynamicTypeChecker.cpp">;
+def StackAddrAsyncEscapeChecker : Checker<"StackAddressAsyncEscape">,
+ HelpText<"Check that addresses to stack memory do not escape the function">,
+ DescFile<"StackAddrEscapeChecker.cpp">;
+
} // end "alpha.core"
let ParentPackage = Nullability in {
@@ -284,6 +292,11 @@ def VirtualCallChecker : Checker<"VirtualCall">,
let ParentPackage = CplusplusAlpha in {
+def DeleteWithNonVirtualDtorChecker : Checker<"DeleteWithNonVirtualDtor">,
+ HelpText<"Reports destructions of polymorphic objects with a non-virtual "
+ "destructor in their base class">,
+ DescFile<"DeleteWithNonVirtualDtorChecker.cpp">;
+
def IteratorRangeChecker : Checker<"IteratorRange">,
HelpText<"Check for iterators used outside their valid ranges">,
DescFile<"IteratorChecker.cpp">;
@@ -740,10 +753,6 @@ def ExplodedGraphViewer : Checker<"ViewExplodedGraph">,
HelpText<"View Exploded Graphs using GraphViz">,
DescFile<"DebugCheckers.cpp">;
-def BugHashDumper : Checker<"DumpBugHash">,
- HelpText<"Dump the bug hash for all statements.">,
- DescFile<"DebugCheckers.cpp">;
-
} // end "debug"
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h
index 25886545e2f7b..e5e857e970297 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h
@@ -145,9 +145,11 @@ public:
/// Indicates that the tracked object is an Objective-C object.
ObjC,
/// Indicates that the tracked object could be a CF or Objective-C object.
- AnyObj
+ AnyObj,
+ /// Indicates that the tracked object is a generalized object.
+ Generalized
};
-
+
private:
Kind K;
ObjKind O;
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Analyses.def b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Analyses.def
index 04bf41bfde4f0..281a2ac3a66fe 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Analyses.def
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Analyses.def
@@ -28,9 +28,10 @@ ANALYSIS_CONSTRAINTS(Z3Constraints, "z3", "Use Z3 contraint solver", CreateZ3Con
#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN)
#endif
-ANALYSIS_DIAGNOSTICS(HTML, "html", "Output analysis results using HTML", createHTMLDiagnosticConsumer)
+ANALYSIS_DIAGNOSTICS(HTML, "html", "Output analysis results using HTML", createHTMLDiagnosticConsumer)
+ANALYSIS_DIAGNOSTICS(HTML_SINGLE_FILE, "html-single-file", "Output analysis results using HTML (not allowing for multi-file bugs)", createHTMLSingleFileDiagnosticConsumer)
ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists", createPlistDiagnosticConsumer)
-ANALYSIS_DIAGNOSTICS(PLIST_MULTI_FILE, "plist-multi-file", "Output analysis results using Plists (allowing for mult-file bugs)", createPlistMultiFileDiagnosticConsumer)
+ANALYSIS_DIAGNOSTICS(PLIST_MULTI_FILE, "plist-multi-file", "Output analysis results using Plists (allowing for multi-file bugs)", createPlistMultiFileDiagnosticConsumer)
ANALYSIS_DIAGNOSTICS(PLIST_HTML, "plist-html", "Output analysis results using HTML wrapped with Plists", createPlistHTMLDiagnosticConsumer)
ANALYSIS_DIAGNOSTICS(TEXT, "text", "Text output of analysis results", createTextPathDiagnosticConsumer)
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
index 5dd6bdf384968..ce50cc582d1e0 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
@@ -214,6 +214,9 @@ private:
/// \sa IncludeLifetimeInCFG
Optional<bool> IncludeLifetimeInCFG;
+ /// \sa IncludeLoopExitInCFG
+ Optional<bool> IncludeLoopExitInCFG;
+
/// \sa mayInlineCXXStandardLibrary
Optional<bool> InlineCXXStandardLibrary;
@@ -275,6 +278,9 @@ private:
/// \sa shouldWidenLoops
Optional<bool> WidenLoops;
+ /// \sa shouldUnrollLoops
+ Optional<bool> UnrollLoops;
+
/// \sa shouldDisplayNotesAsEvents
Optional<bool> DisplayNotesAsEvents;
@@ -415,6 +421,13 @@ public:
/// the values "true" and "false".
bool includeLifetimeInCFG();
+ /// Returns whether or not the end of the loop information should be included
+ /// in the CFG.
+ ///
+ /// This is controlled by the 'cfg-loopexit' config option, which accepts
+ /// the values "true" and "false".
+ bool includeLoopExitInCFG();
+
/// Returns whether or not C++ standard library functions may be considered
/// for inlining.
///
@@ -560,6 +573,10 @@ public:
/// This is controlled by the 'widen-loops' config option.
bool shouldWidenLoops();
+ /// Returns true if the analysis should try to unroll loops with known bounds.
+ /// This is controlled by the 'unroll-loops' config option.
+ bool shouldUnrollLoops();
+
/// Returns true if the bug reporter should transparently treat extra note
/// diagnostic pieces as event diagnostic pieces. Useful when the diagnostic
/// consumer doesn't support the extra note pieces.
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
index 0f1eb096c4958..cd1355d03b639 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
@@ -17,7 +17,7 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
-#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
index b72bce5fc9f82..2043896fd26fe 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
@@ -1,4 +1,4 @@
-//===--- BugReporterVisitor.h - Generate PathDiagnostics -------*- C++ -*-===//
+//===--- BugReporterVisitors.h - Generate PathDiagnostics -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITOR_H
-#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITOR_H
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITORS_H
+#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITORS_H
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "llvm/ADT/FoldingSet.h"
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
index 3e0913ec4eeaa..15b930bc3f1eb 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
@@ -15,7 +15,7 @@
#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_ANALYSISMANAGER_H
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_ANALYSISMANAGER_H
-#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
index fa7ee62ab704d..9fec217aca725 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
@@ -19,7 +19,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
-#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Basic/SourceManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
@@ -436,20 +436,7 @@ public:
return cast<FunctionDecl>(CallEvent::getDecl());
}
- RuntimeDefinition getRuntimeDefinition() const override {
- const FunctionDecl *FD = getDecl();
- // Note that the AnalysisDeclContext will have the FunctionDecl with
- // the definition (if one exists).
- if (FD) {
- AnalysisDeclContext *AD =
- getLocationContext()->getAnalysisDeclContext()->
- getManager()->getContext(FD);
- if (AD->getBody())
- return RuntimeDefinition(AD->getDecl());
- }
-
- return RuntimeDefinition();
- }
+ RuntimeDefinition getRuntimeDefinition() const override;
bool argumentsMayEscape() const override;
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
index e380982d43ea7..78d38a3d598dc 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
@@ -196,6 +196,13 @@ public:
return getState()->getSVal(S, getLocationContext());
}
+ /// \brief Returns true if the value of \p E is greater than or equal to \p
+ /// Val under unsigned comparison
+ bool isGreaterOrEqual(const Expr *E, unsigned long long Val);
+
+ /// Returns true if the value of \p E is negative.
+ bool isNegative(const Expr *E);
+
/// \brief Generates a new transition in the program state graph
/// (ExplodedGraph). Uses the default CheckerContext predecessor node.
///
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
index 12ec5b6c64a4d..7472a7147fca6 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
@@ -16,7 +16,7 @@
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_COREENGINE_H
#include "clang/AST/Expr.h"
-#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h"
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
index a66e1a1aed016..c63ed4a013aa6 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
@@ -14,7 +14,7 @@
#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_ENVIRONMENT_H
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_ENVIRONMENT_H
-#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "llvm/ADT/ImmutableMap.h"
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
index a710ae68be604..dcea5e461d27c 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
@@ -20,14 +20,14 @@
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPLODEDGRAPH_H
#include "clang/AST/Decl.h"
-#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/ProgramPoint.h"
#include "clang/Analysis/Support/BumpVector.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/GraphTraits.h"
-#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SetVector.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
#include <memory>
@@ -404,7 +404,7 @@ private:
};
class ExplodedNodeSet {
- typedef llvm::SmallPtrSet<ExplodedNode*,5> ImplTy;
+ typedef llvm::SmallSetVector<ExplodedNode*, 4> ImplTy;
ImplTy Impl;
public:
@@ -424,7 +424,7 @@ public:
unsigned size() const { return Impl.size(); }
bool empty() const { return Impl.empty(); }
- bool erase(ExplodedNode *N) { return Impl.erase(N); }
+ bool erase(ExplodedNode *N) { return Impl.remove(N); }
void clear() { Impl.clear(); }
void insert(const ExplodedNodeSet &S) {
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index 067d706108689..712cd6361e118 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -196,6 +196,8 @@ public:
void ProcessStmt(const CFGStmt S, ExplodedNode *Pred);
+ void ProcessLoopExit(const Stmt* S, ExplodedNode *Pred);
+
void ProcessInitializer(const CFGInitializer I, ExplodedNode *Pred);
void ProcessImplicitDtor(const CFGImplicitDtor D, ExplodedNode *Pred);
@@ -330,9 +332,9 @@ public:
void Visit(const Stmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst);
/// VisitArraySubscriptExpr - Transfer function for array accesses.
- void VisitLvalArraySubscriptExpr(const ArraySubscriptExpr *Ex,
- ExplodedNode *Pred,
- ExplodedNodeSet &Dst);
+ void VisitArraySubscriptExpr(const ArraySubscriptExpr *Ex,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
/// VisitGCCAsmStmt - Transfer function logic for inline asm.
void VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred,
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h
new file mode 100644
index 0000000000000..a4c505ce5f237
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h
@@ -0,0 +1,50 @@
+//===--- LoopUnrolling.h - Unroll loops -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// This header contains the declarations of functions which are used to decide
+/// which loops should be completely unrolled and mark their corresponding
+/// CFGBlocks. It is done by tracking a stack of loops in the ProgramState. This
+/// way specific loops can be marked as completely unrolled. For considering a
+/// loop to be completely unrolled it has to fulfill the following requirements:
+/// - Currently only forStmts can be considered.
+/// - The bound has to be known.
+/// - The counter variable has not escaped before/in the body of the loop and
+/// changed only in the increment statement corresponding to the loop. It also
+/// has to be initialized by a literal in the corresponding initStmt.
+/// - Does not contain goto, switch and returnStmt.
+///
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_LOOPUNROLLING_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_LOOPUNROLLING_H
+
+#include "clang/Analysis/CFG.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
+namespace clang {
+namespace ento {
+class AnalysisManager;
+
+/// Returns if the given State indicates that is inside a completely unrolled
+/// loop.
+bool isUnrolledState(ProgramStateRef State);
+
+/// Updates the stack of loops contained by the ProgramState.
+ProgramStateRef updateLoopStack(const Stmt *LoopStmt, ASTContext &ASTCtx,
+ ExplodedNode* Pred, unsigned maxVisitOnPath);
+
+/// Updates the given ProgramState. In current implementation it removes the top
+/// element of the stack of loops.
+ProgramStateRef processLoopEnd(const Stmt *LoopStmt, ProgramStateRef State);
+
+} // end namespace ento
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
index 29b1c4cdca04e..8ab6656230888 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -21,7 +21,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExprObjC.h"
-#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Basic/LLVM.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "llvm/ADT/FoldingSet.h"
@@ -1412,21 +1412,18 @@ public:
bool hasTrait(SymbolRef Sym, InvalidationKinds IK) const;
bool hasTrait(const MemRegion *MR, InvalidationKinds IK) const;
};
-
-} // end GR namespace
-
-} // end clang namespace
//===----------------------------------------------------------------------===//
// Pretty-printing regions.
//===----------------------------------------------------------------------===//
-
-namespace llvm {
-static inline raw_ostream &operator<<(raw_ostream &os,
- const clang::ento::MemRegion* R) {
+inline raw_ostream &operator<<(raw_ostream &os,
+ const clang::ento::MemRegion *R) {
R->dumpToStream(os);
return os;
}
-} // end llvm namespace
+
+} // namespace ento
+
+} // namespace clang
#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
index e3a2164b11ff0..dd2564b0a3c3e 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
@@ -308,8 +308,12 @@ public:
/// \brief Return the value bound to the specified location.
/// Returns UnknownVal() if none found.
- SVal getSVal(const MemRegion* R) const;
+ SVal getSVal(const MemRegion* R, QualType T = QualType()) const;
+ /// \brief Return the value bound to the specified location, assuming
+ /// that the value is a scalar integer or an enumeration or a pointer.
+ /// Returns UnknownVal() if none found or the region is not known to hold
+ /// a value of such type.
SVal getSValAsScalarOrLoc(const MemRegion *R) const;
/// \brief Visits the symbols reachable from the given SVal using the provided
@@ -758,9 +762,10 @@ inline SVal ProgramState::getRawSVal(Loc LV, QualType T) const {
return getStateManager().StoreMgr->getBinding(getStore(), LV, T);
}
-inline SVal ProgramState::getSVal(const MemRegion* R) const {
+inline SVal ProgramState::getSVal(const MemRegion* R, QualType T) const {
return getStateManager().StoreMgr->getBinding(getStore(),
- loc::MemRegionVal(R));
+ loc::MemRegionVal(R),
+ T);
}
inline BasicValueFactory &ProgramState::getBasicVals() const {
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
index 935f0018324a2..06132587b4aaf 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
@@ -103,9 +103,6 @@ public:
return *static_cast<const T *>(this);
}
- /// BufferTy - A temporary buffer to hold a set of SVals.
- typedef SmallVector<SVal,5> BufferTy;
-
inline unsigned getRawKind() const { return Kind; }
inline BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
inline unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; }
@@ -198,6 +195,10 @@ public:
}
};
+inline raw_ostream &operator<<(raw_ostream &os, clang::ento::SVal V) {
+ V.dumpToStream(os);
+ return os;
+}
class UndefinedVal : public SVal {
public:
@@ -622,11 +623,6 @@ private:
} // end clang namespace
namespace llvm {
-static inline raw_ostream &operator<<(raw_ostream &os,
- clang::ento::SVal V) {
- V.dumpToStream(os);
- return os;
-}
template <typename T> struct isPodLike;
template <> struct isPodLike<clang::ento::SVal> {
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
index 7619f22f40139..25d20a17afaa7 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
@@ -51,7 +51,7 @@ public:
virtual ~StoreManager() {}
/// Return the value bound to specified location in a given state.
- /// \param[in] store The analysis state.
+ /// \param[in] store The store in which to make the lookup.
/// \param[in] loc The symbolic memory location.
/// \param[in] T An optional type that provides a hint indicating the
/// expected type of the returned value. This is used if the value is
@@ -83,12 +83,12 @@ public:
return getDefaultBinding(lcv.getStore(), lcv.getRegion());
}
- /// Return a state with the specified value bound to the given location.
- /// \param[in] store The analysis state.
+ /// Return a store with the specified value bound to the given location.
+ /// \param[in] store The store in which to make the binding.
/// \param[in] loc The symbolic memory location.
/// \param[in] val The value to bind to location \c loc.
- /// \return A pointer to a ProgramState object that contains the same
- /// bindings as \c state with the addition of having the value specified
+ /// \return A StoreRef object that contains the same
+ /// bindings as \c store with the addition of having the value specified
/// by \c val bound to the location given for \c loc.
virtual StoreRef Bind(Store store, Loc loc, SVal val) = 0;
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h
index f72033955ec31..9780d0144746e 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h
@@ -98,6 +98,12 @@ public:
virtual const MemRegion *getOriginRegion() const { return nullptr; }
};
+inline raw_ostream &operator<<(raw_ostream &os,
+ const clang::ento::SymExpr *SE) {
+ SE->dumpToStream(os);
+ return os;
+}
+
typedef const SymExpr *SymbolRef;
typedef SmallVector<SymbolRef, 2> SymbolRefSmallVectorTy;
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
index e9701142cd9e2..7d2e5ad8ba915 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
@@ -17,7 +17,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
-#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Basic/LLVM.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
@@ -633,11 +633,4 @@ public:
} // end clang namespace
-namespace llvm {
-static inline raw_ostream &operator<<(raw_ostream &os,
- const clang::ento::SymExpr *SE) {
- SE->dumpToStream(os);
- return os;
-}
-} // end llvm namespace
#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/ASTDiff/ASTDiff.h b/contrib/llvm/tools/clang/include/clang/Tooling/ASTDiff/ASTDiff.h
new file mode 100644
index 0000000000000..dd11c91ac0dde
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/ASTDiff/ASTDiff.h
@@ -0,0 +1,127 @@
+//===- ASTDiff.h - AST differencing API -----------------------*- C++ -*- -===//
+//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file specifies an interface that can be used to compare C++ syntax
+// trees.
+//
+// We use the gumtree algorithm which combines a heuristic top-down search that
+// is able to match large subtrees that are equivalent, with an optimal
+// algorithm to match small subtrees.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_ASTDIFF_ASTDIFF_H
+#define LLVM_CLANG_TOOLING_ASTDIFF_ASTDIFF_H
+
+#include "clang/Tooling/ASTDiff/ASTDiffInternal.h"
+
+namespace clang {
+namespace diff {
+
+enum ChangeKind {
+ None,
+ Delete, // (Src): delete node Src.
+ Update, // (Src, Dst): update the value of node Src to match Dst.
+ Insert, // (Src, Dst, Pos): insert Src as child of Dst at offset Pos.
+ Move, // (Src, Dst, Pos): move Src to be a child of Dst at offset Pos.
+ UpdateMove // Same as Move plus Update.
+};
+
+/// Represents a Clang AST node, alongside some additional information.
+struct Node {
+ NodeId Parent, LeftMostDescendant, RightMostDescendant;
+ int Depth, Height, Shift = 0;
+ ast_type_traits::DynTypedNode ASTNode;
+ SmallVector<NodeId, 4> Children;
+ ChangeKind Change = None;
+
+ ast_type_traits::ASTNodeKind getType() const;
+ StringRef getTypeLabel() const;
+ bool isLeaf() const { return Children.empty(); }
+ llvm::Optional<StringRef> getIdentifier() const;
+ llvm::Optional<std::string> getQualifiedIdentifier() const;
+};
+
+class ASTDiff {
+public:
+ ASTDiff(SyntaxTree &Src, SyntaxTree &Dst, const ComparisonOptions &Options);
+ ~ASTDiff();
+
+ // Returns the ID of the node that is mapped to the given node in SourceTree.
+ NodeId getMapped(const SyntaxTree &SourceTree, NodeId Id) const;
+
+ class Impl;
+
+private:
+ std::unique_ptr<Impl> DiffImpl;
+};
+
+/// SyntaxTree objects represent subtrees of the AST.
+/// They can be constructed from any Decl or Stmt.
+class SyntaxTree {
+public:
+ /// Constructs a tree from a translation unit.
+ SyntaxTree(ASTContext &AST);
+ /// Constructs a tree from any AST node.
+ template <class T>
+ SyntaxTree(T *Node, ASTContext &AST)
+ : TreeImpl(llvm::make_unique<Impl>(this, Node, AST)) {}
+ SyntaxTree(SyntaxTree &&Other) = default;
+ ~SyntaxTree();
+
+ const ASTContext &getASTContext() const;
+ StringRef getFilename() const;
+
+ int getSize() const;
+ NodeId getRootId() const;
+ using PreorderIterator = NodeId;
+ PreorderIterator begin() const;
+ PreorderIterator end() const;
+
+ const Node &getNode(NodeId Id) const;
+ int findPositionInParent(NodeId Id) const;
+
+ // Returns the starting and ending offset of the node in its source file.
+ std::pair<unsigned, unsigned> getSourceRangeOffsets(const Node &N) const;
+
+ /// Serialize the node attributes to a string representation. This should
+ /// uniquely distinguish nodes of the same kind. Note that this function just
+ /// returns a representation of the node value, not considering descendants.
+ std::string getNodeValue(NodeId Id) const;
+ std::string getNodeValue(const Node &Node) const;
+
+ class Impl;
+ std::unique_ptr<Impl> TreeImpl;
+};
+
+struct ComparisonOptions {
+ /// During top-down matching, only consider nodes of at least this height.
+ int MinHeight = 2;
+
+ /// During bottom-up matching, match only nodes with at least this value as
+ /// the ratio of their common descendants.
+ double MinSimilarity = 0.5;
+
+ /// Whenever two subtrees are matched in the bottom-up phase, the optimal
+ /// mapping is computed, unless the size of either subtrees exceeds this.
+ int MaxSize = 100;
+
+ bool StopAfterTopDown = false;
+
+ /// Returns false if the nodes should never be matched.
+ bool isMatchingAllowed(const Node &N1, const Node &N2) const {
+ return N1.getType().isSame(N2.getType());
+ }
+};
+
+} // end namespace diff
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/ASTDiff/ASTDiffInternal.h b/contrib/llvm/tools/clang/include/clang/Tooling/ASTDiff/ASTDiffInternal.h
new file mode 100644
index 0000000000000..a76ad37336a68
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/ASTDiff/ASTDiffInternal.h
@@ -0,0 +1,48 @@
+//===- ASTDiffInternal.h --------------------------------------*- C++ -*- -===//
+//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_ASTDIFF_ASTDIFFINTERNAL_H
+#define LLVM_CLANG_TOOLING_ASTDIFF_ASTDIFFINTERNAL_H
+
+#include "clang/AST/ASTTypeTraits.h"
+
+namespace clang {
+namespace diff {
+
+using DynTypedNode = ast_type_traits::DynTypedNode;
+
+class SyntaxTree;
+class SyntaxTreeImpl;
+struct ComparisonOptions;
+
+/// Within a tree, this identifies a node by its preorder offset.
+struct NodeId {
+private:
+ static constexpr int InvalidNodeId = -1;
+
+public:
+ int Id;
+
+ NodeId() : Id(InvalidNodeId) {}
+ NodeId(int Id) : Id(Id) {}
+
+ operator int() const { return Id; }
+ NodeId &operator++() { return ++Id, *this; }
+ NodeId &operator--() { return --Id, *this; }
+ // Support defining iterators on NodeId.
+ NodeId &operator*() { return *this; }
+
+ bool isValid() const { return Id != InvalidNodeId; }
+ bool isInvalid() const { return Id == InvalidNodeId; }
+};
+
+} // end namespace diff
+} // end namespace clang
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/CommonOptionsParser.h b/contrib/llvm/tools/clang/include/clang/Tooling/CommonOptionsParser.h
index 3d630c5f7609c..15e8161dd76fb 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/CommonOptionsParser.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/CommonOptionsParser.h
@@ -27,8 +27,10 @@
#ifndef LLVM_CLANG_TOOLING_COMMONOPTIONSPARSER_H
#define LLVM_CLANG_TOOLING_COMMONOPTIONSPARSER_H
+#include "clang/Tooling/ArgumentsAdjusters.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Error.h"
namespace clang {
namespace tooling {
@@ -84,14 +86,19 @@ public:
///
/// All options not belonging to \p Category become hidden.
///
- /// I also allows calls to set the required number of positional parameters.
- ///
- /// This constructor exits program in case of error.
+ /// It also allows calls to set the required number of positional parameters.
CommonOptionsParser(int &argc, const char **argv,
llvm::cl::OptionCategory &Category,
llvm::cl::NumOccurrencesFlag OccurrencesFlag,
const char *Overview = nullptr);
+ /// \brief A factory method that is similar to the above constructor, except
+ /// this returns an error instead exiting the program on error.
+ static llvm::Expected<CommonOptionsParser>
+ create(int &argc, const char **argv, llvm::cl::OptionCategory &Category,
+ llvm::cl::NumOccurrencesFlag OccurrencesFlag,
+ const char *Overview = nullptr);
+
/// Returns a reference to the loaded compilations database.
CompilationDatabase &getCompilations() {
return *Compilations;
@@ -102,13 +109,46 @@ public:
return SourcePathList;
}
+ /// Returns the argument adjuster calculated from "--extra-arg" and
+ //"--extra-arg-before" options.
+ ArgumentsAdjuster getArgumentsAdjuster() { return Adjuster; }
+
static const char *const HelpMessage;
private:
+ CommonOptionsParser() = default;
+
+ llvm::Error init(int &argc, const char **argv,
+ llvm::cl::OptionCategory &Category,
+ llvm::cl::NumOccurrencesFlag OccurrencesFlag,
+ const char *Overview);
+
std::unique_ptr<CompilationDatabase> Compilations;
std::vector<std::string> SourcePathList;
- std::vector<std::string> ExtraArgsBefore;
- std::vector<std::string> ExtraArgsAfter;
+ ArgumentsAdjuster Adjuster;
+};
+
+class ArgumentsAdjustingCompilations : public CompilationDatabase {
+public:
+ ArgumentsAdjustingCompilations(
+ std::unique_ptr<CompilationDatabase> Compilations)
+ : Compilations(std::move(Compilations)) {}
+
+ void appendArgumentsAdjuster(ArgumentsAdjuster Adjuster);
+
+ std::vector<CompileCommand>
+ getCompileCommands(StringRef FilePath) const override;
+
+ std::vector<std::string> getAllFiles() const override;
+
+ std::vector<CompileCommand> getAllCompileCommands() const override;
+
+private:
+ std::unique_ptr<CompilationDatabase> Compilations;
+ std::vector<ArgumentsAdjuster> Adjusters;
+
+ std::vector<CompileCommand>
+ adjustCommands(std::vector<CompileCommand> Commands) const;
};
} // namespace tooling
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabase.h b/contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabase.h
index e988b84b6eaea..bc3e67b77de25 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabase.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabase.h
@@ -64,10 +64,12 @@ struct CompileCommand {
/// \brief Interface for compilation databases.
///
-/// A compilation database allows the user to retrieve all compile command lines
-/// that a specified file is compiled with in a project.
-/// The retrieved compile command lines can be used to run clang tools over
-/// a subset of the files in a project.
+/// A compilation database allows the user to retrieve compile command lines
+/// for the files in a project.
+///
+/// Many implementations are enumerable, allowing all command lines to be
+/// retrieved. These can be used to run clang tools over a subset of the files
+/// in a project.
class CompilationDatabase {
public:
virtual ~CompilationDatabase();
@@ -104,7 +106,7 @@ public:
/// \brief Returns all compile commands in which the specified file was
/// compiled.
///
- /// This includes compile comamnds that span multiple source files.
+ /// This includes compile commands that span multiple source files.
/// For example, consider a project with the following compilations:
/// $ clang++ -o test a.cc b.cc t.cc
/// $ clang++ -o production a.cc b.cc -DPRODUCTION
@@ -114,7 +116,10 @@ public:
StringRef FilePath) const = 0;
/// \brief Returns the list of all files available in the compilation database.
- virtual std::vector<std::string> getAllFiles() const = 0;
+ ///
+ /// By default, returns nothing. Implementations should override this if they
+ /// can enumerate their source files.
+ virtual std::vector<std::string> getAllFiles() const { return {}; }
/// \brief Returns all compile commands for all the files in the compilation
/// database.
@@ -122,7 +127,10 @@ public:
/// FIXME: Add a layer in Tooling that provides an interface to run a tool
/// over all files in a compilation database. Not all build systems have the
/// ability to provide a feasible implementation for \c getAllCompileCommands.
- virtual std::vector<CompileCommand> getAllCompileCommands() const = 0;
+ ///
+ /// By default, this is implemented in terms of getAllFiles() and
+ /// getCompileCommands(). Subclasses may override this for efficiency.
+ virtual std::vector<CompileCommand> getAllCompileCommands() const;
};
/// \brief Interface for compilation database plugins.
@@ -149,6 +157,7 @@ public:
/// \brief A compilation database that returns a single compile command line.
///
/// Useful when we want a tool to behave more like a compiler invocation.
+/// This compilation database is not enumerable: getAllFiles() returns {}.
class FixedCompilationDatabase : public CompilationDatabase {
public:
/// \brief Creates a FixedCompilationDatabase from the arguments after "--".
@@ -182,6 +191,11 @@ public:
int &Argc, const char *const *Argv, std::string &ErrorMsg,
Twine Directory = ".");
+ /// Reads flags from the given file, one-per line.
+ /// Returns nullptr and sets ErrorMessage if we can't read the file.
+ static std::unique_ptr<FixedCompilationDatabase>
+ loadFromFile(StringRef Path, std::string &ErrorMsg);
+
/// \brief Constructs a compilation data base from a specified directory
/// and command line.
FixedCompilationDatabase(Twine Directory, ArrayRef<std::string> CommandLine);
@@ -194,17 +208,6 @@ public:
std::vector<CompileCommand>
getCompileCommands(StringRef FilePath) const override;
- /// \brief Returns the list of all files available in the compilation database.
- ///
- /// Note: This is always an empty list for the fixed compilation database.
- std::vector<std::string> getAllFiles() const override;
-
- /// \brief Returns all compile commands for all the files in the compilation
- /// database.
- ///
- /// Note: This is always an empty list for the fixed compilation database.
- std::vector<CompileCommand> getAllCompileCommands() const override;
-
private:
/// This is built up to contain a single entry vector to be returned from
/// getCompileCommands after adding the positional argument.
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Core/Replacement.h b/contrib/llvm/tools/clang/include/clang/Tooling/Core/Replacement.h
index 8d4a22adf3680..3fea9aee604ca 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/Core/Replacement.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Core/Replacement.h
@@ -255,7 +255,7 @@ class Replacements {
/// \brief Merges \p Replaces into the current replacements. \p Replaces
/// refers to code after applying the current replacements.
- Replacements merge(const Replacements &Replaces) const;
+ LLVM_NODISCARD Replacements merge(const Replacements &Replaces) const;
// Returns the affected ranges in the changed code.
std::vector<Range> getAffectedRanges() const;
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Execution.h b/contrib/llvm/tools/clang/include/clang/Tooling/Execution.h
new file mode 100644
index 0000000000000..1a44c4788c492
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Execution.h
@@ -0,0 +1,175 @@
+//===--- Execution.h - Executing clang frontend actions -*- C++ ---------*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines framework for executing clang frontend actions.
+//
+// The framework can be extended to support different execution plans including
+// standalone execution on the given TUs or parallel execution on all TUs in
+// the codebase.
+//
+// In order to enable multiprocessing execution, tool actions are expected to
+// output result into the ToolResults provided by the executor. The
+// `ToolResults` is an interface that abstracts how results are stored e.g.
+// in-memory for standalone execution or on-disk for large-scale execution.
+//
+// New executors can be registered as ToolExecutorPlugins via the
+// `ToolExecutorPluginRegistry`. CLI tools can use
+// `createExecutorFromCommandLineArgs` to create a specific registered executor
+// according to the command-line arguments.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_EXECUTION_H
+#define LLVM_CLANG_TOOLING_EXECUTION_H
+
+#include "clang/Tooling/CommonOptionsParser.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Registry.h"
+
+namespace clang {
+namespace tooling {
+
+/// \brief An abstraction for the result of a tool execution. For example, the
+/// underlying result can be in-memory or on-disk.
+///
+/// Results should be string key-value pairs. For example, a refactoring tool
+/// can use source location as key and a replacement in YAML format as value.
+class ToolResults {
+public:
+ virtual ~ToolResults() = default;
+ virtual void addResult(StringRef Key, StringRef Value) = 0;
+ virtual std::vector<std::pair<std::string, std::string>> AllKVResults() = 0;
+ virtual void forEachResult(
+ llvm::function_ref<void(StringRef Key, StringRef Value)> Callback) = 0;
+};
+
+class InMemoryToolResults : public ToolResults {
+public:
+ void addResult(StringRef Key, StringRef Value) override;
+ std::vector<std::pair<std::string, std::string>> AllKVResults() override;
+ void forEachResult(llvm::function_ref<void(StringRef Key, StringRef Value)>
+ Callback) override;
+
+private:
+ std::vector<std::pair<std::string, std::string>> KVResults;
+};
+
+/// \brief The context of an execution, including the information about
+/// compilation and results.
+class ExecutionContext {
+public:
+ virtual ~ExecutionContext() {}
+
+ /// \brief Initializes a context. This does not take ownership of `Results`.
+ explicit ExecutionContext(ToolResults *Results) : Results(Results) {}
+
+ /// \brief Adds a KV pair to the result container of this execution.
+ void reportResult(StringRef Key, StringRef Value);
+
+ // Returns the source control system's revision number if applicable.
+ // Otherwise returns an empty string.
+ virtual std::string getRevision() { return ""; }
+
+ // Returns the corpus being analyzed, e.g. "llvm" for the LLVM codebase, if
+ // applicable.
+ virtual std::string getCorpus() { return ""; }
+
+ // Returns the currently processed compilation unit if available.
+ virtual std::string getCurrentCompilationUnit() { return ""; }
+
+private:
+ ToolResults *Results;
+};
+
+/// \brief Interface for executing clang frontend actions.
+///
+/// This can be extended to support running tool actions in different
+/// execution mode, e.g. on a specific set of TUs or many TUs in parallel.
+///
+/// New executors can be registered as ToolExecutorPlugins via the
+/// `ToolExecutorPluginRegistry`. CLI tools can use
+/// `createExecutorFromCommandLineArgs` to create a specific registered
+/// executor according to the command-line arguments.
+class ToolExecutor {
+public:
+ virtual ~ToolExecutor() {}
+
+ /// \brief Returns the name of a specific executor.
+ virtual StringRef getExecutorName() const = 0;
+
+ /// \brief Executes each action with a corresponding arguments adjuster.
+ virtual llvm::Error
+ execute(llvm::ArrayRef<
+ std::pair<std::unique_ptr<FrontendActionFactory>, ArgumentsAdjuster>>
+ Actions) = 0;
+
+ /// \brief Convenient functions for the above `execute`.
+ llvm::Error execute(std::unique_ptr<FrontendActionFactory> Action);
+ /// Executes an action with an argument adjuster.
+ llvm::Error execute(std::unique_ptr<FrontendActionFactory> Action,
+ ArgumentsAdjuster Adjuster);
+
+ /// \brief Returns a reference to the execution context.
+ ///
+ /// This should be passed to tool callbacks, and tool callbacks should report
+ /// results via the returned context.
+ virtual ExecutionContext *getExecutionContext() = 0;
+
+ /// \brief Returns a reference to the result container.
+ ///
+ /// NOTE: This should only be used after the execution finishes. Tool
+ /// callbacks should report results via `ExecutionContext` instead.
+ virtual ToolResults *getToolResults() = 0;
+
+ /// \brief Map a virtual file to be used while running the tool.
+ ///
+ /// \param FilePath The path at which the content will be mapped.
+ /// \param Content A buffer of the file's content.
+ virtual void mapVirtualFile(StringRef FilePath, StringRef Content) = 0;
+};
+
+/// \brief Interface for factories that create specific executors. This is also
+/// used as a plugin to be registered into ToolExecutorPluginRegistry.
+class ToolExecutorPlugin {
+public:
+ virtual ~ToolExecutorPlugin() {}
+
+ /// \brief Create an `ToolExecutor`.
+ ///
+ /// `OptionsParser` can be consumed (e.g. moved) if the creation succeeds.
+ virtual llvm::Expected<std::unique_ptr<ToolExecutor>>
+ create(CommonOptionsParser &OptionsParser) = 0;
+};
+
+/// \brief This creates a ToolExecutor that is in the global registry based on
+/// commandline arguments.
+///
+/// This picks the right executor based on the `--executor` option. This parses
+/// the commandline arguments with `CommonOptionsParser`, so caller does not
+/// need to parse again.
+///
+/// By default, this creates a `StandaloneToolExecutor` ("standalone") if
+/// `--executor` is not provided.
+llvm::Expected<std::unique_ptr<ToolExecutor>>
+createExecutorFromCommandLineArgs(int &argc, const char **argv,
+ llvm::cl::OptionCategory &Category,
+ const char *Overview = nullptr);
+
+namespace internal {
+llvm::Expected<std::unique_ptr<ToolExecutor>>
+createExecutorFromCommandLineArgsImpl(int &argc, const char **argv,
+ llvm::cl::OptionCategory &Category,
+ const char *Overview = nullptr);
+} // end namespace internal
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_EXECUTION_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/ASTSelection.h b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/ASTSelection.h
new file mode 100644
index 0000000000000..aa02a6899e8fc
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/ASTSelection.h
@@ -0,0 +1,155 @@
+//===--- ASTSelection.h - Clang refactoring library -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_AST_SELECTION_H
+#define LLVM_CLANG_TOOLING_REFACTOR_AST_SELECTION_H
+
+#include "clang/AST/ASTTypeTraits.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include <vector>
+
+namespace clang {
+
+class ASTContext;
+
+namespace tooling {
+
+enum class SourceSelectionKind {
+ /// A node that's not selected.
+ None,
+
+ /// A node that's considered to be selected because the whole selection range
+ /// is inside of its source range.
+ ContainsSelection,
+ /// A node that's considered to be selected because the start of the selection
+ /// range is inside its source range.
+ ContainsSelectionStart,
+ /// A node that's considered to be selected because the end of the selection
+ /// range is inside its source range.
+ ContainsSelectionEnd,
+
+ /// A node that's considered to be selected because the node is entirely in
+ /// the selection range.
+ InsideSelection,
+};
+
+/// Represents a selected AST node.
+///
+/// AST selection is represented using a tree of \c SelectedASTNode. The tree
+/// follows the top-down shape of the actual AST. Each selected node has
+/// a selection kind. The kind might be none as the node itself might not
+/// actually be selected, e.g. a statement in macro whose child is in a macro
+/// argument.
+struct SelectedASTNode {
+ ast_type_traits::DynTypedNode Node;
+ SourceSelectionKind SelectionKind;
+ std::vector<SelectedASTNode> Children;
+
+ SelectedASTNode(const ast_type_traits::DynTypedNode &Node,
+ SourceSelectionKind SelectionKind)
+ : Node(Node), SelectionKind(SelectionKind) {}
+ SelectedASTNode(SelectedASTNode &&) = default;
+ SelectedASTNode &operator=(SelectedASTNode &&) = default;
+
+ void dump(llvm::raw_ostream &OS = llvm::errs()) const;
+
+ using ReferenceType = std::reference_wrapper<const SelectedASTNode>;
+};
+
+/// Traverses the given ASTContext and creates a tree of selected AST nodes.
+///
+/// \returns None if no nodes are selected in the AST, or a selected AST node
+/// that corresponds to the TranslationUnitDecl otherwise.
+Optional<SelectedASTNode> findSelectedASTNodes(const ASTContext &Context,
+ SourceRange SelectionRange);
+
+/// An AST selection value that corresponds to a selection of a set of
+/// statements that belong to one body of code (like one function).
+///
+/// For example, the following selection in the source.
+///
+/// \code
+/// void function() {
+/// // selection begin:
+/// int x = 0;
+/// {
+/// // selection end
+/// x = 1;
+/// }
+/// x = 2;
+/// }
+/// \endcode
+///
+/// Would correspond to a code range selection of statements "int x = 0"
+/// and the entire compound statement that follows it.
+///
+/// A \c CodeRangeASTSelection value stores references to the full
+/// \c SelectedASTNode tree and should not outlive it.
+class CodeRangeASTSelection {
+public:
+ CodeRangeASTSelection(CodeRangeASTSelection &&) = default;
+ CodeRangeASTSelection &operator=(CodeRangeASTSelection &&) = default;
+
+ /// Returns the parent hierarchy (top to bottom) for the selected nodes.
+ ArrayRef<SelectedASTNode::ReferenceType> getParents() { return Parents; }
+
+ /// Returns the number of selected statements.
+ size_t size() const {
+ if (!AreChildrenSelected)
+ return 1;
+ return SelectedNode.get().Children.size();
+ }
+
+ const Stmt *operator[](size_t I) const {
+ if (!AreChildrenSelected) {
+ assert(I == 0 && "Invalid index");
+ return SelectedNode.get().Node.get<Stmt>();
+ }
+ return SelectedNode.get().Children[I].Node.get<Stmt>();
+ }
+
+ /// Returns true when a selected code range is in a function-like body
+ /// of code, like a function, method or a block.
+ ///
+ /// This function can be used to test against selected expressions that are
+ /// located outside of a function, e.g. global variable initializers, default
+ /// argument values, or even template arguments.
+ ///
+ /// Use the \c getFunctionLikeNearestParent to get the function-like parent
+ /// declaration.
+ bool isInFunctionLikeBodyOfCode() const;
+
+ /// Returns the nearest function-like parent declaration or null if such
+ /// declaration doesn't exist.
+ const Decl *getFunctionLikeNearestParent() const;
+
+ static Optional<CodeRangeASTSelection>
+ create(SourceRange SelectionRange, const SelectedASTNode &ASTSelection);
+
+private:
+ CodeRangeASTSelection(SelectedASTNode::ReferenceType SelectedNode,
+ ArrayRef<SelectedASTNode::ReferenceType> Parents,
+ bool AreChildrenSelected)
+ : SelectedNode(SelectedNode), Parents(Parents.begin(), Parents.end()),
+ AreChildrenSelected(AreChildrenSelected) {}
+
+ /// The reference to the selected node (or reference to the selected
+ /// child nodes).
+ SelectedASTNode::ReferenceType SelectedNode;
+ /// The parent hierarchy (top to bottom) for the selected noe.
+ llvm::SmallVector<SelectedASTNode::ReferenceType, 8> Parents;
+ /// True only when the children of the selected node are actually selected.
+ bool AreChildrenSelected;
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_AST_SELECTION_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/AtomicChange.h b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/AtomicChange.h
index 9cccd78677b15..8a468a6de84ef 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/AtomicChange.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/AtomicChange.h
@@ -16,6 +16,7 @@
#define LLVM_CLANG_TOOLING_REFACTOR_ATOMICCHANGE_H
#include "clang/Basic/SourceManager.h"
+#include "clang/Format/Format.h"
#include "clang/Tooling/Core/Replacement.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
@@ -45,6 +46,14 @@ public:
AtomicChange(llvm::StringRef FilePath, llvm::StringRef Key)
: Key(Key), FilePath(FilePath) {}
+ AtomicChange(AtomicChange &&) = default;
+ AtomicChange(const AtomicChange &) = default;
+
+ AtomicChange &operator=(AtomicChange &&) = default;
+ AtomicChange &operator=(const AtomicChange &) = default;
+
+ bool operator==(const AtomicChange &Other) const;
+
/// \brief Returns the atomic change as a YAML string.
std::string toYAMLString();
@@ -129,6 +138,41 @@ private:
tooling::Replacements Replaces;
};
+using AtomicChanges = std::vector<AtomicChange>;
+
+// Defines specs for applying changes.
+struct ApplyChangesSpec {
+ // If true, cleans up redundant/erroneous code around changed code with
+ // clang-format's cleanup functionality, e.g. redundant commas around deleted
+ // parameter or empty namespaces introduced by deletions.
+ bool Cleanup = true;
+
+ format::FormatStyle Style = format::getNoStyle();
+
+ // Options for selectively formatting changes with clang-format:
+ // kAll: Format all changed lines.
+ // kNone: Don't format anything.
+ // kViolations: Format lines exceeding the `ColumnLimit` in `Style`.
+ enum FormatOption { kAll, kNone, kViolations };
+
+ FormatOption Format = kNone;
+};
+
+/// \brief Applies all AtomicChanges in \p Changes to the \p Code.
+///
+/// This completely ignores the file path in each change and replaces them with
+/// \p FilePath, i.e. callers are responsible for ensuring all changes are for
+/// the same file.
+///
+/// \returns The changed code if all changes are applied successfully;
+/// otherwise, an llvm::Error carrying llvm::StringError is returned (the Error
+/// message can be converted to string with `llvm::toString()` and the
+/// error_code should be ignored).
+llvm::Expected<std::string>
+applyAtomicChanges(llvm::StringRef FilePath, llvm::StringRef Code,
+ llvm::ArrayRef<AtomicChange> Changes,
+ const ApplyChangesSpec &Spec);
+
} // end namespace tooling
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Extract/Extract.h b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Extract/Extract.h
new file mode 100644
index 0000000000000..2fd76d252c62b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Extract/Extract.h
@@ -0,0 +1,53 @@
+//===--- Extract.h - Clang refactoring library ----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_EXTRACT_EXTRACT_H
+#define LLVM_CLANG_TOOLING_REFACTOR_EXTRACT_EXTRACT_H
+
+#include "clang/Tooling/Refactoring/ASTSelection.h"
+#include "clang/Tooling/Refactoring/RefactoringActionRules.h"
+
+namespace clang {
+namespace tooling {
+
+/// An "Extract Function" refactoring moves code into a new function that's
+/// then called from the place where the original code was.
+class ExtractFunction final : public SourceChangeRefactoringRule {
+public:
+ /// Initiates the extract function refactoring operation.
+ ///
+ /// \param Code The selected set of statements.
+ /// \param DeclName The name name of the extract function. If None,
+ /// "extracted" is used.
+ static Expected<ExtractFunction> initiate(RefactoringRuleContext &Context,
+ CodeRangeASTSelection Code,
+ Optional<std::string> DeclName);
+
+ static const RefactoringDescriptor &describe();
+
+private:
+ ExtractFunction(CodeRangeASTSelection Code, Optional<std::string> DeclName)
+ : Code(std::move(Code)),
+ DeclName(DeclName ? std::move(*DeclName) : "extracted") {}
+
+ Expected<AtomicChanges>
+ createSourceReplacements(RefactoringRuleContext &Context) override;
+
+ CodeRangeASTSelection Code;
+
+ // FIXME: Account for naming collisions:
+ // - error when name is specified by user.
+ // - rename to "extractedN" when name is implicit.
+ std::string DeclName;
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_EXTRACT_EXTRACT_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
index 8b01a61256f6b..d96ad78ad8768 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
@@ -70,6 +70,18 @@ public:
return visit(Expr->getFoundDecl().getDecl(), Expr->getMemberLoc());
}
+ bool VisitOffsetOfExpr(const OffsetOfExpr *S) {
+ for (unsigned I = 0, E = S->getNumComponents(); I != E; ++I) {
+ const OffsetOfNode &Component = S->getComponent(I);
+ if (Component.getKind() == OffsetOfNode::Field) {
+ if (!visit(Component.getField(), Component.getLocEnd()))
+ return false;
+ }
+ // FIXME: Try to resolve dependent field references.
+ }
+ return true;
+ }
+
// Other visitors:
bool VisitTypeLoc(const TypeLoc Loc) {
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringAction.h b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringAction.h
new file mode 100644
index 0000000000000..c4080237f1c35
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringAction.h
@@ -0,0 +1,64 @@
+//===--- RefactoringAction.h - Clang refactoring library ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_H
+#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Tooling/Refactoring/RefactoringActionRules.h"
+#include <vector>
+
+namespace clang {
+namespace tooling {
+
+/// A refactoring action is a class that defines a set of related refactoring
+/// action rules. These rules get grouped under a common umbrella - a single
+/// clang-refactor subcommand.
+///
+/// A subclass of \c RefactoringAction is responsible for creating the set of
+/// grouped refactoring action rules that represent one refactoring operation.
+/// Although the rules in one action may have a number of different
+/// implementations, they should strive to produce a similar result. It should
+/// be easy for users to identify which refactoring action produced the result
+/// regardless of which refactoring action rule was used.
+///
+/// The distinction between actions and rules enables the creation of action
+/// that uses very different rules, for example:
+/// - local vs global: a refactoring operation like
+/// "add missing switch cases" can be applied to one switch when it's
+/// selected in an editor, or to all switches in a project when an enum
+/// constant is added to an enum.
+/// - tool vs editor: some refactoring operation can be initiated in the
+/// editor when a declaration is selected, or in a tool when the name of
+/// the declaration is passed using a command-line argument.
+class RefactoringAction {
+public:
+ virtual ~RefactoringAction() {}
+
+ /// Returns the name of the subcommand that's used by clang-refactor for this
+ /// action.
+ virtual StringRef getCommand() const = 0;
+
+ virtual StringRef getDescription() const = 0;
+
+ RefactoringActionRules createActiveActionRules();
+
+protected:
+ /// Returns a set of refactoring actions rules that are defined by this
+ /// action.
+ virtual RefactoringActionRules createActionRules() const = 0;
+};
+
+/// Returns the list of all the available refactoring actions.
+std::vector<std::unique_ptr<RefactoringAction>> createRefactoringActions();
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringActionRule.h b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringActionRule.h
new file mode 100644
index 0000000000000..4130e29d8dea5
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringActionRule.h
@@ -0,0 +1,74 @@
+//===--- RefactoringActionRule.h - Clang refactoring library -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULE_H
+#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULE_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include <vector>
+
+namespace clang {
+namespace tooling {
+
+class RefactoringOptionVisitor;
+class RefactoringResultConsumer;
+class RefactoringRuleContext;
+
+struct RefactoringDescriptor {
+ /// A unique identifier for the specific refactoring.
+ StringRef Name;
+ /// A human readable title for the refactoring.
+ StringRef Title;
+ /// A human readable description of what the refactoring does.
+ StringRef Description;
+};
+
+/// A common refactoring action rule interface that defines the 'invoke'
+/// function that performs the refactoring operation (either fully or
+/// partially).
+class RefactoringActionRuleBase {
+public:
+ virtual ~RefactoringActionRuleBase() {}
+
+ /// Initiates and performs a specific refactoring action.
+ ///
+ /// The specific rule will invoke an appropriate \c handle method on a
+ /// consumer to propagate the result of the refactoring action.
+ virtual void invoke(RefactoringResultConsumer &Consumer,
+ RefactoringRuleContext &Context) = 0;
+
+ /// Returns the structure that describes the refactoring.
+ // static const RefactoringDescriptor &describe() = 0;
+};
+
+/// A refactoring action rule is a wrapper class around a specific refactoring
+/// action rule (SourceChangeRefactoringRule, etc) that, in addition to invoking
+/// the action, describes the requirements that determine when the action can be
+/// initiated.
+class RefactoringActionRule : public RefactoringActionRuleBase {
+public:
+ /// Returns true when the rule has a source selection requirement that has
+ /// to be fullfilled before refactoring can be performed.
+ virtual bool hasSelectionRequirement() = 0;
+
+ /// Traverses each refactoring option used by the rule and invokes the
+ /// \c visit callback in the consumer for each option.
+ ///
+ /// Options are visited in the order of use, e.g. if a rule has two
+ /// requirements that use options, the options from the first requirement
+ /// are visited before the options in the second requirement.
+ virtual void visitRefactoringOptions(RefactoringOptionVisitor &Visitor) = 0;
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULE_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h
new file mode 100644
index 0000000000000..355a6a55f22fd
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h
@@ -0,0 +1,123 @@
+//===--- RefactoringActionRuleRequirements.h - Clang refactoring library --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULE_REQUIREMENTS_H
+#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULE_REQUIREMENTS_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Tooling/Refactoring/ASTSelection.h"
+#include "clang/Tooling/Refactoring/RefactoringDiagnostic.h"
+#include "clang/Tooling/Refactoring/RefactoringOption.h"
+#include "clang/Tooling/Refactoring/RefactoringRuleContext.h"
+#include "llvm/Support/Error.h"
+#include <type_traits>
+
+namespace clang {
+namespace tooling {
+
+/// A refactoring action rule requirement determines when a refactoring action
+/// rule can be invoked. The rule can be invoked only when all of the
+/// requirements are satisfied.
+///
+/// Subclasses must implement the
+/// 'Expected<T> evaluate(RefactoringRuleContext &) const' member function.
+/// \c T is used to determine the return type that is passed to the
+/// refactoring rule's constructor.
+/// For example, the \c SourceRangeSelectionRequirement subclass defines
+/// 'Expected<SourceRange> evaluate(RefactoringRuleContext &Context) const'
+/// function. When this function returns a non-error value, the resulting
+/// source range is passed to the specific refactoring action rule
+/// constructor (provided all other requirements are satisfied).
+class RefactoringActionRuleRequirement {
+ // Expected<T> evaluate(RefactoringRuleContext &Context) const;
+};
+
+/// A base class for any requirement that expects some part of the source to be
+/// selected in an editor (or the refactoring tool with the -selection option).
+class SourceSelectionRequirement : public RefactoringActionRuleRequirement {};
+
+/// A selection requirement that is satisfied when any portion of the source
+/// text is selected.
+class SourceRangeSelectionRequirement : public SourceSelectionRequirement {
+public:
+ Expected<SourceRange> evaluate(RefactoringRuleContext &Context) const {
+ if (Context.getSelectionRange().isValid())
+ return Context.getSelectionRange();
+ return Context.createDiagnosticError(diag::err_refactor_no_selection);
+ }
+};
+
+/// An AST selection requirement is satisfied when any portion of the AST
+/// overlaps with the selection range.
+///
+/// The requirement will be evaluated only once during the initiation and
+/// search of matching refactoring action rules.
+class ASTSelectionRequirement : public SourceRangeSelectionRequirement {
+public:
+ Expected<SelectedASTNode> evaluate(RefactoringRuleContext &Context) const;
+};
+
+/// A selection requirement that is satisfied when the selection range overlaps
+/// with a number of neighbouring statements in the AST. The statemenst must be
+/// contained in declaration like a function. The selection range must be a
+/// non-empty source selection (i.e. cursors won't be accepted).
+///
+/// The requirement will be evaluated only once during the initiation and search
+/// of matching refactoring action rules.
+///
+/// \see CodeRangeASTSelection
+class CodeRangeASTSelectionRequirement : public ASTSelectionRequirement {
+public:
+ Expected<CodeRangeASTSelection>
+ evaluate(RefactoringRuleContext &Context) const;
+};
+
+/// A base class for any requirement that requires some refactoring options.
+class RefactoringOptionsRequirement : public RefactoringActionRuleRequirement {
+public:
+ virtual ~RefactoringOptionsRequirement() {}
+
+ /// Returns the set of refactoring options that are used when evaluating this
+ /// requirement.
+ virtual ArrayRef<std::shared_ptr<RefactoringOption>>
+ getRefactoringOptions() const = 0;
+};
+
+/// A requirement that evaluates to the value of the given \c OptionType when
+/// the \c OptionType is a required option. When the \c OptionType is an
+/// optional option, the requirement will evaluate to \c None if the option is
+/// not specified or to an appropriate value otherwise.
+template <typename OptionType>
+class OptionRequirement : public RefactoringOptionsRequirement {
+public:
+ OptionRequirement() : Opt(createRefactoringOption<OptionType>()) {}
+
+ ArrayRef<std::shared_ptr<RefactoringOption>>
+ getRefactoringOptions() const final override {
+ return Opt;
+ }
+
+ Expected<typename OptionType::ValueType>
+ evaluate(RefactoringRuleContext &) const {
+ return static_cast<OptionType *>(Opt.get())->getValue();
+ }
+
+private:
+ /// The partially-owned option.
+ ///
+ /// The ownership of the option is shared among the different requirements
+ /// because the same option can be used by multiple rules in one refactoring
+ /// action.
+ std::shared_ptr<RefactoringOption> Opt;
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULE_REQUIREMENTS_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringActionRules.h b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringActionRules.h
new file mode 100644
index 0000000000000..33206d9a5dd1e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringActionRules.h
@@ -0,0 +1,94 @@
+//===--- RefactoringActionRules.h - Clang refactoring library -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULES_H
+#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULES_H
+
+#include "clang/Tooling/Refactoring/RefactoringActionRule.h"
+#include "clang/Tooling/Refactoring/RefactoringActionRulesInternal.h"
+
+namespace clang {
+namespace tooling {
+
+/// Creates a new refactoring action rule that constructs and invokes the
+/// \c RuleType rule when all of the requirements are satisfied.
+///
+/// This function takes in a list of values whose type derives from
+/// \c RefactoringActionRuleRequirement. These values describe the initiation
+/// requirements that have to be satisfied by the refactoring engine before
+/// the provided action rule can be constructed and invoked. The engine
+/// verifies that the requirements are satisfied by evaluating them (using the
+/// 'evaluate' member function) and checking that the results don't contain
+/// any errors. Once all requirements are satisfied, the provided refactoring
+/// rule is constructed by passing in the values returned by the requirements'
+/// evaluate functions as arguments to the constructor. The rule is then invoked
+/// immediately after construction.
+///
+/// The separation of requirements, their evaluation and the invocation of the
+/// refactoring action rule allows the refactoring clients to:
+/// - Disable refactoring action rules whose requirements are not supported.
+/// - Gather the set of options and define a command-line / visual interface
+/// that allows users to input these options without ever invoking the
+/// action.
+template <typename RuleType, typename... RequirementTypes>
+std::unique_ptr<RefactoringActionRule>
+createRefactoringActionRule(const RequirementTypes &... Requirements);
+
+/// A set of refactoring action rules that should have unique initiation
+/// requirements.
+using RefactoringActionRules =
+ std::vector<std::unique_ptr<RefactoringActionRule>>;
+
+/// A type of refactoring action rule that produces source replacements in the
+/// form of atomic changes.
+///
+/// This action rule is typically used for local refactorings that replace
+/// source in a single AST unit.
+class SourceChangeRefactoringRule : public RefactoringActionRuleBase {
+public:
+ void invoke(RefactoringResultConsumer &Consumer,
+ RefactoringRuleContext &Context) final override {
+ Expected<AtomicChanges> Changes = createSourceReplacements(Context);
+ if (!Changes)
+ Consumer.handleError(Changes.takeError());
+ else
+ Consumer.handle(std::move(*Changes));
+ }
+
+private:
+ virtual Expected<AtomicChanges>
+ createSourceReplacements(RefactoringRuleContext &Context) = 0;
+};
+
+/// A type of refactoring action rule that finds a set of symbol occurrences
+/// that reference a particular symbol.
+///
+/// This action rule is typically used for an interactive rename that allows
+/// users to specify the new name and the set of selected occurrences during
+/// the refactoring.
+class FindSymbolOccurrencesRefactoringRule : public RefactoringActionRuleBase {
+public:
+ void invoke(RefactoringResultConsumer &Consumer,
+ RefactoringRuleContext &Context) final override {
+ Expected<SymbolOccurrences> Occurrences = findSymbolOccurrences(Context);
+ if (!Occurrences)
+ Consumer.handleError(Occurrences.takeError());
+ else
+ Consumer.handle(std::move(*Occurrences));
+ }
+
+private:
+ virtual Expected<SymbolOccurrences>
+ findSymbolOccurrences(RefactoringRuleContext &Context) = 0;
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULES_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringActionRulesInternal.h b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringActionRulesInternal.h
new file mode 100644
index 0000000000000..75b6c8f70d173
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringActionRulesInternal.h
@@ -0,0 +1,158 @@
+//===--- RefactoringActionRulesInternal.h - Clang refactoring library -----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULES_INTERNAL_H
+#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULES_INTERNAL_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Tooling/Refactoring/RefactoringActionRule.h"
+#include "clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h"
+#include "clang/Tooling/Refactoring/RefactoringResultConsumer.h"
+#include "clang/Tooling/Refactoring/RefactoringRuleContext.h"
+#include "llvm/Support/Error.h"
+#include <type_traits>
+
+namespace clang {
+namespace tooling {
+namespace internal {
+
+inline llvm::Error findError() { return llvm::Error::success(); }
+
+inline void ignoreError() {}
+
+template <typename FirstT, typename... RestT>
+void ignoreError(Expected<FirstT> &First, Expected<RestT> &... Rest) {
+ if (!First)
+ llvm::consumeError(First.takeError());
+ ignoreError(Rest...);
+}
+
+/// Scans the tuple and returns a valid \c Error if any of the values are
+/// invalid.
+template <typename FirstT, typename... RestT>
+llvm::Error findError(Expected<FirstT> &First, Expected<RestT> &... Rest) {
+ if (!First) {
+ ignoreError(Rest...);
+ return First.takeError();
+ }
+ return findError(Rest...);
+}
+
+template <typename RuleType, typename... RequirementTypes, size_t... Is>
+void invokeRuleAfterValidatingRequirements(
+ RefactoringResultConsumer &Consumer, RefactoringRuleContext &Context,
+ const std::tuple<RequirementTypes...> &Requirements,
+ llvm::index_sequence<Is...>) {
+ // Check if the requirements we're interested in can be evaluated.
+ auto Values =
+ std::make_tuple(std::get<Is>(Requirements).evaluate(Context)...);
+ auto Err = findError(std::get<Is>(Values)...);
+ if (Err)
+ return Consumer.handleError(std::move(Err));
+ // Construct the target action rule by extracting the evaluated
+ // requirements from Expected<> wrappers and then run it.
+ auto Rule =
+ RuleType::initiate(Context, std::move((*std::get<Is>(Values)))...);
+ if (!Rule)
+ return Consumer.handleError(Rule.takeError());
+ Rule->invoke(Consumer, Context);
+}
+
+inline void visitRefactoringOptionsImpl(RefactoringOptionVisitor &) {}
+
+/// Scans the list of requirements in a rule and visits all the refactoring
+/// options that are used by all the requirements.
+template <typename FirstT, typename... RestT>
+void visitRefactoringOptionsImpl(RefactoringOptionVisitor &Visitor,
+ const FirstT &First, const RestT &... Rest) {
+ struct OptionGatherer {
+ RefactoringOptionVisitor &Visitor;
+
+ void operator()(const RefactoringOptionsRequirement &Requirement) {
+ for (const auto &Option : Requirement.getRefactoringOptions())
+ Option->passToVisitor(Visitor);
+ }
+ void operator()(const RefactoringActionRuleRequirement &) {}
+ };
+ (OptionGatherer{Visitor})(First);
+ return visitRefactoringOptionsImpl(Visitor, Rest...);
+}
+
+template <typename... RequirementTypes, size_t... Is>
+void visitRefactoringOptions(
+ RefactoringOptionVisitor &Visitor,
+ const std::tuple<RequirementTypes...> &Requirements,
+ llvm::index_sequence<Is...>) {
+ visitRefactoringOptionsImpl(Visitor, std::get<Is>(Requirements)...);
+}
+
+/// A type trait that returns true when the given type list has at least one
+/// type whose base is the given base type.
+template <typename Base, typename First, typename... Rest>
+struct HasBaseOf : std::conditional<HasBaseOf<Base, First>::value ||
+ HasBaseOf<Base, Rest...>::value,
+ std::true_type, std::false_type>::type {};
+
+template <typename Base, typename T>
+struct HasBaseOf<Base, T> : std::is_base_of<Base, T> {};
+
+/// A type trait that returns true when the given type list contains types that
+/// derive from Base.
+template <typename Base, typename First, typename... Rest>
+struct AreBaseOf : std::conditional<AreBaseOf<Base, First>::value &&
+ AreBaseOf<Base, Rest...>::value,
+ std::true_type, std::false_type>::type {};
+
+template <typename Base, typename T>
+struct AreBaseOf<Base, T> : std::is_base_of<Base, T> {};
+
+} // end namespace internal
+
+template <typename RuleType, typename... RequirementTypes>
+std::unique_ptr<RefactoringActionRule>
+createRefactoringActionRule(const RequirementTypes &... Requirements) {
+ static_assert(std::is_base_of<RefactoringActionRuleBase, RuleType>::value,
+ "Expected a refactoring action rule type");
+ static_assert(internal::AreBaseOf<RefactoringActionRuleRequirement,
+ RequirementTypes...>::value,
+ "Expected a list of refactoring action rules");
+
+ class Rule final : public RefactoringActionRule {
+ public:
+ Rule(std::tuple<RequirementTypes...> Requirements)
+ : Requirements(Requirements) {}
+
+ void invoke(RefactoringResultConsumer &Consumer,
+ RefactoringRuleContext &Context) override {
+ internal::invokeRuleAfterValidatingRequirements<RuleType>(
+ Consumer, Context, Requirements,
+ llvm::index_sequence_for<RequirementTypes...>());
+ }
+
+ bool hasSelectionRequirement() override {
+ return internal::HasBaseOf<SourceSelectionRequirement,
+ RequirementTypes...>::value;
+ }
+
+ void visitRefactoringOptions(RefactoringOptionVisitor &Visitor) override {
+ internal::visitRefactoringOptions(
+ Visitor, Requirements,
+ llvm::index_sequence_for<RequirementTypes...>());
+ }
+ private:
+ std::tuple<RequirementTypes...> Requirements;
+ };
+
+ return llvm::make_unique<Rule>(std::make_tuple(Requirements...));
+}
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULES_INTERNAL_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringDiagnostic.h
new file mode 100644
index 0000000000000..6767dc708e017
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringDiagnostic.h
@@ -0,0 +1,30 @@
+//===--- RefactoringDiagnostic.h - ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGDIAGNOSTIC_H
+#define LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGDIAGNOSTIC_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/PartialDiagnostic.h"
+
+namespace clang {
+namespace diag {
+enum {
+#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \
+ SHOWINSYSHEADER, CATEGORY) \
+ ENUM,
+#define REFACTORINGSTART
+#include "clang/Basic/DiagnosticRefactoringKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_REFACTORING_DIAGNOSTICS
+};
+} // end namespace diag
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGDIAGNOSTIC_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringOption.h b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringOption.h
new file mode 100644
index 0000000000000..5011223cce690
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringOption.h
@@ -0,0 +1,64 @@
+//===--- RefactoringOption.h - Clang refactoring library ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTION_H
+#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTION_H
+
+#include "clang/Basic/LLVM.h"
+#include <memory>
+#include <type_traits>
+
+namespace clang {
+namespace tooling {
+
+class RefactoringOptionVisitor;
+
+/// A refactoring option is an interface that describes a value that
+/// has an impact on the outcome of a refactoring.
+///
+/// Refactoring options can be specified using command-line arguments when
+/// the clang-refactor tool is used.
+class RefactoringOption {
+public:
+ virtual ~RefactoringOption() {}
+
+ /// Returns the name of the refactoring option.
+ ///
+ /// Each refactoring option must have a unique name.
+ virtual StringRef getName() const = 0;
+
+ virtual StringRef getDescription() const = 0;
+
+ /// True when this option must be specified before invoking the refactoring
+ /// action.
+ virtual bool isRequired() const = 0;
+
+ /// Invokes the \c visit method in the option consumer that's appropriate
+ /// for the option's value type.
+ ///
+ /// For example, if the option stores a string value, this method will
+ /// invoke the \c visit method with a reference to an std::string value.
+ virtual void passToVisitor(RefactoringOptionVisitor &Visitor) = 0;
+};
+
+/// Constructs a refactoring option of the given type.
+///
+/// The ownership of options is shared among requirements that use it because
+/// one option can be used by multiple rules in a refactoring action.
+template <typename OptionType>
+std::shared_ptr<OptionType> createRefactoringOption() {
+ static_assert(std::is_base_of<RefactoringOption, OptionType>::value,
+ "invalid option type");
+ return std::make_shared<OptionType>();
+}
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTION_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringOptionVisitor.h b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringOptionVisitor.h
new file mode 100644
index 0000000000000..aea8fa549392b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringOptionVisitor.h
@@ -0,0 +1,62 @@
+//===--- RefactoringOptionVisitor.h - Clang refactoring library -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTION_VISITOR_H
+#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTION_VISITOR_H
+
+#include "clang/Basic/LLVM.h"
+#include <type_traits>
+
+namespace clang {
+namespace tooling {
+
+class RefactoringOption;
+
+/// An interface that declares functions that handle different refactoring
+/// option types.
+///
+/// A valid refactoring option type must have a corresponding \c visit
+/// declaration in this interface.
+class RefactoringOptionVisitor {
+public:
+ virtual ~RefactoringOptionVisitor() {}
+
+ virtual void visit(const RefactoringOption &Opt,
+ Optional<std::string> &Value) = 0;
+};
+
+namespace traits {
+namespace internal {
+
+template <typename T> struct HasHandle {
+private:
+ template <typename ClassT>
+ static auto check(ClassT *) -> typename std::is_same<
+ decltype(std::declval<RefactoringOptionVisitor>().visit(
+ std::declval<RefactoringOption>(), *std::declval<Optional<T> *>())),
+ void>::type;
+
+ template <typename> static std::false_type check(...);
+
+public:
+ using Type = decltype(check<RefactoringOptionVisitor>(nullptr));
+};
+
+} // end namespace internal
+
+/// A type trait that returns true iff the given type is a type that can be
+/// stored in a refactoring option.
+template <typename T>
+struct IsValidOptionType : internal::HasHandle<T>::Type {};
+
+} // end namespace traits
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTION_VISITOR_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringOptions.h b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringOptions.h
new file mode 100644
index 0000000000000..e45c0a09fd67b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringOptions.h
@@ -0,0 +1,58 @@
+//===--- RefactoringOptions.h - Clang refactoring library -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTIONS_H
+#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTIONS_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h"
+#include "clang/Tooling/Refactoring/RefactoringOption.h"
+#include "clang/Tooling/Refactoring/RefactoringOptionVisitor.h"
+#include "llvm/Support/Error.h"
+#include <type_traits>
+
+namespace clang {
+namespace tooling {
+
+/// A refactoring option that stores a value of type \c T.
+template <typename T, typename = typename std::enable_if<
+ traits::IsValidOptionType<T>::value>::type>
+class OptionalRefactoringOption : public RefactoringOption {
+public:
+ void passToVisitor(RefactoringOptionVisitor &Visitor) final override {
+ Visitor.visit(*this, Value);
+ }
+
+ bool isRequired() const override { return false; }
+
+ using ValueType = Optional<T>;
+
+ const ValueType &getValue() const { return Value; }
+
+protected:
+ Optional<T> Value;
+};
+
+/// A required refactoring option that stores a value of type \c T.
+template <typename T, typename = typename std::enable_if<
+ traits::IsValidOptionType<T>::value>::type>
+class RequiredRefactoringOption : public OptionalRefactoringOption<T> {
+public:
+ using ValueType = T;
+
+ const ValueType &getValue() const {
+ return *OptionalRefactoringOption<T>::Value;
+ }
+ bool isRequired() const final override { return true; }
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTIONS_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringResultConsumer.h b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringResultConsumer.h
new file mode 100644
index 0000000000000..fe7738e734997
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringResultConsumer.h
@@ -0,0 +1,52 @@
+//===--- RefactoringResultConsumer.h - Clang refactoring library ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_RESULT_CONSUMER_H
+#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_RESULT_CONSUMER_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Tooling/Refactoring/AtomicChange.h"
+#include "clang/Tooling/Refactoring/Rename/SymbolOccurrences.h"
+#include "llvm/Support/Error.h"
+
+namespace clang {
+namespace tooling {
+
+/// An abstract interface that consumes the various refactoring results that can
+/// be produced by refactoring actions.
+///
+/// A valid refactoring result must be handled by a \c handle method.
+class RefactoringResultConsumer {
+public:
+ virtual ~RefactoringResultConsumer() {}
+
+ /// Handles an initation or an invication error. An initiation error typically
+ /// has a \c DiagnosticError payload that describes why initation failed.
+ virtual void handleError(llvm::Error Err) = 0;
+
+ /// Handles the source replacements that are produced by a refactoring action.
+ virtual void handle(AtomicChanges SourceReplacements) {
+ defaultResultHandler();
+ }
+
+ /// Handles the symbol occurrences that are found by an interactive
+ /// refactoring action.
+ virtual void handle(SymbolOccurrences Occurrences) { defaultResultHandler(); }
+
+private:
+ void defaultResultHandler() {
+ handleError(llvm::make_error<llvm::StringError>(
+ "unsupported refactoring result", llvm::inconvertibleErrorCode()));
+ }
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_RESULT_CONSUMER_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringRuleContext.h b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringRuleContext.h
new file mode 100644
index 0000000000000..882ab824b6390
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringRuleContext.h
@@ -0,0 +1,90 @@
+//===--- RefactoringRuleContext.h - Clang refactoring library -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_RULE_CONTEXT_H
+#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_RULE_CONTEXT_H
+
+#include "clang/Basic/DiagnosticError.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Tooling/Refactoring/ASTSelection.h"
+
+namespace clang {
+
+class ASTContext;
+
+namespace tooling {
+
+/// The refactoring rule context stores all of the inputs that might be needed
+/// by a refactoring action rule. It can create the specialized
+/// \c ASTRefactoringOperation or \c PreprocessorRefactoringOperation values
+/// that can be used by the refactoring action rules.
+///
+/// The following inputs are stored by the operation:
+///
+/// - SourceManager: a reference to a valid source manager.
+///
+/// - SelectionRange: an optional source selection ranges that can be used
+/// to represent a selection in an editor.
+class RefactoringRuleContext {
+public:
+ RefactoringRuleContext(const SourceManager &SM) : SM(SM) {}
+
+ const SourceManager &getSources() const { return SM; }
+
+ /// Returns the current source selection range as set by the
+ /// refactoring engine. Can be invalid.
+ SourceRange getSelectionRange() const { return SelectionRange; }
+
+ void setSelectionRange(SourceRange R) { SelectionRange = R; }
+
+ bool hasASTContext() const { return AST; }
+
+ ASTContext &getASTContext() const {
+ assert(AST && "no AST!");
+ return *AST;
+ }
+
+ void setASTContext(ASTContext &Context) { AST = &Context; }
+
+ /// Creates an llvm::Error value that contains a diagnostic.
+ ///
+ /// The errors should not outlive the context.
+ llvm::Error createDiagnosticError(SourceLocation Loc, unsigned DiagID) {
+ return DiagnosticError::create(Loc, PartialDiagnostic(DiagID, DiagStorage));
+ }
+
+ llvm::Error createDiagnosticError(unsigned DiagID) {
+ return createDiagnosticError(SourceLocation(), DiagID);
+ }
+
+ void setASTSelection(std::unique_ptr<SelectedASTNode> Node) {
+ ASTNodeSelection = std::move(Node);
+ }
+
+private:
+ /// The source manager for the translation unit / file on which a refactoring
+ /// action might operate on.
+ const SourceManager &SM;
+ /// An optional source selection range that's commonly used to represent
+ /// a selection in an editor.
+ SourceRange SelectionRange;
+ /// An optional AST for the translation unit on which a refactoring action
+ /// might operate on.
+ ASTContext *AST = nullptr;
+ /// The allocator for diagnostics.
+ PartialDiagnostic::StorageAllocator DiagStorage;
+
+ // FIXME: Remove when memoized.
+ std::unique_ptr<SelectedASTNode> ASTNodeSelection;
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_RULE_CONTEXT_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/RenamingAction.h b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/RenamingAction.h
index 099eaca6c42ae..734b624d777ba 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/RenamingAction.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/RenamingAction.h
@@ -16,6 +16,11 @@
#define LLVM_CLANG_TOOLING_REFACTOR_RENAME_RENAMING_ACTION_H
#include "clang/Tooling/Refactoring.h"
+#include "clang/Tooling/Refactoring/AtomicChange.h"
+#include "clang/Tooling/Refactoring/RefactoringActionRules.h"
+#include "clang/Tooling/Refactoring/RefactoringOptions.h"
+#include "clang/Tooling/Refactoring/Rename/SymbolOccurrences.h"
+#include "llvm/Support/Error.h"
namespace clang {
class ASTConsumer;
@@ -42,6 +47,53 @@ private:
bool PrintLocations;
};
+class RenameOccurrences final : public SourceChangeRefactoringRule {
+public:
+ static Expected<RenameOccurrences> initiate(RefactoringRuleContext &Context,
+ SourceRange SelectionRange,
+ std::string NewName);
+
+ static const RefactoringDescriptor &describe();
+
+private:
+ RenameOccurrences(const NamedDecl *ND, std::string NewName)
+ : ND(ND), NewName(std::move(NewName)) {}
+
+ Expected<AtomicChanges>
+ createSourceReplacements(RefactoringRuleContext &Context) override;
+
+ const NamedDecl *ND;
+ std::string NewName;
+};
+
+class QualifiedRenameRule final : public SourceChangeRefactoringRule {
+public:
+ static Expected<QualifiedRenameRule> initiate(RefactoringRuleContext &Context,
+ std::string OldQualifiedName,
+ std::string NewQualifiedName);
+
+ static const RefactoringDescriptor &describe();
+
+private:
+ QualifiedRenameRule(const NamedDecl *ND,
+ std::string NewQualifiedName)
+ : ND(ND), NewQualifiedName(std::move(NewQualifiedName)) {}
+
+ Expected<AtomicChanges>
+ createSourceReplacements(RefactoringRuleContext &Context) override;
+
+ // A NamedDecl which indentifies the the symbol being renamed.
+ const NamedDecl *ND;
+ // The new qualified name to change the symbol to.
+ std::string NewQualifiedName;
+};
+
+/// Returns source replacements that correspond to the rename of the given
+/// symbol occurrences.
+llvm::Expected<std::vector<AtomicChange>>
+createRenameReplacements(const SymbolOccurrences &Occurrences,
+ const SourceManager &SM, const SymbolName &NewName);
+
/// Rename all symbols identified by the given USRs.
class QualifiedRenamingAction {
public:
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/SymbolName.h b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/SymbolName.h
new file mode 100644
index 0000000000000..e69d2908b5d30
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/SymbolName.h
@@ -0,0 +1,49 @@
+//===--- SymbolName.h - Clang refactoring library -------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_RENAME_SYMBOL_NAME_H
+#define LLVM_CLANG_TOOLING_REFACTOR_RENAME_SYMBOL_NAME_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+namespace tooling {
+
+/// A name of a symbol.
+///
+/// Symbol's name can be composed of multiple strings. For example, Objective-C
+/// methods can contain multiple argument lables:
+///
+/// \code
+/// - (void) myMethodNamePiece: (int)x anotherNamePieces:(int)y;
+/// // ^~ string 0 ~~~~~ ^~ string 1 ~~~~~
+/// \endcode
+class SymbolName {
+public:
+ explicit SymbolName(StringRef Name) {
+ // While empty symbol names are valid (Objective-C selectors can have empty
+ // name pieces), occurrences Objective-C selectors are created using an
+ // array of strings instead of just one string.
+ assert(!Name.empty() && "Invalid symbol name!");
+ this->Name.push_back(Name.str());
+ }
+
+ ArrayRef<std::string> getNamePieces() const { return Name; }
+
+private:
+ llvm::SmallVector<std::string, 1> Name;
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_RENAME_SYMBOL_NAME_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/SymbolOccurrences.h b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/SymbolOccurrences.h
new file mode 100644
index 0000000000000..0f853011978f1
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/SymbolOccurrences.h
@@ -0,0 +1,91 @@
+//===--- SymbolOccurrences.h - Clang refactoring library ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_RENAME_SYMBOL_OCCURRENCES_H
+#define LLVM_CLANG_TOOLING_REFACTOR_RENAME_SYMBOL_OCCURRENCES_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include <vector>
+
+namespace clang {
+namespace tooling {
+
+class SymbolName;
+
+/// An occurrence of a symbol in the source.
+///
+/// Occurrences can have difference kinds, that describe whether this occurrence
+/// is an exact semantic match, or whether this is a weaker textual match that's
+/// not guaranteed to represent the exact declaration.
+///
+/// A single occurrence of a symbol can span more than one source range. For
+/// example, Objective-C selectors can contain multiple argument labels:
+///
+/// \code
+/// [object selectorPiece1: ... selectorPiece2: ...];
+/// // ^~~ range 0 ~~ ^~~ range 1 ~~
+/// \endcode
+///
+/// We have to replace the text in both range 0 and range 1 when renaming the
+/// Objective-C method 'selectorPiece1:selectorPiece2'.
+class SymbolOccurrence {
+public:
+ enum OccurrenceKind {
+ /// This occurrence is an exact match and can be renamed automatically.
+ ///
+ /// Note:
+ /// Symbol occurrences in macro arguments that expand to different
+ /// declarations get marked as exact matches, and thus the renaming engine
+ /// will rename them e.g.:
+ ///
+ /// \code
+ /// #define MACRO(x) x + ns::x
+ /// int foo(int var) {
+ /// return MACRO(var); // var is renamed automatically here when
+ /// // either var or ns::var is renamed.
+ /// };
+ /// \endcode
+ ///
+ /// The user will have to fix their code manually after performing such a
+ /// rename.
+ /// FIXME: The rename verifier should notify user about this issue.
+ MatchingSymbol
+ };
+
+ SymbolOccurrence(const SymbolName &Name, OccurrenceKind Kind,
+ ArrayRef<SourceLocation> Locations);
+
+ SymbolOccurrence(SymbolOccurrence &&) = default;
+ SymbolOccurrence &operator=(SymbolOccurrence &&) = default;
+
+ OccurrenceKind getKind() const { return Kind; }
+
+ ArrayRef<SourceRange> getNameRanges() const {
+ if (MultipleRanges) {
+ return llvm::makeArrayRef(MultipleRanges.get(),
+ RangeOrNumRanges.getBegin().getRawEncoding());
+ }
+ return RangeOrNumRanges;
+ }
+
+private:
+ OccurrenceKind Kind;
+ std::unique_ptr<SourceRange[]> MultipleRanges;
+ SourceRange RangeOrNumRanges;
+};
+
+using SymbolOccurrences = std::vector<SymbolOccurrence>;
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_RENAME_SYMBOL_OCCURRENCES_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h
index 8aafee95bc097..f1c5ae60f875c 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h
@@ -23,11 +23,25 @@
namespace clang {
class ASTConsumer;
+class ASTContext;
class CompilerInstance;
class NamedDecl;
namespace tooling {
+/// Returns the canonical declaration that best represents a symbol that can be
+/// renamed.
+///
+/// The following canonicalization rules are currently used:
+///
+/// - A constructor is canonicalized to its class.
+/// - A destructor is canonicalized to its class.
+const NamedDecl *getCanonicalSymbolDeclaration(const NamedDecl *FoundDecl);
+
+/// Returns the set of USRs that correspond to the given declaration.
+std::vector<std::string> getUSRsForDeclaration(const NamedDecl *ND,
+ ASTContext &Context);
+
struct USRFindingAction {
USRFindingAction(ArrayRef<unsigned> SymbolOffsets,
ArrayRef<std::string> QualifiedNames, bool Force)
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h
index 733ea1a6ac9ed..801a8ad9e99c6 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h
@@ -19,6 +19,7 @@
#include "clang/AST/AST.h"
#include "clang/Tooling/Core/Replacement.h"
#include "clang/Tooling/Refactoring/AtomicChange.h"
+#include "clang/Tooling/Refactoring/Rename/SymbolOccurrences.h"
#include "llvm/ADT/StringRef.h"
#include <string>
#include <vector>
@@ -38,10 +39,13 @@ std::vector<tooling::AtomicChange>
createRenameAtomicChanges(llvm::ArrayRef<std::string> USRs,
llvm::StringRef NewName, Decl *TranslationUnitDecl);
-// FIXME: make this an AST matcher. Wouldn't that be awesome??? I agree!
-std::vector<SourceLocation>
-getLocationsOfUSRs(const std::vector<std::string> &USRs,
- llvm::StringRef PrevName, Decl *Decl);
+/// Finds the symbol occurrences for the symbol that's identified by the given
+/// USR set.
+///
+/// \return SymbolOccurrences that can be converted to AtomicChanges when
+/// renaming.
+SymbolOccurrences getOccurrencesOfUSRs(ArrayRef<std::string> USRs,
+ StringRef PrevName, Decl *Decl);
} // end namespace tooling
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/StandaloneExecution.h b/contrib/llvm/tools/clang/include/clang/Tooling/StandaloneExecution.h
new file mode 100644
index 0000000000000..f5f32d737a452
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/StandaloneExecution.h
@@ -0,0 +1,97 @@
+//===--- StandaloneExecution.h - Standalone execution. -*- C++ ----------*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines standalone execution of clang tools.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_STANDALONEEXECUTION_H
+#define LLVM_CLANG_TOOLING_STANDALONEEXECUTION_H
+
+#include "clang/Tooling/ArgumentsAdjusters.h"
+#include "clang/Tooling/Execution.h"
+
+namespace clang {
+namespace tooling {
+
+/// \brief A standalone executor that runs FrontendActions on a given set of
+/// TUs in sequence.
+///
+/// By default, this executor uses the following arguments adjusters (as defined
+/// in `clang/Tooling/ArgumentsAdjusters.h`):
+/// - `getClangStripOutputAdjuster()`
+/// - `getClangSyntaxOnlyAdjuster()`
+/// - `getClangStripDependencyFileAdjuster()`
+class StandaloneToolExecutor : public ToolExecutor {
+public:
+ static const char *ExecutorName;
+
+ /// \brief Init with \p CompilationDatabase and the paths of all files to be
+ /// proccessed.
+ StandaloneToolExecutor(
+ const CompilationDatabase &Compilations,
+ llvm::ArrayRef<std::string> SourcePaths,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps =
+ std::make_shared<PCHContainerOperations>());
+
+ /// \brief Init with \p CommonOptionsParser. This is expected to be used by
+ /// `createExecutorFromCommandLineArgs` based on commandline options.
+ ///
+ /// The executor takes ownership of \p Options.
+ StandaloneToolExecutor(
+ CommonOptionsParser Options,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps =
+ std::make_shared<PCHContainerOperations>());
+
+ StringRef getExecutorName() const override { return ExecutorName; }
+
+ using ToolExecutor::execute;
+
+ llvm::Error
+ execute(llvm::ArrayRef<
+ std::pair<std::unique_ptr<FrontendActionFactory>, ArgumentsAdjuster>>
+ Actions) override;
+
+ /// \brief Set a \c DiagnosticConsumer to use during parsing.
+ void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer) {
+ Tool.setDiagnosticConsumer(DiagConsumer);
+ }
+
+ ExecutionContext *getExecutionContext() override { return &Context; };
+
+ ToolResults *getToolResults() override { return &Results; }
+
+ llvm::ArrayRef<std::string> getSourcePaths() const {
+ return Tool.getSourcePaths();
+ }
+
+ void mapVirtualFile(StringRef FilePath, StringRef Content) override {
+ Tool.mapVirtualFile(FilePath, Content);
+ }
+
+ /// \brief Returns the file manager used in the tool.
+ ///
+ /// The file manager is shared between all translation units.
+ FileManager &getFiles() { return Tool.getFiles(); }
+
+private:
+ // Used to store the parser when the executor is initialized with parser.
+ llvm::Optional<CommonOptionsParser> OptionsParser;
+ // FIXME: The standalone executor is currently just a wrapper of `ClangTool`.
+ // Merge `ClangTool` implementation into the this.
+ ClangTool Tool;
+ ExecutionContext Context;
+ InMemoryToolResults Results;
+ ArgumentsAdjuster ArgsAdjuster;
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_STANDALONEEXECUTION_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/ToolExecutorPluginRegistry.h b/contrib/llvm/tools/clang/include/clang/Tooling/ToolExecutorPluginRegistry.h
new file mode 100644
index 0000000000000..11ba89546e9ea
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/ToolExecutorPluginRegistry.h
@@ -0,0 +1,24 @@
+//===--- ToolExecutorPluginRegistry.h - -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H
+#define LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H
+
+#include "clang/Tooling/Execution.h"
+#include "llvm/Support/Registry.h"
+
+namespace clang {
+namespace tooling {
+
+typedef llvm::Registry<ToolExecutorPlugin> ToolExecutorPluginRegistry;
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Tooling.h b/contrib/llvm/tools/clang/include/clang/Tooling/Tooling.h
index 6f9bc9e1a1504..e64be07d9ab44 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/Tooling.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Tooling.h
@@ -31,12 +31,12 @@
#define LLVM_CLANG_TOOLING_TOOLING_H
#include "clang/AST/ASTConsumer.h"
-#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LLVM.h"
#include "clang/Driver/Util.h"
#include "clang/Frontend/FrontendAction.h"
+#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/Lex/ModuleLoader.h"
#include "clang/Tooling/ArgumentsAdjusters.h"
#include "clang/Tooling/CompilationDatabase.h"
@@ -337,7 +337,9 @@ class ClangTool {
/// The file manager is shared between all translation units.
FileManager &getFiles() { return *Files; }
- private:
+ llvm::ArrayRef<std::string> getSourcePaths() const { return SourcePaths; }
+
+private:
const CompilationDatabase &Compilations;
std::vector<std::string> SourcePaths;
std::shared_ptr<PCHContainerOperations> PCHContainerOps;
diff --git a/contrib/llvm/tools/clang/include/clang/module.modulemap b/contrib/llvm/tools/clang/include/clang/module.modulemap
index d850bd552e1fd..4097ad2dc7164 100644
--- a/contrib/llvm/tools/clang/include/clang/module.modulemap
+++ b/contrib/llvm/tools/clang/include/clang/module.modulemap
@@ -49,6 +49,7 @@ module Clang_Basic {
textual header "Basic/OperatorKinds.def"
textual header "Basic/Sanitizers.def"
textual header "Basic/TokenKinds.def"
+ textual header "Basic/X86Target.def"
module * { export * }
}
@@ -69,9 +70,9 @@ module Clang_Diagnostics {
module Frontend { header "Frontend/FrontendDiagnostic.h" export * }
module Lex { header "Lex/LexDiagnostic.h" export * }
module Parse { header "Parse/ParseDiagnostic.h" export * }
- // FIXME: This breaks the build of Clang_Sema, for unknown reasons.
- //module Sema { header "Sema/SemaDiagnostic.h" export * }
+ module Sema { header "Sema/SemaDiagnostic.h" export * }
module Serialization { header "Serialization/SerializationDiagnostic.h" export * }
+ module Refactoring { header "Tooling/Refactoring/RefactoringDiagnostic.h" export * }
}
module Clang_Driver {
@@ -90,7 +91,6 @@ module Clang_Frontend {
requires cplusplus
umbrella "Frontend"
- textual header "Frontend/CodeGenOptions.def"
textual header "Frontend/LangStandards.def"
module * { export * }
@@ -99,11 +99,20 @@ module Clang_Frontend {
exclude header "Frontend/PCHContainerOperations.h"
}
+// Used in clangBasic
+module Clang_Frontend_CodeGenOptions {
+ requires cplusplus
+ header "Frontend/CodeGenOptions.h"
+ textual header "Frontend/CodeGenOptions.def"
+ export *
+}
+
module Clang_FrontendTool { requires cplusplus umbrella "FrontendTool" module * { export * } }
module Clang_Index { requires cplusplus umbrella "Index" module * { export * } }
module Clang_Lex { requires cplusplus umbrella "Lex" module * { export * } }
module Clang_Parse { requires cplusplus umbrella "Parse" module * { export * } }
-module Clang_Rewrite { requires cplusplus umbrella "Rewrite" module * { export * } }
+module Clang_Rewrite { requires cplusplus umbrella "Rewrite/Core" module * { export * } }
+module Clang_RewriteFrontend { requires cplusplus umbrella "Rewrite/Frontend" module * { export * } }
module Clang_Sema { requires cplusplus umbrella "Sema" module * { export * } }
module Clang_Serialization { requires cplusplus umbrella "Serialization" module * { export * } }
@@ -139,3 +148,8 @@ module Clang_Tooling {
// matchers (and thus the AST), which clang-format should not have.
exclude header "Tooling/RefactoringCallbacks.h"
}
+
+module Clang_ToolingCore {
+ requires cplusplus
+ umbrella "Tooling/Core" module * { export * }
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp
index c60373c5a90a4..dd96148edb272 100644
--- a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp
@@ -1,4 +1,4 @@
-//===--- ASTContext.cpp - Context to hold long-lived AST nodes ------------===//
+//===- ASTContext.cpp - Context to hold long-lived AST nodes --------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,33 +13,83 @@
#include "clang/AST/ASTContext.h"
#include "CXXABI.h"
+#include "clang/AST/APValue.h"
#include "clang/AST/ASTMutationListener.h"
+#include "clang/AST/ASTTypeTraits.h"
#include "clang/AST/Attr.h"
+#include "clang/AST/AttrIterator.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/Comment.h"
-#include "clang/AST/CommentCommandTraits.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclContextInternals.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclOpenMP.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/Mangle.h"
#include "clang/AST/MangleNumberingContext.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/RawCommentList.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/TemplateName.h"
+#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
+#include "clang/AST/UnresolvedSet.h"
#include "clang/AST/VTableBuilder.h"
+#include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/Builtins.h"
+#include "clang/Basic/CommentOptions.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/Linkage.h"
+#include "clang/Basic/ObjCRuntime.h"
+#include "clang/Basic/SanitizerBlacklist.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Basic/TargetCXXABI.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/XRayLists.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/Capacity.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
#include <map>
+#include <memory>
+#include <string>
+#include <tuple>
+#include <utility>
using namespace clang;
@@ -57,7 +107,7 @@ unsigned ASTContext::NumImplicitDestructors;
unsigned ASTContext::NumImplicitDestructorsDeclared;
enum FloatingRank {
- HalfRank, FloatRank, DoubleRank, LongDoubleRank, Float128Rank
+ Float16Rank, HalfRank, FloatRank, DoubleRank, LongDoubleRank, Float128Rank
};
RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const {
@@ -256,11 +306,10 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const {
return *Comment;
}
-namespace {
/// If we have a 'templated' declaration for a template, adjust 'D' to
/// refer to the actual template.
/// If we have an implicit instantiation, adjust 'D' to refer to template.
-const Decl *adjustDeclToTemplate(const Decl *D) {
+static const Decl *adjustDeclToTemplate(const Decl *D) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
// Is this function declaration part of a function template?
if (const FunctionTemplateDecl *FTD = FD->getDescribedFunctionTemplate())
@@ -327,7 +376,6 @@ const Decl *adjustDeclToTemplate(const Decl *D) {
// FIXME: Adjust alias templates?
return D;
}
-} // anonymous namespace
const RawComment *ASTContext::getRawCommentForAnyRedecl(
const Decl *D,
@@ -697,8 +745,8 @@ CXXABI *ASTContext::createCXXABI(const TargetInfo &T) {
llvm_unreachable("Invalid CXXABI type!");
}
-static const LangAS::Map *getAddressSpaceMap(const TargetInfo &T,
- const LangOptions &LOpts) {
+static const LangASMap *getAddressSpaceMap(const TargetInfo &T,
+ const LangOptions &LOpts) {
if (LOpts.FakeAddressSpaceMap) {
// The fake address space map must have a distinct entry for each
// language-specific address space.
@@ -707,6 +755,7 @@ static const LangAS::Map *getAddressSpaceMap(const TargetInfo &T,
1, // opencl_global
3, // opencl_local
2, // opencl_constant
+ 0, // opencl_private
4, // opencl_generic
5, // cuda_device
6, // cuda_constant
@@ -736,25 +785,12 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM,
Builtin::Context &builtins)
: FunctionProtoTypes(this_()), TemplateSpecializationTypes(this_()),
DependentTemplateSpecializationTypes(this_()),
- SubstTemplateTemplateParmPacks(this_()),
- GlobalNestedNameSpecifier(nullptr), Int128Decl(nullptr),
- UInt128Decl(nullptr), BuiltinVaListDecl(nullptr),
- BuiltinMSVaListDecl(nullptr), ObjCIdDecl(nullptr), ObjCSelDecl(nullptr),
- ObjCClassDecl(nullptr), ObjCProtocolClassDecl(nullptr), BOOLDecl(nullptr),
- CFConstantStringTagDecl(nullptr), CFConstantStringTypeDecl(nullptr),
- ObjCInstanceTypeDecl(nullptr), FILEDecl(nullptr), jmp_bufDecl(nullptr),
- sigjmp_bufDecl(nullptr), ucontext_tDecl(nullptr),
- BlockDescriptorType(nullptr), BlockDescriptorExtendedType(nullptr),
- cudaConfigureCallDecl(nullptr), FirstLocalImport(), LastLocalImport(),
- ExternCContext(nullptr), MakeIntegerSeqDecl(nullptr),
- TypePackElementDecl(nullptr), SourceMgr(SM), LangOpts(LOpts),
+ SubstTemplateTemplateParmPacks(this_()), SourceMgr(SM), LangOpts(LOpts),
SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFiles, SM)),
XRayFilter(new XRayFunctionFilter(LangOpts.XRayAlwaysInstrumentFiles,
LangOpts.XRayNeverInstrumentFiles, SM)),
- AddrSpaceMap(nullptr), Target(nullptr), AuxTarget(nullptr),
PrintingPolicy(LOpts), Idents(idents), Selectors(sels),
- BuiltinInfo(builtins), DeclarationNames(*this), ExternalSource(nullptr),
- Listener(nullptr), Comments(SM), CommentsLoaded(false),
+ BuiltinInfo(builtins), DeclarationNames(*this), Comments(SM),
CommentCommandTraits(BumpAlloc, LOpts.CommentOpts), LastSDM(nullptr, 0) {
TUDecl = TranslationUnitDecl::Create(*this);
}
@@ -1093,6 +1129,9 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target,
// GNU extension, __float128 for IEEE quadruple precision
InitBuiltinType(Float128Ty, BuiltinType::Float128);
+ // C11 extension ISO/IEC TS 18661-3
+ InitBuiltinType(Float16Ty, BuiltinType::Float16);
+
// GNU extension, 128-bit integers.
InitBuiltinType(Int128Ty, BuiltinType::Int128);
InitBuiltinType(UnsignedInt128Ty, BuiltinType::UInt128);
@@ -1182,7 +1221,14 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target,
ObjCSuperType = QualType();
// void * type
- VoidPtrTy = getPointerType(VoidTy);
+ if (LangOpts.OpenCLVersion >= 200) {
+ auto Q = VoidTy.getQualifiers();
+ Q.setAddressSpace(LangAS::opencl_generic);
+ VoidPtrTy = getPointerType(getCanonicalType(
+ getQualifiedType(VoidTy.getUnqualifiedType(), Q)));
+ } else {
+ VoidPtrTy = getPointerType(VoidTy);
+ }
// nullptr type (C++0x 2.14.7)
InitBuiltinType(NullPtrTy, BuiltinType::NullPtr);
@@ -1209,7 +1255,7 @@ AttrVec& ASTContext::getDeclAttrs(const Decl *D) {
}
/// \brief Erase the attributes corresponding to the given declaration.
-void ASTContext::eraseDeclAttrs(const Decl *D) {
+void ASTContext::eraseDeclAttrs(const Decl *D) {
llvm::DenseMap<const Decl*, AttrVec*>::iterator Pos = DeclAttrs.find(D);
if (Pos != DeclAttrs.end()) {
Pos->second->~AttrVec();
@@ -1332,35 +1378,27 @@ void ASTContext::setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst,
ASTContext::overridden_cxx_method_iterator
ASTContext::overridden_methods_begin(const CXXMethodDecl *Method) const {
- llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos =
- OverriddenMethods.find(Method->getCanonicalDecl());
- if (Pos == OverriddenMethods.end())
- return nullptr;
- return Pos->second.begin();
+ return overridden_methods(Method).begin();
}
ASTContext::overridden_cxx_method_iterator
ASTContext::overridden_methods_end(const CXXMethodDecl *Method) const {
- llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos =
- OverriddenMethods.find(Method->getCanonicalDecl());
- if (Pos == OverriddenMethods.end())
- return nullptr;
- return Pos->second.end();
+ return overridden_methods(Method).end();
}
unsigned
ASTContext::overridden_methods_size(const CXXMethodDecl *Method) const {
- llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos =
- OverriddenMethods.find(Method->getCanonicalDecl());
- if (Pos == OverriddenMethods.end())
- return 0;
- return Pos->second.size();
+ auto Range = overridden_methods(Method);
+ return Range.end() - Range.begin();
}
ASTContext::overridden_method_range
ASTContext::overridden_methods(const CXXMethodDecl *Method) const {
- return overridden_method_range(overridden_methods_begin(Method),
- overridden_methods_end(Method));
+ llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos =
+ OverriddenMethods.find(Method->getCanonicalDecl());
+ if (Pos == OverriddenMethods.end())
+ return overridden_method_range(nullptr, nullptr);
+ return overridden_method_range(Pos->second.begin(), Pos->second.end());
}
void ASTContext::addOverriddenMethod(const CXXMethodDecl *Method,
@@ -1413,7 +1451,9 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const {
assert(BT && "Not a floating point type!");
switch (BT->getKind()) {
default: llvm_unreachable("Not a floating point type!");
- case BuiltinType::Half: return Target->getHalfFormat();
+ case BuiltinType::Float16:
+ case BuiltinType::Half:
+ return Target->getHalfFormat();
case BuiltinType::Float: return Target->getFloatFormat();
case BuiltinType::Double: return Target->getDoubleFormat();
case BuiltinType::LongDouble: return Target->getLongDoubleFormat();
@@ -1450,7 +1490,6 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const {
// else about the declaration and its type.
if (UseAlignAttrOnly) {
// do nothing
-
} else if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
QualType T = VD->getType();
if (const ReferenceType *RT = T->getAs<ReferenceType>()) {
@@ -1624,6 +1663,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
uint64_t Width = 0;
unsigned Align = 8;
bool AlignIsRequired = false;
+ unsigned AS = 0;
switch (T->getTypeClass()) {
#define TYPE(Class, Base)
#define ABSTRACT_TYPE(Class, Base)
@@ -1690,7 +1730,6 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
Width = 0;
Align = 8;
break;
-
case BuiltinType::Bool:
Width = Target->getBoolWidth();
Align = Target->getBoolAlign();
@@ -1740,6 +1779,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
Width = 128;
Align = 128; // int128_t is 128-bit aligned on all targets.
break;
+ case BuiltinType::Float16:
case BuiltinType::Half:
Width = Target->getHalfWidth();
Align = Target->getHalfAlign();
@@ -1770,60 +1810,48 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
Width = Target->getPointerWidth(0);
Align = Target->getPointerAlign(0);
break;
- case BuiltinType::OCLSampler: {
- auto AS = getTargetAddressSpace(LangAS::opencl_constant);
- Width = Target->getPointerWidth(AS);
- Align = Target->getPointerAlign(AS);
- break;
- }
+ case BuiltinType::OCLSampler:
case BuiltinType::OCLEvent:
case BuiltinType::OCLClkEvent:
case BuiltinType::OCLQueue:
case BuiltinType::OCLReserveID:
- // Currently these types are pointers to opaque types.
- Width = Target->getPointerWidth(0);
- Align = Target->getPointerAlign(0);
- break;
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
case BuiltinType::Id:
#include "clang/Basic/OpenCLImageTypes.def"
- {
- auto AS = getTargetAddressSpace(Target->getOpenCLImageAddrSpace());
- Width = Target->getPointerWidth(AS);
- Align = Target->getPointerAlign(AS);
- }
+ AS = getTargetAddressSpace(
+ Target->getOpenCLTypeAddrSpace(getOpenCLTypeKind(T)));
+ Width = Target->getPointerWidth(AS);
+ Align = Target->getPointerAlign(AS);
+ break;
}
break;
case Type::ObjCObjectPointer:
Width = Target->getPointerWidth(0);
Align = Target->getPointerAlign(0);
break;
- case Type::BlockPointer: {
- unsigned AS = getTargetAddressSpace(
- cast<BlockPointerType>(T)->getPointeeType());
+ case Type::BlockPointer:
+ AS = getTargetAddressSpace(cast<BlockPointerType>(T)->getPointeeType());
Width = Target->getPointerWidth(AS);
Align = Target->getPointerAlign(AS);
break;
- }
case Type::LValueReference:
- case Type::RValueReference: {
+ case Type::RValueReference:
// alignof and sizeof should never enter this code path here, so we go
// the pointer route.
- unsigned AS = getTargetAddressSpace(
- cast<ReferenceType>(T)->getPointeeType());
+ AS = getTargetAddressSpace(cast<ReferenceType>(T)->getPointeeType());
Width = Target->getPointerWidth(AS);
Align = Target->getPointerAlign(AS);
break;
- }
- case Type::Pointer: {
- unsigned AS = getTargetAddressSpace(cast<PointerType>(T)->getPointeeType());
+ case Type::Pointer:
+ AS = getTargetAddressSpace(cast<PointerType>(T)->getPointeeType());
Width = Target->getPointerWidth(AS);
Align = Target->getPointerAlign(AS);
break;
- }
case Type::MemberPointer: {
const MemberPointerType *MPT = cast<MemberPointerType>(T);
- std::tie(Width, Align) = ABI->getMemberPointerWidthAndAlign(MPT);
+ CXXABI::MemberPointerInfo MPI = ABI->getMemberPointerInfo(MPT);
+ Width = MPI.Width;
+ Align = MPI.Align;
break;
}
case Type::Complex: {
@@ -1938,11 +1966,10 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
}
break;
- case Type::Pipe: {
+ case Type::Pipe:
Width = Target->getPointerWidth(getTargetAddressSpace(LangAS::opencl_global));
Align = Target->getPointerAlign(getTargetAddressSpace(LangAS::opencl_global));
- }
-
+ break;
}
assert(llvm::isPowerOf2_32(Align) && "Alignment must be power of 2");
@@ -2055,7 +2082,6 @@ CharUnits ASTContext::getOffsetOfBaseWithVBPtr(const CXXRecordDecl *RD) const {
/// super class and then collects all ivars, including those synthesized for
/// current class. This routine is used for implementation of current class
/// when all ivars, declared and synthesized are known.
-///
void ASTContext::DeepCollectObjCIvars(const ObjCInterfaceDecl *OI,
bool leafClass,
SmallVectorImpl<const ObjCIvarDecl*> &Ivars) const {
@@ -2107,6 +2133,171 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl,
}
}
+static bool unionHasUniqueObjectRepresentations(const ASTContext &Context,
+ const RecordDecl *RD) {
+ assert(RD->isUnion() && "Must be union type");
+ CharUnits UnionSize = Context.getTypeSizeInChars(RD->getTypeForDecl());
+
+ for (const auto *Field : RD->fields()) {
+ if (!Context.hasUniqueObjectRepresentations(Field->getType()))
+ return false;
+ CharUnits FieldSize = Context.getTypeSizeInChars(Field->getType());
+ if (FieldSize != UnionSize)
+ return false;
+ }
+ return true;
+}
+
+bool isStructEmpty(QualType Ty) {
+ const RecordDecl *RD = Ty->castAs<RecordType>()->getDecl();
+
+ if (!RD->field_empty())
+ return false;
+
+ if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RD))
+ return ClassDecl->isEmpty();
+
+ return true;
+}
+
+static llvm::Optional<int64_t>
+structHasUniqueObjectRepresentations(const ASTContext &Context,
+ const RecordDecl *RD) {
+ assert(!RD->isUnion() && "Must be struct/class type");
+ const auto &Layout = Context.getASTRecordLayout(RD);
+
+ int64_t CurOffsetInBits = 0;
+ if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RD)) {
+ if (ClassDecl->isDynamicClass())
+ return llvm::None;
+
+ SmallVector<std::pair<QualType, int64_t>, 4> Bases;
+ for (const auto Base : ClassDecl->bases()) {
+ // Empty types can be inherited from, and non-empty types can potentially
+ // have tail padding, so just make sure there isn't an error.
+ if (!isStructEmpty(Base.getType())) {
+ llvm::Optional<int64_t> Size = structHasUniqueObjectRepresentations(
+ Context, Base.getType()->getAs<RecordType>()->getDecl());
+ if (!Size)
+ return llvm::None;
+ Bases.emplace_back(Base.getType(), Size.getValue());
+ }
+ }
+
+ std::sort(
+ Bases.begin(), Bases.end(), [&](const std::pair<QualType, int64_t> &L,
+ const std::pair<QualType, int64_t> &R) {
+ return Layout.getBaseClassOffset(L.first->getAsCXXRecordDecl()) <
+ Layout.getBaseClassOffset(R.first->getAsCXXRecordDecl());
+ });
+
+ for (const auto Base : Bases) {
+ int64_t BaseOffset = Context.toBits(
+ Layout.getBaseClassOffset(Base.first->getAsCXXRecordDecl()));
+ int64_t BaseSize = Base.second;
+ if (BaseOffset != CurOffsetInBits)
+ return llvm::None;
+ CurOffsetInBits = BaseOffset + BaseSize;
+ }
+ }
+
+ for (const auto *Field : RD->fields()) {
+ if (!Field->getType()->isReferenceType() &&
+ !Context.hasUniqueObjectRepresentations(Field->getType()))
+ return llvm::None;
+
+ int64_t FieldSizeInBits =
+ Context.toBits(Context.getTypeSizeInChars(Field->getType()));
+ if (Field->isBitField()) {
+ int64_t BitfieldSize = Field->getBitWidthValue(Context);
+
+ if (BitfieldSize > FieldSizeInBits)
+ return llvm::None;
+ FieldSizeInBits = BitfieldSize;
+ }
+
+ int64_t FieldOffsetInBits = Context.getFieldOffset(Field);
+
+ if (FieldOffsetInBits != CurOffsetInBits)
+ return llvm::None;
+
+ CurOffsetInBits = FieldSizeInBits + FieldOffsetInBits;
+ }
+
+ return CurOffsetInBits;
+}
+
+bool ASTContext::hasUniqueObjectRepresentations(QualType Ty) const {
+ // C++17 [meta.unary.prop]:
+ // The predicate condition for a template specialization
+ // has_unique_object_representations<T> shall be
+ // satisfied if and only if:
+ // (9.1) - T is trivially copyable, and
+ // (9.2) - any two objects of type T with the same value have the same
+ // object representation, where two objects
+ // of array or non-union class type are considered to have the same value
+ // if their respective sequences of
+ // direct subobjects have the same values, and two objects of union type
+ // are considered to have the same
+ // value if they have the same active member and the corresponding members
+ // have the same value.
+ // The set of scalar types for which this condition holds is
+ // implementation-defined. [ Note: If a type has padding
+ // bits, the condition does not hold; otherwise, the condition holds true
+ // for unsigned integral types. -- end note ]
+ assert(!Ty.isNull() && "Null QualType sent to unique object rep check");
+
+ // Arrays are unique only if their element type is unique.
+ if (Ty->isArrayType())
+ return hasUniqueObjectRepresentations(getBaseElementType(Ty));
+
+ // (9.1) - T is trivially copyable...
+ if (!Ty.isTriviallyCopyableType(*this))
+ return false;
+
+ // All integrals and enums are unique.
+ if (Ty->isIntegralOrEnumerationType())
+ return true;
+
+ // All other pointers are unique.
+ if (Ty->isPointerType())
+ return true;
+
+ if (Ty->isMemberPointerType()) {
+ const MemberPointerType *MPT = Ty->getAs<MemberPointerType>();
+ return !ABI->getMemberPointerInfo(MPT).HasPadding;
+ }
+
+ if (Ty->isRecordType()) {
+ const RecordDecl *Record = Ty->getAs<RecordType>()->getDecl();
+
+ if (Record->isInvalidDecl())
+ return false;
+
+ if (Record->isUnion())
+ return unionHasUniqueObjectRepresentations(*this, Record);
+
+ Optional<int64_t> StructSize =
+ structHasUniqueObjectRepresentations(*this, Record);
+
+ return StructSize &&
+ StructSize.getValue() == static_cast<int64_t>(getTypeSize(Ty));
+ }
+
+ // FIXME: More cases to handle here (list by rsmith):
+ // vectors (careful about, eg, vector of 3 foo)
+ // _Complex int and friends
+ // _Atomic T
+ // Obj-C block pointers
+ // Obj-C object pointers
+ // and perhaps OpenCL's various builtin types (pipe, sampler_t, event_t,
+ // clk_event_t, queue_t, reserve_id_t)
+ // There're also Obj-C class types and the Obj-C selector type, but I think it
+ // makes sense for those to return false here.
+
+ return false;
+}
+
unsigned ASTContext::CountNonClassIvars(const ObjCInterfaceDecl *OI) const {
unsigned count = 0;
// Count ivars declared in class extension.
@@ -2139,7 +2330,8 @@ bool ASTContext::isSentinelNullExpr(const Expr *E) {
return false;
}
-/// \brief Get the implementation of ObjCInterfaceDecl,or NULL if none exists.
+/// \brief Get the implementation of ObjCInterfaceDecl, or nullptr if none
+/// exists.
ObjCImplementationDecl *ASTContext::getObjCImplementation(ObjCInterfaceDecl *D) {
llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*>::iterator
I = ObjCImpls.find(D);
@@ -2147,7 +2339,9 @@ ObjCImplementationDecl *ASTContext::getObjCImplementation(ObjCInterfaceDecl *D)
return cast<ObjCImplementationDecl>(I->second);
return nullptr;
}
-/// \brief Get the implementation of ObjCCategoryDecl, or NULL if none exists.
+
+/// \brief Get the implementation of ObjCCategoryDecl, or nullptr if none
+/// exists.
ObjCCategoryImplDecl *ASTContext::getObjCImplementation(ObjCCategoryDecl *D) {
llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*>::iterator
I = ObjCImpls.find(D);
@@ -2162,6 +2356,7 @@ void ASTContext::setObjCImplementation(ObjCInterfaceDecl *IFaceD,
assert(IFaceD && ImplD && "Passed null params");
ObjCImpls[IFaceD] = ImplD;
}
+
/// \brief Set the implementation of ObjCCategoryDecl.
void ASTContext::setObjCImplementation(ObjCCategoryDecl *CatD,
ObjCCategoryImplDecl *ImplD) {
@@ -2195,7 +2390,7 @@ const ObjCInterfaceDecl *ASTContext::getObjContainingInterface(
return nullptr;
}
-/// \brief Get the copy initialization expression of VarDecl,or NULL if
+/// \brief Get the copy initialization expression of VarDecl, or nullptr if
/// none exists.
Expr *ASTContext::getBlockVarCopyInits(const VarDecl*VD) {
assert(VD && "Passed null params");
@@ -2280,8 +2475,8 @@ ASTContext::getExtQualType(const Type *baseType, Qualifiers quals) const {
return QualType(eq, fastQuals);
}
-QualType
-ASTContext::getAddrSpaceQualType(QualType T, unsigned AddressSpace) const {
+QualType ASTContext::getAddrSpaceQualType(QualType T,
+ LangAS AddressSpace) const {
QualType CanT = getCanonicalType(T);
if (CanT.getAddressSpace() == AddressSpace)
return T;
@@ -2300,6 +2495,27 @@ ASTContext::getAddrSpaceQualType(QualType T, unsigned AddressSpace) const {
return getExtQualType(TypeNode, Quals);
}
+QualType ASTContext::removeAddrSpaceQualType(QualType T) const {
+ // If we are composing extended qualifiers together, merge together
+ // into one ExtQuals node.
+ QualifierCollector Quals;
+ const Type *TypeNode = Quals.strip(T);
+
+ // If the qualifier doesn't have an address space just return it.
+ if (!Quals.hasAddressSpace())
+ return T;
+
+ Quals.removeAddressSpace();
+
+ // Removal of the address space can mean there are no longer any
+ // non-fast qualifiers, so creating an ExtQualType isn't possible (asserts)
+ // or required.
+ if (Quals.hasNonFastQualifiers())
+ return getExtQualType(TypeNode, Quals);
+ else
+ return QualType(TypeNode, Quals.getFastQualifiers());
+}
+
QualType ASTContext::getObjCGCQualType(QualType T,
Qualifiers::GC GCAttr) const {
QualType CanT = getCanonicalType(T);
@@ -2393,7 +2609,7 @@ static QualType getFunctionTypeWithExceptionSpec(
bool ASTContext::hasSameFunctionTypeIgnoringExceptionSpec(QualType T,
QualType U) {
return hasSameType(T, U) ||
- (getLangOpts().CPlusPlus1z &&
+ (getLangOpts().CPlusPlus17 &&
hasSameType(getFunctionTypeWithExceptionSpec(*this, T, EST_None),
getFunctionTypeWithExceptionSpec(*this, U, EST_None)));
}
@@ -2750,6 +2966,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const {
case Type::Vector:
case Type::ExtVector:
case Type::DependentSizedExtVector:
+ case Type::DependentAddressSpace:
case Type::ObjCObject:
case Type::ObjCInterface:
case Type::ObjCObjectPointer:
@@ -3098,6 +3315,41 @@ ASTContext::getDependentSizedExtVectorType(QualType vecType,
return QualType(New, 0);
}
+QualType ASTContext::getDependentAddressSpaceType(QualType PointeeType,
+ Expr *AddrSpaceExpr,
+ SourceLocation AttrLoc) const {
+ assert(AddrSpaceExpr->isInstantiationDependent());
+
+ QualType canonPointeeType = getCanonicalType(PointeeType);
+
+ void *insertPos = nullptr;
+ llvm::FoldingSetNodeID ID;
+ DependentAddressSpaceType::Profile(ID, *this, canonPointeeType,
+ AddrSpaceExpr);
+
+ DependentAddressSpaceType *canonTy =
+ DependentAddressSpaceTypes.FindNodeOrInsertPos(ID, insertPos);
+
+ if (!canonTy) {
+ canonTy = new (*this, TypeAlignment)
+ DependentAddressSpaceType(*this, canonPointeeType,
+ QualType(), AddrSpaceExpr, AttrLoc);
+ DependentAddressSpaceTypes.InsertNode(canonTy, insertPos);
+ Types.push_back(canonTy);
+ }
+
+ if (canonPointeeType == PointeeType &&
+ canonTy->getAddrSpaceExpr() == AddrSpaceExpr)
+ return QualType(canonTy, 0);
+
+ DependentAddressSpaceType *sugaredType
+ = new (*this, TypeAlignment)
+ DependentAddressSpaceType(*this, PointeeType, QualType(canonTy, 0),
+ AddrSpaceExpr, AttrLoc);
+ Types.push_back(sugaredType);
+ return QualType(sugaredType, 0);
+}
+
/// \brief Determine whether \p T is canonical as the result type of a function.
static bool isCanonicalResultType(QualType T) {
return T.isCanonical() &&
@@ -3106,7 +3358,6 @@ static bool isCanonicalResultType(QualType T) {
}
/// getFunctionNoProtoType - Return a K&R style C function type like 'int()'.
-///
QualType
ASTContext::getFunctionNoProtoType(QualType ResultTy,
const FunctionType::ExtInfo &Info) const {
@@ -3222,7 +3473,7 @@ QualType ASTContext::getFunctionTypeInternal(
Unique = true;
}
- bool NoexceptInType = getLangOpts().CPlusPlus1z;
+ bool NoexceptInType = getLangOpts().CPlusPlus17;
bool IsCanonicalExceptionSpec =
isCanonicalExceptionSpecification(EPI.ExceptionSpec, NoexceptInType);
@@ -3358,7 +3609,7 @@ QualType ASTContext::getPipeType(QualType T, bool ReadOnly) const {
llvm::FoldingSetNodeID ID;
PipeType::Profile(ID, T, ReadOnly);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
if (PipeType *PT = PipeTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(PT, 0);
@@ -3986,7 +4237,7 @@ SortAndUniqueProtocols(SmallVectorImpl<ObjCProtocolDecl *> &Protocols) {
QualType ASTContext::getObjCObjectType(QualType BaseType,
ObjCProtocolDecl * const *Protocols,
unsigned NumProtocols) const {
- return getObjCObjectType(BaseType, { },
+ return getObjCObjectType(BaseType, {},
llvm::makeArrayRef(Protocols, NumProtocols),
/*isKindOf=*/false);
}
@@ -4123,13 +4374,13 @@ ASTContext::applyObjCProtocolQualifiers(QualType type,
// FIXME: Check for protocols to which the class type is already
// known to conform.
- return getObjCObjectType(type, { }, protocols, false);
+ return getObjCObjectType(type, {}, protocols, false);
}
// id<protocol-list>
if (type->isObjCIdType()) {
const ObjCObjectPointerType *objPtr = type->castAs<ObjCObjectPointerType>();
- type = getObjCObjectType(ObjCBuiltinIdTy, { }, protocols,
+ type = getObjCObjectType(ObjCBuiltinIdTy, {}, protocols,
objPtr->isKindOfType());
return getObjCObjectPointerType(type);
}
@@ -4137,7 +4388,7 @@ ASTContext::applyObjCProtocolQualifiers(QualType type,
// Class<protocol-list>
if (type->isObjCClassType()) {
const ObjCObjectPointerType *objPtr = type->castAs<ObjCObjectPointerType>();
- type = getObjCObjectType(ObjCBuiltinClassTy, { }, protocols,
+ type = getObjCObjectType(ObjCBuiltinClassTy, {}, protocols,
objPtr->isKindOfType());
return getObjCObjectPointerType(type);
}
@@ -4512,7 +4763,7 @@ QualType ASTContext::getAutoRRefDeductType() const {
/// getTagDeclType - Return the unique reference to the type for the
/// specified TagDecl (struct/union/class/enum) decl.
QualType ASTContext::getTagDeclType(const TagDecl *Decl) const {
- assert (Decl);
+ assert(Decl);
// FIXME: What is the design on getTagDeclType when it requires casting
// away const? mutable?
return getTypeDeclType(const_cast<TagDecl*>(Decl));
@@ -4569,6 +4820,13 @@ QualType ASTContext::getPointerDiffType() const {
return getFromTargetType(Target->getPtrDiffType(0));
}
+/// \brief Return the unique unsigned counterpart of "ptrdiff_t"
+/// integer type. The standard (C11 7.21.6.1p7) refers to this type
+/// in the definition of %tu format specifier.
+QualType ASTContext::getUnsignedPointerDiffType() const {
+ return getFromTargetType(Target->getUnsignedPtrDiffType(0));
+}
+
/// \brief Return the unique type for "pid_t" defined in
/// <sys/types.h>. We need this to compute the correct type for vfork().
QualType ASTContext::getProcessIDType() const {
@@ -5051,6 +5309,7 @@ static FloatingRank getFloatingRank(QualType T) {
assert(T->getAs<BuiltinType>() && "getFloatingRank(): not a floating type");
switch (T->getAs<BuiltinType>()->getKind()) {
default: llvm_unreachable("getFloatingRank(): not a floating type");
+ case BuiltinType::Float16: return Float16Rank;
case BuiltinType::Half: return HalfRank;
case BuiltinType::Float: return FloatRank;
case BuiltinType::Double: return DoubleRank;
@@ -5068,6 +5327,7 @@ QualType ASTContext::getFloatingTypeOfSizeWithinDomain(QualType Size,
FloatingRank EltRank = getFloatingRank(Size);
if (Domain->isComplexType()) {
switch (EltRank) {
+ case Float16Rank:
case HalfRank: llvm_unreachable("Complex half is not supported");
case FloatRank: return FloatComplexTy;
case DoubleRank: return DoubleComplexTy;
@@ -5078,6 +5338,7 @@ QualType ASTContext::getFloatingTypeOfSizeWithinDomain(QualType Size,
assert(Domain->isRealFloatingType() && "Unknown domain!");
switch (EltRank) {
+ case Float16Rank: return HalfTy;
case HalfRank: return HalfTy;
case FloatRank: return FloatTy;
case DoubleRank: return DoubleTy;
@@ -5455,6 +5716,46 @@ QualType ASTContext::getBlockDescriptorExtendedType() const {
return getTagDeclType(BlockDescriptorExtendedType);
}
+TargetInfo::OpenCLTypeKind ASTContext::getOpenCLTypeKind(const Type *T) const {
+ auto BT = dyn_cast<BuiltinType>(T);
+
+ if (!BT) {
+ if (isa<PipeType>(T))
+ return TargetInfo::OCLTK_Pipe;
+
+ return TargetInfo::OCLTK_Default;
+ }
+
+ switch (BT->getKind()) {
+#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
+ case BuiltinType::Id: \
+ return TargetInfo::OCLTK_Image;
+#include "clang/Basic/OpenCLImageTypes.def"
+
+ case BuiltinType::OCLClkEvent:
+ return TargetInfo::OCLTK_ClkEvent;
+
+ case BuiltinType::OCLEvent:
+ return TargetInfo::OCLTK_Event;
+
+ case BuiltinType::OCLQueue:
+ return TargetInfo::OCLTK_Queue;
+
+ case BuiltinType::OCLReserveID:
+ return TargetInfo::OCLTK_ReserveID;
+
+ case BuiltinType::OCLSampler:
+ return TargetInfo::OCLTK_Sampler;
+
+ default:
+ return TargetInfo::OCLTK_Default;
+ }
+}
+
+LangAS ASTContext::getOpenCLTypeAddrSpace(const Type *T) const {
+ return Target->getOpenCLTypeAddrSpace(getOpenCLTypeKind(T));
+}
+
/// BlockRequiresCopying - Returns true if byref variable "D" of type "Ty"
/// requires copy/dispose. Note that this must match the logic
/// in buildByrefHelpers.
@@ -5497,7 +5798,6 @@ bool ASTContext::BlockRequiresCopying(QualType Ty,
bool ASTContext::getByrefLifetime(QualType Ty,
Qualifiers::ObjCLifetime &LifeTime,
bool &HasByrefExtendedLayout) const {
-
if (!getLangOpts().ObjC1 ||
getLangOpts().getGC() != LangOptions::NonGC)
return false;
@@ -5565,14 +5865,14 @@ ASTContext::getInlineVariableDefinitionKind(const VarDecl *VD) const {
// In almost all cases, it's a weak definition.
auto *First = VD->getFirstDecl();
- if (!First->isConstexpr() || First->isInlineSpecified() ||
- !VD->isStaticDataMember())
+ if (First->isInlineSpecified() || !First->isStaticDataMember())
return InlineVariableDefinitionKind::Weak;
// If there's a file-context declaration in this translation unit, it's a
// non-discardable definition.
for (auto *D : VD->redecls())
- if (D->getLexicalDeclContext()->isFileContext())
+ if (D->getLexicalDeclContext()->isFileContext() &&
+ !D->isInlineSpecified() && (D->isConstexpr() || First->isConstexpr()))
return InlineVariableDefinitionKind::Strong;
// If we've not seen one yet, we don't know.
@@ -5602,7 +5902,6 @@ std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const {
// Compute size of all parameters.
// Start with computing size of a pointer in number of bytes.
// FIXME: There might(should) be a better way of doing this computation!
- SourceLocation Loc;
CharUnits PtrSize = getTypeSizeInChars(VoidPtrTy);
CharUnits ParmOffset = PtrSize;
for (auto PI : Decl->parameters()) {
@@ -5610,7 +5909,7 @@ std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const {
CharUnits sz = getObjCEncodingTypeSize(PType);
if (sz.isZero())
continue;
- assert (sz.isPositive() && "BlockExpr - Incomplete param type");
+ assert(sz.isPositive() && "BlockExpr - Incomplete param type");
ParmOffset += sz;
}
// Size of the argument frame
@@ -5710,7 +6009,6 @@ std::string ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,
// Compute size of all parameters.
// Start with computing size of a pointer in number of bytes.
// FIXME: There might(should) be a better way of doing this computation!
- SourceLocation Loc;
CharUnits PtrSize = getTypeSizeInChars(VoidPtrTy);
// The first two arguments (self and _cmd) are pointers; account for
// their size.
@@ -5722,8 +6020,8 @@ std::string ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,
if (sz.isZero())
continue;
- assert (sz.isPositive() &&
- "getObjCEncodingForMethodDecl - Incomplete param type");
+ assert(sz.isPositive() &&
+ "getObjCEncodingForMethodDecl - Incomplete param type");
ParmOffset += sz;
}
S += charUnitsToString(ParmOffset);
@@ -5870,7 +6168,6 @@ ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD,
/// Another legacy compatibility encoding: 32-bit longs are encoded as
/// 'l' or 'L' , but not always. For typedefs, we need to use
/// 'i' or 'I' instead if encoding a struct field, or a pointer!
-///
void ASTContext::getLegacyIntegralTypeEncoding (QualType &PointeeTy) const {
if (isa<TypedefType>(PointeeTy.getTypePtr())) {
if (const BuiltinType *BT = PointeeTy->getAs<BuiltinType>()) {
@@ -5935,6 +6232,7 @@ static char getObjCEncodingForPrimitiveKind(const ASTContext *C,
case BuiltinType::LongDouble: return 'D';
case BuiltinType::NullPtr: return '*'; // like char*
+ case BuiltinType::Float16:
case BuiltinType::Float128:
case BuiltinType::Half:
// FIXME: potentially need @encodes for these!
@@ -6176,9 +6474,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
= dyn_cast<ClassTemplateSpecializationDecl>(RDecl)) {
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
llvm::raw_string_ostream OS(S);
- TemplateSpecializationType::PrintTemplateArgumentList(OS,
- TemplateArgs.asArray(),
- (*this).getPrintingPolicy());
+ printTemplateArgumentList(OS, TemplateArgs.asArray(),
+ getPrintingPolicy());
}
} else {
S += '?';
@@ -6370,10 +6667,9 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
case Type::Vector:
case Type::ExtVector:
// Until we have a coherent encoding of these three types, issue warning.
- { if (NotEncodedT)
- *NotEncodedT = T;
- return;
- }
+ if (NotEncodedT)
+ *NotEncodedT = T;
+ return;
// We could see an undeduced auto type here during error recovery.
// Just ignore it.
@@ -6557,7 +6853,7 @@ void ASTContext::getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT,
TypedefDecl *ASTContext::getObjCIdDecl() const {
if (!ObjCIdDecl) {
- QualType T = getObjCObjectType(ObjCBuiltinIdTy, { }, { });
+ QualType T = getObjCObjectType(ObjCBuiltinIdTy, {}, {});
T = getObjCObjectPointerType(T);
ObjCIdDecl = buildImplicitTypedef(T, "id");
}
@@ -6574,7 +6870,7 @@ TypedefDecl *ASTContext::getObjCSelDecl() const {
TypedefDecl *ASTContext::getObjCClassDecl() const {
if (!ObjCClassDecl) {
- QualType T = getObjCObjectType(ObjCBuiltinClassTy, { }, { });
+ QualType T = getObjCObjectType(ObjCBuiltinClassTy, {}, {});
T = getObjCObjectPointerType(T);
ObjCClassDecl = buildImplicitTypedef(T, "Class");
}
@@ -7236,7 +7532,7 @@ bool ASTContext::ObjCQualifiedClassTypesAreCompatible(QualType lhs,
QualType rhs) {
const ObjCObjectPointerType *lhsQID = lhs->getAs<ObjCObjectPointerType>();
const ObjCObjectPointerType *rhsOPT = rhs->getAs<ObjCObjectPointerType>();
- assert ((lhsQID && rhsOPT) && "ObjCQualifiedClassTypesAreCompatible");
+ assert((lhsQID && rhsOPT) && "ObjCQualifiedClassTypesAreCompatible");
for (auto *lhsProto : lhsQID->quals()) {
bool match = false;
@@ -7374,7 +7670,6 @@ bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
/// canAssignObjCInterfaces - Return true if the two interface types are
/// compatible for assignment from RHS to LHS. This handles validation of any
/// protocol qualifiers on the LHS or RHS.
-///
bool ASTContext::canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
const ObjCObjectPointerType *RHSOPT) {
const ObjCObjectType* LHS = LHSOPT->getObjectType();
@@ -7480,7 +7775,6 @@ bool ASTContext::canAssignObjCInterfacesInBlockPointer(
static int compareObjCProtocolsByName(ObjCProtocolDecl * const *lhs,
ObjCProtocolDecl * const *rhs) {
return (*lhs)->getName().compare((*rhs)->getName());
-
}
/// getIntersectionOfProtocols - This routine finds the intersection of set
@@ -7649,7 +7943,7 @@ QualType ASTContext::areCommonBaseCompatible(
} else if (LHS->isSpecialized() != RHS->isSpecialized()) {
// If only one has type arguments, the result will not have type
// arguments.
- LHSTypeArgs = { };
+ LHSTypeArgs = {};
anyChanges = true;
}
@@ -7700,7 +7994,7 @@ QualType ASTContext::areCommonBaseCompatible(
} else if (LHS->isSpecialized() != RHS->isSpecialized()) {
// If only one has type arguments, the result will not have type
// arguments.
- RHSTypeArgs = { };
+ RHSTypeArgs = {};
anyChanges = true;
}
@@ -7962,9 +8256,17 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
if (lproto->getTypeQuals() != rproto->getTypeQuals())
return QualType();
- if (!doFunctionTypesMatchOnExtParameterInfos(rproto, lproto))
+ SmallVector<FunctionProtoType::ExtParameterInfo, 4> newParamInfos;
+ bool canUseLeft, canUseRight;
+ if (!mergeExtParameterInfo(lproto, rproto, canUseLeft, canUseRight,
+ newParamInfos))
return QualType();
+ if (!canUseLeft)
+ allLTypes = false;
+ if (!canUseRight)
+ allRTypes = false;
+
// Check parameter type compatibility
SmallVector<QualType, 10> types;
for (unsigned i = 0, n = lproto->getNumParams(); i < n; i++) {
@@ -7995,6 +8297,8 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
FunctionProtoType::ExtProtoInfo EPI = lproto->getExtProtoInfo();
EPI.ExtInfo = einfo;
+ EPI.ExtParameterInfos =
+ newParamInfos.empty() ? nullptr : newParamInfos.data();
return getFunctionType(retType, types, EPI);
}
@@ -8328,7 +8632,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
return QualType();
}
- case Type::ObjCObjectPointer: {
+ case Type::ObjCObjectPointer:
if (OfBlockPointer) {
if (canAssignObjCInterfacesInBlockPointer(
LHS->getAs<ObjCObjectPointerType>(),
@@ -8342,38 +8646,59 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
return LHS;
return QualType();
- }
case Type::Pipe:
- {
assert(LHS != RHS &&
"Equivalent pipe types should have already been handled!");
return QualType();
}
- }
llvm_unreachable("Invalid Type::Class!");
}
-bool ASTContext::doFunctionTypesMatchOnExtParameterInfos(
- const FunctionProtoType *firstFnType,
- const FunctionProtoType *secondFnType) {
+bool ASTContext::mergeExtParameterInfo(
+ const FunctionProtoType *FirstFnType, const FunctionProtoType *SecondFnType,
+ bool &CanUseFirst, bool &CanUseSecond,
+ SmallVectorImpl<FunctionProtoType::ExtParameterInfo> &NewParamInfos) {
+ assert(NewParamInfos.empty() && "param info list not empty");
+ CanUseFirst = CanUseSecond = true;
+ bool FirstHasInfo = FirstFnType->hasExtParameterInfos();
+ bool SecondHasInfo = SecondFnType->hasExtParameterInfos();
+
// Fast path: if the first type doesn't have ext parameter infos,
- // we match if and only if they second type also doesn't have them.
- if (!firstFnType->hasExtParameterInfos())
- return !secondFnType->hasExtParameterInfos();
+ // we match if and only if the second type also doesn't have them.
+ if (!FirstHasInfo && !SecondHasInfo)
+ return true;
- // Otherwise, we can only match if the second type has them.
- if (!secondFnType->hasExtParameterInfos())
- return false;
+ bool NeedParamInfo = false;
+ size_t E = FirstHasInfo ? FirstFnType->getExtParameterInfos().size()
+ : SecondFnType->getExtParameterInfos().size();
- auto firstEPI = firstFnType->getExtParameterInfos();
- auto secondEPI = secondFnType->getExtParameterInfos();
- assert(firstEPI.size() == secondEPI.size());
+ for (size_t I = 0; I < E; ++I) {
+ FunctionProtoType::ExtParameterInfo FirstParam, SecondParam;
+ if (FirstHasInfo)
+ FirstParam = FirstFnType->getExtParameterInfo(I);
+ if (SecondHasInfo)
+ SecondParam = SecondFnType->getExtParameterInfo(I);
- for (size_t i = 0, n = firstEPI.size(); i != n; ++i) {
- if (firstEPI[i] != secondEPI[i])
+ // Cannot merge unless everything except the noescape flag matches.
+ if (FirstParam.withIsNoEscape(false) != SecondParam.withIsNoEscape(false))
return false;
+
+ bool FirstNoEscape = FirstParam.isNoEscape();
+ bool SecondNoEscape = SecondParam.isNoEscape();
+ bool IsNoEscape = FirstNoEscape && SecondNoEscape;
+ NewParamInfos.push_back(FirstParam.withIsNoEscape(IsNoEscape));
+ if (NewParamInfos.back().getOpaqueValue())
+ NeedParamInfo = true;
+ if (FirstNoEscape != IsNoEscape)
+ CanUseFirst = false;
+ if (SecondNoEscape != IsNoEscape)
+ CanUseSecond = false;
}
+
+ if (!NeedParamInfo)
+ NewParamInfos.clear();
+
return true;
}
@@ -8502,7 +8827,7 @@ QualType ASTContext::getCorrespondingUnsignedType(QualType T) const {
}
}
-ASTMutationListener::~ASTMutationListener() { }
+ASTMutationListener::~ASTMutationListener() = default;
void ASTMutationListener::DeducedReturnType(const FunctionDecl *FD,
QualType ReturnType) {}
@@ -8554,7 +8879,7 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
assert(HowLong <= 2 && "Can't have LLLL modifier");
++HowLong;
break;
- case 'N': {
+ case 'N':
// 'N' behaves like 'L' for all non LP64 targets and 'int' otherwise.
assert(!IsSpecialLong && "Can't use two 'N' or 'W' modifiers!");
assert(HowLong == 0 && "Can't use both 'L' and 'N' modifiers!");
@@ -8564,7 +8889,6 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
if (Context.getTargetInfo().getLongWidth() == 32)
++HowLong;
break;
- }
case 'W':
// This modifier represents int64 type.
assert(!IsSpecialLong && "Can't use two 'N' or 'W' modifiers!");
@@ -8719,10 +9043,9 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
Type = Context.getComplexType(ElementType);
break;
}
- case 'Y' : {
+ case 'Y':
Type = Context.getPointerDiffType();
break;
- }
case 'P':
Type = Context.getFILEType();
if (Type.isNull()) {
@@ -8767,8 +9090,8 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
char *End;
unsigned AddrSpace = strtoul(Str, &End, 10);
if (End != Str && AddrSpace != 0) {
- Type = Context.getAddrSpaceQualType(
- Type, AddrSpace + LangAS::FirstTargetAddressSpace);
+ Type = Context.getAddrSpaceQualType(Type,
+ getLangASFromTargetAS(AddrSpace));
Str = End;
}
if (c == '*')
@@ -8860,6 +9183,12 @@ static GVALinkage basicGVALinkageForFunction(const ASTContext &Context,
if (!FD->isExternallyVisible())
return GVA_Internal;
+ // Non-user-provided functions get emitted as weak definitions with every
+ // use, no matter whether they've been explicitly instantiated etc.
+ if (auto *MD = dyn_cast<CXXMethodDecl>(FD))
+ if (!MD->isUserProvided())
+ return GVA_DiscardableODR;
+
GVALinkage External;
switch (FD->getTemplateSpecializationKind()) {
case TSK_Undeclared:
@@ -8912,7 +9241,7 @@ static GVALinkage basicGVALinkageForFunction(const ASTContext &Context,
}
static GVALinkage adjustGVALinkageForAttributes(const ASTContext &Context,
- GVALinkage L, const Decl *D) {
+ const Decl *D, GVALinkage L) {
// See http://msdn.microsoft.com/en-us/library/xa0d9ste.aspx
// dllexport/dllimport on inline functions.
if (D->hasAttr<DLLImportAttr>()) {
@@ -8931,25 +9260,37 @@ static GVALinkage adjustGVALinkageForAttributes(const ASTContext &Context,
return L;
}
-GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) const {
- auto L = adjustGVALinkageForAttributes(
- *this, basicGVALinkageForFunction(*this, FD), FD);
- auto EK = ExternalASTSource::EK_ReplyHazy;
- if (auto *Ext = getExternalSource())
- EK = Ext->hasExternalDefinitions(FD);
- switch (EK) {
+/// Adjust the GVALinkage for a declaration based on what an external AST source
+/// knows about whether there can be other definitions of this declaration.
+static GVALinkage
+adjustGVALinkageForExternalDefinitionKind(const ASTContext &Ctx, const Decl *D,
+ GVALinkage L) {
+ ExternalASTSource *Source = Ctx.getExternalSource();
+ if (!Source)
+ return L;
+
+ switch (Source->hasExternalDefinitions(D)) {
case ExternalASTSource::EK_Never:
+ // Other translation units rely on us to provide the definition.
if (L == GVA_DiscardableODR)
return GVA_StrongODR;
break;
+
case ExternalASTSource::EK_Always:
return GVA_AvailableExternally;
+
case ExternalASTSource::EK_ReplyHazy:
break;
}
return L;
}
+GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) const {
+ return adjustGVALinkageForExternalDefinitionKind(*this, FD,
+ adjustGVALinkageForAttributes(*this, FD,
+ basicGVALinkageForFunction(*this, FD)));
+}
+
static GVALinkage basicGVALinkageForVariable(const ASTContext &Context,
const VarDecl *VD) {
if (!VD->isExternallyVisible())
@@ -9028,8 +9369,9 @@ static GVALinkage basicGVALinkageForVariable(const ASTContext &Context,
}
GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) {
- return adjustGVALinkageForAttributes(
- *this, basicGVALinkageForVariable(*this, VD), VD);
+ return adjustGVALinkageForExternalDefinitionKind(*this, VD,
+ adjustGVALinkageForAttributes(*this, VD,
+ basicGVALinkageForVariable(*this, VD)));
}
bool ASTContext::DeclMustBeEmitted(const Decl *D) {
@@ -9112,9 +9454,14 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
return false;
// Variables that can be needed in other TUs are required.
- if (!isDiscardableGVALinkage(GetGVALinkageForVariable(VD)))
+ auto Linkage = GetGVALinkageForVariable(VD);
+ if (!isDiscardableGVALinkage(Linkage))
return true;
+ // We never need to emit a variable that is available in another TU.
+ if (Linkage == GVA_AvailableExternally)
+ return false;
+
// Variables that have destruction with side-effects are required.
if (VD->getType().isDestructedType())
return true;
@@ -9148,7 +9495,7 @@ CallingConv ASTContext::getDefaultCallingConvention(bool IsVariadic,
case LangOptions::DCC_CDecl:
return CC_C;
case LangOptions::DCC_FastCall:
- if (getTargetInfo().hasFeature("sse2"))
+ if (getTargetInfo().hasFeature("sse2") && !IsVariadic)
return CC_X86FastCall;
break;
case LangOptions::DCC_StdCall:
@@ -9160,6 +9507,11 @@ CallingConv ASTContext::getDefaultCallingConvention(bool IsVariadic,
if (!IsVariadic)
return CC_X86VectorCall;
break;
+ case LangOptions::DCC_RegCall:
+ // __regcall cannot be applied to variadic functions.
+ if (!IsVariadic)
+ return CC_X86RegCall;
+ break;
}
return Target->getDefaultCallingConv(TargetInfo::CCMT_Unknown);
}
@@ -9196,7 +9548,7 @@ MangleContext *ASTContext::createMangleContext() {
llvm_unreachable("Unsupported ABI");
}
-CXXABI::~CXXABI() {}
+CXXABI::~CXXABI() = default;
size_t ASTContext::getSideTableAllocatedMemory() const {
return ASTRecordLayouts.getMemorySize() +
@@ -9359,9 +9711,7 @@ bool ASTContext::AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const {
return (Size != Align || toBits(sizeChars) > MaxInlineWidthInBits);
}
-namespace {
-
-ast_type_traits::DynTypedNode getSingleDynTypedNodeFromParentMap(
+static ast_type_traits::DynTypedNode getSingleDynTypedNodeFromParentMap(
ASTContext::ParentMapPointers::mapped_type U) {
if (const auto *D = U.dyn_cast<const Decl *>())
return ast_type_traits::DynTypedNode::create(*D);
@@ -9370,6 +9720,8 @@ ast_type_traits::DynTypedNode getSingleDynTypedNodeFromParentMap(
return *U.get<ast_type_traits::DynTypedNode *>();
}
+namespace {
+
/// Template specializations to abstract away from pointers and TypeLocs.
/// @{
template <typename T>
@@ -9410,7 +9762,9 @@ createDynTypedNode(const NestedNameSpecifierLoc &Node) {
}
private:
- typedef RecursiveASTVisitor<ParentMapASTVisitor> VisitorBase;
+ friend class RecursiveASTVisitor<ParentMapASTVisitor>;
+
+ using VisitorBase = RecursiveASTVisitor<ParentMapASTVisitor>;
ParentMapASTVisitor(ASTContext::ParentMapPointers *Parents,
ASTContext::ParentMapOtherNodes *OtherParents)
@@ -9419,6 +9773,7 @@ createDynTypedNode(const NestedNameSpecifierLoc &Node) {
bool shouldVisitTemplateInstantiations() const {
return true;
}
+
bool shouldVisitImplicitCode() const {
return true;
}
@@ -9508,11 +9863,9 @@ createDynTypedNode(const NestedNameSpecifierLoc &Node) {
ASTContext::ParentMapPointers *Parents;
ASTContext::ParentMapOtherNodes *OtherParents;
llvm::SmallVector<ast_type_traits::DynTypedNode, 16> ParentStack;
-
- friend class RecursiveASTVisitor<ParentMapASTVisitor>;
};
-} // anonymous namespace
+} // namespace
template <typename NodeTy, typename MapTy>
static ASTContext::DynTypedNodeList getDynNodeFromMap(const NodeTy &Node,
@@ -9568,25 +9921,25 @@ ASTContext::ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl,
if (!hasSameType(DeclVar->getType(), ImplVar->getType()))
return false;
}
+
return (MethodDecl->isVariadic() == MethodImpl->isVariadic());
-
}
uint64_t ASTContext::getTargetNullPointerValue(QualType QT) const {
- unsigned AS;
+ LangAS AS;
if (QT->getUnqualifiedDesugaredType()->isNullPtrType())
- AS = 0;
+ AS = LangAS::Default;
else
AS = QT->getPointeeType().getAddressSpace();
return getTargetInfo().getNullPointerValue(AS);
}
-unsigned ASTContext::getTargetAddressSpace(unsigned AS) const {
- if (AS >= LangAS::FirstTargetAddressSpace)
- return AS - LangAS::FirstTargetAddressSpace;
+unsigned ASTContext::getTargetAddressSpace(LangAS AS) const {
+ if (isTargetAddressSpace(AS))
+ return toTargetAddressSpace(AS);
else
- return (*AddrSpaceMap)[AS];
+ return (*AddrSpaceMap)[(unsigned)AS];
}
// Explicitly instantiate this in case a Redeclarable<T> is used from a TU that
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp b/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp
index 92ed7da94d8e8..157b29fd84b6b 100644
--- a/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp
@@ -537,6 +537,7 @@ namespace {
void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node);
void VisitCXXThisExpr(const CXXThisExpr *Node);
void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *Node);
+ void VisitCXXUnresolvedConstructExpr(const CXXUnresolvedConstructExpr *Node);
void VisitCXXConstructExpr(const CXXConstructExpr *Node);
void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node);
void VisitCXXNewExpr(const CXXNewExpr *Node);
@@ -1184,7 +1185,7 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) {
I != E; ++I)
dumpCXXCtorInitializer(*I);
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D))
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
if (MD->size_overridden_methods() != 0) {
auto dumpOverride =
[=](const CXXMethodDecl *D) {
@@ -1194,16 +1195,18 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) {
};
dumpChild([=] {
- auto FirstOverrideItr = MD->begin_overridden_methods();
+ auto Overrides = MD->overridden_methods();
OS << "Overrides: [ ";
- dumpOverride(*FirstOverrideItr);
+ dumpOverride(*Overrides.begin());
for (const auto *Override :
- llvm::make_range(FirstOverrideItr + 1,
- MD->end_overridden_methods()))
+ llvm::make_range(Overrides.begin() + 1, Overrides.end())) {
+ OS << ", ";
dumpOverride(Override);
+ }
OS << " ]";
});
}
+ }
if (D->doesThisDeclarationHaveABody())
dumpStmt(D->getBody());
@@ -1313,6 +1316,16 @@ void ASTDumper::VisitOMPDeclareReductionDecl(const OMPDeclareReductionDecl *D) {
dumpStmt(D->getCombiner());
if (auto *Initializer = D->getInitializer()) {
OS << " initializer";
+ switch (D->getInitializerKind()) {
+ case OMPDeclareReductionDecl::DirectInit:
+ OS << " omp_priv = ";
+ break;
+ case OMPDeclareReductionDecl::CopyInit:
+ OS << " omp_priv ()";
+ break;
+ case OMPDeclareReductionDecl::CallInit:
+ break;
+ }
dumpStmt(Initializer);
}
}
@@ -1362,6 +1375,128 @@ void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) {
if (!D->isCompleteDefinition())
return;
+ dumpChild([=] {
+ {
+ ColorScope Color(*this, DeclKindNameColor);
+ OS << "DefinitionData";
+ }
+#define FLAG(fn, name) if (D->fn()) OS << " " #name;
+ FLAG(isParsingBaseSpecifiers, parsing_base_specifiers);
+
+ FLAG(isGenericLambda, generic);
+ FLAG(isLambda, lambda);
+
+ FLAG(canPassInRegisters, pass_in_registers);
+ FLAG(isEmpty, empty);
+ FLAG(isAggregate, aggregate);
+ FLAG(isStandardLayout, standard_layout);
+ FLAG(isTriviallyCopyable, trivially_copyable);
+ FLAG(isPOD, pod);
+ FLAG(isTrivial, trivial);
+ FLAG(isPolymorphic, polymorphic);
+ FLAG(isAbstract, abstract);
+ FLAG(isLiteral, literal);
+
+ FLAG(hasUserDeclaredConstructor, has_user_declared_ctor);
+ FLAG(hasConstexprNonCopyMoveConstructor, has_constexpr_non_copy_move_ctor);
+ FLAG(hasMutableFields, has_mutable_fields);
+ FLAG(hasVariantMembers, has_variant_members);
+ FLAG(allowConstDefaultInit, can_const_default_init);
+
+ dumpChild([=] {
+ {
+ ColorScope Color(*this, DeclKindNameColor);
+ OS << "DefaultConstructor";
+ }
+ FLAG(hasDefaultConstructor, exists);
+ FLAG(hasTrivialDefaultConstructor, trivial);
+ FLAG(hasNonTrivialDefaultConstructor, non_trivial);
+ FLAG(hasUserProvidedDefaultConstructor, user_provided);
+ FLAG(hasConstexprDefaultConstructor, constexpr);
+ FLAG(needsImplicitDefaultConstructor, needs_implicit);
+ FLAG(defaultedDefaultConstructorIsConstexpr, defaulted_is_constexpr);
+ });
+
+ dumpChild([=] {
+ {
+ ColorScope Color(*this, DeclKindNameColor);
+ OS << "CopyConstructor";
+ }
+ FLAG(hasSimpleCopyConstructor, simple);
+ FLAG(hasTrivialCopyConstructor, trivial);
+ FLAG(hasNonTrivialCopyConstructor, non_trivial);
+ FLAG(hasUserDeclaredCopyConstructor, user_declared);
+ FLAG(hasCopyConstructorWithConstParam, has_const_param);
+ FLAG(needsImplicitCopyConstructor, needs_implicit);
+ FLAG(needsOverloadResolutionForCopyConstructor,
+ needs_overload_resolution);
+ if (!D->needsOverloadResolutionForCopyConstructor())
+ FLAG(defaultedCopyConstructorIsDeleted, defaulted_is_deleted);
+ FLAG(implicitCopyConstructorHasConstParam, implicit_has_const_param);
+ });
+
+ dumpChild([=] {
+ {
+ ColorScope Color(*this, DeclKindNameColor);
+ OS << "MoveConstructor";
+ }
+ FLAG(hasMoveConstructor, exists);
+ FLAG(hasSimpleMoveConstructor, simple);
+ FLAG(hasTrivialMoveConstructor, trivial);
+ FLAG(hasNonTrivialMoveConstructor, non_trivial);
+ FLAG(hasUserDeclaredMoveConstructor, user_declared);
+ FLAG(needsImplicitMoveConstructor, needs_implicit);
+ FLAG(needsOverloadResolutionForMoveConstructor,
+ needs_overload_resolution);
+ if (!D->needsOverloadResolutionForMoveConstructor())
+ FLAG(defaultedMoveConstructorIsDeleted, defaulted_is_deleted);
+ });
+
+ dumpChild([=] {
+ {
+ ColorScope Color(*this, DeclKindNameColor);
+ OS << "CopyAssignment";
+ }
+ FLAG(hasTrivialCopyAssignment, trivial);
+ FLAG(hasNonTrivialCopyAssignment, non_trivial);
+ FLAG(hasCopyAssignmentWithConstParam, has_const_param);
+ FLAG(hasUserDeclaredCopyAssignment, user_declared);
+ FLAG(needsImplicitCopyAssignment, needs_implicit);
+ FLAG(needsOverloadResolutionForCopyAssignment, needs_overload_resolution);
+ FLAG(implicitCopyAssignmentHasConstParam, implicit_has_const_param);
+ });
+
+ dumpChild([=] {
+ {
+ ColorScope Color(*this, DeclKindNameColor);
+ OS << "MoveAssignment";
+ }
+ FLAG(hasMoveAssignment, exists);
+ FLAG(hasSimpleMoveAssignment, simple);
+ FLAG(hasTrivialMoveAssignment, trivial);
+ FLAG(hasNonTrivialMoveAssignment, non_trivial);
+ FLAG(hasUserDeclaredMoveAssignment, user_declared);
+ FLAG(needsImplicitMoveAssignment, needs_implicit);
+ FLAG(needsOverloadResolutionForMoveAssignment, needs_overload_resolution);
+ });
+
+ dumpChild([=] {
+ {
+ ColorScope Color(*this, DeclKindNameColor);
+ OS << "Destructor";
+ }
+ FLAG(hasSimpleDestructor, simple);
+ FLAG(hasIrrelevantDestructor, irrelevant);
+ FLAG(hasTrivialDestructor, trivial);
+ FLAG(hasNonTrivialDestructor, non_trivial);
+ FLAG(hasUserDeclaredDestructor, user_declared);
+ FLAG(needsImplicitDestructor, needs_implicit);
+ FLAG(needsOverloadResolutionForDestructor, needs_overload_resolution);
+ if (!D->needsOverloadResolutionForDestructor())
+ FLAG(defaultedDestructorIsDeleted, defaulted_is_deleted);
+ });
+ });
+
for (const auto &I : D->bases()) {
dumpChild([=] {
if (I.isVirtual())
@@ -2166,12 +2301,24 @@ void ASTDumper::VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *Node) {
<< " <" << Node->getCastKindName() << ">";
}
+void ASTDumper::VisitCXXUnresolvedConstructExpr(
+ const CXXUnresolvedConstructExpr *Node) {
+ VisitExpr(Node);
+ dumpType(Node->getTypeAsWritten());
+ if (Node->isListInitialization())
+ OS << " list";
+}
+
void ASTDumper::VisitCXXConstructExpr(const CXXConstructExpr *Node) {
VisitExpr(Node);
CXXConstructorDecl *Ctor = Node->getConstructor();
dumpType(Ctor->getType());
if (Node->isElidable())
OS << " elidable";
+ if (Node->isListInitialization())
+ OS << " list";
+ if (Node->isStdInitListInitialization())
+ OS << " std::initializer_list";
if (Node->requiresZeroInitialization())
OS << " zeroing";
}
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp
index 2c0bb11cc4bc3..84b0d7ecff93f 100644
--- a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp
@@ -58,7 +58,7 @@ namespace clang {
QualType VisitExtVectorType(const ExtVectorType *T);
QualType VisitFunctionNoProtoType(const FunctionNoProtoType *T);
QualType VisitFunctionProtoType(const FunctionProtoType *T);
- // FIXME: UnresolvedUsingType
+ QualType VisitUnresolvedUsingType(const UnresolvedUsingType *T);
QualType VisitParenType(const ParenType *T);
QualType VisitTypedefType(const TypedefType *T);
QualType VisitTypeOfExprType(const TypeOfExprType *T);
@@ -77,6 +77,7 @@ namespace clang {
QualType VisitTemplateSpecializationType(const TemplateSpecializationType *T);
QualType VisitElaboratedType(const ElaboratedType *T);
// FIXME: DependentNameType
+ QualType VisitPackExpansionType(const PackExpansionType *T);
// FIXME: DependentTemplateSpecializationType
QualType VisitObjCInterfaceType(const ObjCInterfaceType *T);
QualType VisitObjCObjectType(const ObjCObjectType *T);
@@ -128,27 +129,35 @@ namespace clang {
TemplateParameterList *ImportTemplateParameterList(
TemplateParameterList *Params);
TemplateArgument ImportTemplateArgument(const TemplateArgument &From);
- TemplateArgumentLoc ImportTemplateArgumentLoc(
- const TemplateArgumentLoc &TALoc, bool &Error);
+ Optional<TemplateArgumentLoc> ImportTemplateArgumentLoc(
+ const TemplateArgumentLoc &TALoc);
bool ImportTemplateArguments(const TemplateArgument *FromArgs,
unsigned NumFromArgs,
SmallVectorImpl<TemplateArgument> &ToArgs);
+ template <typename InContainerTy>
+ bool ImportTemplateArgumentListInfo(const InContainerTy &Container,
+ TemplateArgumentListInfo &ToTAInfo);
bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord,
bool Complain = true);
bool IsStructuralMatch(VarDecl *FromVar, VarDecl *ToVar,
bool Complain = true);
bool IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToRecord);
bool IsStructuralMatch(EnumConstantDecl *FromEC, EnumConstantDecl *ToEC);
+ bool IsStructuralMatch(FunctionTemplateDecl *From,
+ FunctionTemplateDecl *To);
bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To);
bool IsStructuralMatch(VarTemplateDecl *From, VarTemplateDecl *To);
Decl *VisitDecl(Decl *D);
+ Decl *VisitEmptyDecl(EmptyDecl *D);
Decl *VisitAccessSpecDecl(AccessSpecDecl *D);
Decl *VisitStaticAssertDecl(StaticAssertDecl *D);
Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D);
Decl *VisitNamespaceDecl(NamespaceDecl *D);
+ Decl *VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
Decl *VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias);
Decl *VisitTypedefDecl(TypedefDecl *D);
Decl *VisitTypeAliasDecl(TypeAliasDecl *D);
+ Decl *VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
Decl *VisitLabelDecl(LabelDecl *D);
Decl *VisitEnumDecl(EnumDecl *D);
Decl *VisitRecordDecl(RecordDecl *D);
@@ -170,6 +179,12 @@ namespace clang {
Decl *VisitObjCCategoryDecl(ObjCCategoryDecl *D);
Decl *VisitObjCProtocolDecl(ObjCProtocolDecl *D);
Decl *VisitLinkageSpecDecl(LinkageSpecDecl *D);
+ Decl *VisitUsingDecl(UsingDecl *D);
+ Decl *VisitUsingShadowDecl(UsingShadowDecl *D);
+ Decl *VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
+ Decl *VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
+ Decl *VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
+
ObjCTypeParamList *ImportObjCTypeParamList(ObjCTypeParamList *list);
Decl *VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
@@ -185,6 +200,7 @@ namespace clang {
ClassTemplateSpecializationDecl *D);
Decl *VisitVarTemplateDecl(VarTemplateDecl *D);
Decl *VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D);
+ Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
// Importing statements
DeclGroupRef ImportDeclGroup(DeclGroupRef DG);
@@ -265,13 +281,16 @@ namespace clang {
Expr *VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E);
Expr *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *CE);
Expr *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E);
+ Expr *VisitPackExpansionExpr(PackExpansionExpr *E);
Expr *VisitCXXNewExpr(CXXNewExpr *CE);
Expr *VisitCXXDeleteExpr(CXXDeleteExpr *E);
Expr *VisitCXXConstructExpr(CXXConstructExpr *E);
Expr *VisitCXXMemberCallExpr(CXXMemberCallExpr *E);
+ Expr *VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E);
Expr *VisitExprWithCleanups(ExprWithCleanups *EWC);
Expr *VisitCXXThisExpr(CXXThisExpr *E);
Expr *VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E);
+ Expr *VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E);
Expr *VisitMemberExpr(MemberExpr *E);
Expr *VisitCallExpr(CallExpr *E);
Expr *VisitInitListExpr(InitListExpr *E);
@@ -280,6 +299,7 @@ namespace clang {
Expr *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E);
Expr *VisitCXXNamedCastExpr(CXXNamedCastExpr *E);
Expr *VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E);
+ Expr *VisitTypeTraitExpr(TypeTraitExpr *E);
template<typename IIter, typename OIter>
@@ -566,6 +586,22 @@ QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) {
return Importer.getToContext().getFunctionType(ToResultType, ArgTypes, ToEPI);
}
+QualType ASTNodeImporter::VisitUnresolvedUsingType(
+ const UnresolvedUsingType *T) {
+ UnresolvedUsingTypenameDecl *ToD = cast_or_null<UnresolvedUsingTypenameDecl>(
+ Importer.Import(T->getDecl()));
+ if (!ToD)
+ return QualType();
+
+ UnresolvedUsingTypenameDecl *ToPrevD =
+ cast_or_null<UnresolvedUsingTypenameDecl>(
+ Importer.Import(T->getDecl()->getPreviousDecl()));
+ if (!ToPrevD && T->getDecl()->getPreviousDecl())
+ return QualType();
+
+ return Importer.getToContext().getTypeDeclType(ToD, ToPrevD);
+}
+
QualType ASTNodeImporter::VisitParenType(const ParenType *T) {
QualType ToInnerType = Importer.Import(T->getInnerType());
if (ToInnerType.isNull())
@@ -767,6 +803,15 @@ QualType ASTNodeImporter::VisitElaboratedType(const ElaboratedType *T) {
ToQualifier, ToNamedType);
}
+QualType ASTNodeImporter::VisitPackExpansionType(const PackExpansionType *T) {
+ QualType Pattern = Importer.Import(T->getPattern());
+ if (Pattern.isNull())
+ return QualType();
+
+ return Importer.getToContext().getPackExpansionType(Pattern,
+ T->getNumExpansions());
+}
+
QualType ASTNodeImporter::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
ObjCInterfaceDecl *Class
= dyn_cast_or_null<ObjCInterfaceDecl>(Importer.Import(T->getDecl()));
@@ -1171,9 +1216,8 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) {
llvm_unreachable("Invalid template argument kind");
}
-TemplateArgumentLoc ASTNodeImporter::ImportTemplateArgumentLoc(
- const TemplateArgumentLoc &TALoc, bool &Error) {
- Error = false;
+Optional<TemplateArgumentLoc>
+ASTNodeImporter::ImportTemplateArgumentLoc(const TemplateArgumentLoc &TALoc) {
TemplateArgument Arg = ImportTemplateArgument(TALoc.getArgument());
TemplateArgumentLocInfo FromInfo = TALoc.getLocInfo();
TemplateArgumentLocInfo ToInfo;
@@ -1181,12 +1225,12 @@ TemplateArgumentLoc ASTNodeImporter::ImportTemplateArgumentLoc(
Expr *E = Importer.Import(FromInfo.getAsExpr());
ToInfo = TemplateArgumentLocInfo(E);
if (!E)
- Error = true;
+ return None;
} else if (Arg.getKind() == TemplateArgument::Type) {
if (TypeSourceInfo *TSI = Importer.Import(FromInfo.getAsTypeSourceInfo()))
ToInfo = TemplateArgumentLocInfo(TSI);
else
- Error = true;
+ return None;
} else {
ToInfo = TemplateArgumentLocInfo(
Importer.Import(FromInfo.getTemplateQualifierLoc()),
@@ -1210,6 +1254,18 @@ bool ASTNodeImporter::ImportTemplateArguments(const TemplateArgument *FromArgs,
return false;
}
+template <typename InContainerTy>
+bool ASTNodeImporter::ImportTemplateArgumentListInfo(
+ const InContainerTy &Container, TemplateArgumentListInfo &ToTAInfo) {
+ for (const auto &FromLoc : Container) {
+ if (auto ToLoc = ImportTemplateArgumentLoc(FromLoc))
+ ToTAInfo.addArgument(*ToLoc);
+ else
+ return true;
+ }
+ return false;
+}
+
bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord,
RecordDecl *ToRecord, bool Complain) {
// Eliminate a potential failure point where we attempt to re-import
@@ -1243,6 +1299,14 @@ bool ASTNodeImporter::IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToEnum) {
return Ctx.IsStructurallyEquivalent(FromEnum, ToEnum);
}
+bool ASTNodeImporter::IsStructuralMatch(FunctionTemplateDecl *From,
+ FunctionTemplateDecl *To) {
+ StructuralEquivalenceContext Ctx(
+ Importer.getFromContext(), Importer.getToContext(),
+ Importer.getNonEquivalentDecls(), false, false);
+ return Ctx.IsStructurallyEquivalent(From, To);
+}
+
bool ASTNodeImporter::IsStructuralMatch(EnumConstantDecl *FromEC,
EnumConstantDecl *ToEC)
{
@@ -1276,6 +1340,29 @@ Decl *ASTNodeImporter::VisitDecl(Decl *D) {
return nullptr;
}
+Decl *ASTNodeImporter::VisitEmptyDecl(EmptyDecl *D) {
+ // Import the context of this declaration.
+ DeclContext *DC = Importer.ImportContext(D->getDeclContext());
+ if (!DC)
+ return nullptr;
+
+ DeclContext *LexicalDC = DC;
+ if (D->getDeclContext() != D->getLexicalDeclContext()) {
+ LexicalDC = Importer.ImportContext(D->getLexicalDeclContext());
+ if (!LexicalDC)
+ return nullptr;
+ }
+
+ // Import the location of this declaration.
+ SourceLocation Loc = Importer.Import(D->getLocation());
+
+ EmptyDecl *ToD = EmptyDecl::Create(Importer.getToContext(), DC, Loc);
+ ToD->setLexicalDeclContext(LexicalDC);
+ Importer.Imported(D, ToD);
+ LexicalDC->addDeclInternal(ToD);
+ return ToD;
+}
+
Decl *ASTNodeImporter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
TranslationUnitDecl *ToD =
Importer.getToContext().getTranslationUnitDecl();
@@ -1410,6 +1497,44 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) {
return ToNamespace;
}
+Decl *ASTNodeImporter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
+ // Import the major distinguishing characteristics of this namespace.
+ DeclContext *DC, *LexicalDC;
+ DeclarationName Name;
+ SourceLocation Loc;
+ NamedDecl *LookupD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, LookupD, Loc))
+ return nullptr;
+ if (LookupD)
+ return LookupD;
+
+ // NOTE: No conflict resolution is done for namespace aliases now.
+
+ NamespaceDecl *TargetDecl = cast_or_null<NamespaceDecl>(
+ Importer.Import(D->getNamespace()));
+ if (!TargetDecl)
+ return nullptr;
+
+ IdentifierInfo *ToII = Importer.Import(D->getIdentifier());
+ if (!ToII)
+ return nullptr;
+
+ NestedNameSpecifierLoc ToQLoc = Importer.Import(D->getQualifierLoc());
+ if (D->getQualifierLoc() && !ToQLoc)
+ return nullptr;
+
+ NamespaceAliasDecl *ToD = NamespaceAliasDecl::Create(
+ Importer.getToContext(), DC, Importer.Import(D->getNamespaceLoc()),
+ Importer.Import(D->getAliasLoc()), ToII, ToQLoc,
+ Importer.Import(D->getTargetNameLoc()), TargetDecl);
+
+ ToD->setLexicalDeclContext(LexicalDC);
+ Importer.Imported(D, ToD);
+ LexicalDC->addDeclInternal(ToD);
+
+ return ToD;
+}
+
Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) {
// Import the major distinguishing characteristics of this typedef.
DeclContext *DC, *LexicalDC;
@@ -1487,6 +1612,63 @@ Decl *ASTNodeImporter::VisitTypeAliasDecl(TypeAliasDecl *D) {
return VisitTypedefNameDecl(D, /*IsAlias=*/true);
}
+Decl *ASTNodeImporter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
+ // Import the major distinguishing characteristics of this typedef.
+ DeclContext *DC, *LexicalDC;
+ DeclarationName Name;
+ SourceLocation Loc;
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return nullptr;
+ if (ToD)
+ return ToD;
+
+ // If this typedef is not in block scope, determine whether we've
+ // seen a typedef with the same name (that we can merge with) or any
+ // other entity by that name (which name lookup could conflict with).
+ if (!DC->isFunctionOrMethod()) {
+ SmallVector<NamedDecl *, 4> ConflictingDecls;
+ unsigned IDNS = Decl::IDNS_Ordinary;
+ SmallVector<NamedDecl *, 2> FoundDecls;
+ DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
+ for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
+ if (!FoundDecls[I]->isInIdentifierNamespace(IDNS))
+ continue;
+ if (auto *FoundAlias =
+ dyn_cast<TypeAliasTemplateDecl>(FoundDecls[I]))
+ return Importer.Imported(D, FoundAlias);
+ ConflictingDecls.push_back(FoundDecls[I]);
+ }
+
+ if (!ConflictingDecls.empty()) {
+ Name = Importer.HandleNameConflict(Name, DC, IDNS,
+ ConflictingDecls.data(),
+ ConflictingDecls.size());
+ if (!Name)
+ return nullptr;
+ }
+ }
+
+ TemplateParameterList *Params = ImportTemplateParameterList(
+ D->getTemplateParameters());
+ if (!Params)
+ return nullptr;
+
+ NamedDecl *TemplDecl = cast_or_null<NamedDecl>(
+ Importer.Import(D->getTemplatedDecl()));
+ if (!TemplDecl)
+ return nullptr;
+
+ TypeAliasTemplateDecl *ToAlias = TypeAliasTemplateDecl::Create(
+ Importer.getToContext(), DC, Loc, Name, Params, TemplDecl);
+
+ ToAlias->setAccess(D->getAccess());
+ ToAlias->setLexicalDeclContext(LexicalDC);
+ Importer.Imported(D, ToAlias);
+ LexicalDC->addDeclInternal(ToAlias);
+ return ToD;
+}
+
Decl *ASTNodeImporter::VisitLabelDecl(LabelDecl *D) {
// Import the major distinguishing characteristics of this label.
DeclContext *DC, *LexicalDC;
@@ -1752,6 +1934,31 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
}
D2 = D2CXX;
D2->setAccess(D->getAccess());
+
+ Importer.Imported(D, D2);
+
+ if (ClassTemplateDecl *FromDescribed =
+ DCXX->getDescribedClassTemplate()) {
+ ClassTemplateDecl *ToDescribed = cast_or_null<ClassTemplateDecl>(
+ Importer.Import(FromDescribed));
+ if (!ToDescribed)
+ return nullptr;
+ D2CXX->setDescribedClassTemplate(ToDescribed);
+
+ } else if (MemberSpecializationInfo *MemberInfo =
+ DCXX->getMemberSpecializationInfo()) {
+ TemplateSpecializationKind SK =
+ MemberInfo->getTemplateSpecializationKind();
+ CXXRecordDecl *FromInst = DCXX->getInstantiatedFromMemberClass();
+ CXXRecordDecl *ToInst =
+ cast_or_null<CXXRecordDecl>(Importer.Import(FromInst));
+ if (FromInst && !ToInst)
+ return nullptr;
+ D2CXX->setInstantiationOfMemberClass(ToInst, SK);
+ D2CXX->getMemberSpecializationInfo()->setPointOfInstantiation(
+ Importer.Import(MemberInfo->getPointOfInstantiation()));
+ }
+
} else {
D2 = RecordDecl::Create(Importer.getToContext(), D->getTagKind(),
DC, StartLoc, Loc, Name.getAsIdentifierInfo());
@@ -1846,6 +2053,8 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
if (ToD)
return ToD;
+ const FunctionDecl *FoundWithoutBody = nullptr;
+
// Try to find a function in our own ("to") context with the same name, same
// type, and in the same context as the function we're importing.
if (!LexicalDC->isFunctionOrMethod()) {
@@ -1863,6 +2072,13 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
if (Importer.IsStructurallyEquivalent(D->getType(),
FoundFunction->getType())) {
// FIXME: Actually try to merge the body and other attributes.
+ const FunctionDecl *FromBodyDecl = nullptr;
+ D->hasBody(FromBodyDecl);
+ if (D == FromBodyDecl && !FoundFunction->hasBody()) {
+ // This function is needed to merge completely.
+ FoundWithoutBody = FoundFunction;
+ break;
+ }
return Importer.Imported(D, FoundFunction);
}
@@ -2013,6 +2229,12 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
}
ToFunction->setParams(Parameters);
+ if (FoundWithoutBody) {
+ auto *Recent = const_cast<FunctionDecl *>(
+ FoundWithoutBody->getMostRecentDecl());
+ ToFunction->setPreviousDecl(Recent);
+ }
+
if (usedDifferentExceptionSpec) {
// Update FunctionProtoType::ExtProtoInfo.
QualType T = Importer.Import(D->getType());
@@ -2876,6 +3098,178 @@ Decl *ASTNodeImporter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
return ToLinkageSpec;
}
+Decl *ASTNodeImporter::VisitUsingDecl(UsingDecl *D) {
+ DeclContext *DC, *LexicalDC;
+ DeclarationName Name;
+ SourceLocation Loc;
+ NamedDecl *ToD = nullptr;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return nullptr;
+ if (ToD)
+ return ToD;
+
+ DeclarationNameInfo NameInfo(Name,
+ Importer.Import(D->getNameInfo().getLoc()));
+ ImportDeclarationNameLoc(D->getNameInfo(), NameInfo);
+
+ UsingDecl *ToUsing = UsingDecl::Create(Importer.getToContext(), DC,
+ Importer.Import(D->getUsingLoc()),
+ Importer.Import(D->getQualifierLoc()),
+ NameInfo, D->hasTypename());
+ ToUsing->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDeclInternal(ToUsing);
+ Importer.Imported(D, ToUsing);
+
+ if (NamedDecl *FromPattern =
+ Importer.getFromContext().getInstantiatedFromUsingDecl(D)) {
+ if (NamedDecl *ToPattern =
+ dyn_cast_or_null<NamedDecl>(Importer.Import(FromPattern)))
+ Importer.getToContext().setInstantiatedFromUsingDecl(ToUsing, ToPattern);
+ else
+ return nullptr;
+ }
+
+ for (UsingShadowDecl *FromShadow : D->shadows()) {
+ if (UsingShadowDecl *ToShadow =
+ dyn_cast_or_null<UsingShadowDecl>(Importer.Import(FromShadow)))
+ ToUsing->addShadowDecl(ToShadow);
+ else
+ // FIXME: We return a nullptr here but the definition is already created
+ // and available with lookups. How to fix this?..
+ return nullptr;
+ }
+ return ToUsing;
+}
+
+Decl *ASTNodeImporter::VisitUsingShadowDecl(UsingShadowDecl *D) {
+ DeclContext *DC, *LexicalDC;
+ DeclarationName Name;
+ SourceLocation Loc;
+ NamedDecl *ToD = nullptr;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return nullptr;
+ if (ToD)
+ return ToD;
+
+ UsingDecl *ToUsing = dyn_cast_or_null<UsingDecl>(
+ Importer.Import(D->getUsingDecl()));
+ if (!ToUsing)
+ return nullptr;
+
+ NamedDecl *ToTarget = dyn_cast_or_null<NamedDecl>(
+ Importer.Import(D->getTargetDecl()));
+ if (!ToTarget)
+ return nullptr;
+
+ UsingShadowDecl *ToShadow = UsingShadowDecl::Create(
+ Importer.getToContext(), DC, Loc, ToUsing, ToTarget);
+
+ ToShadow->setLexicalDeclContext(LexicalDC);
+ ToShadow->setAccess(D->getAccess());
+ Importer.Imported(D, ToShadow);
+
+ if (UsingShadowDecl *FromPattern =
+ Importer.getFromContext().getInstantiatedFromUsingShadowDecl(D)) {
+ if (UsingShadowDecl *ToPattern =
+ dyn_cast_or_null<UsingShadowDecl>(Importer.Import(FromPattern)))
+ Importer.getToContext().setInstantiatedFromUsingShadowDecl(ToShadow,
+ ToPattern);
+ else
+ // FIXME: We return a nullptr here but the definition is already created
+ // and available with lookups. How to fix this?..
+ return nullptr;
+ }
+
+ LexicalDC->addDeclInternal(ToShadow);
+
+ return ToShadow;
+}
+
+
+Decl *ASTNodeImporter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
+ DeclContext *DC, *LexicalDC;
+ DeclarationName Name;
+ SourceLocation Loc;
+ NamedDecl *ToD = nullptr;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return nullptr;
+ if (ToD)
+ return ToD;
+
+ DeclContext *ToComAncestor = Importer.ImportContext(D->getCommonAncestor());
+ if (!ToComAncestor)
+ return nullptr;
+
+ NamespaceDecl *ToNominated = cast_or_null<NamespaceDecl>(
+ Importer.Import(D->getNominatedNamespace()));
+ if (!ToNominated)
+ return nullptr;
+
+ UsingDirectiveDecl *ToUsingDir = UsingDirectiveDecl::Create(
+ Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()),
+ Importer.Import(D->getNamespaceKeyLocation()),
+ Importer.Import(D->getQualifierLoc()),
+ Importer.Import(D->getIdentLocation()), ToNominated, ToComAncestor);
+ ToUsingDir->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDeclInternal(ToUsingDir);
+ Importer.Imported(D, ToUsingDir);
+
+ return ToUsingDir;
+}
+
+Decl *ASTNodeImporter::VisitUnresolvedUsingValueDecl(
+ UnresolvedUsingValueDecl *D) {
+ DeclContext *DC, *LexicalDC;
+ DeclarationName Name;
+ SourceLocation Loc;
+ NamedDecl *ToD = nullptr;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return nullptr;
+ if (ToD)
+ return ToD;
+
+ DeclarationNameInfo NameInfo(Name, Importer.Import(D->getNameInfo().getLoc()));
+ ImportDeclarationNameLoc(D->getNameInfo(), NameInfo);
+
+ UnresolvedUsingValueDecl *ToUsingValue = UnresolvedUsingValueDecl::Create(
+ Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()),
+ Importer.Import(D->getQualifierLoc()), NameInfo,
+ Importer.Import(D->getEllipsisLoc()));
+
+ Importer.Imported(D, ToUsingValue);
+ ToUsingValue->setAccess(D->getAccess());
+ ToUsingValue->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDeclInternal(ToUsingValue);
+
+ return ToUsingValue;
+}
+
+Decl *ASTNodeImporter::VisitUnresolvedUsingTypenameDecl(
+ UnresolvedUsingTypenameDecl *D) {
+ DeclContext *DC, *LexicalDC;
+ DeclarationName Name;
+ SourceLocation Loc;
+ NamedDecl *ToD = nullptr;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return nullptr;
+ if (ToD)
+ return ToD;
+
+ UnresolvedUsingTypenameDecl *ToUsing = UnresolvedUsingTypenameDecl::Create(
+ Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()),
+ Importer.Import(D->getTypenameLoc()),
+ Importer.Import(D->getQualifierLoc()), Loc, Name,
+ Importer.Import(D->getEllipsisLoc()));
+
+ Importer.Imported(D, ToUsing);
+ ToUsing->setAccess(D->getAccess());
+ ToUsing->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDeclInternal(ToUsing);
+
+ return ToUsing;
+}
+
+
bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From,
ObjCInterfaceDecl *To,
ImportDefinitionKind Kind) {
@@ -3453,7 +3847,6 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
CXXRecordDecl *DTemplated = D->getTemplatedDecl();
// Create the declaration that is being templated.
- // Create the declaration that is being templated.
CXXRecordDecl *D2Templated = cast_or_null<CXXRecordDecl>(
Importer.Import(DTemplated));
if (!D2Templated)
@@ -3560,11 +3953,10 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl(
TemplateArgumentListInfo ToTAInfo;
auto &ASTTemplateArgs = *PartialSpec->getTemplateArgsAsWritten();
for (unsigned I = 0, E = ASTTemplateArgs.NumTemplateArgs; I < E; ++I) {
- bool Error = false;
- auto ToLoc = ImportTemplateArgumentLoc(ASTTemplateArgs[I], Error);
- if (Error)
+ if (auto ToLoc = ImportTemplateArgumentLoc(ASTTemplateArgs[I]))
+ ToTAInfo.addArgument(*ToLoc);
+ else
return nullptr;
- ToTAInfo.addArgument(ToLoc);
}
QualType CanonInjType = Importer.Import(
@@ -3832,6 +4224,64 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl(
return D2;
}
+Decl *ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
+ DeclContext *DC, *LexicalDC;
+ DeclarationName Name;
+ SourceLocation Loc;
+ NamedDecl *ToD;
+
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return nullptr;
+
+ if (ToD)
+ return ToD;
+
+ // Try to find a function in our own ("to") context with the same name, same
+ // type, and in the same context as the function we're importing.
+ if (!LexicalDC->isFunctionOrMethod()) {
+ unsigned IDNS = Decl::IDNS_Ordinary;
+ SmallVector<NamedDecl *, 2> FoundDecls;
+ DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
+ for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
+ if (!FoundDecls[I]->isInIdentifierNamespace(IDNS))
+ continue;
+
+ if (FunctionTemplateDecl *FoundFunction =
+ dyn_cast<FunctionTemplateDecl>(FoundDecls[I])) {
+ if (FoundFunction->hasExternalFormalLinkage() &&
+ D->hasExternalFormalLinkage()) {
+ if (IsStructuralMatch(D, FoundFunction)) {
+ Importer.Imported(D, FoundFunction);
+ // FIXME: Actually try to merge the body and other attributes.
+ return FoundFunction;
+ }
+ }
+ }
+ }
+ }
+
+ TemplateParameterList *Params =
+ ImportTemplateParameterList(D->getTemplateParameters());
+ if (!Params)
+ return nullptr;
+
+ FunctionDecl *TemplatedFD =
+ cast_or_null<FunctionDecl>(Importer.Import(D->getTemplatedDecl()));
+ if (!TemplatedFD)
+ return nullptr;
+
+ FunctionTemplateDecl *ToFunc = FunctionTemplateDecl::Create(
+ Importer.getToContext(), DC, Loc, Name, Params, TemplatedFD);
+
+ TemplatedFD->setDescribedFunctionTemplate(ToFunc);
+ ToFunc->setAccess(D->getAccess());
+ ToFunc->setLexicalDeclContext(LexicalDC);
+ Importer.Imported(D, ToFunc);
+
+ LexicalDC->addDeclInternal(ToFunc);
+ return ToFunc;
+}
+
//----------------------------------------------------------------------------
// Import Statements
//----------------------------------------------------------------------------
@@ -3968,12 +4418,16 @@ Stmt *ASTNodeImporter::VisitCaseStmt(CaseStmt *S) {
Expr *ToRHS = Importer.Import(S->getRHS());
if (!ToRHS && S->getRHS())
return nullptr;
+ Stmt *ToSubStmt = Importer.Import(S->getSubStmt());
+ if (!ToSubStmt && S->getSubStmt())
+ return nullptr;
SourceLocation ToCaseLoc = Importer.Import(S->getCaseLoc());
SourceLocation ToEllipsisLoc = Importer.Import(S->getEllipsisLoc());
SourceLocation ToColonLoc = Importer.Import(S->getColonLoc());
- return new (Importer.getToContext()) CaseStmt(ToLHS, ToRHS,
- ToCaseLoc, ToEllipsisLoc,
- ToColonLoc);
+ CaseStmt *ToStmt = new (Importer.getToContext())
+ CaseStmt(ToLHS, ToRHS, ToCaseLoc, ToEllipsisLoc, ToColonLoc);
+ ToStmt->setSubStmt(ToSubStmt);
+ return ToStmt;
}
Stmt *ASTNodeImporter::VisitDefaultStmt(DefaultStmt *S) {
@@ -4443,11 +4897,10 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
TemplateArgumentListInfo *ResInfo = nullptr;
if (E->hasExplicitTemplateArgs()) {
for (const auto &FromLoc : E->template_arguments()) {
- bool Error = false;
- TemplateArgumentLoc ToTALoc = ImportTemplateArgumentLoc(FromLoc, Error);
- if (Error)
+ if (auto ToTALoc = ImportTemplateArgumentLoc(FromLoc))
+ ToTAInfo.addArgument(*ToTALoc);
+ else
return nullptr;
- ToTAInfo.addArgument(ToTALoc);
}
ResInfo = &ToTAInfo;
}
@@ -5161,6 +5614,20 @@ ASTNodeImporter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
return ToMTE;
}
+Expr *ASTNodeImporter::VisitPackExpansionExpr(PackExpansionExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ Expr *Pattern = Importer.Import(E->getPattern());
+ if (!Pattern)
+ return nullptr;
+
+ return new (Importer.getToContext()) PackExpansionExpr(
+ T, Pattern, Importer.Import(E->getEllipsisLoc()),
+ E->getNumExpansions());
+}
+
Expr *ASTNodeImporter::VisitCXXNewExpr(CXXNewExpr *CE) {
QualType T = Importer.Import(CE->getType());
if (T.isNull())
@@ -5344,6 +5811,80 @@ Expr *ASTNodeImporter::VisitMemberExpr(MemberExpr *E) {
E->getObjectKind());
}
+Expr *ASTNodeImporter::VisitCXXPseudoDestructorExpr(
+ CXXPseudoDestructorExpr *E) {
+
+ Expr *BaseE = Importer.Import(E->getBase());
+ if (!BaseE)
+ return nullptr;
+
+ TypeSourceInfo *ScopeInfo = Importer.Import(E->getScopeTypeInfo());
+ if (!ScopeInfo && E->getScopeTypeInfo())
+ return nullptr;
+
+ PseudoDestructorTypeStorage Storage;
+ if (IdentifierInfo *FromII = E->getDestroyedTypeIdentifier()) {
+ IdentifierInfo *ToII = Importer.Import(FromII);
+ if (!ToII)
+ return nullptr;
+ Storage = PseudoDestructorTypeStorage(
+ ToII, Importer.Import(E->getDestroyedTypeLoc()));
+ } else {
+ TypeSourceInfo *TI = Importer.Import(E->getDestroyedTypeInfo());
+ if (!TI)
+ return nullptr;
+ Storage = PseudoDestructorTypeStorage(TI);
+ }
+
+ return new (Importer.getToContext()) CXXPseudoDestructorExpr(
+ Importer.getToContext(), BaseE, E->isArrow(),
+ Importer.Import(E->getOperatorLoc()),
+ Importer.Import(E->getQualifierLoc()),
+ ScopeInfo, Importer.Import(E->getColonColonLoc()),
+ Importer.Import(E->getTildeLoc()), Storage);
+}
+
+Expr *ASTNodeImporter::VisitCXXDependentScopeMemberExpr(
+ CXXDependentScopeMemberExpr *E) {
+ Expr *Base = nullptr;
+ if (!E->isImplicitAccess()) {
+ Base = Importer.Import(E->getBase());
+ if (!Base)
+ return nullptr;
+ }
+
+ QualType BaseType = Importer.Import(E->getBaseType());
+ if (BaseType.isNull())
+ return nullptr;
+
+ TemplateArgumentListInfo ToTAInfo(Importer.Import(E->getLAngleLoc()),
+ Importer.Import(E->getRAngleLoc()));
+ TemplateArgumentListInfo *ResInfo = nullptr;
+ if (E->hasExplicitTemplateArgs()) {
+ if (ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo))
+ return nullptr;
+ ResInfo = &ToTAInfo;
+ }
+
+ DeclarationName Name = Importer.Import(E->getMember());
+ if (!E->getMember().isEmpty() && Name.isEmpty())
+ return nullptr;
+
+ DeclarationNameInfo MemberNameInfo(Name, Importer.Import(E->getMemberLoc()));
+ // Import additional name location/type info.
+ ImportDeclarationNameLoc(E->getMemberNameInfo(), MemberNameInfo);
+ auto ToFQ = Importer.Import(E->getFirstQualifierFoundInScope());
+ if (!ToFQ && E->getFirstQualifierFoundInScope())
+ return nullptr;
+
+ return CXXDependentScopeMemberExpr::Create(
+ Importer.getToContext(), Base, BaseType, E->isArrow(),
+ Importer.Import(E->getOperatorLoc()),
+ Importer.Import(E->getQualifierLoc()),
+ Importer.Import(E->getTemplateKeywordLoc()),
+ cast_or_null<NamedDecl>(ToFQ), MemberNameInfo, ResInfo);
+}
+
Expr *ASTNodeImporter::VisitCallExpr(CallExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
@@ -5510,6 +6051,26 @@ Expr *ASTNodeImporter::VisitSubstNonTypeTemplateParmExpr(
Replacement);
}
+Expr *ASTNodeImporter::VisitTypeTraitExpr(TypeTraitExpr *E) {
+ QualType ToType = Importer.Import(E->getType());
+ if (ToType.isNull())
+ return nullptr;
+
+ SmallVector<TypeSourceInfo *, 4> ToArgs(E->getNumArgs());
+ if (ImportContainerChecked(E->getArgs(), ToArgs))
+ return nullptr;
+
+ // According to Sema::BuildTypeTrait(), if E is value-dependent,
+ // Value is always false.
+ bool ToValue = false;
+ if (!E->isValueDependent())
+ ToValue = E->getValue();
+
+ return TypeTraitExpr::Create(
+ Importer.getToContext(), ToType, Importer.Import(E->getLocStart()),
+ E->getTrait(), ToArgs, Importer.Import(E->getLocEnd()), ToValue);
+}
+
void ASTNodeImporter::ImportOverrides(CXXMethodDecl *ToMethod,
CXXMethodDecl *FromMethod) {
for (auto *FromOverriddenMethod : FromMethod->overridden_methods())
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTStructuralEquivalence.cpp b/contrib/llvm/tools/clang/lib/AST/ASTStructuralEquivalence.cpp
index ea7faab767edf..0df8e5653f3b5 100644
--- a/contrib/llvm/tools/clang/lib/AST/ASTStructuralEquivalence.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ASTStructuralEquivalence.cpp
@@ -365,6 +365,21 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
break;
}
+ case Type::DependentAddressSpace: {
+ const DependentAddressSpaceType *DepAddressSpace1 =
+ cast<DependentAddressSpaceType>(T1);
+ const DependentAddressSpaceType *DepAddressSpace2 =
+ cast<DependentAddressSpaceType>(T2);
+ if (!IsStructurallyEquivalent(Context, DepAddressSpace1->getAddrSpaceExpr(),
+ DepAddressSpace2->getAddrSpaceExpr()))
+ return false;
+ if (!IsStructurallyEquivalent(Context, DepAddressSpace1->getPointeeType(),
+ DepAddressSpace2->getPointeeType()))
+ return false;
+
+ break;
+ }
+
case Type::DependentSizedExtVector: {
const DependentSizedExtVectorType *Vec1 =
cast<DependentSizedExtVectorType>(T1);
diff --git a/contrib/llvm/tools/clang/lib/AST/CXXABI.h b/contrib/llvm/tools/clang/lib/AST/CXXABI.h
index 924ef00e8147a..06295b58178bf 100644
--- a/contrib/llvm/tools/clang/lib/AST/CXXABI.h
+++ b/contrib/llvm/tools/clang/lib/AST/CXXABI.h
@@ -31,9 +31,16 @@ class CXXABI {
public:
virtual ~CXXABI();
- /// Returns the width and alignment of a member pointer in bits.
- virtual std::pair<uint64_t, unsigned>
- getMemberPointerWidthAndAlign(const MemberPointerType *MPT) const = 0;
+ struct MemberPointerInfo {
+ uint64_t Width;
+ unsigned Align;
+ bool HasPadding;
+ };
+
+ /// Returns the width and alignment of a member pointer in bits, as well as
+ /// whether it has padding.
+ virtual MemberPointerInfo
+ getMemberPointerInfo(const MemberPointerType *MPT) const = 0;
/// Returns the default calling convention for C++ methods.
virtual CallingConv getDefaultMethodCallConv(bool isVariadic) const = 0;
diff --git a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp
index fc4d8b137337f..24e96ba38015c 100644
--- a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp
@@ -1,4 +1,4 @@
-//===------ CXXInheritance.cpp - C++ Inheritance ----------------*- C++ -*-===//
+//===- CXXInheritance.cpp - C++ Inheritance -------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,13 +10,27 @@
// This file provides routines that help analyzing C++ inheritance hierarchies.
//
//===----------------------------------------------------------------------===//
+
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/RecordLayout.h"
+#include "clang/AST/TemplateName.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Casting.h"
#include <algorithm>
+#include <utility>
+#include <cassert>
+#include <vector>
using namespace clang;
@@ -26,7 +40,7 @@ void CXXBasePaths::ComputeDeclsFound() {
assert(NumDeclsFound == 0 && !DeclsFound &&
"Already computed the set of declarations");
- llvm::SetVector<NamedDecl *, SmallVector<NamedDecl *, 8> > Decls;
+ llvm::SetVector<NamedDecl *, SmallVector<NamedDecl *, 8>> Decls;
for (paths_iterator Path = begin(), PathEnd = end(); Path != PathEnd; ++Path)
Decls.insert(Path->Decls.front());
@@ -419,8 +433,8 @@ bool CXXRecordDecl::FindTagMember(const CXXBaseSpecifier *Specifier,
static bool findOrdinaryMember(RecordDecl *BaseRecord, CXXBasePath &Path,
DeclarationName Name) {
- const unsigned IDNS = clang::Decl::IDNS_Ordinary | clang::Decl::IDNS_Tag |
- clang::Decl::IDNS_Member;
+ const unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag |
+ Decl::IDNS_Member;
for (Path.Decls = BaseRecord->lookup(Name);
!Path.Decls.empty();
Path.Decls = Path.Decls.slice(1)) {
@@ -550,26 +564,27 @@ void OverridingMethods::replaceAll(UniqueVirtualMethod Overriding) {
}
}
-
namespace {
- class FinalOverriderCollector {
- /// \brief The number of subobjects of a given class type that
- /// occur within the class hierarchy.
- llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCount;
- /// \brief Overriders for each virtual base subobject.
- llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *> VirtualOverriders;
+class FinalOverriderCollector {
+ /// \brief The number of subobjects of a given class type that
+ /// occur within the class hierarchy.
+ llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCount;
- CXXFinalOverriderMap FinalOverriders;
+ /// \brief Overriders for each virtual base subobject.
+ llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *> VirtualOverriders;
- public:
- ~FinalOverriderCollector();
+ CXXFinalOverriderMap FinalOverriders;
- void Collect(const CXXRecordDecl *RD, bool VirtualBase,
- const CXXRecordDecl *InVirtualSubobject,
- CXXFinalOverriderMap &Overriders);
- };
-}
+public:
+ ~FinalOverriderCollector();
+
+ void Collect(const CXXRecordDecl *RD, bool VirtualBase,
+ const CXXRecordDecl *InVirtualSubobject,
+ CXXFinalOverriderMap &Overriders);
+};
+
+} // namespace
void FinalOverriderCollector::Collect(const CXXRecordDecl *RD,
bool VirtualBase,
@@ -635,9 +650,11 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD,
continue;
CXXMethodDecl *CanonM = cast<CXXMethodDecl>(M->getCanonicalDecl());
+ using OverriddenMethodsRange =
+ llvm::iterator_range<CXXMethodDecl::method_iterator>;
+ OverriddenMethodsRange OverriddenMethods = CanonM->overridden_methods();
- if (CanonM->begin_overridden_methods()
- == CanonM->end_overridden_methods()) {
+ if (OverriddenMethods.begin() == OverriddenMethods.end()) {
// This is a new virtual function that does not override any
// other virtual function. Add it to the map of virtual
// functions for which we are tracking overridders.
@@ -656,11 +673,7 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD,
// overrider. To do so, we dig down to the original virtual
// functions using data recursion and update all of the methods it
// overrides.
- typedef llvm::iterator_range<CXXMethodDecl::method_iterator>
- OverriddenMethods;
- SmallVector<OverriddenMethods, 4> Stack;
- Stack.push_back(llvm::make_range(CanonM->begin_overridden_methods(),
- CanonM->end_overridden_methods()));
+ SmallVector<OverriddenMethodsRange, 4> Stack(1, OverriddenMethods);
while (!Stack.empty()) {
for (const CXXMethodDecl *OM : Stack.pop_back_val()) {
const CXXMethodDecl *CanonOM = OM->getCanonicalDecl();
@@ -678,14 +691,13 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD,
UniqueVirtualMethod(CanonM, SubobjectNumber,
InVirtualSubobject));
- if (CanonOM->begin_overridden_methods()
- == CanonOM->end_overridden_methods())
+ auto OverriddenMethods = CanonOM->overridden_methods();
+ if (OverriddenMethods.begin() == OverriddenMethods.end())
continue;
// Continue recursion to the methods that this virtual method
// overrides.
- Stack.push_back(llvm::make_range(CanonOM->begin_overridden_methods(),
- CanonOM->end_overridden_methods()));
+ Stack.push_back(OverriddenMethods);
}
}
diff --git a/contrib/llvm/tools/clang/lib/AST/CommentSema.cpp b/contrib/llvm/tools/clang/lib/AST/CommentSema.cpp
index 403454d3ab7e6..6c2019e1a72b6 100644
--- a/contrib/llvm/tools/clang/lib/AST/CommentSema.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/CommentSema.cpp
@@ -813,7 +813,7 @@ bool Sema::isAnyFunctionDecl() {
}
bool Sema::isFunctionOrMethodVariadic() {
- if (!isAnyFunctionDecl() && !isObjCMethodDecl() && !isFunctionTemplateDecl())
+ if (!isFunctionDecl() || !ThisDeclInfo->CurrentDecl)
return false;
if (const FunctionDecl *FD =
dyn_cast<FunctionDecl>(ThisDeclInfo->CurrentDecl))
@@ -824,6 +824,14 @@ bool Sema::isFunctionOrMethodVariadic() {
if (const ObjCMethodDecl *MD =
dyn_cast<ObjCMethodDecl>(ThisDeclInfo->CurrentDecl))
return MD->isVariadic();
+ if (const TypedefNameDecl *TD =
+ dyn_cast<TypedefNameDecl>(ThisDeclInfo->CurrentDecl)) {
+ QualType Type = TD->getUnderlyingType();
+ if (Type->isFunctionPointerType() || Type->isBlockPointerType())
+ Type = Type->getPointeeType();
+ if (const auto *FT = Type->getAs<FunctionProtoType>())
+ return FT->isVariadic();
+ }
return false;
}
diff --git a/contrib/llvm/tools/clang/lib/AST/DataCollection.cpp b/contrib/llvm/tools/clang/lib/AST/DataCollection.cpp
new file mode 100644
index 0000000000000..c2ecabe8e6f8a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/DataCollection.cpp
@@ -0,0 +1,50 @@
+//===-- DataCollection.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/DataCollection.h"
+
+#include "clang/Lex/Lexer.h"
+
+namespace clang {
+namespace data_collection {
+
+/// Prints the macro name that contains the given SourceLocation into the given
+/// raw_string_ostream.
+static void printMacroName(llvm::raw_string_ostream &MacroStack,
+ ASTContext &Context, SourceLocation Loc) {
+ MacroStack << Lexer::getImmediateMacroName(Loc, Context.getSourceManager(),
+ Context.getLangOpts());
+
+ // Add an empty space at the end as a padding to prevent
+ // that macro names concatenate to the names of other macros.
+ MacroStack << " ";
+}
+
+/// Returns a string that represents all macro expansions that expanded into the
+/// given SourceLocation.
+///
+/// If 'getMacroStack(A) == getMacroStack(B)' is true, then the SourceLocations
+/// A and B are expanded from the same macros in the same order.
+std::string getMacroStack(SourceLocation Loc, ASTContext &Context) {
+ std::string MacroStack;
+ llvm::raw_string_ostream MacroStackStream(MacroStack);
+ SourceManager &SM = Context.getSourceManager();
+
+ // Iterate over all macros that expanded into the given SourceLocation.
+ while (Loc.isMacroID()) {
+ // Add the macro name to the stream.
+ printMacroName(MacroStackStream, Context, Loc);
+ Loc = SM.getImmediateMacroCallerLoc(Loc);
+ }
+ MacroStackStream.flush();
+ return MacroStack;
+}
+
+} // end namespace data_collection
+} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/AST/Decl.cpp b/contrib/llvm/tools/clang/lib/AST/Decl.cpp
index 573a98efe980b..2f51ec31a7bdc 100644
--- a/contrib/llvm/tools/clang/lib/AST/Decl.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Decl.cpp
@@ -1,4 +1,4 @@
-//===--- Decl.cpp - Declaration AST Node Implementation -------------------===//
+//===- Decl.cpp - Declaration AST Node Implementation ---------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,27 +12,62 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/Decl.h"
+#include "Linkage.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/ASTMutationListener.h"
-#include "clang/AST/Attr.h"
+#include "clang/AST/CanonicalType.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclOpenMP.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/PrettyPrinter.h"
+#include "clang/AST/Redeclarable.h"
#include "clang/AST/Stmt.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/Linkage.h"
#include "clang/Basic/Module.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SanitizerBlacklist.h"
+#include "clang/Basic/Sanitizers.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Specifiers.h"
+#include "clang/Basic/TargetCXXABI.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/Visibility.h"
#include "clang/Frontend/FrontendDiagnostic.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstring>
+#include <memory>
+#include <string>
+#include <tuple>
+#include <type_traits>
using namespace clang;
@@ -47,7 +82,7 @@ bool Decl::isOutOfLine() const {
TranslationUnitDecl::TranslationUnitDecl(ASTContext &ctx)
: Decl(TranslationUnit, nullptr, SourceLocation()),
- DeclContext(TranslationUnit), Ctx(ctx), AnonymousNamespace(nullptr) {}
+ DeclContext(TranslationUnit), Ctx(ctx) {}
//===----------------------------------------------------------------------===//
// NamedDecl Implementation
@@ -99,63 +134,25 @@ TranslationUnitDecl::TranslationUnitDecl(ASTContext &ctx)
// and 'matcher' is a type only matters when looking for attributes
// and settings from the immediate context.
-const unsigned IgnoreExplicitVisibilityBit = 2;
-const unsigned IgnoreAllVisibilityBit = 4;
-
-/// Kinds of LV computation. The linkage side of the computation is
-/// always the same, but different things can change how visibility is
-/// computed.
-enum LVComputationKind {
- /// Do an LV computation for, ultimately, a type.
- /// Visibility may be restricted by type visibility settings and
- /// the visibility of template arguments.
- LVForType = NamedDecl::VisibilityForType,
-
- /// Do an LV computation for, ultimately, a non-type declaration.
- /// Visibility may be restricted by value visibility settings and
- /// the visibility of template arguments.
- LVForValue = NamedDecl::VisibilityForValue,
-
- /// Do an LV computation for, ultimately, a type that already has
- /// some sort of explicit visibility. Visibility may only be
- /// restricted by the visibility of template arguments.
- LVForExplicitType = (LVForType | IgnoreExplicitVisibilityBit),
-
- /// Do an LV computation for, ultimately, a non-type declaration
- /// that already has some sort of explicit visibility. Visibility
- /// may only be restricted by the visibility of template arguments.
- LVForExplicitValue = (LVForValue | IgnoreExplicitVisibilityBit),
-
- /// Do an LV computation when we only care about the linkage.
- LVForLinkageOnly =
- LVForValue | IgnoreExplicitVisibilityBit | IgnoreAllVisibilityBit
-};
-
/// Does this computation kind permit us to consider additional
/// visibility settings from attributes and the like?
static bool hasExplicitVisibilityAlready(LVComputationKind computation) {
- return ((unsigned(computation) & IgnoreExplicitVisibilityBit) != 0);
+ return computation.IgnoreExplicitVisibility;
}
/// Given an LVComputationKind, return one of the same type/value sort
/// that records that it already has explicit visibility.
static LVComputationKind
-withExplicitVisibilityAlready(LVComputationKind oldKind) {
- LVComputationKind newKind =
- static_cast<LVComputationKind>(unsigned(oldKind) |
- IgnoreExplicitVisibilityBit);
- assert(oldKind != LVForType || newKind == LVForExplicitType);
- assert(oldKind != LVForValue || newKind == LVForExplicitValue);
- assert(oldKind != LVForExplicitType || newKind == LVForExplicitType);
- assert(oldKind != LVForExplicitValue || newKind == LVForExplicitValue);
- return newKind;
+withExplicitVisibilityAlready(LVComputationKind Kind) {
+ Kind.IgnoreExplicitVisibility = true;
+ return Kind;
}
static Optional<Visibility> getExplicitVisibility(const NamedDecl *D,
LVComputationKind kind) {
- assert(!hasExplicitVisibilityAlready(kind) &&
+ assert(!kind.IgnoreExplicitVisibility &&
"asking for explicit visibility when we shouldn't be");
- return D->getExplicitVisibility((NamedDecl::ExplicitVisibilityKind) kind);
+ return D->getExplicitVisibility(kind.getExplicitVisibilityKind());
}
/// Is the given declaration a "type" or a "value" for the purposes of
@@ -216,30 +213,21 @@ static Optional<Visibility> getVisibilityOf(const NamedDecl *D,
return getVisibilityFromAttr(A);
}
- // If we're on Mac OS X, an 'availability' for Mac OS X attribute
- // implies visibility(default).
- if (D->getASTContext().getTargetInfo().getTriple().isOSDarwin()) {
- for (const auto *A : D->specific_attrs<AvailabilityAttr>())
- if (A->getPlatform()->getName().equals("macos"))
- return DefaultVisibility;
- }
-
return None;
}
-static LinkageInfo
-getLVForType(const Type &T, LVComputationKind computation) {
- if (computation == LVForLinkageOnly)
+LinkageInfo LinkageComputer::getLVForType(const Type &T,
+ LVComputationKind computation) {
+ if (computation.IgnoreAllVisibility)
return LinkageInfo(T.getLinkage(), DefaultVisibility, true);
- return T.getLinkageAndVisibility();
+ return getTypeLinkageAndVisibility(&T);
}
/// \brief Get the most restrictive linkage for the types in the given
/// template parameter list. For visibility purposes, template
/// parameters are part of the signature of a template.
-static LinkageInfo
-getLVForTemplateParameterList(const TemplateParameterList *Params,
- LVComputationKind computation) {
+LinkageInfo LinkageComputer::getLVForTemplateParameterList(
+ const TemplateParameterList *Params, LVComputationKind computation) {
LinkageInfo LV;
for (const NamedDecl *P : *Params) {
// Template type parameters are the most common and never
@@ -264,7 +252,7 @@ getLVForTemplateParameterList(const TemplateParameterList *Params,
for (unsigned i = 0, n = NTTP->getNumExpansionTypes(); i != n; ++i) {
QualType type = NTTP->getExpansionType(i);
if (!type->isDependentType())
- LV.merge(type->getLinkageAndVisibility());
+ LV.merge(getTypeLinkageAndVisibility(type));
}
continue;
}
@@ -291,10 +279,6 @@ getLVForTemplateParameterList(const TemplateParameterList *Params,
return LV;
}
-/// getLVForDecl - Get the linkage and visibility for the given declaration.
-static LinkageInfo getLVForDecl(const NamedDecl *D,
- LVComputationKind computation);
-
static const Decl *getOutermostFuncOrBlockContext(const Decl *D) {
const Decl *Ret = nullptr;
const DeclContext *DC = D->getDeclContext();
@@ -311,8 +295,9 @@ static const Decl *getOutermostFuncOrBlockContext(const Decl *D) {
///
/// Note that we don't take an LVComputationKind because we always
/// want to honor the visibility of template arguments in the same way.
-static LinkageInfo getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args,
- LVComputationKind computation) {
+LinkageInfo
+LinkageComputer::getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args,
+ LVComputationKind computation) {
LinkageInfo LV;
for (const TemplateArgument &Arg : Args) {
@@ -334,7 +319,7 @@ static LinkageInfo getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args,
continue;
case TemplateArgument::NullPtr:
- LV.merge(Arg.getNullPtrType()->getLinkageAndVisibility());
+ LV.merge(getTypeLinkageAndVisibility(Arg.getNullPtrType()));
continue;
case TemplateArgument::Template:
@@ -354,9 +339,9 @@ static LinkageInfo getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args,
return LV;
}
-static LinkageInfo
-getLVForTemplateArgumentList(const TemplateArgumentList &TArgs,
- LVComputationKind computation) {
+LinkageInfo
+LinkageComputer::getLVForTemplateArgumentList(const TemplateArgumentList &TArgs,
+ LVComputationKind computation) {
return getLVForTemplateArgumentList(TArgs.asArray(), computation);
}
@@ -379,10 +364,10 @@ static bool shouldConsiderTemplateVisibility(const FunctionDecl *fn,
/// LVForValue.
///
/// \param[out] LV the computation to use for the parent
-static void
-mergeTemplateLV(LinkageInfo &LV, const FunctionDecl *fn,
- const FunctionTemplateSpecializationInfo *specInfo,
- LVComputationKind computation) {
+void LinkageComputer::mergeTemplateLV(
+ LinkageInfo &LV, const FunctionDecl *fn,
+ const FunctionTemplateSpecializationInfo *specInfo,
+ LVComputationKind computation) {
bool considerVisibility =
shouldConsiderTemplateVisibility(fn, specInfo);
@@ -402,21 +387,11 @@ mergeTemplateLV(LinkageInfo &LV, const FunctionDecl *fn,
/// that would match the given rules?
static bool hasDirectVisibilityAttribute(const NamedDecl *D,
LVComputationKind computation) {
- switch (computation) {
- case LVForType:
- case LVForExplicitType:
- if (D->hasAttr<TypeVisibilityAttr>())
- return true;
- // fallthrough
- case LVForValue:
- case LVForExplicitValue:
- if (D->hasAttr<VisibilityAttr>())
- return true;
- return false;
- case LVForLinkageOnly:
+ if (computation.IgnoreAllVisibility)
return false;
- }
- llvm_unreachable("bad visibility computation kind");
+
+ return (computation.isTypeVisibility() && D->hasAttr<TypeVisibilityAttr>()) ||
+ D->hasAttr<VisibilityAttr>();
}
/// Should we consider visibility associated with the template
@@ -457,9 +432,9 @@ static bool shouldConsiderTemplateVisibility(
/// Merge in template-related linkage and visibility for the given
/// class template specialization.
-static void mergeTemplateLV(LinkageInfo &LV,
- const ClassTemplateSpecializationDecl *spec,
- LVComputationKind computation) {
+void LinkageComputer::mergeTemplateLV(
+ LinkageInfo &LV, const ClassTemplateSpecializationDecl *spec,
+ LVComputationKind computation) {
bool considerVisibility = shouldConsiderTemplateVisibility(spec, computation);
// Merge information from the template parameters, but ignore
@@ -509,9 +484,9 @@ static bool shouldConsiderTemplateVisibility(
/// Merge in template-related linkage and visibility for the given
/// variable template specialization. As usual, follow class template
/// specialization logic up to initialization.
-static void mergeTemplateLV(LinkageInfo &LV,
- const VarTemplateSpecializationDecl *spec,
- LVComputationKind computation) {
+void LinkageComputer::mergeTemplateLV(LinkageInfo &LV,
+ const VarTemplateSpecializationDecl *spec,
+ LVComputationKind computation) {
bool considerVisibility = shouldConsiderTemplateVisibility(spec, computation);
// Merge information from the template parameters, but ignore
@@ -574,6 +549,7 @@ static bool isSingleLineLanguageLinkage(const Decl &D) {
}
static bool isExportedFromModuleIntefaceUnit(const NamedDecl *D) {
+ // FIXME: Handle isModulePrivate.
switch (D->getModuleOwnershipKind()) {
case Decl::ModuleOwnershipKind::Unowned:
case Decl::ModuleOwnershipKind::ModulePrivate:
@@ -605,14 +581,17 @@ static LinkageInfo getExternalLinkageFor(const NamedDecl *D) {
// declaration has module linkage.
if (auto *M = D->getOwningModule())
if (M->Kind == Module::ModuleInterfaceUnit)
- if (!isExportedFromModuleIntefaceUnit(D))
+ if (!isExportedFromModuleIntefaceUnit(
+ cast<NamedDecl>(D->getCanonicalDecl())))
return LinkageInfo(ModuleLinkage, DefaultVisibility, false);
return LinkageInfo::external();
}
-static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
- LVComputationKind computation) {
+LinkageInfo
+LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
+ LVComputationKind computation,
+ bool IgnoreVarTypeLinkage) {
assert(D->getDeclContext()->getRedeclContext()->isFileContext() &&
"Not a name having namespace scope");
ASTContext &Context = D->getASTContext();
@@ -652,7 +631,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
PrevVar = PrevVar->getPreviousDecl()) {
if (PrevVar->getStorageClass() == SC_PrivateExtern &&
Var->getStorageClass() == SC_None)
- return PrevVar->getLinkageAndVisibility();
+ return getDeclLinkageAndVisibility(PrevVar);
// Explicitly declared static.
if (PrevVar->getStorageClass() == SC_Static)
return getInternalLinkageFor(Var);
@@ -669,23 +648,23 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
// - a data member of an anonymous union.
const VarDecl *VD = IFD->getVarDecl();
assert(VD && "Expected a VarDecl in this IndirectFieldDecl!");
- return getLVForNamespaceScopeDecl(VD, computation);
+ return getLVForNamespaceScopeDecl(VD, computation, IgnoreVarTypeLinkage);
}
assert(!isa<FieldDecl>(D) && "Didn't expect a FieldDecl!");
if (D->isInAnonymousNamespace()) {
const auto *Var = dyn_cast<VarDecl>(D);
const auto *Func = dyn_cast<FunctionDecl>(D);
- // FIXME: In C++11 onwards, anonymous namespaces should give decls
- // within them (including those inside extern "C" contexts) internal
- // linkage, not unique external linkage:
+ // FIXME: The check for extern "C" here is not justified by the standard
+ // wording, but we retain it from the pre-DR1113 model to avoid breaking
+ // code.
//
// C++11 [basic.link]p4:
// An unnamed namespace or a namespace declared directly or indirectly
// within an unnamed namespace has internal linkage.
if ((!Var || !isFirstInExternCContext(Var)) &&
(!Func || !isFirstInExternCContext(Func)))
- return LinkageInfo::uniqueExternal();
+ return getInternalLinkageFor(D);
}
// Set up the defaults.
@@ -694,7 +673,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
// If the declaration of an identifier for an object has file
// scope and no storage-class specifier, its linkage is
// external.
- LinkageInfo LV;
+ LinkageInfo LV = getExternalLinkageFor(D);
if (!hasExplicitVisibilityAlready(computation)) {
if (Optional<Visibility> Vis = getExplicitVisibility(D, computation)) {
@@ -717,13 +696,10 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
// Add in global settings if the above didn't give us direct visibility.
if (!LV.isVisibilityExplicit()) {
// Use global type/value visibility as appropriate.
- Visibility globalVisibility;
- if (computation == LVForValue) {
- globalVisibility = Context.getLangOpts().getValueVisibilityMode();
- } else {
- assert(computation == LVForType);
- globalVisibility = Context.getLangOpts().getTypeVisibilityMode();
- }
+ Visibility globalVisibility =
+ computation.isValueVisibility()
+ ? Context.getLangOpts().getValueVisibilityMode()
+ : Context.getLangOpts().getTypeVisibilityMode();
LV.mergeVisibility(globalVisibility, /*explicit*/ false);
// If we're paying attention to global visibility, apply
@@ -761,10 +737,10 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
//
// Note that we don't want to make the variable non-external
// because of this, but unique-external linkage suits us.
- if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Var)) {
+ if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Var) &&
+ !IgnoreVarTypeLinkage) {
LinkageInfo TypeLV = getLVForType(*Var->getType(), computation);
- if (TypeLV.getLinkage() != ExternalLinkage &&
- TypeLV.getLinkage() != ModuleLinkage)
+ if (!isExternallyVisible(TypeLV.getLinkage()))
return LinkageInfo::uniqueExternal();
if (!LV.isVisibilityExplicit())
LV.mergeVisibility(TypeLV);
@@ -802,19 +778,13 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
// unique-external linkage, it's not legally usable from outside
// this translation unit. However, we should use the C linkage
// rules instead for extern "C" declarations.
- if (Context.getLangOpts().CPlusPlus &&
- !Function->isInExternCContext()) {
- // Only look at the type-as-written. If this function has an auto-deduced
- // return type, we can't compute the linkage of that type because it could
- // require looking at the linkage of this function, and we don't need this
- // for correctness because the type is not part of the function's
- // signature.
- // FIXME: This is a hack. We should be able to solve this circularity and
- // the one in getLVForClassMember for Functions some other way.
+ if (Context.getLangOpts().CPlusPlus && !Function->isInExternCContext()) {
+ // Only look at the type-as-written. Otherwise, deducing the return type
+ // of a function could change its linkage.
QualType TypeAsWritten = Function->getType();
if (TypeSourceInfo *TSI = Function->getTypeSourceInfo())
TypeAsWritten = TSI->getType();
- if (TypeAsWritten->getLinkage() == UniqueExternalLinkage)
+ if (!isExternallyVisible(TypeAsWritten->getLinkage()))
return LinkageInfo::uniqueExternal();
}
@@ -883,16 +853,18 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
return LinkageInfo::none();
}
- // If we ended up with non-external linkage, visibility should
+ // If we ended up with non-externally-visible linkage, visibility should
// always be default.
- if (LV.getLinkage() != ExternalLinkage)
+ if (!isExternallyVisible(LV.getLinkage()))
return LinkageInfo(LV.getLinkage(), DefaultVisibility, false);
return LV;
}
-static LinkageInfo getLVForClassMember(const NamedDecl *D,
- LVComputationKind computation) {
+LinkageInfo
+LinkageComputer::getLVForClassMember(const NamedDecl *D,
+ LVComputationKind computation,
+ bool IgnoreVarTypeLinkage) {
// Only certain class members have linkage. Note that fields don't
// really have linkage, but it's convenient to say they do for the
// purposes of calculating linkage of pointer-to-data-member
@@ -935,12 +907,11 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D,
LinkageInfo classLV =
getLVForDecl(cast<RecordDecl>(D->getDeclContext()), classComputation);
- // If the class already has unique-external linkage, we can't improve.
- if (classLV.getLinkage() == UniqueExternalLinkage)
- return LinkageInfo::uniqueExternal();
-
+ // The member has the same linkage as the class. If that's not externally
+ // visible, we don't need to compute anything about the linkage.
+ // FIXME: If we're only computing linkage, can we bail out here?
if (!isExternallyVisible(classLV.getLinkage()))
- return LinkageInfo::none();
+ return classLV;
// Otherwise, don't merge in classLV yet, because in certain cases
@@ -950,22 +921,14 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D,
const NamedDecl *explicitSpecSuppressor = nullptr;
if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
- // If the type of the function uses a type with unique-external
- // linkage, it's not legally usable from outside this translation unit.
- // But only look at the type-as-written. If this function has an
- // auto-deduced return type, we can't compute the linkage of that type
- // because it could require looking at the linkage of this function, and we
- // don't need this for correctness because the type is not part of the
- // function's signature.
- // FIXME: This is a hack. We should be able to solve this circularity and
- // the one in getLVForNamespaceScopeDecl for Functions some other way.
- {
- QualType TypeAsWritten = MD->getType();
- if (TypeSourceInfo *TSI = MD->getTypeSourceInfo())
- TypeAsWritten = TSI->getType();
- if (TypeAsWritten->getLinkage() == UniqueExternalLinkage)
- return LinkageInfo::uniqueExternal();
- }
+ // Only look at the type-as-written. Otherwise, deducing the return type
+ // of a function could change its linkage.
+ QualType TypeAsWritten = MD->getType();
+ if (TypeSourceInfo *TSI = MD->getTypeSourceInfo())
+ TypeAsWritten = TSI->getType();
+ if (!isExternallyVisible(TypeAsWritten->getLinkage()))
+ return LinkageInfo::uniqueExternal();
+
// If this is a method template specialization, use the linkage for
// the template parameters and arguments.
if (FunctionTemplateSpecializationInfo *spec
@@ -1002,10 +965,14 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D,
// Modify the variable's linkage by its type, but ignore the
// type's visibility unless it's a definition.
- LinkageInfo typeLV = getLVForType(*VD->getType(), computation);
- if (!LV.isVisibilityExplicit() && !classLV.isVisibilityExplicit())
- LV.mergeVisibility(typeLV);
- LV.mergeExternalVisibility(typeLV);
+ if (!IgnoreVarTypeLinkage) {
+ LinkageInfo typeLV = getLVForType(*VD->getType(), computation);
+ // FIXME: If the type's linkage is not externally visible, we can
+ // give this static data member UniqueExternalLinkage.
+ if (!LV.isVisibilityExplicit() && !classLV.isVisibilityExplicit())
+ LV.mergeVisibility(typeLV);
+ LV.mergeExternalVisibility(typeLV);
+ }
if (isExplicitMemberSpecialization(VD)) {
explicitSpecSuppressor = VD;
@@ -1047,17 +1014,16 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D,
return LV;
}
-void NamedDecl::anchor() { }
-
-static LinkageInfo computeLVForDecl(const NamedDecl *D,
- LVComputationKind computation);
+void NamedDecl::anchor() {}
bool NamedDecl::isLinkageValid() const {
if (!hasCachedLinkage())
return true;
- return computeLVForDecl(this, LVForLinkageOnly).getLinkage() ==
- getCachedLinkage();
+ Linkage L = LinkageComputer{}
+ .computeLVForDecl(this, LVComputationKind::forLinkageOnly())
+ .getLinkage();
+ return L == getCachedLinkage();
}
ObjCStringFormatFamily NamedDecl::getObjCFStringFormattingFamily() const {
@@ -1076,13 +1042,13 @@ ObjCStringFormatFamily NamedDecl::getObjCFStringFormattingFamily() const {
Linkage NamedDecl::getLinkageInternal() const {
// We don't care about visibility here, so ask for the cheapest
// possible visibility analysis.
- return getLVForDecl(this, LVForLinkageOnly).getLinkage();
+ return LinkageComputer{}
+ .getLVForDecl(this, LVComputationKind::forLinkageOnly())
+ .getLinkage();
}
LinkageInfo NamedDecl::getLinkageAndVisibility() const {
- LVComputationKind computation =
- (usesTypeVisibility(this) ? LVForType : LVForValue);
- return getLVForDecl(this, computation);
+ return LinkageComputer{}.getDeclLinkageAndVisibility(this);
}
static Optional<Visibility>
@@ -1160,30 +1126,46 @@ NamedDecl::getExplicitVisibility(ExplicitVisibilityKind kind) const {
return getExplicitVisibilityAux(this, kind, false);
}
-static LinkageInfo getLVForClosure(const DeclContext *DC, Decl *ContextDecl,
- LVComputationKind computation) {
+LinkageInfo LinkageComputer::getLVForClosure(const DeclContext *DC,
+ Decl *ContextDecl,
+ LVComputationKind computation) {
// This lambda has its linkage/visibility determined by its owner.
- if (ContextDecl) {
- if (isa<ParmVarDecl>(ContextDecl))
- DC = ContextDecl->getDeclContext()->getRedeclContext();
- else
- return getLVForDecl(cast<NamedDecl>(ContextDecl), computation);
- }
+ const NamedDecl *Owner;
+ if (!ContextDecl)
+ Owner = dyn_cast<NamedDecl>(DC);
+ else if (isa<ParmVarDecl>(ContextDecl))
+ Owner =
+ dyn_cast<NamedDecl>(ContextDecl->getDeclContext()->getRedeclContext());
+ else
+ Owner = cast<NamedDecl>(ContextDecl);
- if (const auto *ND = dyn_cast<NamedDecl>(DC))
- return getLVForDecl(ND, computation);
+ if (!Owner)
+ return LinkageInfo::none();
- // FIXME: We have a closure at TU scope with no context declaration. This
- // should probably have no linkage.
- return LinkageInfo::external();
+ // If the owner has a deduced type, we need to skip querying the linkage and
+ // visibility of that type, because it might involve this closure type. The
+ // only effect of this is that we might give a lambda VisibleNoLinkage rather
+ // than NoLinkage when we don't strictly need to, which is benign.
+ auto *VD = dyn_cast<VarDecl>(Owner);
+ LinkageInfo OwnerLV =
+ VD && VD->getType()->getContainedDeducedType()
+ ? computeLVForDecl(Owner, computation, /*IgnoreVarTypeLinkage*/true)
+ : getLVForDecl(Owner, computation);
+
+ // A lambda never formally has linkage. But if the owner is externally
+ // visible, then the lambda is too. We apply the same rules to blocks.
+ if (!isExternallyVisible(OwnerLV.getLinkage()))
+ return LinkageInfo::none();
+ return LinkageInfo(VisibleNoLinkage, OwnerLV.getVisibility(),
+ OwnerLV.isVisibilityExplicit());
}
-static LinkageInfo getLVForLocalDecl(const NamedDecl *D,
- LVComputationKind computation) {
+LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D,
+ LVComputationKind computation) {
if (const auto *Function = dyn_cast<FunctionDecl>(D)) {
if (Function->isInAnonymousNamespace() &&
!Function->isInExternCContext())
- return LinkageInfo::uniqueExternal();
+ return getInternalLinkageFor(Function);
// This is a "void f();" which got merged with a file static.
if (Function->getCanonicalDecl()->getStorageClass() == SC_Static)
@@ -1206,7 +1188,7 @@ static LinkageInfo getLVForLocalDecl(const NamedDecl *D,
if (const auto *Var = dyn_cast<VarDecl>(D)) {
if (Var->hasExternalStorage()) {
if (Var->isInAnonymousNamespace() && !Var->isInExternCContext())
- return LinkageInfo::uniqueExternal();
+ return getInternalLinkageFor(Var);
LinkageInfo LV;
if (Var->getStorageClass() == SC_PrivateExtern)
@@ -1272,8 +1254,9 @@ getOutermostEnclosingLambda(const CXXRecordDecl *Record) {
return Ret;
}
-static LinkageInfo computeLVForDecl(const NamedDecl *D,
- LVComputationKind computation) {
+LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D,
+ LVComputationKind computation,
+ bool IgnoreVarTypeLinkage) {
// Internal_linkage attribute overrides other considerations.
if (D->hasAttr<InternalLinkageAttr>())
return getInternalLinkageFor(D);
@@ -1361,7 +1344,7 @@ static LinkageInfo computeLVForDecl(const NamedDecl *D,
// Handle linkage for namespace-scope names.
if (D->getDeclContext()->getRedeclContext()->isFileContext())
- return getLVForNamespaceScopeDecl(D, computation);
+ return getLVForNamespaceScopeDecl(D, computation, IgnoreVarTypeLinkage);
// C++ [basic.link]p5:
// In addition, a member function, static data member, a named
@@ -1371,7 +1354,7 @@ static LinkageInfo computeLVForDecl(const NamedDecl *D,
// purposes (7.1.3), has external linkage if the name of the class
// has external linkage.
if (D->getDeclContext()->isRecord())
- return getLVForClassMember(D, computation);
+ return getLVForClassMember(D, computation, IgnoreVarTypeLinkage);
// C++ [basic.link]p6:
// The name of a function declared in block scope and the name of
@@ -1392,56 +1375,93 @@ static LinkageInfo computeLVForDecl(const NamedDecl *D,
return LinkageInfo::none();
}
-namespace clang {
-class LinkageComputer {
-public:
- static LinkageInfo getLVForDecl(const NamedDecl *D,
- LVComputationKind computation) {
- // Internal_linkage attribute overrides other considerations.
- if (D->hasAttr<InternalLinkageAttr>())
- return getInternalLinkageFor(D);
+/// getLVForDecl - Get the linkage and visibility for the given declaration.
+LinkageInfo LinkageComputer::getLVForDecl(const NamedDecl *D,
+ LVComputationKind computation) {
+ // Internal_linkage attribute overrides other considerations.
+ if (D->hasAttr<InternalLinkageAttr>())
+ return getInternalLinkageFor(D);
+
+ if (computation.IgnoreAllVisibility && D->hasCachedLinkage())
+ return LinkageInfo(D->getCachedLinkage(), DefaultVisibility, false);
- if (computation == LVForLinkageOnly && D->hasCachedLinkage())
- return LinkageInfo(D->getCachedLinkage(), DefaultVisibility, false);
+ if (llvm::Optional<LinkageInfo> LI = lookup(D, computation))
+ return *LI;
- LinkageInfo LV = computeLVForDecl(D, computation);
- if (D->hasCachedLinkage())
- assert(D->getCachedLinkage() == LV.getLinkage());
+ LinkageInfo LV = computeLVForDecl(D, computation);
+ if (D->hasCachedLinkage())
+ assert(D->getCachedLinkage() == LV.getLinkage());
- D->setCachedLinkage(LV.getLinkage());
+ D->setCachedLinkage(LV.getLinkage());
+ cache(D, computation, LV);
#ifndef NDEBUG
- // In C (because of gnu inline) and in c++ with microsoft extensions an
- // static can follow an extern, so we can have two decls with different
- // linkages.
- const LangOptions &Opts = D->getASTContext().getLangOpts();
- if (!Opts.CPlusPlus || Opts.MicrosoftExt)
- return LV;
+ // In C (because of gnu inline) and in c++ with microsoft extensions an
+ // static can follow an extern, so we can have two decls with different
+ // linkages.
+ const LangOptions &Opts = D->getASTContext().getLangOpts();
+ if (!Opts.CPlusPlus || Opts.MicrosoftExt)
+ return LV;
- // We have just computed the linkage for this decl. By induction we know
- // that all other computed linkages match, check that the one we just
- // computed also does.
- NamedDecl *Old = nullptr;
- for (auto I : D->redecls()) {
- auto *T = cast<NamedDecl>(I);
- if (T == D)
- continue;
- if (!T->isInvalidDecl() && T->hasCachedLinkage()) {
- Old = T;
- break;
- }
+ // We have just computed the linkage for this decl. By induction we know
+ // that all other computed linkages match, check that the one we just
+ // computed also does.
+ NamedDecl *Old = nullptr;
+ for (auto I : D->redecls()) {
+ auto *T = cast<NamedDecl>(I);
+ if (T == D)
+ continue;
+ if (!T->isInvalidDecl() && T->hasCachedLinkage()) {
+ Old = T;
+ break;
}
- assert(!Old || Old->getCachedLinkage() == D->getCachedLinkage());
+ }
+ assert(!Old || Old->getCachedLinkage() == D->getCachedLinkage());
#endif
- return LV;
- }
-};
+ return LV;
+}
+
+LinkageInfo LinkageComputer::getDeclLinkageAndVisibility(const NamedDecl *D) {
+ return getLVForDecl(D,
+ LVComputationKind(usesTypeVisibility(D)
+ ? NamedDecl::VisibilityForType
+ : NamedDecl::VisibilityForValue));
}
-static LinkageInfo getLVForDecl(const NamedDecl *D,
- LVComputationKind computation) {
- return clang::LinkageComputer::getLVForDecl(D, computation);
+Module *Decl::getOwningModuleForLinkage(bool IgnoreLinkage) const {
+ Module *M = getOwningModule();
+ if (!M)
+ return nullptr;
+
+ switch (M->Kind) {
+ case Module::ModuleMapModule:
+ // Module map modules have no special linkage semantics.
+ return nullptr;
+
+ case Module::ModuleInterfaceUnit:
+ return M;
+
+ case Module::GlobalModuleFragment: {
+ // External linkage declarations in the global module have no owning module
+ // for linkage purposes. But internal linkage declarations in the global
+ // module fragment of a particular module are owned by that module for
+ // linkage purposes.
+ if (IgnoreLinkage)
+ return nullptr;
+ bool InternalLinkage;
+ if (auto *ND = dyn_cast<NamedDecl>(this))
+ InternalLinkage = !ND->hasExternalFormalLinkage();
+ else {
+ auto *NSD = dyn_cast<NamespaceDecl>(this);
+ InternalLinkage = (NSD && NSD->isAnonymousNamespace()) ||
+ isInAnonymousNamespace();
+ }
+ return InternalLinkage ? M->Parent : nullptr;
+ }
+ }
+
+ llvm_unreachable("unknown module kind");
}
void NamedDecl::printName(raw_ostream &os) const {
@@ -1473,7 +1493,7 @@ void NamedDecl::printQualifiedName(raw_ostream &OS,
return;
}
- typedef SmallVector<const DeclContext *, 8> ContextsTy;
+ using ContextsTy = SmallVector<const DeclContext *, 8>;
ContextsTy Contexts;
// Collect contexts.
@@ -1482,12 +1502,11 @@ void NamedDecl::printQualifiedName(raw_ostream &OS,
Ctx = Ctx->getParent();
}
- for (const DeclContext *DC : reverse(Contexts)) {
+ for (const DeclContext *DC : llvm::reverse(Contexts)) {
if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
OS << Spec->getName();
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
- TemplateSpecializationType::PrintTemplateArgumentList(
- OS, TemplateArgs.asArray(), P);
+ printTemplateArgumentList(OS, TemplateArgs.asArray(), P);
} else if (const auto *ND = dyn_cast<NamespaceDecl>(DC)) {
if (P.SuppressUnwrittenScope &&
(ND->isAnonymousNamespace() || ND->isInline()))
@@ -1612,14 +1631,6 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD, bool IsKnownNewer) const {
cast<UnresolvedUsingValueDecl>(OldD)->getQualifier());
}
- // UsingDirectiveDecl's are not really NamedDecl's, and all have same name.
- // They can be replaced if they nominate the same namespace.
- // FIXME: Is this true even if they have different module visibility?
- if (auto *UD = dyn_cast<UsingDirectiveDecl>(this))
- return UD->getNominatedNamespace()->getOriginalNamespace() ==
- cast<UsingDirectiveDecl>(OldD)->getNominatedNamespace()
- ->getOriginalNamespace();
-
if (isRedeclarable(getKind())) {
if (getCanonicalDecl() != OldD->getCanonicalDecl())
return false;
@@ -1754,11 +1765,9 @@ SourceLocation DeclaratorDecl::getOuterLocStart() const {
return getTemplateOrInnerLocStart(this);
}
-namespace {
-
// Helper function: returns true if QT is or contains a type
// having a postfix component.
-bool typeIsPostfix(clang::QualType QT) {
+static bool typeIsPostfix(QualType QT) {
while (true) {
const Type* T = QT.getTypePtr();
switch (T->getTypeClass()) {
@@ -1792,8 +1801,6 @@ bool typeIsPostfix(clang::QualType QT) {
}
}
-} // namespace
-
SourceRange DeclaratorDecl::getSourceRange() const {
SourceLocation RangeEnd = getLocation();
if (TypeSourceInfo *TInfo = getTypeSourceInfo()) {
@@ -1843,7 +1850,7 @@ VarDecl::VarDecl(Kind DK, ASTContext &C, DeclContext *DC,
IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
StorageClass SC)
: DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc),
- redeclarable_base(C), Init() {
+ redeclarable_base(C) {
static_assert(sizeof(VarDeclBitfields) <= sizeof(unsigned),
"VarDeclBitfields too large!");
static_assert(sizeof(ParmVarDeclBitfields) <= sizeof(unsigned),
@@ -1967,6 +1974,9 @@ VarDecl *VarDecl::getCanonicalDecl() { return getFirstDecl(); }
VarDecl::DefinitionKind
VarDecl::isThisDeclarationADefinition(ASTContext &C) const {
+ if (isThisDeclarationADemotedDefinition())
+ return DeclarationOnly;
+
// C++ [basic.def]p2:
// A declaration is a definition unless [...] it contains the 'extern'
// specifier or a linkage-specification and neither an initializer [...],
@@ -1980,9 +1990,6 @@ VarDecl::isThisDeclarationADefinition(ASTContext &C) const {
//
// FIXME: How do you declare (but not define) a partial specialization of
// a static data member template outside the containing class?
- if (isThisDeclarationADemotedDefinition())
- return DeclarationOnly;
-
if (isStaticDataMember()) {
if (isOutOfLine() &&
!(getCanonicalDecl()->isInline() &&
@@ -2022,9 +2029,12 @@ VarDecl::isThisDeclarationADefinition(ASTContext &C) const {
// A variable template specialization (other than a static data member
// template or an explicit specialization) is a declaration until we
// instantiate its initializer.
- if (isa<VarTemplateSpecializationDecl>(this) &&
- getTemplateSpecializationKind() != TSK_ExplicitSpecialization)
- return DeclarationOnly;
+ if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(this)) {
+ if (VTSD->getTemplateSpecializationKind() != TSK_ExplicitSpecialization &&
+ !isa<VarTemplatePartialSpecializationDecl>(VTSD) &&
+ !VTSD->IsCompleteDefinition)
+ return DeclarationOnly;
+ }
if (hasExternalStorage())
return DeclarationOnly;
@@ -2408,15 +2418,21 @@ void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
dyn_cast<VarTemplateSpecializationDecl>(this)) {
Spec->setSpecializationKind(TSK);
if (TSK != TSK_ExplicitSpecialization && PointOfInstantiation.isValid() &&
- Spec->getPointOfInstantiation().isInvalid())
+ Spec->getPointOfInstantiation().isInvalid()) {
Spec->setPointOfInstantiation(PointOfInstantiation);
+ if (ASTMutationListener *L = getASTContext().getASTMutationListener())
+ L->InstantiationRequested(this);
+ }
}
if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) {
MSI->setTemplateSpecializationKind(TSK);
if (TSK != TSK_ExplicitSpecialization && PointOfInstantiation.isValid() &&
- MSI->getPointOfInstantiation().isInvalid())
+ MSI->getPointOfInstantiation().isInvalid()) {
MSI->setPointOfInstantiation(PointOfInstantiation);
+ if (ASTMutationListener *L = getASTContext().getASTMutationListener())
+ L->InstantiationRequested(this);
+ }
}
}
@@ -2548,8 +2564,7 @@ void FunctionDecl::getNameForDiagnostic(
NamedDecl::getNameForDiagnostic(OS, Policy, Qualified);
const TemplateArgumentList *TemplateArgs = getTemplateSpecializationArgs();
if (TemplateArgs)
- TemplateSpecializationType::PrintTemplateArgumentList(
- OS, TemplateArgs->asArray(), Policy);
+ printTemplateArgumentList(OS, TemplateArgs->asArray(), Policy);
}
bool FunctionDecl::isVariadic() const {
@@ -2747,6 +2762,20 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction(bool *IsAligned) const
return Params == FPT->getNumParams();
}
+bool FunctionDecl::isDestroyingOperatorDelete() const {
+ // C++ P0722:
+ // Within a class C, a single object deallocation function with signature
+ // (T, std::destroying_delete_t, <more params>)
+ // is a destroying operator delete.
+ if (!isa<CXXMethodDecl>(this) || getOverloadedOperator() != OO_Delete ||
+ getNumParams() < 2)
+ return false;
+
+ auto *RD = getParamDecl(1)->getType()->getAsCXXRecordDecl();
+ return RD && RD->isInStdNamespace() && RD->getIdentifier() &&
+ RD->getIdentifier()->isStr("destroying_delete_t");
+}
+
LanguageLinkage FunctionDecl::getLanguageLinkage() const {
return getDeclLanguageLinkage(*this);
}
@@ -2871,7 +2900,6 @@ unsigned FunctionDecl::getBuiltinID() const {
return BuiltinID;
}
-
/// getNumParams - Return the number of parameters this function must have
/// based on its FunctionType. This is the length of the ParamInfo array
/// after it has been created.
@@ -3057,7 +3085,8 @@ SourceRange FunctionDecl::getExceptionSpecSourceRange() const {
const Attr *FunctionDecl::getUnusedResultAttr() const {
QualType RetType = getReturnType();
if (RetType->isRecordType()) {
- if (const CXXRecordDecl *Ret = RetType->getAsCXXRecordDecl()) {
+ if (const auto *Ret =
+ dyn_cast_or_null<RecordDecl>(RetType->getAsTagDecl())) {
if (const auto *R = Ret->getAttr<WarnUnusedResultAttr>())
return R;
}
@@ -3382,7 +3411,6 @@ DependentFunctionTemplateSpecializationInfo::
DependentFunctionTemplateSpecializationInfo(const UnresolvedSetImpl &Ts,
const TemplateArgumentListInfo &TArgs)
: AngleLocs(TArgs.getLAngleLoc(), TArgs.getRAngleLoc()) {
-
NumTemplates = Ts.size();
NumArgs = TArgs.size();
@@ -3420,15 +3448,21 @@ FunctionDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
FTSInfo->setTemplateSpecializationKind(TSK);
if (TSK != TSK_ExplicitSpecialization &&
PointOfInstantiation.isValid() &&
- FTSInfo->getPointOfInstantiation().isInvalid())
+ FTSInfo->getPointOfInstantiation().isInvalid()) {
FTSInfo->setPointOfInstantiation(PointOfInstantiation);
+ if (ASTMutationListener *L = getASTContext().getASTMutationListener())
+ L->InstantiationRequested(this);
+ }
} else if (MemberSpecializationInfo *MSInfo
= TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>()) {
MSInfo->setTemplateSpecializationKind(TSK);
if (TSK != TSK_ExplicitSpecialization &&
PointOfInstantiation.isValid() &&
- MSInfo->getPointOfInstantiation().isInvalid())
+ MSInfo->getPointOfInstantiation().isInvalid()) {
MSInfo->setPointOfInstantiation(PointOfInstantiation);
+ if (ASTMutationListener *L = getASTContext().getASTMutationListener())
+ L->InstantiationRequested(this);
+ }
} else
llvm_unreachable("Function cannot have a template specialization kind");
}
@@ -3598,8 +3632,7 @@ bool FieldDecl::isAnonymousStructOrUnion() const {
unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const {
assert(isBitField() && "not a bitfield");
- auto *BitWidth = static_cast<Expr *>(InitStorage.getPointer());
- return BitWidth->EvaluateKnownConstInt(Ctx).getZExtValue();
+ return getBitWidth()->EvaluateKnownConstInt(Ctx).getZExtValue();
}
unsigned FieldDecl::getFieldIndex() const {
@@ -3610,7 +3643,8 @@ unsigned FieldDecl::getFieldIndex() const {
if (CachedFieldIndex) return CachedFieldIndex - 1;
unsigned Index = 0;
- const RecordDecl *RD = getParent();
+ const RecordDecl *RD = getParent()->getDefinition();
+ assert(RD && "requested index for field of struct with no definition");
for (auto *Field : RD->fields()) {
Field->getCanonicalDecl()->CachedFieldIndex = Index + 1;
@@ -3622,25 +3656,18 @@ unsigned FieldDecl::getFieldIndex() const {
}
SourceRange FieldDecl::getSourceRange() const {
- switch (InitStorage.getInt()) {
- // All three of these cases store an optional Expr*.
- case ISK_BitWidthOrNothing:
- case ISK_InClassCopyInit:
- case ISK_InClassListInit:
- if (const auto *E = static_cast<const Expr *>(InitStorage.getPointer()))
- return SourceRange(getInnerLocStart(), E->getLocEnd());
- // FALLTHROUGH
-
- case ISK_CapturedVLAType:
- return DeclaratorDecl::getSourceRange();
- }
- llvm_unreachable("bad init storage kind");
+ const Expr *FinalExpr = getInClassInitializer();
+ if (!FinalExpr)
+ FinalExpr = getBitWidth();
+ if (FinalExpr)
+ return SourceRange(getInnerLocStart(), FinalExpr->getLocEnd());
+ return DeclaratorDecl::getSourceRange();
}
void FieldDecl::setCapturedVLAType(const VariableArrayType *VLAType) {
assert((getParent()->isLambda() || getParent()->isCapturedRecord()) &&
"capturing type in non-lambda or captured record.");
- assert(InitStorage.getInt() == ISK_BitWidthOrNothing &&
+ assert(InitStorage.getInt() == ISK_NoInit &&
InitStorage.getPointer() == nullptr &&
"bit width, initializer or captured type already set");
InitStorage.setPointerAndInt(const_cast<VariableArrayType *>(VLAType),
@@ -3753,7 +3780,7 @@ void TagDecl::setTemplateParameterListsInfo(
// EnumDecl Implementation
//===----------------------------------------------------------------------===//
-void EnumDecl::anchor() { }
+void EnumDecl::anchor() {}
EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
@@ -3862,12 +3889,10 @@ RecordDecl::RecordDecl(Kind DK, TagKind TK, const ASTContext &C,
DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
RecordDecl *PrevDecl)
- : TagDecl(DK, TK, C, DC, IdLoc, Id, PrevDecl, StartLoc) {
- HasFlexibleArrayMember = false;
- AnonymousStructOrUnion = false;
- HasObjectMember = false;
- HasVolatileMember = false;
- LoadedFieldsFromExternalStorage = false;
+ : TagDecl(DK, TK, C, DC, IdLoc, Id, PrevDecl, StartLoc),
+ HasFlexibleArrayMember(false), AnonymousStructOrUnion(false),
+ HasObjectMember(false), HasVolatileMember(false),
+ LoadedFieldsFromExternalStorage(false) {
assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!");
}
@@ -3958,9 +3983,9 @@ void RecordDecl::LoadFieldsFromExternalStorage() const {
bool RecordDecl::mayInsertExtraPadding(bool EmitRemark) const {
ASTContext &Context = getASTContext();
- if (!Context.getLangOpts().Sanitize.hasOneOf(
- SanitizerKind::Address | SanitizerKind::KernelAddress) ||
- !Context.getLangOpts().SanitizeAddressFieldPadding)
+ const SanitizerMask EnabledAsanMask = Context.getLangOpts().Sanitize.Mask &
+ (SanitizerKind::Address | SanitizerKind::KernelAddress);
+ if (!EnabledAsanMask || !Context.getLangOpts().SanitizeAddressFieldPadding)
return false;
const auto &Blacklist = Context.getSanitizerBlacklist();
const auto *CXXRD = dyn_cast<CXXRecordDecl>(this);
@@ -3978,9 +4003,11 @@ bool RecordDecl::mayInsertExtraPadding(bool EmitRemark) const {
ReasonToReject = 4; // has trivial destructor.
else if (CXXRD->isStandardLayout())
ReasonToReject = 5; // is standard layout.
- else if (Blacklist.isBlacklistedLocation(getLocation(), "field-padding"))
+ else if (Blacklist.isBlacklistedLocation(EnabledAsanMask, getLocation(),
+ "field-padding"))
ReasonToReject = 6; // is in a blacklisted file.
- else if (Blacklist.isBlacklistedType(getQualifiedNameAsString(),
+ else if (Blacklist.isBlacklistedType(EnabledAsanMask,
+ getQualifiedNameAsString(),
"field-padding"))
ReasonToReject = 7; // is blacklisted.
@@ -4014,7 +4041,6 @@ const FieldDecl *RecordDecl::findFirstNamedDataMember() const {
return nullptr;
}
-
//===----------------------------------------------------------------------===//
// BlockDecl Implementation
//===----------------------------------------------------------------------===//
@@ -4060,13 +4086,13 @@ SourceRange BlockDecl::getSourceRange() const {
// Other Decl Allocation/Deallocation Method Implementations
//===----------------------------------------------------------------------===//
-void TranslationUnitDecl::anchor() { }
+void TranslationUnitDecl::anchor() {}
TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) {
return new (C, (DeclContext *)nullptr) TranslationUnitDecl(C);
}
-void PragmaCommentDecl::anchor() { }
+void PragmaCommentDecl::anchor() {}
PragmaCommentDecl *PragmaCommentDecl::Create(const ASTContext &C,
TranslationUnitDecl *DC,
@@ -4088,7 +4114,7 @@ PragmaCommentDecl *PragmaCommentDecl::CreateDeserialized(ASTContext &C,
PragmaCommentDecl(nullptr, SourceLocation(), PCK_Unknown);
}
-void PragmaDetectMismatchDecl::anchor() { }
+void PragmaDetectMismatchDecl::anchor() {}
PragmaDetectMismatchDecl *
PragmaDetectMismatchDecl::Create(const ASTContext &C, TranslationUnitDecl *DC,
@@ -4113,14 +4139,14 @@ PragmaDetectMismatchDecl::CreateDeserialized(ASTContext &C, unsigned ID,
PragmaDetectMismatchDecl(nullptr, SourceLocation(), 0);
}
-void ExternCContextDecl::anchor() { }
+void ExternCContextDecl::anchor() {}
ExternCContextDecl *ExternCContextDecl::Create(const ASTContext &C,
TranslationUnitDecl *DC) {
return new (C, DC) ExternCContextDecl(DC);
}
-void LabelDecl::anchor() { }
+void LabelDecl::anchor() {}
LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation IdentL, IdentifierInfo *II) {
@@ -4146,7 +4172,7 @@ void LabelDecl::setMSAsmLabel(StringRef Name) {
MSAsmName = Buffer;
}
-void ValueDecl::anchor() { }
+void ValueDecl::anchor() {}
bool ValueDecl::isWeak() const {
for (const auto *I : attrs())
@@ -4156,7 +4182,7 @@ bool ValueDecl::isWeak() const {
return isWeakImported();
}
-void ImplicitParamDecl::anchor() { }
+void ImplicitParamDecl::anchor() {}
ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation IdLoc,
@@ -4239,7 +4265,7 @@ EnumConstantDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
QualType(), nullptr, llvm::APSInt());
}
-void IndirectFieldDecl::anchor() { }
+void IndirectFieldDecl::anchor() {}
IndirectFieldDecl::IndirectFieldDecl(ASTContext &C, DeclContext *DC,
SourceLocation L, DeclarationName N,
@@ -4273,7 +4299,7 @@ SourceRange EnumConstantDecl::getSourceRange() const {
return SourceRange(getLocation(), End);
}
-void TypeDecl::anchor() { }
+void TypeDecl::anchor() {}
TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
@@ -4281,7 +4307,7 @@ TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC,
return new (C, DC) TypedefDecl(C, DC, StartLoc, IdLoc, Id, TInfo);
}
-void TypedefNameDecl::anchor() { }
+void TypedefNameDecl::anchor() {}
TagDecl *TypedefNameDecl::getAnonDeclWithTypedefName(bool AnyRedecl) const {
if (auto *TT = getTypeSourceInfo()->getType()->getAs<TagType>()) {
@@ -4355,7 +4381,7 @@ SourceRange TypeAliasDecl::getSourceRange() const {
return SourceRange(getLocStart(), RangeEnd);
}
-void FileScopeAsmDecl::anchor() { }
+void FileScopeAsmDecl::anchor() {}
FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC,
StringLiteral *Str,
@@ -4398,9 +4424,7 @@ static unsigned getNumModuleIdentifiers(Module *Mod) {
ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc,
Module *Imported,
ArrayRef<SourceLocation> IdentifierLocs)
- : Decl(Import, DC, StartLoc), ImportedAndComplete(Imported, true),
- NextLocalImport()
-{
+ : Decl(Import, DC, StartLoc), ImportedAndComplete(Imported, true) {
assert(getNumModuleIdentifiers(Imported) == IdentifierLocs.size());
auto *StoredLocs = getTrailingObjects<SourceLocation>();
std::uninitialized_copy(IdentifierLocs.begin(), IdentifierLocs.end(),
@@ -4409,9 +4433,7 @@ ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc,
ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc,
Module *Imported, SourceLocation EndLoc)
- : Decl(Import, DC, StartLoc), ImportedAndComplete(Imported, false),
- NextLocalImport()
-{
+ : Decl(Import, DC, StartLoc), ImportedAndComplete(Imported, false) {
*getTrailingObjects<SourceLocation>() = EndLoc;
}
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp
index cd2c83a02f599..29ce7ae034b5c 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp
@@ -1,4 +1,4 @@
-//===--- DeclBase.cpp - Declaration AST Node Implementation ---------------===//
+//===- DeclBase.cpp - Declaration AST Node Implementation -----------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,6 +15,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/Attr.h"
+#include "clang/AST/AttrIterator.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclContextInternals.h"
@@ -25,11 +26,30 @@
#include "clang/AST/DependentDiagnostic.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/Stmt.h"
-#include "clang/AST/StmtCXX.h"
#include "clang/AST/Type.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/ObjCRuntime.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/VersionTuple.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <string>
+#include <tuple>
+#include <utility>
+
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -74,8 +94,9 @@ void *Decl::operator new(std::size_t Size, const ASTContext &Ctx,
DeclContext *Parent, std::size_t Extra) {
assert(!Parent || &Parent->getParentASTContext() == &Ctx);
// With local visibility enabled, we track the owning module even for local
- // declarations.
- if (Ctx.getLangOpts().trackLocalOwningModule()) {
+ // declarations. We create the TU decl early and may not yet know what the
+ // LangOpts are, so conservatively allocate the storage.
+ if (Ctx.getLangOpts().trackLocalOwningModule() || !Parent) {
// Ensure required alignment of the resulting object by adding extra
// padding at the start if required.
size_t ExtraAlign =
@@ -229,7 +250,6 @@ const DeclContext *Decl::getParentFunctionOrMethod() const {
return nullptr;
}
-
//===----------------------------------------------------------------------===//
// PrettyStackTraceDecl Implementation
//===----------------------------------------------------------------------===//
@@ -259,7 +279,7 @@ void PrettyStackTraceDecl::print(raw_ostream &OS) const {
//===----------------------------------------------------------------------===//
// Out-of-line virtual method providing a home for Decl.
-Decl::~Decl() { }
+Decl::~Decl() = default;
void Decl::setDeclContext(DeclContext *DC) {
DeclCtx = DC;
@@ -314,12 +334,11 @@ bool Decl::isLexicallyWithinFunctionOrMethod() const {
}
bool Decl::isInAnonymousNamespace() const {
- const DeclContext *DC = getDeclContext();
- do {
+ for (const DeclContext *DC = getDeclContext(); DC; DC = DC->getParent()) {
if (const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC))
if (ND->isAnonymousNamespace())
return true;
- } while ((DC = DC->getParent()));
+ }
return false;
}
@@ -680,7 +699,6 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case CXXConversion:
case EnumConstant:
case Var:
- case Binding:
case ImplicitParam:
case ParmVar:
case ObjCMethod:
@@ -692,10 +710,11 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case IndirectField:
return IDNS_Ordinary | IDNS_Member;
+ case Binding:
case NonTypeTemplateParm:
- // Non-type template parameters are not found by lookups that ignore
- // non-types, but they are found by redeclaration lookups for tag types,
- // so we include them in the tag namespace.
+ case VarTemplate:
+ // These (C++-only) declarations are found by redeclaration lookup for
+ // tag types, so we include them in the tag namespace.
return IDNS_Ordinary | IDNS_Tag;
case ObjCCompatibleAlias:
@@ -704,7 +723,6 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case Typedef:
case TypeAlias:
- case TypeAliasTemplate:
case TemplateTypeParm:
case ObjCTypeParam:
return IDNS_Ordinary | IDNS_Type;
@@ -740,11 +758,11 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
return IDNS_Namespace;
case FunctionTemplate:
- case VarTemplate:
return IDNS_Ordinary;
case ClassTemplate:
case TemplateTemplateParm:
+ case TypeAliasTemplate:
return IDNS_Ordinary | IDNS_Tag | IDNS_Type;
case OMPDeclareReduction:
@@ -914,7 +932,6 @@ const FunctionType *Decl::getFunctionType(bool BlocksToo) const {
return Ty->getAs<FunctionType>();
}
-
/// Starting at a given context (a Decl or DeclContext), look for a
/// code context that is not a closure (a lambda, block, etc.).
template <class T> static Decl *getNonClosureContext(T *D) {
@@ -967,7 +984,7 @@ bool DeclContext::classof(const Decl *D) {
}
}
-DeclContext::~DeclContext() { }
+DeclContext::~DeclContext() = default;
/// \brief Find the parent context of this context that will be
/// used for unqualified name lookup.
@@ -1058,15 +1075,14 @@ static bool isLinkageSpecContext(const DeclContext *DC,
}
bool DeclContext::isExternCContext() const {
- return isLinkageSpecContext(this, clang::LinkageSpecDecl::lang_c);
+ return isLinkageSpecContext(this, LinkageSpecDecl::lang_c);
}
const LinkageSpecDecl *DeclContext::getExternCContext() const {
const DeclContext *DC = this;
while (DC->getDeclKind() != Decl::TranslationUnit) {
if (DC->getDeclKind() == Decl::LinkageSpec &&
- cast<LinkageSpecDecl>(DC)->getLanguage() ==
- clang::LinkageSpecDecl::lang_c)
+ cast<LinkageSpecDecl>(DC)->getLanguage() == LinkageSpecDecl::lang_c)
return cast<LinkageSpecDecl>(DC);
DC = DC->getLexicalParent();
}
@@ -1074,7 +1090,7 @@ const LinkageSpecDecl *DeclContext::getExternCContext() const {
}
bool DeclContext::isExternCXXContext() const {
- return isLinkageSpecContext(this, clang::LinkageSpecDecl::lang_cxx);
+ return isLinkageSpecContext(this, LinkageSpecDecl::lang_cxx);
}
bool DeclContext::Encloses(const DeclContext *DC) const {
@@ -1109,13 +1125,11 @@ DeclContext *DeclContext::getPrimaryContext() {
case Decl::ObjCInterface:
if (ObjCInterfaceDecl *Def = cast<ObjCInterfaceDecl>(this)->getDefinition())
return Def;
-
return this;
case Decl::ObjCProtocol:
if (ObjCProtocolDecl *Def = cast<ObjCProtocolDecl>(this)->getDefinition())
return Def;
-
return this;
case Decl::ObjCCategory:
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp
index 5782b7b56c963..41f2449a9d6a0 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp
@@ -1,4 +1,4 @@
-//===--- DeclCXX.cpp - C++ Declaration AST Node Implementation ------------===//
+//===- DeclCXX.cpp - C++ Declaration AST Node Implementation --------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,26 +10,51 @@
// This file implements the C++ related Decl classes.
//
//===----------------------------------------------------------------------===//
+
#include "clang/AST/DeclCXX.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/ASTMutationListener.h"
+#include "clang/AST/ASTUnresolvedSet.h"
#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/LambdaCapture.h"
+#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/ODRHash.h"
+#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
+#include "clang/AST/UnresolvedSet.h"
+#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/IdentifierTable.h"
-#include "llvm/ADT/STLExtras.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/OperatorKinds.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
+#include "llvm/ADT/None.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+
using namespace clang;
//===----------------------------------------------------------------------===//
// Decl Allocation/Deallocation Method Implementations
//===----------------------------------------------------------------------===//
-void AccessSpecDecl::anchor() { }
+void AccessSpecDecl::anchor() {}
AccessSpecDecl *AccessSpecDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
return new (C, ID) AccessSpecDecl(EmptyShell());
@@ -76,9 +101,7 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
ImplicitCopyAssignmentHasConstParam(true),
HasDeclaredCopyConstructorWithConstParam(false),
HasDeclaredCopyAssignmentWithConstParam(false), IsLambda(false),
- IsParsingBaseSpecifiers(false), HasODRHash(false), ODRHash(0),
- NumBases(0), NumVBases(0), Bases(), VBases(), Definition(D),
- FirstFriend() {}
+ IsParsingBaseSpecifiers(false), HasODRHash(false), Definition(D) {}
CXXBaseSpecifier *CXXRecordDecl::DefinitionData::getBasesSlowCase() const {
return Bases.get(Definition->getASTContext().getExternalSource());
@@ -94,13 +117,12 @@ CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, const ASTContext &C,
CXXRecordDecl *PrevDecl)
: RecordDecl(K, TK, C, DC, StartLoc, IdLoc, Id, PrevDecl),
DefinitionData(PrevDecl ? PrevDecl->DefinitionData
- : nullptr),
- TemplateOrInstantiation() {}
+ : nullptr) {}
CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK,
DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
- CXXRecordDecl* PrevDecl,
+ CXXRecordDecl *PrevDecl,
bool DelayTypeCreation) {
CXXRecordDecl *R = new (C, DC) CXXRecordDecl(CXXRecord, TK, C, DC, StartLoc,
IdLoc, Id, PrevDecl);
@@ -148,7 +170,7 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
C.Deallocate(data().getBases());
if (NumBases) {
- if (!C.getLangOpts().CPlusPlus1z) {
+ if (!C.getLangOpts().CPlusPlus17) {
// C++ [dcl.init.aggr]p1:
// An aggregate is [...] a class with [...] no base classes [...].
data().Aggregate = false;
@@ -403,7 +425,6 @@ unsigned CXXRecordDecl::getODRHash() const {
return DefinitionData->ODRHash;
}
-
void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) {
// C++11 [class.copy]p11:
// A defaulted copy/move constructor for a class X is defined as
@@ -1470,6 +1491,66 @@ bool CXXRecordDecl::isAnyDestructorNoReturn() const {
return false;
}
+static bool isDeclContextInNamespace(const DeclContext *DC) {
+ while (!DC->isTranslationUnit()) {
+ if (DC->isNamespace())
+ return true;
+ DC = DC->getParent();
+ }
+ return false;
+}
+
+bool CXXRecordDecl::isInterfaceLike() const {
+ assert(hasDefinition() && "checking for interface-like without a definition");
+ // All __interfaces are inheritently interface-like.
+ if (isInterface())
+ return true;
+
+ // Interface-like types cannot have a user declared constructor, destructor,
+ // friends, VBases, conversion functions, or fields. Additionally, lambdas
+ // cannot be interface types.
+ if (isLambda() || hasUserDeclaredConstructor() ||
+ hasUserDeclaredDestructor() || !field_empty() || hasFriends() ||
+ getNumVBases() > 0 || conversion_end() - conversion_begin() > 0)
+ return false;
+
+ // No interface-like type can have a method with a definition.
+ for (const auto *const Method : methods())
+ if (Method->isDefined() && !Method->isImplicit())
+ return false;
+
+ // Check "Special" types.
+ const auto *Uuid = getAttr<UuidAttr>();
+ // MS SDK declares IUnknown/IDispatch both in the root of a TU, or in an
+ // extern C++ block directly in the TU. These are only valid if in one
+ // of these two situations.
+ if (Uuid && isStruct() && !getDeclContext()->isExternCContext() &&
+ !isDeclContextInNamespace(getDeclContext()) &&
+ ((getName() == "IUnknown" &&
+ Uuid->getGuid() == "00000000-0000-0000-C000-000000000046") ||
+ (getName() == "IDispatch" &&
+ Uuid->getGuid() == "00020400-0000-0000-C000-000000000046"))) {
+ if (getNumBases() > 0)
+ return false;
+ return true;
+ }
+
+ // FIXME: Any access specifiers is supposed to make this no longer interface
+ // like.
+
+ // If this isn't a 'special' type, it must have a single interface-like base.
+ if (getNumBases() != 1)
+ return false;
+
+ const auto BaseSpec = *bases_begin();
+ if (BaseSpec.isVirtual() || BaseSpec.getAccessSpecifier() != AS_public)
+ return false;
+ const auto *Base = BaseSpec.getType()->getAsCXXRecordDecl();
+ if (Base->isInterface() || !Base->isInterfaceLike())
+ return false;
+ return true;
+}
+
void CXXRecordDecl::completeDefinition() {
completeDefinition(nullptr);
}
@@ -1530,7 +1611,7 @@ bool CXXRecordDecl::mayBeAbstract() const {
return false;
}
-void CXXDeductionGuideDecl::anchor() { }
+void CXXDeductionGuideDecl::anchor() {}
CXXDeductionGuideDecl *CXXDeductionGuideDecl::Create(
ASTContext &C, DeclContext *DC, SourceLocation StartLoc, bool IsExplicit,
@@ -1547,7 +1628,7 @@ CXXDeductionGuideDecl *CXXDeductionGuideDecl::CreateDeserialized(ASTContext &C,
nullptr, SourceLocation());
}
-void CXXMethodDecl::anchor() { }
+void CXXMethodDecl::anchor() {}
bool CXXMethodDecl::isStatic() const {
const CXXMethodDecl *MD = getCanonicalDecl();
@@ -1561,9 +1642,7 @@ bool CXXMethodDecl::isStatic() const {
static bool recursivelyOverrides(const CXXMethodDecl *DerivedMD,
const CXXMethodDecl *BaseMD) {
- for (CXXMethodDecl::method_iterator I = DerivedMD->begin_overridden_methods(),
- E = DerivedMD->end_overridden_methods(); I != E; ++I) {
- const CXXMethodDecl *MD = *I;
+ for (const CXXMethodDecl *MD : DerivedMD->overridden_methods()) {
if (MD->getCanonicalDecl() == BaseMD->getCanonicalDecl())
return true;
if (recursivelyOverrides(MD, BaseMD))
@@ -1728,6 +1807,14 @@ bool CXXMethodDecl::isUsualDeallocationFunction() const {
return true;
unsigned UsualParams = 1;
+ // C++ P0722:
+ // A destroying operator delete is a usual deallocation function if
+ // removing the std::destroying_delete_t parameter and changing the
+ // first parameter type from T* to void* results in the signature of
+ // a usual deallocation function.
+ if (isDestroyingOperatorDelete())
+ ++UsualParams;
+
// C++ <=14 [basic.stc.dynamic.deallocation]p2:
// [...] If class T does not declare such an operator delete but does
// declare a member deallocation function named operator delete with
@@ -1886,43 +1973,34 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
SourceLocation L, Expr *Init,
SourceLocation R,
SourceLocation EllipsisLoc)
- : Initializee(TInfo), MemberOrEllipsisLocation(EllipsisLoc), Init(Init),
- LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(IsVirtual),
- IsWritten(false), SourceOrder(0)
-{
-}
+ : Initializee(TInfo), MemberOrEllipsisLocation(EllipsisLoc), Init(Init),
+ LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(IsVirtual),
+ IsWritten(false), SourceOrder(0) {}
CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
FieldDecl *Member,
SourceLocation MemberLoc,
SourceLocation L, Expr *Init,
SourceLocation R)
- : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init),
- LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false),
- IsWritten(false), SourceOrder(0)
-{
-}
+ : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init),
+ LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false),
+ IsWritten(false), SourceOrder(0) {}
CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
IndirectFieldDecl *Member,
SourceLocation MemberLoc,
SourceLocation L, Expr *Init,
SourceLocation R)
- : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init),
- LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false),
- IsWritten(false), SourceOrder(0)
-{
-}
+ : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init),
+ LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false),
+ IsWritten(false), SourceOrder(0) {}
CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
TypeSourceInfo *TInfo,
SourceLocation L, Expr *Init,
SourceLocation R)
- : Initializee(TInfo), MemberOrEllipsisLocation(), Init(Init),
- LParenLoc(L), RParenLoc(R), IsDelegating(true), IsVirtual(false),
- IsWritten(false), SourceOrder(0)
-{
-}
+ : Initializee(TInfo), Init(Init), LParenLoc(L), RParenLoc(R),
+ IsDelegating(true), IsVirtual(false), IsWritten(false), SourceOrder(0) {}
TypeLoc CXXCtorInitializer::getBaseClassLoc() const {
if (isBaseInitializer())
@@ -1962,7 +2040,7 @@ SourceRange CXXCtorInitializer::getSourceRange() const {
return SourceRange(getSourceLocation(), getRParenLoc());
}
-void CXXConstructorDecl::anchor() { }
+void CXXConstructorDecl::anchor() {}
CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C,
unsigned ID,
@@ -2105,7 +2183,7 @@ bool CXXConstructorDecl::isSpecializationCopyingObject() const {
return true;
}
-void CXXDestructorDecl::anchor() { }
+void CXXDestructorDecl::anchor() {}
CXXDestructorDecl *
CXXDestructorDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
@@ -2127,16 +2205,17 @@ CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
isInline, isImplicitlyDeclared);
}
-void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD) {
+void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD, Expr *ThisArg) {
auto *First = cast<CXXDestructorDecl>(getFirstDecl());
if (OD && !First->OperatorDelete) {
First->OperatorDelete = OD;
+ First->OperatorDeleteThisArg = ThisArg;
if (auto *L = getASTMutationListener())
- L->ResolvedOperatorDelete(First, OD);
+ L->ResolvedOperatorDelete(First, OD, ThisArg);
}
}
-void CXXConversionDecl::anchor() { }
+void CXXConversionDecl::anchor() {}
CXXConversionDecl *
CXXConversionDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
@@ -2166,7 +2245,7 @@ bool CXXConversionDecl::isLambdaToBlockPointerConversion() const {
getConversionType()->isBlockPointerType();
}
-void LinkageSpecDecl::anchor() { }
+void LinkageSpecDecl::anchor() {}
LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
DeclContext *DC,
@@ -2183,7 +2262,7 @@ LinkageSpecDecl *LinkageSpecDecl::CreateDeserialized(ASTContext &C,
SourceLocation(), lang_c, false);
}
-void UsingDirectiveDecl::anchor() { }
+void UsingDirectiveDecl::anchor() {}
UsingDirectiveDecl *UsingDirectiveDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
@@ -2217,7 +2296,7 @@ NamespaceDecl::NamespaceDecl(ASTContext &C, DeclContext *DC, bool Inline,
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, NamespaceDecl *PrevDecl)
: NamedDecl(Namespace, DC, IdLoc, Id), DeclContext(Namespace),
- redeclarable_base(C), LocStart(StartLoc), RBraceLoc(),
+ redeclarable_base(C), LocStart(StartLoc),
AnonOrFirstNamespaceAndInline(nullptr, Inline) {
setPreviousDecl(PrevDecl);
@@ -2257,21 +2336,25 @@ bool NamespaceDecl::isOriginalNamespace() const { return isFirstDecl(); }
NamespaceDecl *NamespaceDecl::getNextRedeclarationImpl() {
return getNextRedeclaration();
}
+
NamespaceDecl *NamespaceDecl::getPreviousDeclImpl() {
return getPreviousDecl();
}
+
NamespaceDecl *NamespaceDecl::getMostRecentDeclImpl() {
return getMostRecentDecl();
}
-void NamespaceAliasDecl::anchor() { }
+void NamespaceAliasDecl::anchor() {}
NamespaceAliasDecl *NamespaceAliasDecl::getNextRedeclarationImpl() {
return getNextRedeclaration();
}
+
NamespaceAliasDecl *NamespaceAliasDecl::getPreviousDeclImpl() {
return getPreviousDecl();
}
+
NamespaceAliasDecl *NamespaceAliasDecl::getMostRecentDeclImpl() {
return getMostRecentDecl();
}
@@ -2298,7 +2381,7 @@ NamespaceAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
SourceLocation(), nullptr);
}
-void UsingShadowDecl::anchor() { }
+void UsingShadowDecl::anchor() {}
UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, DeclContext *DC,
SourceLocation Loc, UsingDecl *Using,
@@ -2313,7 +2396,7 @@ UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, DeclContext *DC,
UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, EmptyShell Empty)
: NamedDecl(K, nullptr, SourceLocation(), DeclarationName()),
- redeclarable_base(C), Underlying(), UsingOrNextShadow() {}
+ redeclarable_base(C) {}
UsingShadowDecl *
UsingShadowDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
@@ -2328,7 +2411,7 @@ UsingDecl *UsingShadowDecl::getUsingDecl() const {
return cast<UsingDecl>(Shadow->UsingOrNextShadow);
}
-void ConstructorUsingShadowDecl::anchor() { }
+void ConstructorUsingShadowDecl::anchor() {}
ConstructorUsingShadowDecl *
ConstructorUsingShadowDecl::Create(ASTContext &C, DeclContext *DC,
@@ -2347,7 +2430,7 @@ CXXRecordDecl *ConstructorUsingShadowDecl::getNominatedBaseClass() const {
return getUsingDecl()->getQualifier()->getAsRecordDecl();
}
-void UsingDecl::anchor() { }
+void UsingDecl::anchor() {}
void UsingDecl::addShadowDecl(UsingShadowDecl *S) {
assert(std::find(shadow_begin(), shadow_end(), S) == shadow_end() &&
@@ -2399,7 +2482,7 @@ SourceRange UsingDecl::getSourceRange() const {
return SourceRange(Begin, getNameInfo().getEndLoc());
}
-void UsingPackDecl::anchor() { }
+void UsingPackDecl::anchor() {}
UsingPackDecl *UsingPackDecl::Create(ASTContext &C, DeclContext *DC,
NamedDecl *InstantiatedFrom,
@@ -2419,7 +2502,7 @@ UsingPackDecl *UsingPackDecl::CreateDeserialized(ASTContext &C, unsigned ID,
return Result;
}
-void UnresolvedUsingValueDecl::anchor() { }
+void UnresolvedUsingValueDecl::anchor() {}
UnresolvedUsingValueDecl *
UnresolvedUsingValueDecl::Create(ASTContext &C, DeclContext *DC,
@@ -2447,7 +2530,7 @@ SourceRange UnresolvedUsingValueDecl::getSourceRange() const {
return SourceRange(Begin, getNameInfo().getEndLoc());
}
-void UnresolvedUsingTypenameDecl::anchor() { }
+void UnresolvedUsingTypenameDecl::anchor() {}
UnresolvedUsingTypenameDecl *
UnresolvedUsingTypenameDecl::Create(ASTContext &C, DeclContext *DC,
@@ -2469,7 +2552,7 @@ UnresolvedUsingTypenameDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
SourceLocation(), nullptr, SourceLocation());
}
-void StaticAssertDecl::anchor() { }
+void StaticAssertDecl::anchor() {}
StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation StaticAssertLoc,
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp b/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp
index 121403b07e575..461bf36858b74 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp
@@ -1,4 +1,4 @@
-//===--- DeclFriend.cpp - C++ Friend Declaration AST Node Implementation --===//
+//===- DeclFriend.cpp - C++ Friend Declaration AST Node Implementation ----===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,12 +12,20 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclFriend.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/Support/Casting.h"
+#include <cassert>
+#include <cstddef>
+
using namespace clang;
-void FriendDecl::anchor() { }
+void FriendDecl::anchor() {}
FriendDecl *FriendDecl::getNextFriendSlowCase() {
return cast_or_null<FriendDecl>(
@@ -28,9 +36,9 @@ FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
FriendUnion Friend,
SourceLocation FriendL,
- ArrayRef<TemplateParameterList*> FriendTypeTPLists) {
+ ArrayRef<TemplateParameterList *> FriendTypeTPLists) {
#ifndef NDEBUG
- if (Friend.is<NamedDecl*>()) {
+ if (Friend.is<NamedDecl *>()) {
NamedDecl *D = Friend.get<NamedDecl*>();
assert(isa<FunctionDecl>(D) ||
isa<CXXRecordDecl>(D) ||
@@ -42,7 +50,7 @@ FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC,
assert(D->getFriendObjectKind() ||
(cast<CXXRecordDecl>(DC)->getTemplateSpecializationKind()));
// These template parameters are for friend types only.
- assert(FriendTypeTPLists.size() == 0);
+ assert(FriendTypeTPLists.empty());
}
#endif
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp b/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp
index 2f95e1f1c345f..f74ef9bbb8391 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp
@@ -1,4 +1,4 @@
-//===--- DeclGroup.cpp - Classes for representing groups of Decls -*- C++ -*-==//
+//===- DeclGroup.cpp - Classes for representing groups of Decls -----------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,7 +13,9 @@
#include "clang/AST/DeclGroup.h"
#include "clang/AST/ASTContext.h"
-#include "clang/AST/Decl.h"
+#include <cassert>
+#include <memory>
+
using namespace clang;
DeclGroup* DeclGroup::Create(ASTContext &C, Decl **Decls, unsigned NumDecls) {
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp
index d8bdb6369e947..f95d5def47acc 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp
@@ -1,4 +1,4 @@
-//===--- DeclObjC.cpp - ObjC Declaration AST Node Implementation ----------===//
+//===- DeclObjC.cpp - ObjC Declaration AST Node Implementation ------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,9 +15,27 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/Attr.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/Stmt.h"
-#include "llvm/ADT/STLExtras.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/None.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <cstring>
+#include <utility>
+
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -28,7 +46,6 @@ void ObjCListBase::set(void *const* InList, unsigned Elts, ASTContext &Ctx) {
List = nullptr;
if (Elts == 0) return; // Setting to an empty list is a noop.
-
List = new (Ctx) void*[Elts];
NumElts = Elts;
memcpy(List, InList, sizeof(void*)*Elts);
@@ -48,7 +65,7 @@ void ObjCProtocolList::set(ObjCProtocolDecl* const* InList, unsigned Elts,
// ObjCInterfaceDecl
//===----------------------------------------------------------------------===//
-void ObjCContainerDecl::anchor() { }
+void ObjCContainerDecl::anchor() {}
/// getIvarDecl - This method looks up an ivar in this ContextDecl.
///
@@ -82,7 +99,6 @@ ObjCContainerDecl::getMethod(Selector Sel, bool isInstance,
// - (int) class_method;
// + (float) class_method;
// @end
- //
lookup_result R = lookup(Sel);
for (lookup_iterator Meth = R.begin(), MethEnd = R.end();
Meth != MethEnd; ++Meth) {
@@ -280,7 +296,7 @@ ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration(
return nullptr;
}
-void ObjCInterfaceDecl::anchor() { }
+void ObjCInterfaceDecl::anchor() {}
ObjCTypeParamList *ObjCInterfaceDecl::getTypeParamList() const {
// If this particular declaration has a type parameter list, return it.
@@ -341,7 +357,6 @@ SourceLocation ObjCInterfaceDecl::getSuperClassLoc() const {
/// FindPropertyVisibleInPrimaryClass - Finds declaration of the property
/// with name 'PropertyId' in the primary class; including those in protocols
/// (direct or indirect) used by the primary class.
-///
ObjCPropertyDecl *
ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass(
IdentifierInfo *PropertyId,
@@ -409,8 +424,7 @@ const ObjCInterfaceDecl *ObjCInterfaceDecl::isObjCRequiresPropertyDefs() const {
void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
ObjCProtocolDecl *const* ExtList, unsigned ExtNum,
- ASTContext &C)
-{
+ ASTContext &C) {
if (data().ExternallyCompleted)
LoadExternalDefinition();
@@ -488,7 +502,7 @@ bool ObjCInterfaceDecl::inheritsDesignatedInitializers() const {
return true;
case DefinitionData::IDI_NotInherited:
return false;
- case DefinitionData::IDI_Unknown: {
+ case DefinitionData::IDI_Unknown:
// If the class introduced initializers we conservatively assume that we
// don't know if any of them is a designated initializer to avoid possible
// misleading warnings.
@@ -510,7 +524,6 @@ bool ObjCInterfaceDecl::inheritsDesignatedInitializers() const {
return data().InheritedDesignatedInitializers ==
DefinitionData::IDI_Inherited;
}
- }
llvm_unreachable("unexpected InheritedDesignatedInitializers value");
}
@@ -902,7 +915,6 @@ ObjCMethodDecl *ObjCMethodDecl::getCanonicalDecl() {
if (ObjCMethodDecl *MD = IFD->getMethod(getSelector(),
isInstanceMethod()))
return MD;
-
} else if (ObjCCategoryImplDecl *CImplD =
dyn_cast<ObjCCategoryImplDecl>(CtxD)) {
if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl())
@@ -1312,7 +1324,8 @@ ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const {
if (!CheckOverrides)
return nullptr;
- typedef SmallVector<const ObjCMethodDecl *, 8> OverridesTy;
+ using OverridesTy = SmallVector<const ObjCMethodDecl *, 8>;
+
OverridesTy Overrides;
getOverriddenMethods(Overrides);
for (OverridesTy::const_iterator I = Overrides.begin(), E = Overrides.end();
@@ -1328,7 +1341,7 @@ ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const {
// ObjCTypeParamDecl
//===----------------------------------------------------------------------===//
-void ObjCTypeParamDecl::anchor() { }
+void ObjCTypeParamDecl::anchor() {}
ObjCTypeParamDecl *ObjCTypeParamDecl::Create(ASTContext &ctx, DeclContext *dc,
ObjCTypeParamVariance variance,
@@ -1373,14 +1386,12 @@ SourceRange ObjCTypeParamDecl::getSourceRange() const {
ObjCTypeParamList::ObjCTypeParamList(SourceLocation lAngleLoc,
ArrayRef<ObjCTypeParamDecl *> typeParams,
SourceLocation rAngleLoc)
- : NumParams(typeParams.size())
-{
+ : NumParams(typeParams.size()) {
Brackets.Begin = lAngleLoc.getRawEncoding();
Brackets.End = rAngleLoc.getRawEncoding();
std::copy(typeParams.begin(), typeParams.end(), begin());
}
-
ObjCTypeParamList *ObjCTypeParamList::create(
ASTContext &ctx,
SourceLocation lAngleLoc,
@@ -1438,8 +1449,7 @@ ObjCInterfaceDecl::ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC,
ObjCInterfaceDecl *PrevDecl,
bool IsInternal)
: ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, AtLoc),
- redeclarable_base(C), TypeForDecl(nullptr), TypeParamList(nullptr),
- Data() {
+ redeclarable_base(C) {
setPreviousDecl(PrevDecl);
// Copy the 'data' pointer over.
@@ -1518,19 +1528,22 @@ void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) {
}
namespace {
- struct SynthesizeIvarChunk {
- uint64_t Size;
- ObjCIvarDecl *Ivar;
- SynthesizeIvarChunk(uint64_t size, ObjCIvarDecl *ivar)
+
+struct SynthesizeIvarChunk {
+ uint64_t Size;
+ ObjCIvarDecl *Ivar;
+
+ SynthesizeIvarChunk(uint64_t size, ObjCIvarDecl *ivar)
: Size(size), Ivar(ivar) {}
- };
+};
- bool operator<(const SynthesizeIvarChunk & LHS,
- const SynthesizeIvarChunk &RHS) {
- return LHS.Size < RHS.Size;
- }
+bool operator<(const SynthesizeIvarChunk & LHS,
+ const SynthesizeIvarChunk &RHS) {
+ return LHS.Size < RHS.Size;
}
+} // namespace
+
/// all_declared_ivar_begin - return first ivar declared in this class,
/// its extensions and its implementation. Lazily build the list on first
/// access.
@@ -1694,7 +1707,7 @@ bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto,
// ObjCIvarDecl
//===----------------------------------------------------------------------===//
-void ObjCIvarDecl::anchor() { }
+void ObjCIvarDecl::anchor() {}
ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC,
SourceLocation StartLoc,
@@ -1771,7 +1784,7 @@ QualType ObjCIvarDecl::getUsageType(QualType objectType) const {
// ObjCAtDefsFieldDecl
//===----------------------------------------------------------------------===//
-void ObjCAtDefsFieldDecl::anchor() { }
+void ObjCAtDefsFieldDecl::anchor() {}
ObjCAtDefsFieldDecl
*ObjCAtDefsFieldDecl::Create(ASTContext &C, DeclContext *DC,
@@ -1791,14 +1804,14 @@ ObjCAtDefsFieldDecl *ObjCAtDefsFieldDecl::CreateDeserialized(ASTContext &C,
// ObjCProtocolDecl
//===----------------------------------------------------------------------===//
-void ObjCProtocolDecl::anchor() { }
+void ObjCProtocolDecl::anchor() {}
ObjCProtocolDecl::ObjCProtocolDecl(ASTContext &C, DeclContext *DC,
IdentifierInfo *Id, SourceLocation nameLoc,
SourceLocation atStartLoc,
ObjCProtocolDecl *PrevDecl)
: ObjCContainerDecl(ObjCProtocol, DC, Id, nameLoc, atStartLoc),
- redeclarable_base(C), Data() {
+ redeclarable_base(C) {
setPreviousDecl(PrevDecl);
if (PrevDecl)
Data = PrevDecl->Data;
@@ -1874,7 +1887,6 @@ void ObjCProtocolDecl::startDefinition() {
void ObjCProtocolDecl::collectPropertiesToImplement(PropertyMap &PM,
PropertyDeclOrder &PO) const {
-
if (const ObjCProtocolDecl *PDecl = getDefinition()) {
for (auto *Prop : PDecl->properties()) {
// Insert into PM if not there already.
@@ -1921,7 +1933,7 @@ ObjCProtocolDecl::getObjCRuntimeNameAsString() const {
// ObjCCategoryDecl
//===----------------------------------------------------------------------===//
-void ObjCCategoryDecl::anchor() { }
+void ObjCCategoryDecl::anchor() {}
ObjCCategoryDecl::ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc,
SourceLocation ClassNameLoc,
@@ -1930,11 +1942,9 @@ ObjCCategoryDecl::ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc,
ObjCTypeParamList *typeParamList,
SourceLocation IvarLBraceLoc,
SourceLocation IvarRBraceLoc)
- : ObjCContainerDecl(ObjCCategory, DC, Id, ClassNameLoc, AtLoc),
- ClassInterface(IDecl), TypeParamList(nullptr),
- NextClassCategory(nullptr), CategoryNameLoc(CategoryNameLoc),
- IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc)
-{
+ : ObjCContainerDecl(ObjCCategory, DC, Id, ClassNameLoc, AtLoc),
+ ClassInterface(IDecl), CategoryNameLoc(CategoryNameLoc),
+ IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc) {
setTypeParamList(typeParamList);
}
@@ -1994,7 +2004,7 @@ void ObjCCategoryDecl::setTypeParamList(ObjCTypeParamList *TPL) {
// ObjCCategoryImplDecl
//===----------------------------------------------------------------------===//
-void ObjCCategoryImplDecl::anchor() { }
+void ObjCCategoryImplDecl::anchor() {}
ObjCCategoryImplDecl *
ObjCCategoryImplDecl::Create(ASTContext &C, DeclContext *DC,
@@ -2023,8 +2033,7 @@ ObjCCategoryDecl *ObjCCategoryImplDecl::getCategoryDecl() const {
return nullptr;
}
-
-void ObjCImplDecl::anchor() { }
+void ObjCImplDecl::anchor() {}
void ObjCImplDecl::addPropertyImplementation(ObjCPropertyImplDecl *property) {
// FIXME: The context should be correct before we get here.
@@ -2052,7 +2061,6 @@ void ObjCImplDecl::setClassInterface(ObjCInterfaceDecl *IFace) {
/// FindPropertyImplIvarDecl - This method lookup the ivar in the list of
/// properties implemented in this \@implementation block and returns
/// the implemented property that uses it.
-///
ObjCPropertyImplDecl *ObjCImplDecl::
FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const {
for (auto *PID : property_impls())
@@ -2065,7 +2073,6 @@ FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const {
/// FindPropertyImplDecl - This method looks up a previous ObjCPropertyImplDecl
/// added to the list of those properties \@synthesized/\@dynamic in this
/// category \@implementation block.
-///
ObjCPropertyImplDecl *ObjCImplDecl::
FindPropertyImplDecl(IdentifierInfo *Id,
ObjCPropertyQueryKind QueryKind) const {
@@ -2103,7 +2110,7 @@ raw_ostream &clang::operator<<(raw_ostream &OS,
// ObjCImplementationDecl
//===----------------------------------------------------------------------===//
-void ObjCImplementationDecl::anchor() { }
+void ObjCImplementationDecl::anchor() {}
ObjCImplementationDecl *
ObjCImplementationDecl::Create(ASTContext &C, DeclContext *DC,
@@ -2155,7 +2162,7 @@ raw_ostream &clang::operator<<(raw_ostream &OS,
// ObjCCompatibleAliasDecl
//===----------------------------------------------------------------------===//
-void ObjCCompatibleAliasDecl::anchor() { }
+void ObjCCompatibleAliasDecl::anchor() {}
ObjCCompatibleAliasDecl *
ObjCCompatibleAliasDecl::Create(ASTContext &C, DeclContext *DC,
@@ -2175,7 +2182,7 @@ ObjCCompatibleAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
// ObjCPropertyDecl
//===----------------------------------------------------------------------===//
-void ObjCPropertyDecl::anchor() { }
+void ObjCPropertyDecl::anchor() {}
ObjCPropertyDecl *ObjCPropertyDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp
index 6eeba88e40336..b792c5920a553 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp
@@ -28,6 +28,7 @@ namespace {
class DeclPrinter : public DeclVisitor<DeclPrinter> {
raw_ostream &Out;
PrintingPolicy Policy;
+ const ASTContext &Context;
unsigned Indentation;
bool PrintInstantiation;
@@ -36,6 +37,8 @@ namespace {
void ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls);
void Print(AccessSpecifier AS);
+ void PrintConstructorInitializers(CXXConstructorDecl *CDecl,
+ std::string &Proto);
/// Print an Objective-C method type in parentheses.
///
@@ -48,9 +51,10 @@ namespace {
public:
DeclPrinter(raw_ostream &Out, const PrintingPolicy &Policy,
- unsigned Indentation = 0, bool PrintInstantiation = false)
- : Out(Out), Policy(Policy), Indentation(Indentation),
- PrintInstantiation(PrintInstantiation) { }
+ const ASTContext &Context, unsigned Indentation = 0,
+ bool PrintInstantiation = false)
+ : Out(Out), Policy(Policy), Context(Context), Indentation(Indentation),
+ PrintInstantiation(PrintInstantiation) {}
void VisitDeclContext(DeclContext *DC, bool Indent = true);
@@ -115,7 +119,8 @@ void Decl::print(raw_ostream &Out, unsigned Indentation,
void Decl::print(raw_ostream &Out, const PrintingPolicy &Policy,
unsigned Indentation, bool PrintInstantiation) const {
- DeclPrinter Printer(Out, Policy, Indentation, PrintInstantiation);
+ DeclPrinter Printer(Out, Policy, getASTContext(), Indentation,
+ PrintInstantiation);
Printer.Visit(const_cast<Decl*>(this));
}
@@ -192,7 +197,7 @@ LLVM_DUMP_METHOD void DeclContext::dumpDeclContext() const {
DC = DC->getParent();
ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
- DeclPrinter Printer(llvm::errs(), Ctx.getPrintingPolicy(), 0);
+ DeclPrinter Printer(llvm::errs(), Ctx.getPrintingPolicy(), Ctx, 0);
Printer.VisitDeclContext(const_cast<DeclContext *>(this), /*Indent=*/false);
}
@@ -271,6 +276,71 @@ void DeclPrinter::Print(AccessSpecifier AS) {
}
}
+void DeclPrinter::PrintConstructorInitializers(CXXConstructorDecl *CDecl,
+ std::string &Proto) {
+ bool HasInitializerList = false;
+ for (const auto *BMInitializer : CDecl->inits()) {
+ if (BMInitializer->isInClassMemberInitializer())
+ continue;
+
+ if (!HasInitializerList) {
+ Proto += " : ";
+ Out << Proto;
+ Proto.clear();
+ HasInitializerList = true;
+ } else
+ Out << ", ";
+
+ if (BMInitializer->isAnyMemberInitializer()) {
+ FieldDecl *FD = BMInitializer->getAnyMember();
+ Out << *FD;
+ } else {
+ Out << QualType(BMInitializer->getBaseClass(), 0).getAsString(Policy);
+ }
+
+ Out << "(";
+ if (!BMInitializer->getInit()) {
+ // Nothing to print
+ } else {
+ Expr *Init = BMInitializer->getInit();
+ if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init))
+ Init = Tmp->getSubExpr();
+
+ Init = Init->IgnoreParens();
+
+ Expr *SimpleInit = nullptr;
+ Expr **Args = nullptr;
+ unsigned NumArgs = 0;
+ if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
+ Args = ParenList->getExprs();
+ NumArgs = ParenList->getNumExprs();
+ } else if (CXXConstructExpr *Construct =
+ dyn_cast<CXXConstructExpr>(Init)) {
+ Args = Construct->getArgs();
+ NumArgs = Construct->getNumArgs();
+ } else
+ SimpleInit = Init;
+
+ if (SimpleInit)
+ SimpleInit->printPretty(Out, nullptr, Policy, Indentation);
+ else {
+ for (unsigned I = 0; I != NumArgs; ++I) {
+ assert(Args[I] != nullptr && "Expected non-null Expr");
+ if (isa<CXXDefaultArgExpr>(Args[I]))
+ break;
+
+ if (I)
+ Out << ", ";
+ Args[I]->printPretty(Out, nullptr, Policy, Indentation);
+ }
+ }
+ }
+ Out << ")";
+ if (BMInitializer->isPackExpansion())
+ Out << "...";
+ }
+}
+
//----------------------------------------------------------------------------
// Common C declarations
//----------------------------------------------------------------------------
@@ -467,7 +537,7 @@ void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) {
prettyPrintAttributes(D);
if (Expr *Init = D->getInitExpr()) {
Out << " = ";
- Init->printPretty(Out, nullptr, Policy, Indentation);
+ Init->printPretty(Out, nullptr, Policy, Indentation, &Context);
}
}
@@ -510,18 +580,24 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
PrintingPolicy SubPolicy(Policy);
SubPolicy.SuppressSpecifiers = false;
std::string Proto;
- if (!Policy.SuppressScope) {
- if (const NestedNameSpecifier *NS = D->getQualifier()) {
- llvm::raw_string_ostream OS(Proto);
- NS->print(OS, Policy);
+
+ if (Policy.FullyQualifiedName) {
+ Proto += D->getQualifiedNameAsString();
+ } else {
+ if (!Policy.SuppressScope) {
+ if (const NestedNameSpecifier *NS = D->getQualifier()) {
+ llvm::raw_string_ostream OS(Proto);
+ NS->print(OS, Policy);
+ }
}
+ Proto += D->getNameInfo().getAsString();
}
- Proto += D->getNameInfo().getAsString();
+
if (GuideDecl)
Proto = GuideDecl->getDeducedTemplate()->getDeclName().getAsString();
if (const TemplateArgumentList *TArgs = D->getTemplateSpecializationArgs()) {
llvm::raw_string_ostream POut(Proto);
- DeclPrinter TArgPrinter(POut, SubPolicy, Indentation);
+ DeclPrinter TArgPrinter(POut, SubPolicy, Context, Indentation);
TArgPrinter.printTemplateArguments(*TArgs);
}
@@ -539,7 +615,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
Proto += "(";
if (FT) {
llvm::raw_string_ostream POut(Proto);
- DeclPrinter ParamPrinter(POut, SubPolicy, Indentation);
+ DeclPrinter ParamPrinter(POut, SubPolicy, Context, Indentation);
for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
if (i) POut << ", ";
ParamPrinter.VisitParmVarDecl(D->getParamDecl(i));
@@ -605,67 +681,8 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
}
if (CDecl) {
- bool HasInitializerList = false;
- for (const auto *BMInitializer : CDecl->inits()) {
- if (BMInitializer->isInClassMemberInitializer())
- continue;
-
- if (!HasInitializerList) {
- Proto += " : ";
- Out << Proto;
- Proto.clear();
- HasInitializerList = true;
- } else
- Out << ", ";
-
- if (BMInitializer->isAnyMemberInitializer()) {
- FieldDecl *FD = BMInitializer->getAnyMember();
- Out << *FD;
- } else {
- Out << QualType(BMInitializer->getBaseClass(), 0).getAsString(Policy);
- }
-
- Out << "(";
- if (!BMInitializer->getInit()) {
- // Nothing to print
- } else {
- Expr *Init = BMInitializer->getInit();
- if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init))
- Init = Tmp->getSubExpr();
-
- Init = Init->IgnoreParens();
-
- Expr *SimpleInit = nullptr;
- Expr **Args = nullptr;
- unsigned NumArgs = 0;
- if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
- Args = ParenList->getExprs();
- NumArgs = ParenList->getNumExprs();
- } else if (CXXConstructExpr *Construct
- = dyn_cast<CXXConstructExpr>(Init)) {
- Args = Construct->getArgs();
- NumArgs = Construct->getNumArgs();
- } else
- SimpleInit = Init;
-
- if (SimpleInit)
- SimpleInit->printPretty(Out, nullptr, Policy, Indentation);
- else {
- for (unsigned I = 0; I != NumArgs; ++I) {
- assert(Args[I] != nullptr && "Expected non-null Expr");
- if (isa<CXXDefaultArgExpr>(Args[I]))
- break;
-
- if (I)
- Out << ", ";
- Args[I]->printPretty(Out, nullptr, Policy, Indentation);
- }
- }
- }
- Out << ")";
- if (BMInitializer->isPackExpansion())
- Out << "...";
- }
+ if (!Policy.TerseOutput)
+ PrintConstructorInitializers(CDecl, Proto);
} else if (!ConversionDecl && !isa<CXXDestructorDecl>(D)) {
if (FT && FT->hasTrailingReturn()) {
if (!GuideDecl)
@@ -695,7 +712,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
// This is a K&R function definition, so we need to print the
// parameters.
Out << '\n';
- DeclPrinter ParamPrinter(Out, SubPolicy, Indentation);
+ DeclPrinter ParamPrinter(Out, SubPolicy, Context, Indentation);
Indentation += Policy.Indentation;
for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
Indent();
@@ -709,7 +726,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
if (D->getBody())
D->getBody()->printPretty(Out, nullptr, SubPolicy, Indentation);
} else {
- if (isa<CXXConstructorDecl>(*D))
+ if (!Policy.TerseOutput && isa<CXXConstructorDecl>(*D))
Out << " {}";
}
}
@@ -1541,7 +1558,19 @@ void DeclPrinter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) {
Out << ")";
if (auto *Init = D->getInitializer()) {
Out << " initializer(";
+ switch (D->getInitializerKind()) {
+ case OMPDeclareReductionDecl::DirectInit:
+ Out << "omp_priv(";
+ break;
+ case OMPDeclareReductionDecl::CopyInit:
+ Out << "omp_priv = ";
+ break;
+ case OMPDeclareReductionDecl::CallInit:
+ break;
+ }
Init->printPretty(Out, nullptr, Policy, 0);
+ if (D->getInitializerKind() == OMPDeclareReductionDecl::DirectInit)
+ Out << ")";
Out << ")";
}
}
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp
index 00a6739478bd4..a7949b310cefc 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp
@@ -1,4 +1,4 @@
-//===--- DeclTemplate.cpp - Template Declaration AST Node Implementation --===//
+//===- DeclTemplate.cpp - Template Declaration AST Node Implementation ----===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,13 +15,28 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
-#include "clang/AST/ExprCXX.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/TemplateName.h"
+#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/Builtins.h"
-#include "clang/Basic/IdentifierTable.h"
-#include "llvm/ADT/STLExtras.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
#include <memory>
+#include <utility>
+
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -33,9 +48,9 @@ TemplateParameterList::TemplateParameterList(SourceLocation TemplateLoc,
ArrayRef<NamedDecl *> Params,
SourceLocation RAngleLoc,
Expr *RequiresClause)
- : TemplateLoc(TemplateLoc), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc),
- NumParams(Params.size()), ContainsUnexpandedParameterPack(false),
- HasRequiresClause(static_cast<bool>(RequiresClause)) {
+ : TemplateLoc(TemplateLoc), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc),
+ NumParams(Params.size()), ContainsUnexpandedParameterPack(false),
+ HasRequiresClause(static_cast<bool>(RequiresClause)) {
for (unsigned Idx = 0; Idx < NumParams; ++Idx) {
NamedDecl *P = Params[Idx];
begin()[Idx] = P;
@@ -124,10 +139,12 @@ static void AdoptTemplateParameterList(TemplateParameterList *Params,
}
namespace clang {
+
void *allocateDefaultArgStorageChain(const ASTContext &C) {
return new (C) char[sizeof(void*) * 2];
}
-}
+
+} // namespace clang
//===----------------------------------------------------------------------===//
// RedeclarableTemplateDecl Implementation
@@ -165,14 +182,28 @@ RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() c
return Common;
}
+void RedeclarableTemplateDecl::loadLazySpecializationsImpl() const {
+ // Grab the most recent declaration to ensure we've loaded any lazy
+ // redeclarations of this template.
+ CommonBase *CommonBasePtr = getMostRecentDecl()->getCommonPtr();
+ if (CommonBasePtr->LazySpecializations) {
+ ASTContext &Context = getASTContext();
+ uint32_t *Specs = CommonBasePtr->LazySpecializations;
+ CommonBasePtr->LazySpecializations = nullptr;
+ for (uint32_t I = 0, N = *Specs++; I != N; ++I)
+ (void)Context.getExternalSource()->GetExternalDecl(Specs[I]);
+ }
+}
+
template<class EntryType>
typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType *
RedeclarableTemplateDecl::findSpecializationImpl(
llvm::FoldingSetVector<EntryType> &Specs, ArrayRef<TemplateArgument> Args,
void *&InsertPos) {
- typedef SpecEntryTraits<EntryType> SETraits;
+ using SETraits = SpecEntryTraits<EntryType>;
+
llvm::FoldingSetNodeID ID;
- EntryType::Profile(ID,Args, getASTContext());
+ EntryType::Profile(ID, Args, getASTContext());
EntryType *Entry = Specs.FindNodeOrInsertPos(ID, InsertPos);
return Entry ? SETraits::getDecl(Entry)->getMostRecentDecl() : nullptr;
}
@@ -181,7 +212,8 @@ template<class Derived, class EntryType>
void RedeclarableTemplateDecl::addSpecializationImpl(
llvm::FoldingSetVector<EntryType> &Specializations, EntryType *Entry,
void *InsertPos) {
- typedef SpecEntryTraits<EntryType> SETraits;
+ using SETraits = SpecEntryTraits<EntryType>;
+
if (InsertPos) {
#ifndef NDEBUG
void *CorrectInsertPos;
@@ -232,18 +264,7 @@ FunctionTemplateDecl::newCommon(ASTContext &C) const {
}
void FunctionTemplateDecl::LoadLazySpecializations() const {
- // Grab the most recent declaration to ensure we've loaded any lazy
- // redeclarations of this template.
- //
- // FIXME: Avoid walking the entire redeclaration chain here.
- Common *CommonPtr = getMostRecentDecl()->getCommonPtr();
- if (CommonPtr->LazySpecializations) {
- ASTContext &Context = getASTContext();
- uint32_t *Specs = CommonPtr->LazySpecializations;
- CommonPtr->LazySpecializations = nullptr;
- for (uint32_t I = 0, N = *Specs++; I != N; ++I)
- (void)Context.getExternalSource()->GetExternalDecl(Specs[I]);
- }
+ loadLazySpecializationsImpl();
}
llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> &
@@ -311,18 +332,7 @@ ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C,
}
void ClassTemplateDecl::LoadLazySpecializations() const {
- // Grab the most recent declaration to ensure we've loaded any lazy
- // redeclarations of this template.
- //
- // FIXME: Avoid walking the entire redeclaration chain here.
- Common *CommonPtr = getMostRecentDecl()->getCommonPtr();
- if (CommonPtr->LazySpecializations) {
- ASTContext &Context = getASTContext();
- uint32_t *Specs = CommonPtr->LazySpecializations;
- CommonPtr->LazySpecializations = nullptr;
- for (uint32_t I = 0, N = *Specs++; I != N; ++I)
- (void)Context.getExternalSource()->GetExternalDecl(Specs[I]);
- }
+ loadLazySpecializationsImpl();
}
llvm::FoldingSetVector<ClassTemplateSpecializationDecl> &
@@ -562,7 +572,7 @@ SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const {
// TemplateTemplateParmDecl Method Implementations
//===----------------------------------------------------------------------===//
-void TemplateTemplateParmDecl::anchor() { }
+void TemplateTemplateParmDecl::anchor() {}
TemplateTemplateParmDecl::TemplateTemplateParmDecl(
DeclContext *DC, SourceLocation L, unsigned D, unsigned P,
@@ -665,11 +675,12 @@ FunctionTemplateSpecializationInfo::Create(ASTContext &C, FunctionDecl *FD,
// TemplateDecl Implementation
//===----------------------------------------------------------------------===//
-void TemplateDecl::anchor() { }
+void TemplateDecl::anchor() {}
//===----------------------------------------------------------------------===//
// ClassTemplateSpecializationDecl Implementation
//===----------------------------------------------------------------------===//
+
ClassTemplateSpecializationDecl::
ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK,
DeclContext *DC, SourceLocation StartLoc,
@@ -677,11 +688,9 @@ ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK,
ClassTemplateDecl *SpecializedTemplate,
ArrayRef<TemplateArgument> Args,
ClassTemplateSpecializationDecl *PrevDecl)
- : CXXRecordDecl(DK, TK, Context, DC, StartLoc, IdLoc,
- SpecializedTemplate->getIdentifier(),
- PrevDecl),
+ : CXXRecordDecl(DK, TK, Context, DC, StartLoc, IdLoc,
+ SpecializedTemplate->getIdentifier(), PrevDecl),
SpecializedTemplate(SpecializedTemplate),
- ExplicitInfo(nullptr),
TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args)),
SpecializationKind(TSK_Undeclared) {
}
@@ -690,7 +699,7 @@ ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(ASTContext &C,
Kind DK)
: CXXRecordDecl(DK, TTK_Struct, C, nullptr, SourceLocation(),
SourceLocation(), nullptr, nullptr),
- ExplicitInfo(nullptr), SpecializationKind(TSK_Undeclared) {}
+ SpecializationKind(TSK_Undeclared) {}
ClassTemplateSpecializationDecl *
ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK,
@@ -726,12 +735,10 @@ void ClassTemplateSpecializationDecl::getNameForDiagnostic(
auto *PS = dyn_cast<ClassTemplatePartialSpecializationDecl>(this);
if (const ASTTemplateArgumentListInfo *ArgsAsWritten =
PS ? PS->getTemplateArgsAsWritten() : nullptr) {
- TemplateSpecializationType::PrintTemplateArgumentList(
- OS, ArgsAsWritten->arguments(), Policy);
+ printTemplateArgumentList(OS, ArgsAsWritten->arguments(), Policy);
} else {
const TemplateArgumentList &TemplateArgs = getTemplateArgs();
- TemplateSpecializationType::PrintTemplateArgumentList(
- OS, TemplateArgs.asArray(), Policy);
+ printTemplateArgumentList(OS, TemplateArgs.asArray(), Policy);
}
}
@@ -762,7 +769,7 @@ ClassTemplateSpecializationDecl::getSourceRange() const {
// An implicit instantiation of a class template partial specialization
// uses ExplicitInfo to record the TypeAsWritten, but the source
// locations should be retrieved from the instantiation pattern.
- typedef ClassTemplatePartialSpecializationDecl CTPSDecl;
+ using CTPSDecl = ClassTemplatePartialSpecializationDecl;
CTPSDecl *ctpsd = const_cast<CTPSDecl*>(cast<CTPSDecl>(this));
CTPSDecl *inst_from = ctpsd->getInstantiatedFromMember();
assert(inst_from != nullptr);
@@ -785,7 +792,7 @@ ClassTemplateSpecializationDecl::getSourceRange() const {
//===----------------------------------------------------------------------===//
// ClassTemplatePartialSpecializationDecl Implementation
//===----------------------------------------------------------------------===//
-void ClassTemplatePartialSpecializationDecl::anchor() { }
+void ClassTemplatePartialSpecializationDecl::anchor() {}
ClassTemplatePartialSpecializationDecl::
ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK,
@@ -797,14 +804,12 @@ ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK,
ArrayRef<TemplateArgument> Args,
const ASTTemplateArgumentListInfo *ArgInfos,
ClassTemplatePartialSpecializationDecl *PrevDecl)
- : ClassTemplateSpecializationDecl(Context,
- ClassTemplatePartialSpecialization,
- TK, DC, StartLoc, IdLoc,
- SpecializedTemplate,
- Args, PrevDecl),
- TemplateParams(Params), ArgsAsWritten(ArgInfos),
- InstantiatedFromMember(nullptr, false)
-{
+ : ClassTemplateSpecializationDecl(Context,
+ ClassTemplatePartialSpecialization,
+ TK, DC, StartLoc, IdLoc,
+ SpecializedTemplate, Args, PrevDecl),
+ TemplateParams(Params), ArgsAsWritten(ArgInfos),
+ InstantiatedFromMember(nullptr, false) {
AdoptTemplateParameterList(Params, this);
}
@@ -845,7 +850,7 @@ ClassTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
// FriendTemplateDecl Implementation
//===----------------------------------------------------------------------===//
-void FriendTemplateDecl::anchor() { }
+void FriendTemplateDecl::anchor() {}
FriendTemplateDecl *
FriendTemplateDecl::Create(ASTContext &Context, DeclContext *DC,
@@ -891,7 +896,7 @@ TypeAliasTemplateDecl::newCommon(ASTContext &C) const {
// ClassScopeFunctionSpecializationDecl Implementation
//===----------------------------------------------------------------------===//
-void ClassScopeFunctionSpecializationDecl::anchor() { }
+void ClassScopeFunctionSpecializationDecl::anchor() {}
ClassScopeFunctionSpecializationDecl *
ClassScopeFunctionSpecializationDecl::CreateDeserialized(ASTContext &C,
@@ -927,21 +932,8 @@ VarTemplateDecl *VarTemplateDecl::CreateDeserialized(ASTContext &C,
DeclarationName(), nullptr, nullptr);
}
-// TODO: Unify across class, function and variable templates?
-// May require moving this and Common to RedeclarableTemplateDecl.
void VarTemplateDecl::LoadLazySpecializations() const {
- // Grab the most recent declaration to ensure we've loaded any lazy
- // redeclarations of this template.
- //
- // FIXME: Avoid walking the entire redeclaration chain here.
- Common *CommonPtr = getMostRecentDecl()->getCommonPtr();
- if (CommonPtr->LazySpecializations) {
- ASTContext &Context = getASTContext();
- uint32_t *Specs = CommonPtr->LazySpecializations;
- CommonPtr->LazySpecializations = nullptr;
- for (uint32_t I = 0, N = *Specs++; I != N; ++I)
- (void)Context.getExternalSource()->GetExternalDecl(Specs[I]);
- }
+ loadLazySpecializationsImpl();
}
llvm::FoldingSetVector<VarTemplateSpecializationDecl> &
@@ -1020,21 +1012,22 @@ VarTemplateDecl::findPartialSpecInstantiatedFromMember(
//===----------------------------------------------------------------------===//
// VarTemplateSpecializationDecl Implementation
//===----------------------------------------------------------------------===//
+
VarTemplateSpecializationDecl::VarTemplateSpecializationDecl(
Kind DK, ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T,
TypeSourceInfo *TInfo, StorageClass S, ArrayRef<TemplateArgument> Args)
: VarDecl(DK, Context, DC, StartLoc, IdLoc,
SpecializedTemplate->getIdentifier(), T, TInfo, S),
- SpecializedTemplate(SpecializedTemplate), ExplicitInfo(nullptr),
+ SpecializedTemplate(SpecializedTemplate),
TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args)),
- SpecializationKind(TSK_Undeclared) {}
+ SpecializationKind(TSK_Undeclared), IsCompleteDefinition(false) {}
VarTemplateSpecializationDecl::VarTemplateSpecializationDecl(Kind DK,
ASTContext &C)
: VarDecl(DK, C, nullptr, SourceLocation(), SourceLocation(), nullptr,
QualType(), nullptr, SC_None),
- ExplicitInfo(nullptr), SpecializationKind(TSK_Undeclared) {}
+ SpecializationKind(TSK_Undeclared), IsCompleteDefinition(false) {}
VarTemplateSpecializationDecl *VarTemplateSpecializationDecl::Create(
ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
@@ -1058,12 +1051,10 @@ void VarTemplateSpecializationDecl::getNameForDiagnostic(
auto *PS = dyn_cast<VarTemplatePartialSpecializationDecl>(this);
if (const ASTTemplateArgumentListInfo *ArgsAsWritten =
PS ? PS->getTemplateArgsAsWritten() : nullptr) {
- TemplateSpecializationType::PrintTemplateArgumentList(
- OS, ArgsAsWritten->arguments(), Policy);
+ printTemplateArgumentList(OS, ArgsAsWritten->arguments(), Policy);
} else {
const TemplateArgumentList &TemplateArgs = getTemplateArgs();
- TemplateSpecializationType::PrintTemplateArgumentList(
- OS, TemplateArgs.asArray(), Policy);
+ printTemplateArgumentList(OS, TemplateArgs.asArray(), Policy);
}
}
@@ -1085,6 +1076,7 @@ void VarTemplateSpecializationDecl::setTemplateArgsInfo(
//===----------------------------------------------------------------------===//
// VarTemplatePartialSpecializationDecl Implementation
//===----------------------------------------------------------------------===//
+
void VarTemplatePartialSpecializationDecl::anchor() {}
VarTemplatePartialSpecializationDecl::VarTemplatePartialSpecializationDecl(
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp b/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp
index 1f8e26deda979..31bae93c3cb56 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp
@@ -1,4 +1,4 @@
-//===-- DeclarationName.cpp - Declaration names implementation --*- C++ -*-===//
+//===- DeclarationName.cpp - Declaration names implementation -------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,20 +11,36 @@
// classes.
//
//===----------------------------------------------------------------------===//
+
#include "clang/AST/DeclarationName.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeOrdering.h"
#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/OperatorKinds.h"
+#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/FoldingSet.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <string>
+
using namespace clang;
namespace clang {
+
/// CXXSpecialName - Records the type associated with one of the
/// "special" kinds of declaration names in C++, e.g., constructors,
/// destructors, and conversion functions.
@@ -89,6 +105,8 @@ public:
}
};
+} // namespace clang
+
static int compareInt(unsigned A, unsigned B) {
return (A < B ? -1 : (A > B ? 1 : 0));
}
@@ -197,10 +215,9 @@ void DeclarationName::print(raw_ostream &OS, const PrintingPolicy &Policy) {
case DeclarationName::CXXConstructorName:
return printCXXConstructorDestructorName(N.getCXXNameType(), OS, Policy);
- case DeclarationName::CXXDestructorName: {
+ case DeclarationName::CXXDestructorName:
OS << '~';
return printCXXConstructorDestructorName(N.getCXXNameType(), OS, Policy);
- }
case DeclarationName::CXXDeductionGuideName:
OS << "<deduction guide for ";
@@ -250,13 +267,15 @@ void DeclarationName::print(raw_ostream &OS, const PrintingPolicy &Policy) {
llvm_unreachable("Unexpected declaration name kind");
}
+namespace clang {
+
raw_ostream &operator<<(raw_ostream &OS, DeclarationName N) {
LangOptions LO;
N.print(OS, PrintingPolicy(LO));
return OS;
}
-} // end namespace clang
+} // namespace clang
DeclarationName::NameKind DeclarationName::getNameKind() const {
switch (getStoredNameKind()) {
diff --git a/contrib/llvm/tools/clang/lib/AST/Expr.cpp b/contrib/llvm/tools/clang/lib/AST/Expr.cpp
index afc7fa8ea0949..55061aa462e5c 100644
--- a/contrib/llvm/tools/clang/lib/AST/Expr.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Expr.cpp
@@ -1695,6 +1695,26 @@ CXXBaseSpecifier **CastExpr::path_buffer() {
}
}
+const FieldDecl *CastExpr::getTargetFieldForToUnionCast(QualType unionType,
+ QualType opType) {
+ auto RD = unionType->castAs<RecordType>()->getDecl();
+ return getTargetFieldForToUnionCast(RD, opType);
+}
+
+const FieldDecl *CastExpr::getTargetFieldForToUnionCast(const RecordDecl *RD,
+ QualType OpType) {
+ auto &Ctx = RD->getASTContext();
+ RecordDecl::field_iterator Field, FieldEnd;
+ for (Field = RD->field_begin(), FieldEnd = RD->field_end();
+ Field != FieldEnd; ++Field) {
+ if (Ctx.hasSameUnqualifiedType(Field->getType(), OpType) &&
+ !Field->isUnnamedBitfield()) {
+ return *Field;
+ }
+ }
+ return nullptr;
+}
+
ImplicitCastExpr *ImplicitCastExpr::Create(const ASTContext &C, QualType T,
CastKind Kind, Expr *Operand,
const CXXCastPath *BasePath,
@@ -1760,6 +1780,7 @@ BinaryOperator::getOverloadedOpcode(OverloadedOperatorKind OO) {
case OO_Amp: return BO_And;
case OO_Pipe: return BO_Or;
case OO_Equal: return BO_Assign;
+ case OO_Spaceship: return BO_Cmp;
case OO_Less: return BO_LT;
case OO_Greater: return BO_GT;
case OO_PlusEqual: return BO_AddAssign;
@@ -1791,6 +1812,7 @@ OverloadedOperatorKind BinaryOperator::getOverloadedOperator(Opcode Opc) {
OO_Star, OO_Slash, OO_Percent,
OO_Plus, OO_Minus,
OO_LessLess, OO_GreaterGreater,
+ OO_Spaceship,
OO_Less, OO_Greater, OO_LessEqual, OO_GreaterEqual,
OO_EqualEqual, OO_ExclaimEqual,
OO_Amp,
@@ -1809,6 +1831,38 @@ OverloadedOperatorKind BinaryOperator::getOverloadedOperator(Opcode Opc) {
return OverOps[Opc];
}
+bool BinaryOperator::isNullPointerArithmeticExtension(ASTContext &Ctx,
+ Opcode Opc,
+ Expr *LHS, Expr *RHS) {
+ if (Opc != BO_Add)
+ return false;
+
+ // Check that we have one pointer and one integer operand.
+ Expr *PExp;
+ if (LHS->getType()->isPointerType()) {
+ if (!RHS->getType()->isIntegerType())
+ return false;
+ PExp = LHS;
+ } else if (RHS->getType()->isPointerType()) {
+ if (!LHS->getType()->isIntegerType())
+ return false;
+ PExp = RHS;
+ } else {
+ return false;
+ }
+
+ // Check that the pointer is a nullptr.
+ if (!PExp->IgnoreParenCasts()
+ ->isNullPointerConstant(Ctx, Expr::NPC_ValueDependentIsNotNull))
+ return false;
+
+ // Check that the pointee type is char-sized.
+ const PointerType *PTy = PExp->getType()->getAs<PointerType>();
+ if (!PTy || !PTy->getPointeeType()->isCharType())
+ return false;
+
+ return true;
+}
InitListExpr::InitListExpr(const ASTContext &C, SourceLocation lbraceloc,
ArrayRef<Expr*> initExprs, SourceLocation rbraceloc)
: Expr(InitListExprClass, QualType(), VK_RValue, OK_Ordinary, false, false,
@@ -1899,6 +1953,17 @@ bool InitListExpr::isTransparent() const {
getInit(0)->getType().getCanonicalType();
}
+bool InitListExpr::isIdiomaticZeroInitializer(const LangOptions &LangOpts) const {
+ assert(isSyntacticForm() && "only test syntactic form as zero initializer");
+
+ if (LangOpts.CPlusPlus || getNumInits() != 1) {
+ return false;
+ }
+
+ const IntegerLiteral *Lit = dyn_cast<IntegerLiteral>(getInit(0));
+ return Lit && Lit->getValue() == 0;
+}
+
SourceLocation InitListExpr::getLocStart() const {
if (InitListExpr *SyntacticForm = getSyntacticForm())
return SyntacticForm->getLocStart();
@@ -2235,7 +2300,8 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
const DeclRefExpr *DRE =
dyn_cast<DeclRefExpr>(CE->getSubExpr()->IgnoreParens());
if (!(DRE && isa<VarDecl>(DRE->getDecl()) &&
- cast<VarDecl>(DRE->getDecl())->hasLocalStorage())) {
+ cast<VarDecl>(DRE->getDecl())->hasLocalStorage()) &&
+ !isa<CallExpr>(CE->getSubExpr()->IgnoreParens())) {
return CE->getSubExpr()->isUnusedResultAWarning(WarnE, Loc,
R1, R2, Ctx);
}
@@ -3230,20 +3296,20 @@ Expr::isNullPointerConstant(ASTContext &Ctx,
// Check that it is a cast to void*.
if (const PointerType *PT = CE->getType()->getAs<PointerType>()) {
QualType Pointee = PT->getPointeeType();
- Qualifiers Q = Pointee.getQualifiers();
- // In OpenCL v2.0 generic address space acts as a placeholder
- // and should be ignored.
- bool IsASValid = true;
- if (Ctx.getLangOpts().OpenCLVersion >= 200) {
- if (Pointee.getAddressSpace() == LangAS::opencl_generic)
- Q.removeAddressSpace();
- else
- IsASValid = false;
- }
+ // Only (void*)0 or equivalent are treated as nullptr. If pointee type
+ // has non-default address space it is not treated as nullptr.
+ // (__generic void*)0 in OpenCL 2.0 should not be treated as nullptr
+ // since it cannot be assigned to a pointer to constant address space.
+ bool PointeeHasDefaultAS =
+ Pointee.getAddressSpace() == LangAS::Default ||
+ (Ctx.getLangOpts().OpenCLVersion >= 200 &&
+ Pointee.getAddressSpace() == LangAS::opencl_generic) ||
+ (Ctx.getLangOpts().OpenCL &&
+ Ctx.getLangOpts().OpenCLVersion < 200 &&
+ Pointee.getAddressSpace() == LangAS::opencl_private);
- if (IsASValid && !Q.hasQualifiers() &&
- Pointee->isVoidType() && // to void*
- CE->getSubExpr()->getType()->isIntegerType()) // from int.
+ if (PointeeHasDefaultAS && Pointee->isVoidType() && // to void*
+ CE->getSubExpr()->getType()->isIntegerType()) // from int.
return CE->getSubExpr()->isNullPointerConstant(Ctx, NPC);
}
}
@@ -3938,10 +4004,12 @@ AtomicExpr::AtomicExpr(SourceLocation BLoc, ArrayRef<Expr*> args,
unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) {
switch (Op) {
case AO__c11_atomic_init:
+ case AO__opencl_atomic_init:
case AO__c11_atomic_load:
case AO__atomic_load_n:
return 2;
+ case AO__opencl_atomic_load:
case AO__c11_atomic_store:
case AO__c11_atomic_exchange:
case AO__atomic_load:
@@ -3967,6 +4035,15 @@ unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) {
case AO__atomic_nand_fetch:
return 3;
+ case AO__opencl_atomic_store:
+ case AO__opencl_atomic_exchange:
+ case AO__opencl_atomic_fetch_add:
+ case AO__opencl_atomic_fetch_sub:
+ case AO__opencl_atomic_fetch_and:
+ case AO__opencl_atomic_fetch_or:
+ case AO__opencl_atomic_fetch_xor:
+ case AO__opencl_atomic_fetch_min:
+ case AO__opencl_atomic_fetch_max:
case AO__atomic_exchange:
return 4;
@@ -3974,6 +4051,8 @@ unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) {
case AO__c11_atomic_compare_exchange_weak:
return 5;
+ case AO__opencl_atomic_compare_exchange_strong:
+ case AO__opencl_atomic_compare_exchange_weak:
case AO__atomic_compare_exchange:
case AO__atomic_compare_exchange_n:
return 6;
@@ -3981,6 +4060,13 @@ unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) {
llvm_unreachable("unknown atomic op");
}
+QualType AtomicExpr::getValueType() const {
+ auto T = getPtr()->getType()->castAs<PointerType>()->getPointeeType();
+ if (auto AT = T->getAs<AtomicType>())
+ return AT->getValueType();
+ return T;
+}
+
QualType OMPArraySectionExpr::getBaseOriginalType(const Expr *Base) {
unsigned ArraySectionCount = 0;
while (auto *OASE = dyn_cast<OMPArraySectionExpr>(Base->IgnoreParens())) {
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp
index fe45b5e47f36d..262a1e3ff9d58 100644
--- a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp
@@ -1,4 +1,4 @@
-//===--- ExprCXX.cpp - (C++) Expression AST Node Implementation -----------===//
+//===- ExprCXX.cpp - (C++) Expression AST Node Implementation -------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,15 +11,33 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/AST/ExprCXX.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclAccessPair.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclTemplate.h"
-#include "clang/AST/ExprCXX.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/LambdaCapture.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
-#include "clang/Basic/IdentifierTable.h"
-using namespace clang;
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/OperatorKinds.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <cassert>
+#include <cstddef>
+#include <cstring>
+#include <memory>
+using namespace clang;
//===----------------------------------------------------------------------===//
// Child Iterators for iterating over subexpressions/substatements
@@ -85,15 +103,14 @@ CXXNewExpr::CXXNewExpr(const ASTContext &C, bool globalNew,
Expr *initializer, QualType ty,
TypeSourceInfo *allocatedTypeInfo,
SourceRange Range, SourceRange directInitRange)
- : Expr(CXXNewExprClass, ty, VK_RValue, OK_Ordinary,
- ty->isDependentType(), ty->isDependentType(),
- ty->isInstantiationDependentType(),
- ty->containsUnexpandedParameterPack()),
- SubExprs(nullptr), OperatorNew(operatorNew), OperatorDelete(operatorDelete),
- AllocatedTypeInfo(allocatedTypeInfo), TypeIdParens(typeIdParens),
- Range(Range), DirectInitRange(directInitRange),
- GlobalNew(globalNew), PassAlignment(PassAlignment),
- UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) {
+ : Expr(CXXNewExprClass, ty, VK_RValue, OK_Ordinary, ty->isDependentType(),
+ ty->isDependentType(), ty->isInstantiationDependentType(),
+ ty->containsUnexpandedParameterPack()),
+ OperatorNew(operatorNew), OperatorDelete(operatorDelete),
+ AllocatedTypeInfo(allocatedTypeInfo), TypeIdParens(typeIdParens),
+ Range(Range), DirectInitRange(directInitRange), GlobalNew(globalNew),
+ PassAlignment(PassAlignment),
+ UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) {
assert((initializer != nullptr || initializationStyle == NoInit) &&
"Only NoInit can have no initializer.");
StoredInitializationStyle = initializer ? initializationStyle + 1 : 0;
@@ -160,6 +177,22 @@ bool CXXNewExpr::shouldNullCheckAllocation(const ASTContext &Ctx) const {
// CXXDeleteExpr
QualType CXXDeleteExpr::getDestroyedType() const {
const Expr *Arg = getArgument();
+
+ // For a destroying operator delete, we may have implicitly converted the
+ // pointer type to the type of the parameter of the 'operator delete'
+ // function.
+ while (auto *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
+ if (ICE->getCastKind() == CK_DerivedToBase ||
+ ICE->getCastKind() == CK_UncheckedDerivedToBase ||
+ ICE->getCastKind() == CK_NoOp) {
+ assert((ICE->getCastKind() == CK_NoOp ||
+ getOperatorDelete()->isDestroyingOperatorDelete()) &&
+ "only a destroying operator delete can have a converted arg");
+ Arg = ICE->getSubExpr();
+ } else
+ break;
+ }
+
// The type-to-delete may not be a pointer if it's a dependent type.
const QualType ArgType = Arg->getType();
@@ -171,8 +204,7 @@ QualType CXXDeleteExpr::getDestroyedType() const {
// CXXPseudoDestructorExpr
PseudoDestructorTypeStorage::PseudoDestructorTypeStorage(TypeSourceInfo *Info)
- : Type(Info)
-{
+ : Type(Info) {
Location = Info->getTypeLoc().getLocalSourceRange().getBegin();
}
@@ -209,7 +241,7 @@ CXXPseudoDestructorExpr::CXXPseudoDestructorExpr(const ASTContext &Context,
Base(static_cast<Stmt *>(Base)), IsArrow(isArrow),
OperatorLoc(OperatorLoc), QualifierLoc(QualifierLoc),
ScopeType(ScopeType), ColonColonLoc(ColonColonLoc), TildeLoc(TildeLoc),
- DestroyedType(DestroyedType) { }
+ DestroyedType(DestroyedType) {}
QualType CXXPseudoDestructorExpr::getDestroyedType() const {
if (TypeSourceInfo *TInfo = DestroyedType.getTypeSourceInfo())
@@ -235,8 +267,7 @@ UnresolvedLookupExpr::Create(const ASTContext &C,
bool ADL,
const TemplateArgumentListInfo *Args,
UnresolvedSetIterator Begin,
- UnresolvedSetIterator End)
-{
+ UnresolvedSetIterator End) {
assert(Args || TemplateKWLoc.isValid());
unsigned num_args = Args ? Args->size() : 0;
@@ -274,21 +305,20 @@ OverloadExpr::OverloadExpr(StmtClass K, const ASTContext &C,
bool KnownDependent,
bool KnownInstantiationDependent,
bool KnownContainsUnexpandedParameterPack)
- : Expr(K, C.OverloadTy, VK_LValue, OK_Ordinary, KnownDependent,
- KnownDependent,
- (KnownInstantiationDependent ||
- NameInfo.isInstantiationDependent() ||
- (QualifierLoc &&
- QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())),
- (KnownContainsUnexpandedParameterPack ||
- NameInfo.containsUnexpandedParameterPack() ||
- (QualifierLoc &&
- QualifierLoc.getNestedNameSpecifier()
- ->containsUnexpandedParameterPack()))),
- NameInfo(NameInfo), QualifierLoc(QualifierLoc),
- Results(nullptr), NumResults(End - Begin),
- HasTemplateKWAndArgsInfo(TemplateArgs != nullptr ||
- TemplateKWLoc.isValid()) {
+ : Expr(K, C.OverloadTy, VK_LValue, OK_Ordinary, KnownDependent,
+ KnownDependent,
+ (KnownInstantiationDependent ||
+ NameInfo.isInstantiationDependent() ||
+ (QualifierLoc &&
+ QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())),
+ (KnownContainsUnexpandedParameterPack ||
+ NameInfo.containsUnexpandedParameterPack() ||
+ (QualifierLoc &&
+ QualifierLoc.getNestedNameSpecifier()
+ ->containsUnexpandedParameterPack()))),
+ NameInfo(NameInfo), QualifierLoc(QualifierLoc), NumResults(End - Begin),
+ HasTemplateKWAndArgsInfo(TemplateArgs != nullptr ||
+ TemplateKWLoc.isValid()) {
NumResults = End - Begin;
if (NumResults) {
// Determine whether this expression is type-dependent.
@@ -493,7 +523,6 @@ CXXMethodDecl *CXXMemberCallExpr::getMethodDecl() const {
return nullptr;
}
-
CXXRecordDecl *CXXMemberCallExpr::getRecordDecl() const {
Expr* ThisArg = getImplicitObjectArgument();
if (!ThisArg)
@@ -505,7 +534,6 @@ CXXRecordDecl *CXXMemberCallExpr::getRecordDecl() const {
return ThisArg->getType()->getAsCXXRecordDecl();
}
-
//===----------------------------------------------------------------------===//
// Named casts
//===----------------------------------------------------------------------===//
@@ -742,16 +770,12 @@ CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(const ASTContext &C,
bool ListInitialization,
bool StdInitListInitialization,
bool ZeroInitialization)
- : CXXConstructExpr(C, CXXTemporaryObjectExprClass, Type,
- TSI->getTypeLoc().getBeginLoc(),
- Cons, false, Args,
- HadMultipleCandidates,
- ListInitialization,
- StdInitListInitialization,
- ZeroInitialization,
- CXXConstructExpr::CK_Complete, ParenOrBraceRange),
- Type(TSI) {
-}
+ : CXXConstructExpr(C, CXXTemporaryObjectExprClass, Type,
+ TSI->getTypeLoc().getBeginLoc(), Cons, false, Args,
+ HadMultipleCandidates, ListInitialization,
+ StdInitListInitialization, ZeroInitialization,
+ CXXConstructExpr::CK_Complete, ParenOrBraceRange),
+ Type(TSI) {}
SourceLocation CXXTemporaryObjectExpr::getLocStart() const {
return Type->getTypeLoc().getBeginLoc();
@@ -794,18 +818,16 @@ CXXConstructExpr::CXXConstructExpr(const ASTContext &C, StmtClass SC,
bool ZeroInitialization,
ConstructionKind ConstructKind,
SourceRange ParenOrBraceRange)
- : Expr(SC, T, VK_RValue, OK_Ordinary,
- T->isDependentType(), T->isDependentType(),
- T->isInstantiationDependentType(),
- T->containsUnexpandedParameterPack()),
- Constructor(Ctor), Loc(Loc), ParenOrBraceRange(ParenOrBraceRange),
- NumArgs(Args.size()),
- Elidable(Elidable), HadMultipleCandidates(HadMultipleCandidates),
- ListInitialization(ListInitialization),
- StdInitListInitialization(StdInitListInitialization),
- ZeroInitialization(ZeroInitialization),
- ConstructKind(ConstructKind), Args(nullptr)
-{
+ : Expr(SC, T, VK_RValue, OK_Ordinary,
+ T->isDependentType(), T->isDependentType(),
+ T->isInstantiationDependentType(),
+ T->containsUnexpandedParameterPack()),
+ Constructor(Ctor), Loc(Loc), ParenOrBraceRange(ParenOrBraceRange),
+ NumArgs(Args.size()), Elidable(Elidable),
+ HadMultipleCandidates(HadMultipleCandidates),
+ ListInitialization(ListInitialization),
+ StdInitListInitialization(StdInitListInitialization),
+ ZeroInitialization(ZeroInitialization), ConstructKind(ConstructKind) {
if (NumArgs) {
this->Args = new (C) Stmt*[Args.size()];
@@ -827,8 +849,7 @@ CXXConstructExpr::CXXConstructExpr(const ASTContext &C, StmtClass SC,
LambdaCapture::LambdaCapture(SourceLocation Loc, bool Implicit,
LambdaCaptureKind Kind, VarDecl *Var,
SourceLocation EllipsisLoc)
- : DeclAndBits(Var, 0), Loc(Loc), EllipsisLoc(EllipsisLoc)
-{
+ : DeclAndBits(Var, 0), Loc(Loc), EllipsisLoc(EllipsisLoc) {
unsigned Bits = 0;
if (Implicit)
Bits |= Capture_Implicit;
@@ -995,7 +1016,7 @@ CompoundStmt *LambdaExpr::getBody() const {
// initialized in ASTStmtReader::VisitLambdaExpr, but for reasons I
// don't understand, that doesn't work.
if (!getStoredStmts()[NumCaptures])
- *const_cast<clang::Stmt **>(&getStoredStmts()[NumCaptures]) =
+ *const_cast<Stmt **>(&getStoredStmts()[NumCaptures]) =
getCallOperator()->getBody();
return static_cast<CompoundStmt *>(getStoredStmts()[NumCaptures]);
@@ -1008,12 +1029,12 @@ bool LambdaExpr::isMutable() const {
ExprWithCleanups::ExprWithCleanups(Expr *subexpr,
bool CleanupsHaveSideEffects,
ArrayRef<CleanupObject> objects)
- : Expr(ExprWithCleanupsClass, subexpr->getType(),
- subexpr->getValueKind(), subexpr->getObjectKind(),
- subexpr->isTypeDependent(), subexpr->isValueDependent(),
- subexpr->isInstantiationDependent(),
- subexpr->containsUnexpandedParameterPack()),
- SubExpr(subexpr) {
+ : Expr(ExprWithCleanupsClass, subexpr->getType(),
+ subexpr->getValueKind(), subexpr->getObjectKind(),
+ subexpr->isTypeDependent(), subexpr->isValueDependent(),
+ subexpr->isInstantiationDependent(),
+ subexpr->containsUnexpandedParameterPack()),
+ SubExpr(subexpr) {
ExprWithCleanupsBits.CleanupsHaveSideEffects = CleanupsHaveSideEffects;
ExprWithCleanupsBits.NumObjects = objects.size();
for (unsigned i = 0, e = objects.size(); i != e; ++i)
@@ -1030,7 +1051,7 @@ ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C, Expr *subexpr,
}
ExprWithCleanups::ExprWithCleanups(EmptyShell empty, unsigned numObjects)
- : Expr(ExprWithCleanupsClass, empty) {
+ : Expr(ExprWithCleanupsClass, empty) {
ExprWithCleanupsBits.NumObjects = numObjects;
}
@@ -1046,20 +1067,18 @@ CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(TypeSourceInfo *Type,
SourceLocation LParenLoc,
ArrayRef<Expr*> Args,
SourceLocation RParenLoc)
- : Expr(CXXUnresolvedConstructExprClass,
- Type->getType().getNonReferenceType(),
- (Type->getType()->isLValueReferenceType() ? VK_LValue
- :Type->getType()->isRValueReferenceType()? VK_XValue
- :VK_RValue),
- OK_Ordinary,
- Type->getType()->isDependentType() ||
- Type->getType()->getContainedDeducedType(),
- true, true,
- Type->getType()->containsUnexpandedParameterPack()),
- Type(Type),
- LParenLoc(LParenLoc),
- RParenLoc(RParenLoc),
- NumArgs(Args.size()) {
+ : Expr(CXXUnresolvedConstructExprClass,
+ Type->getType().getNonReferenceType(),
+ (Type->getType()->isLValueReferenceType()
+ ? VK_LValue
+ : Type->getType()->isRValueReferenceType() ? VK_XValue
+ : VK_RValue),
+ OK_Ordinary,
+ Type->getType()->isDependentType() ||
+ Type->getType()->getContainedDeducedType(),
+ true, true, Type->getType()->containsUnexpandedParameterPack()),
+ Type(Type), LParenLoc(LParenLoc), RParenLoc(RParenLoc),
+ NumArgs(Args.size()) {
Expr **StoredArgs = getTrailingObjects<Expr *>();
for (unsigned I = 0; I != Args.size(); ++I) {
if (Args[I]->containsUnexpandedParameterPack())
@@ -1159,7 +1178,7 @@ CXXDependentScopeMemberExpr::CreateEmpty(const ASTContext &C,
void *Mem = C.Allocate(Size, alignof(CXXDependentScopeMemberExpr));
CXXDependentScopeMemberExpr *E
= new (Mem) CXXDependentScopeMemberExpr(C, nullptr, QualType(),
- 0, SourceLocation(),
+ false, SourceLocation(),
NestedNameSpecifierLoc(),
SourceLocation(), nullptr,
DeclarationNameInfo(), nullptr);
@@ -1202,19 +1221,18 @@ UnresolvedMemberExpr::UnresolvedMemberExpr(const ASTContext &C,
const TemplateArgumentListInfo *TemplateArgs,
UnresolvedSetIterator Begin,
UnresolvedSetIterator End)
- : OverloadExpr(UnresolvedMemberExprClass, C, QualifierLoc, TemplateKWLoc,
- MemberNameInfo, TemplateArgs, Begin, End,
- // Dependent
- ((Base && Base->isTypeDependent()) ||
- BaseType->isDependentType()),
- ((Base && Base->isInstantiationDependent()) ||
- BaseType->isInstantiationDependentType()),
- // Contains unexpanded parameter pack
- ((Base && Base->containsUnexpandedParameterPack()) ||
- BaseType->containsUnexpandedParameterPack())),
- IsArrow(IsArrow), HasUnresolvedUsing(HasUnresolvedUsing),
- Base(Base), BaseType(BaseType), OperatorLoc(OperatorLoc) {
-
+ : OverloadExpr(
+ UnresolvedMemberExprClass, C, QualifierLoc, TemplateKWLoc,
+ MemberNameInfo, TemplateArgs, Begin, End,
+ // Dependent
+ ((Base && Base->isTypeDependent()) || BaseType->isDependentType()),
+ ((Base && Base->isInstantiationDependent()) ||
+ BaseType->isInstantiationDependentType()),
+ // Contains unexpanded parameter pack
+ ((Base && Base->containsUnexpandedParameterPack()) ||
+ BaseType->containsUnexpandedParameterPack())),
+ IsArrow(IsArrow), HasUnresolvedUsing(HasUnresolvedUsing), Base(Base),
+ BaseType(BaseType), OperatorLoc(OperatorLoc) {
// Check whether all of the members are non-static member functions,
// and if so, mark give this bound-member type instead of overload type.
if (hasOnlyNonStaticMemberFunctions(Begin, End))
@@ -1315,10 +1333,10 @@ SubstNonTypeTemplateParmPackExpr(QualType T,
NonTypeTemplateParmDecl *Param,
SourceLocation NameLoc,
const TemplateArgument &ArgPack)
- : Expr(SubstNonTypeTemplateParmPackExprClass, T, VK_RValue, OK_Ordinary,
- true, true, true, true),
- Param(Param), Arguments(ArgPack.pack_begin()),
- NumArguments(ArgPack.pack_size()), NameLoc(NameLoc) { }
+ : Expr(SubstNonTypeTemplateParmPackExprClass, T, VK_RValue, OK_Ordinary,
+ true, true, true, true),
+ Param(Param), Arguments(ArgPack.pack_begin()),
+ NumArguments(ArgPack.pack_size()), NameLoc(NameLoc) {}
TemplateArgument SubstNonTypeTemplateParmPackExpr::getArgumentPack() const {
return TemplateArgument(llvm::makeArrayRef(Arguments, NumArguments));
@@ -1374,13 +1392,12 @@ TypeTraitExpr::TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind,
ArrayRef<TypeSourceInfo *> Args,
SourceLocation RParenLoc,
bool Value)
- : Expr(TypeTraitExprClass, T, VK_RValue, OK_Ordinary,
- /*TypeDependent=*/false,
- /*ValueDependent=*/false,
- /*InstantiationDependent=*/false,
- /*ContainsUnexpandedParameterPack=*/false),
- Loc(Loc), RParenLoc(RParenLoc)
-{
+ : Expr(TypeTraitExprClass, T, VK_RValue, OK_Ordinary,
+ /*TypeDependent=*/false,
+ /*ValueDependent=*/false,
+ /*InstantiationDependent=*/false,
+ /*ContainsUnexpandedParameterPack=*/false),
+ Loc(Loc), RParenLoc(RParenLoc) {
TypeTraitExprBits.Kind = Kind;
TypeTraitExprBits.Value = Value;
TypeTraitExprBits.NumArgs = Args.size();
@@ -1415,4 +1432,4 @@ TypeTraitExpr *TypeTraitExpr::CreateDeserialized(const ASTContext &C,
return new (Mem) TypeTraitExpr(EmptyShell());
}
-void ArrayTypeTraitExpr::anchor() { }
+void ArrayTypeTraitExpr::anchor() {}
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp
index d149bdd0cdf97..3bb2b4eb5fc19 100644
--- a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp
@@ -641,7 +641,7 @@ static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E,
// Records with any const fields (recursively) are not modifiable.
if (const RecordType *R = CT->getAs<RecordType>())
if (R->hasConstFields())
- return Cl::CM_ConstQualified;
+ return Cl::CM_ConstQualifiedField;
return Cl::CM_Modifiable;
}
@@ -695,6 +695,7 @@ Expr::isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc) const {
llvm_unreachable("CM_LValueCast and CL_LValue don't match");
case Cl::CM_NoSetterProperty: return MLV_NoSetterProperty;
case Cl::CM_ConstQualified: return MLV_ConstQualified;
+ case Cl::CM_ConstQualifiedField: return MLV_ConstQualifiedField;
case Cl::CM_ConstAddrSpace: return MLV_ConstAddrSpace;
case Cl::CM_ArrayType: return MLV_ArrayType;
case Cl::CM_IncompleteType: return MLV_IncompleteType;
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
index 792e8cc4a518b..9c9eeb79b40a4 100644
--- a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
@@ -62,7 +62,13 @@ namespace {
static QualType getType(APValue::LValueBase B) {
if (!B) return QualType();
if (const ValueDecl *D = B.dyn_cast<const ValueDecl*>())
- return D->getType();
+ // FIXME: It's unclear where we're supposed to take the type from, and
+ // this actually matters for arrays of unknown bound. Using the type of
+ // the most recent declaration isn't clearly correct in general. Eg:
+ //
+ // extern int arr[]; void f() { extern int arr[3]; };
+ // constexpr int *p = &arr[1]; // valid?
+ return cast<ValueDecl>(D->getMostRecentDecl())->getType();
const Expr *Base = B.get<const Expr*>();
@@ -141,6 +147,12 @@ namespace {
return E && E->getType()->isPointerType() && tryUnwrapAllocSizeCall(E);
}
+ /// The bound to claim that an array of unknown bound has.
+ /// The value in MostDerivedArraySize is undefined in this case. So, set it
+ /// to an arbitrary value that's likely to loudly break things if it's used.
+ static const uint64_t AssumedSizeForUnsizedArray =
+ std::numeric_limits<uint64_t>::max() / 2;
+
/// Determines if an LValue with the given LValueBase will have an unsized
/// array in its designator.
/// Find the path length and type of the most-derived subobject in the given
@@ -148,7 +160,8 @@ namespace {
static unsigned
findMostDerivedSubobject(ASTContext &Ctx, APValue::LValueBase Base,
ArrayRef<APValue::LValuePathEntry> Path,
- uint64_t &ArraySize, QualType &Type, bool &IsArray) {
+ uint64_t &ArraySize, QualType &Type, bool &IsArray,
+ bool &FirstEntryIsUnsizedArray) {
// This only accepts LValueBases from APValues, and APValues don't support
// arrays that lack size info.
assert(!isBaseAnAllocSizeCall(Base) &&
@@ -158,12 +171,18 @@ namespace {
for (unsigned I = 0, N = Path.size(); I != N; ++I) {
if (Type->isArrayType()) {
- const ConstantArrayType *CAT =
- cast<ConstantArrayType>(Ctx.getAsArrayType(Type));
- Type = CAT->getElementType();
- ArraySize = CAT->getSize().getZExtValue();
+ const ArrayType *AT = Ctx.getAsArrayType(Type);
+ Type = AT->getElementType();
MostDerivedLength = I + 1;
IsArray = true;
+
+ if (auto *CAT = dyn_cast<ConstantArrayType>(AT)) {
+ ArraySize = CAT->getSize().getZExtValue();
+ } else {
+ assert(I == 0 && "unexpected unsized array designator");
+ FirstEntryIsUnsizedArray = true;
+ ArraySize = AssumedSizeForUnsizedArray;
+ }
} else if (Type->isAnyComplexType()) {
const ComplexType *CT = Type->castAs<ComplexType>();
Type = CT->getElementType();
@@ -246,10 +265,12 @@ namespace {
Entries.insert(Entries.end(), VEntries.begin(), VEntries.end());
if (V.getLValueBase()) {
bool IsArray = false;
+ bool FirstIsUnsizedArray = false;
MostDerivedPathLength = findMostDerivedSubobject(
Ctx, V.getLValueBase(), V.getLValuePath(), MostDerivedArraySize,
- MostDerivedType, IsArray);
+ MostDerivedType, IsArray, FirstIsUnsizedArray);
MostDerivedIsArrayElement = IsArray;
+ FirstEntryIsAnUnsizedArray = FirstIsUnsizedArray;
}
}
}
@@ -318,7 +339,7 @@ namespace {
// The value in MostDerivedArraySize is undefined in this case. So, set it
// to an arbitrary value that's likely to loudly break things if it's
// used.
- MostDerivedArraySize = std::numeric_limits<uint64_t>::max() / 2;
+ MostDerivedArraySize = AssumedSizeForUnsizedArray;
MostDerivedPathLength = Entries.size();
}
/// Update this designator to refer to the given base or member of this
@@ -350,6 +371,7 @@ namespace {
MostDerivedArraySize = 2;
MostDerivedPathLength = Entries.size();
}
+ void diagnoseUnsizedArrayPointerArithmetic(EvalInfo &Info, const Expr *E);
void diagnosePointerArithmetic(EvalInfo &Info, const Expr *E,
const APSInt &N);
/// Add N to the address of this subobject.
@@ -357,6 +379,7 @@ namespace {
if (Invalid || !N) return;
uint64_t TruncatedN = N.extOrTrunc(64).getZExtValue();
if (isMostDerivedAnUnsizedArray()) {
+ diagnoseUnsizedArrayPointerArithmetic(Info, E);
// Can't verify -- trust that the user is doing the right thing (or if
// not, trust that the caller will catch the bad behavior).
// FIXME: Should we reject if this overflows, at least?
@@ -573,6 +596,31 @@ namespace {
/// declaration whose initializer is being evaluated, if any.
APValue *EvaluatingDeclValue;
+ /// EvaluatingObject - Pair of the AST node that an lvalue represents and
+ /// the call index that that lvalue was allocated in.
+ typedef std::pair<APValue::LValueBase, unsigned> EvaluatingObject;
+
+ /// EvaluatingConstructors - Set of objects that are currently being
+ /// constructed.
+ llvm::DenseSet<EvaluatingObject> EvaluatingConstructors;
+
+ struct EvaluatingConstructorRAII {
+ EvalInfo &EI;
+ EvaluatingObject Object;
+ bool DidInsert;
+ EvaluatingConstructorRAII(EvalInfo &EI, EvaluatingObject Object)
+ : EI(EI), Object(Object) {
+ DidInsert = EI.EvaluatingConstructors.insert(Object).second;
+ }
+ ~EvaluatingConstructorRAII() {
+ if (DidInsert) EI.EvaluatingConstructors.erase(Object);
+ }
+ };
+
+ bool isEvaluatingConstructor(APValue::LValueBase Decl, unsigned CallIndex) {
+ return EvaluatingConstructors.count(EvaluatingObject(Decl, CallIndex));
+ }
+
/// The current array initialization index, if we're performing array
/// initialization.
uint64_t ArrayInitIndex = -1;
@@ -666,6 +714,7 @@ namespace {
void setEvaluatingDecl(APValue::LValueBase Base, APValue &Value) {
EvaluatingDecl = Base;
EvaluatingDeclValue = &Value;
+ EvaluatingConstructors.insert({Base, 0});
}
const LangOptions &getLangOpts() const { return Ctx.getLangOpts(); }
@@ -984,6 +1033,7 @@ namespace {
void moveFromAndCancel(SpeculativeEvaluationRAII &&Other) {
Info = Other.Info;
OldStatus = Other.OldStatus;
+ OldIsSpeculativelyEvaluating = Other.OldIsSpeculativelyEvaluating;
Other.Info = nullptr;
}
@@ -1067,9 +1117,19 @@ bool SubobjectDesignator::checkSubobject(EvalInfo &Info, const Expr *E,
setInvalid();
return false;
}
+ // Note, we do not diagnose if isMostDerivedAnUnsizedArray(), because there
+ // must actually be at least one array element; even a VLA cannot have a
+ // bound of zero. And if our index is nonzero, we already had a CCEDiag.
return true;
}
+void SubobjectDesignator::diagnoseUnsizedArrayPointerArithmetic(EvalInfo &Info,
+ const Expr *E) {
+ Info.CCEDiag(E, diag::note_constexpr_unsized_array_indexed);
+ // Do not set the designator as invalid: we can represent this situation,
+ // and correct handling of __builtin_object_size requires us to do so.
+}
+
void SubobjectDesignator::diagnosePointerArithmetic(EvalInfo &Info,
const Expr *E,
const APSInt &N) {
@@ -1213,8 +1273,6 @@ namespace {
IsNullPtr);
else {
assert(!InvalidBase && "APValues can't handle invalid LValue bases");
- assert(!Designator.FirstEntryIsAnUnsizedArray &&
- "Unsized array with a valid base?");
V = APValue(Base, Offset, Designator.Entries,
Designator.IsOnePastTheEnd, CallIndex, IsNullPtr);
}
@@ -1287,12 +1345,17 @@ namespace {
if (checkSubobject(Info, E, isa<FieldDecl>(D) ? CSK_Field : CSK_Base))
Designator.addDeclUnchecked(D, Virtual);
}
- void addUnsizedArray(EvalInfo &Info, QualType ElemTy) {
- assert(Designator.Entries.empty() && getType(Base)->isPointerType());
- assert(isBaseAnAllocSizeCall(Base) &&
- "Only alloc_size bases can have unsized arrays");
- Designator.FirstEntryIsAnUnsizedArray = true;
- Designator.addUnsizedArrayUnchecked(ElemTy);
+ void addUnsizedArray(EvalInfo &Info, const Expr *E, QualType ElemTy) {
+ if (!Designator.Entries.empty()) {
+ Info.CCEDiag(E, diag::note_constexpr_unsupported_unsized_array);
+ Designator.setInvalid();
+ return;
+ }
+ if (checkSubobject(Info, E, CSK_ArrayToPointer)) {
+ assert(getType(Base)->isPointerType() || getType(Base)->isArrayType());
+ Designator.FirstEntryIsAnUnsizedArray = true;
+ Designator.addUnsizedArrayUnchecked(ElemTy);
+ }
}
void addArray(EvalInfo &Info, const Expr *E, const ConstantArrayType *CAT) {
if (checkSubobject(Info, E, CSK_ArrayToPointer))
@@ -1756,6 +1819,9 @@ static bool CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc,
}
}
for (const auto *I : RD->fields()) {
+ if (I->isUnnamedBitfield())
+ continue;
+
if (!CheckConstantExpression(Info, DiagLoc, I->getType(),
Value.getStructField(I->getFieldIndex())))
return false;
@@ -2597,10 +2663,12 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj,
if (Sub.Invalid)
// A diagnostic will have already been produced.
return handler.failed();
- if (Sub.isOnePastTheEnd()) {
+ if (Sub.isOnePastTheEnd() || Sub.isMostDerivedAnUnsizedArray()) {
if (Info.getLangOpts().CPlusPlus11)
- Info.FFDiag(E, diag::note_constexpr_access_past_end)
- << handler.AccessKind;
+ Info.FFDiag(E, Sub.isOnePastTheEnd()
+ ? diag::note_constexpr_access_past_end
+ : diag::note_constexpr_access_unsized_array)
+ << handler.AccessKind;
else
Info.FFDiag(E);
return handler.failed();
@@ -3097,10 +3165,9 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
}
// During the construction of an object, it is not yet 'const'.
- // FIXME: We don't set up EvaluatingDecl for local variables or temporaries,
- // and this doesn't do quite the right thing for const subobjects of the
+ // FIXME: This doesn't do quite the right thing for const subobjects of the
// object under construction.
- if (LVal.getLValueBase() == Info.EvaluatingDecl) {
+ if (Info.isEvaluatingConstructor(LVal.getLValueBase(), LVal.CallIndex)) {
BaseType = Info.Ctx.getCanonicalType(BaseType);
BaseType.removeLocalConst();
}
@@ -4253,6 +4320,8 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This,
return false;
}
+ EvalInfo::EvaluatingConstructorRAII EvalObj(
+ Info, {This.getLValueBase(), This.CallIndex});
CallStackFrame Frame(Info, CallLoc, Definition, &This, ArgValues);
// FIXME: Creating an APValue just to hold a nonexistent return value is
@@ -5459,7 +5528,7 @@ static bool evaluateLValueAsAllocSize(EvalInfo &Info, APValue::LValueBase Base,
Result.setInvalid(E);
QualType Pointee = E->getType()->castAs<PointerType>()->getPointeeType();
- Result.addUnsizedArray(Info, Pointee);
+ Result.addUnsizedArray(Info, E, Pointee);
return true;
}
@@ -5669,7 +5738,8 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
return true;
}
}
- case CK_ArrayToPointerDecay:
+
+ case CK_ArrayToPointerDecay: {
if (SubExpr->isGLValue()) {
if (!evaluateLValue(SubExpr, Result))
return false;
@@ -5680,12 +5750,13 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
return false;
}
// The result is a pointer to the first element of the array.
- if (const ConstantArrayType *CAT
- = Info.Ctx.getAsConstantArrayType(SubExpr->getType()))
+ auto *AT = Info.Ctx.getAsArrayType(SubExpr->getType());
+ if (auto *CAT = dyn_cast<ConstantArrayType>(AT))
Result.addArray(Info, E, CAT);
else
- Result.Designator.setInvalid();
+ Result.addUnsizedArray(Info, E, AT->getElementType());
return true;
+ }
case CK_FunctionToPointerDecay:
return evaluateLValue(SubExpr, Result);
@@ -5752,7 +5823,7 @@ bool PointerExprEvaluator::visitNonBuiltinCallExpr(const CallExpr *E) {
Result.setInvalid(E);
QualType PointeeTy = E->getType()->castAs<PointerType>()->getPointeeType();
- Result.addUnsizedArray(Info, PointeeTy);
+ Result.addUnsizedArray(Info, E, PointeeTy);
return true;
}
@@ -7313,7 +7384,8 @@ static const Expr *ignorePointerCastsAndParens(const Expr *E) {
/// Please note: this function is specialized for how __builtin_object_size
/// views "objects".
///
-/// If this encounters an invalid RecordDecl, it will always return true.
+/// If this encounters an invalid RecordDecl or otherwise cannot determine the
+/// correct result, it will always return true.
static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) {
assert(!LVal.Designator.Invalid);
@@ -7344,9 +7416,8 @@ static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) {
unsigned I = 0;
QualType BaseType = getType(Base);
if (LVal.Designator.FirstEntryIsAnUnsizedArray) {
- assert(isBaseAnAllocSizeCall(Base) &&
- "Unsized array in non-alloc_size call?");
- // If this is an alloc_size base, we should ignore the initial array index
+ // If we don't know the array bound, conservatively assume we're looking at
+ // the final array element.
++I;
BaseType = BaseType->castAs<PointerType>()->getPointeeType();
}
@@ -7901,6 +7972,9 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
return BuiltinOp == Builtin::BI__atomic_always_lock_free ?
Success(0, E) : Error(E);
}
+ case Builtin::BIomp_is_initial_device:
+ // We can decide statically which value the runtime would return if called.
+ return Success(Info.getLangOpts().OpenMPIsDevice ? 0 : 1, E);
}
}
@@ -10397,6 +10471,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case BO_AndAssign:
case BO_XorAssign:
case BO_OrAssign:
+ case BO_Cmp: // FIXME: Re-enable once we can evaluate this.
// C99 6.6/3 allows assignments within unevaluated subexpressions of
// constant expressions, but they can never be ICEs because an ICE cannot
// contain an lvalue operand.
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprObjC.cpp b/contrib/llvm/tools/clang/lib/AST/ExprObjC.cpp
index 31c1b3f156217..e1a23f5985892 100644
--- a/contrib/llvm/tools/clang/lib/AST/ExprObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ExprObjC.cpp
@@ -1,4 +1,4 @@
-//===--- ExprObjC.cpp - (ObjC) Expression AST Node Implementation ---------===//
+//===- ExprObjC.cpp - (ObjC) Expression AST Node Implementation -----------===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,8 +12,15 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/ExprObjC.h"
-
#include "clang/AST/ASTContext.h"
+#include "clang/AST/SelectorLocationsKind.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
using namespace clang;
@@ -45,7 +52,6 @@ ObjCArrayLiteral *ObjCArrayLiteral::Create(const ASTContext &C,
ObjCArrayLiteral *ObjCArrayLiteral::CreateEmpty(const ASTContext &C,
unsigned NumElements) {
-
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(NumElements));
return new (Mem) ObjCArrayLiteral(EmptyShell(), NumElements);
}
diff --git a/contrib/llvm/tools/clang/lib/AST/ExternalASTMerger.cpp b/contrib/llvm/tools/clang/lib/AST/ExternalASTMerger.cpp
index 4f4a99794c5b0..6b75c51c6420f 100644
--- a/contrib/llvm/tools/clang/lib/AST/ExternalASTMerger.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ExternalASTMerger.cpp
@@ -14,6 +14,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ExternalASTMerger.h"
@@ -32,26 +33,18 @@ template <typename T> struct Source {
typedef std::pair<Source<NamedDecl *>, ASTImporter *> Candidate;
-class LazyASTImporter : public ASTImporter {
-public:
- LazyASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
- ASTContext &FromContext, FileManager &FromFileManager)
- : ASTImporter(ToContext, ToFileManager, FromContext, FromFileManager,
- /*MinimalImport=*/true) {}
- Decl *Imported(Decl *From, Decl *To) override {
- if (auto ToTag = dyn_cast<TagDecl>(To)) {
- ToTag->setHasExternalLexicalStorage();
- ToTag->setMustBuildLookupTable();
- } else if (auto ToNamespace = dyn_cast<NamespaceDecl>(To)) {
- ToNamespace->setHasExternalVisibleStorage();
- }
- return ASTImporter::Imported(From, To);
- }
-};
+/// For the given DC, return the DC that is safe to perform lookups on. This is
+/// the DC we actually want to work with most of the time.
+const DeclContext *CanonicalizeDC(const DeclContext *DC) {
+ if (isa<LinkageSpecDecl>(DC))
+ return DC->getRedeclContext();
+ return DC;
+}
Source<const DeclContext *>
LookupSameContext(Source<TranslationUnitDecl *> SourceTU, const DeclContext *DC,
ASTImporter &ReverseImporter) {
+ DC = CanonicalizeDC(DC);
if (DC->isTranslationUnit()) {
return SourceTU;
}
@@ -61,100 +54,328 @@ LookupSameContext(Source<TranslationUnitDecl *> SourceTU, const DeclContext *DC,
// If we couldn't find the parent DC in this TranslationUnit, give up.
return nullptr;
}
- auto ND = cast<NamedDecl>(DC);
+ auto *ND = cast<NamedDecl>(DC);
DeclarationName Name = ND->getDeclName();
Source<DeclarationName> SourceName = ReverseImporter.Import(Name);
DeclContext::lookup_result SearchResult =
SourceParentDC.get()->lookup(SourceName.get());
size_t SearchResultSize = SearchResult.size();
- // Handle multiple candidates once we have a test for it.
- // This may turn up when we import template specializations correctly.
- assert(SearchResultSize < 2);
- if (SearchResultSize == 0) {
- // couldn't find the name, so we have to give up
+ if (SearchResultSize == 0 || SearchResultSize > 1) {
+ // There are two cases here. First, we might not find the name.
+ // We might also find multiple copies, in which case we have no
+ // guarantee that the one we wanted is the one we pick. (E.g.,
+ // if we have two specializations of the same template it is
+ // very hard to determine which is the one you want.)
+ //
+ // The Origins map fixes this problem by allowing the origin to be
+ // explicitly recorded, so we trigger that recording by returning
+ // nothing (rather than a possibly-inaccurate guess) here.
return nullptr;
} else {
NamedDecl *SearchResultDecl = SearchResult[0];
- return dyn_cast<DeclContext>(SearchResultDecl);
+ if (isa<DeclContext>(SearchResultDecl) &&
+ SearchResultDecl->getKind() == DC->getDeclKind())
+ return cast<DeclContext>(SearchResultDecl)->getPrimaryContext();
+ return nullptr; // This type of lookup is unsupported
}
}
-bool IsForwardDeclaration(Decl *D) {
- assert(!isa<ObjCInterfaceDecl>(D)); // TODO handle this case
- if (auto TD = dyn_cast<TagDecl>(D)) {
- return !TD->isThisDeclarationADefinition();
- } else if (auto FD = dyn_cast<FunctionDecl>(D)) {
- return !FD->isThisDeclarationADefinition();
- } else {
- return false;
- }
-}
+/// A custom implementation of ASTImporter, for ExternalASTMerger's purposes.
+///
+/// There are several modifications:
+///
+/// - It enables lazy lookup (via the HasExternalLexicalStorage flag and a few
+/// others), which instructs Clang to refer to ExternalASTMerger. Also, it
+/// forces MinimalImport to true, which is necessary to make this work.
+/// - It maintains a reverse importer for use with names. This allows lookup of
+/// arbitrary names in the source context.
+/// - It updates the ExternalASTMerger's origin map as needed whenever a
+/// it sees a DeclContext.
+class LazyASTImporter : public ASTImporter {
+private:
+ ExternalASTMerger &Parent;
+ ASTImporter Reverse;
+ const ExternalASTMerger::OriginMap &FromOrigins;
-template <typename CallbackType>
-void ForEachMatchingDC(
- const DeclContext *DC,
- llvm::ArrayRef<ExternalASTMerger::ImporterPair> Importers,
- CallbackType Callback) {
- for (const ExternalASTMerger::ImporterPair &IP : Importers) {
- Source<TranslationUnitDecl *> SourceTU =
- IP.Forward->getFromContext().getTranslationUnitDecl();
- if (auto SourceDC = LookupSameContext(SourceTU, DC, *IP.Reverse))
- Callback(IP, SourceDC);
+ llvm::raw_ostream &logs() { return Parent.logs(); }
+public:
+ LazyASTImporter(ExternalASTMerger &_Parent, ASTContext &ToContext,
+ FileManager &ToFileManager, ASTContext &FromContext,
+ FileManager &FromFileManager,
+ const ExternalASTMerger::OriginMap &_FromOrigins)
+ : ASTImporter(ToContext, ToFileManager, FromContext, FromFileManager,
+ /*MinimalImport=*/true),
+ Parent(_Parent), Reverse(FromContext, FromFileManager, ToContext,
+ ToFileManager, /*MinimalImport=*/true), FromOrigins(_FromOrigins) {}
+
+ /// Whenever a DeclContext is imported, ensure that ExternalASTSource's origin
+ /// map is kept up to date. Also set the appropriate flags.
+ Decl *Imported(Decl *From, Decl *To) override {
+ if (auto *ToDC = dyn_cast<DeclContext>(To)) {
+ const bool LoggingEnabled = Parent.LoggingEnabled();
+ if (LoggingEnabled)
+ logs() << "(ExternalASTMerger*)" << (void*)&Parent
+ << " imported (DeclContext*)" << (void*)ToDC
+ << ", (ASTContext*)" << (void*)&getToContext()
+ << " from (DeclContext*)" << (void*)llvm::cast<DeclContext>(From)
+ << ", (ASTContext*)" << (void*)&getFromContext()
+ << "\n";
+ Source<DeclContext *> FromDC(
+ cast<DeclContext>(From)->getPrimaryContext());
+ if (FromOrigins.count(FromDC) &&
+ Parent.HasImporterForOrigin(*FromOrigins.at(FromDC).AST)) {
+ if (LoggingEnabled)
+ logs() << "(ExternalASTMerger*)" << (void*)&Parent
+ << " forced origin (DeclContext*)"
+ << (void*)FromOrigins.at(FromDC).DC
+ << ", (ASTContext*)"
+ << (void*)FromOrigins.at(FromDC).AST
+ << "\n";
+ Parent.ForceRecordOrigin(ToDC, FromOrigins.at(FromDC));
+ } else {
+ if (LoggingEnabled)
+ logs() << "(ExternalASTMerger*)" << (void*)&Parent
+ << " maybe recording origin (DeclContext*)" << (void*)FromDC
+ << ", (ASTContext*)" << (void*)&getFromContext()
+ << "\n";
+ Parent.MaybeRecordOrigin(ToDC, {FromDC, &getFromContext()});
+ }
+ }
+ if (auto *ToTag = dyn_cast<TagDecl>(To)) {
+ ToTag->setHasExternalLexicalStorage();
+ ToTag->setMustBuildLookupTable();
+ assert(Parent.CanComplete(ToTag));
+ } else if (auto *ToNamespace = dyn_cast<NamespaceDecl>(To)) {
+ ToNamespace->setHasExternalVisibleStorage();
+ assert(Parent.CanComplete(ToNamespace));
+ } else if (auto *ToContainer = dyn_cast<ObjCContainerDecl>(To)) {
+ ToContainer->setHasExternalLexicalStorage();
+ ToContainer->setMustBuildLookupTable();
+ assert(Parent.CanComplete(ToContainer));
+ }
+ return ASTImporter::Imported(From, To);
}
-}
+ ASTImporter &GetReverse() { return Reverse; }
+};
bool HasDeclOfSameType(llvm::ArrayRef<Candidate> Decls, const Candidate &C) {
+ if (isa<FunctionDecl>(C.first.get()))
+ return false;
return llvm::any_of(Decls, [&](const Candidate &D) {
return C.first.get()->getKind() == D.first.get()->getKind();
});
}
+
} // end namespace
-ExternalASTMerger::ExternalASTMerger(const ImporterEndpoint &Target,
- llvm::ArrayRef<ImporterEndpoint> Sources) {
- for (const ImporterEndpoint &S : Sources) {
- Importers.push_back(
- {llvm::make_unique<LazyASTImporter>(Target.AST, Target.FM, S.AST, S.FM),
- llvm::make_unique<ASTImporter>(S.AST, S.FM, Target.AST, Target.FM,
- /*MinimalImport=*/true)});
- }
+ASTImporter &ExternalASTMerger::ImporterForOrigin(ASTContext &OriginContext) {
+ for (const std::unique_ptr<ASTImporter> &I : Importers)
+ if (&I->getFromContext() == &OriginContext)
+ return *I;
+ llvm_unreachable("We should have an importer for this origin!");
}
-bool ExternalASTMerger::FindExternalVisibleDeclsByName(const DeclContext *DC,
- DeclarationName Name) {
- llvm::SmallVector<NamedDecl *, 1> Decls;
- llvm::SmallVector<Candidate, 4> CompleteDecls;
- llvm::SmallVector<Candidate, 4> ForwardDecls;
+namespace {
+LazyASTImporter &LazyImporterForOrigin(ExternalASTMerger &Merger,
+ ASTContext &OriginContext) {
+ return static_cast<LazyASTImporter &>(
+ Merger.ImporterForOrigin(OriginContext));
+}
+}
- auto FilterFoundDecl = [&CompleteDecls, &ForwardDecls](const Candidate &C) {
- if (IsForwardDeclaration(C.first.get())) {
- if (!HasDeclOfSameType(ForwardDecls, C)) {
- ForwardDecls.push_back(C);
+bool ExternalASTMerger::HasImporterForOrigin(ASTContext &OriginContext) {
+ for (const std::unique_ptr<ASTImporter> &I : Importers)
+ if (&I->getFromContext() == &OriginContext)
+ return true;
+ return false;
+}
+
+template <typename CallbackType>
+void ExternalASTMerger::ForEachMatchingDC(const DeclContext *DC,
+ CallbackType Callback) {
+ if (Origins.count(DC)) {
+ ExternalASTMerger::DCOrigin Origin = Origins[DC];
+ LazyASTImporter &Importer = LazyImporterForOrigin(*this, *Origin.AST);
+ Callback(Importer, Importer.GetReverse(), Origin.DC);
+ } else {
+ bool DidCallback = false;
+ for (const std::unique_ptr<ASTImporter> &Importer : Importers) {
+ Source<TranslationUnitDecl *> SourceTU =
+ Importer->getFromContext().getTranslationUnitDecl();
+ ASTImporter &Reverse =
+ static_cast<LazyASTImporter *>(Importer.get())->GetReverse();
+ if (auto SourceDC = LookupSameContext(SourceTU, DC, Reverse)) {
+ DidCallback = true;
+ if (Callback(*Importer, Reverse, SourceDC))
+ break;
}
- } else {
- CompleteDecls.push_back(C);
}
- };
+ if (!DidCallback && LoggingEnabled())
+ logs() << "(ExternalASTMerger*)" << (void*)this
+ << " asserting for (DeclContext*)" << (const void*)DC
+ << ", (ASTContext*)" << (void*)&Target.AST
+ << "\n";
+ assert(DidCallback && "Couldn't find a source context matching our DC");
+ }
+}
+
+void ExternalASTMerger::CompleteType(TagDecl *Tag) {
+ assert(Tag->hasExternalLexicalStorage());
+ ForEachMatchingDC(Tag, [&](ASTImporter &Forward, ASTImporter &Reverse,
+ Source<const DeclContext *> SourceDC) -> bool {
+ auto *SourceTag = const_cast<TagDecl *>(cast<TagDecl>(SourceDC.get()));
+ if (SourceTag->hasExternalLexicalStorage())
+ SourceTag->getASTContext().getExternalSource()->CompleteType(SourceTag);
+ if (!SourceTag->getDefinition())
+ return false;
+ Forward.Imported(SourceTag, Tag);
+ Forward.ImportDefinition(SourceTag);
+ Tag->setCompleteDefinition(SourceTag->isCompleteDefinition());
+ return true;
+ });
+}
+void ExternalASTMerger::CompleteType(ObjCInterfaceDecl *Interface) {
+ assert(Interface->hasExternalLexicalStorage());
ForEachMatchingDC(
- DC, Importers,
- [&](const ImporterPair &IP, Source<const DeclContext *> SourceDC) {
- DeclarationName FromName = IP.Reverse->Import(Name);
- DeclContextLookupResult Result = SourceDC.get()->lookup(FromName);
- for (NamedDecl *FromD : Result) {
- FilterFoundDecl(std::make_pair(FromD, IP.Forward.get()));
- }
+ Interface, [&](ASTImporter &Forward, ASTImporter &Reverse,
+ Source<const DeclContext *> SourceDC) -> bool {
+ auto *SourceInterface = const_cast<ObjCInterfaceDecl *>(
+ cast<ObjCInterfaceDecl>(SourceDC.get()));
+ if (SourceInterface->hasExternalLexicalStorage())
+ SourceInterface->getASTContext().getExternalSource()->CompleteType(
+ SourceInterface);
+ if (!SourceInterface->getDefinition())
+ return false;
+ Forward.Imported(SourceInterface, Interface);
+ Forward.ImportDefinition(SourceInterface);
+ return true;
});
+}
- llvm::ArrayRef<Candidate> DeclsToReport =
- CompleteDecls.empty() ? ForwardDecls : CompleteDecls;
+bool ExternalASTMerger::CanComplete(DeclContext *Interface) {
+ assert(Interface->hasExternalLexicalStorage() ||
+ Interface->hasExternalVisibleStorage());
+ bool FoundMatchingDC = false;
+ ForEachMatchingDC(Interface,
+ [&](ASTImporter &Forward, ASTImporter &Reverse,
+ Source<const DeclContext *> SourceDC) -> bool {
+ FoundMatchingDC = true;
+ return true;
+ });
+ return FoundMatchingDC;
+}
- if (DeclsToReport.empty()) {
- return false;
+namespace {
+bool IsSameDC(const DeclContext *D1, const DeclContext *D2) {
+ if (isa<ObjCContainerDecl>(D1) && isa<ObjCContainerDecl>(D2))
+ return true; // There are many cases where Objective-C is ambiguous.
+ if (auto *T1 = dyn_cast<TagDecl>(D1))
+ if (auto *T2 = dyn_cast<TagDecl>(D2))
+ if (T1->getFirstDecl() == T2->getFirstDecl())
+ return true;
+ return D1 == D2 || D1 == CanonicalizeDC(D2);
+}
+}
+
+void ExternalASTMerger::MaybeRecordOrigin(const DeclContext *ToDC,
+ DCOrigin Origin) {
+ LazyASTImporter &Importer = LazyImporterForOrigin(*this, *Origin.AST);
+ ASTImporter &Reverse = Importer.GetReverse();
+ Source<const DeclContext *> FoundFromDC =
+ LookupSameContext(Origin.AST->getTranslationUnitDecl(), ToDC, Reverse);
+ const bool DoRecord = !FoundFromDC || !IsSameDC(FoundFromDC.get(), Origin.DC);
+ if (DoRecord)
+ RecordOriginImpl(ToDC, Origin, Importer);
+ if (LoggingEnabled())
+ logs() << "(ExternalASTMerger*)" << (void*)this
+ << (DoRecord ? " decided " : " decided NOT")
+ << " to record origin (DeclContext*)" << (void*)Origin.DC
+ << ", (ASTContext*)" << (void*)&Origin.AST
+ << "\n";
+}
+
+void ExternalASTMerger::ForceRecordOrigin(const DeclContext *ToDC,
+ DCOrigin Origin) {
+ RecordOriginImpl(ToDC, Origin, ImporterForOrigin(*Origin.AST));
+}
+
+void ExternalASTMerger::RecordOriginImpl(const DeclContext *ToDC, DCOrigin Origin,
+ ASTImporter &Importer) {
+ Origins[ToDC] = Origin;
+ Importer.ASTImporter::Imported(cast<Decl>(Origin.DC), const_cast<Decl*>(cast<Decl>(ToDC)));
+}
+
+ExternalASTMerger::ExternalASTMerger(const ImporterTarget &Target,
+ llvm::ArrayRef<ImporterSource> Sources) : LogStream(&llvm::nulls()), Target(Target) {
+ AddSources(Sources);
+}
+
+void ExternalASTMerger::AddSources(llvm::ArrayRef<ImporterSource> Sources) {
+ for (const ImporterSource &S : Sources) {
+ assert(&S.AST != &Target.AST);
+ Importers.push_back(llvm::make_unique<LazyASTImporter>(
+ *this, Target.AST, Target.FM, S.AST, S.FM, S.OM));
+ }
+}
+
+void ExternalASTMerger::RemoveSources(llvm::ArrayRef<ImporterSource> Sources) {
+ if (LoggingEnabled())
+ for (const ImporterSource &S : Sources)
+ logs() << "(ExternalASTMerger*)" << (void*)this
+ << " removing source (ASTContext*)" << (void*)&S.AST
+ << "\n";
+ Importers.erase(
+ std::remove_if(Importers.begin(), Importers.end(),
+ [&Sources](std::unique_ptr<ASTImporter> &Importer) -> bool {
+ for (const ImporterSource &S : Sources) {
+ if (&Importer->getFromContext() == &S.AST)
+ return true;
+ }
+ return false;
+ }),
+ Importers.end());
+ for (OriginMap::iterator OI = Origins.begin(), OE = Origins.end(); OI != OE; ) {
+ std::pair<const DeclContext *, DCOrigin> Origin = *OI;
+ bool Erase = false;
+ for (const ImporterSource &S : Sources) {
+ if (&S.AST == Origin.second.AST) {
+ Erase = true;
+ break;
+ }
+ }
+ if (Erase)
+ OI = Origins.erase(OI);
+ else
+ ++OI;
}
+}
+
+bool ExternalASTMerger::FindExternalVisibleDeclsByName(const DeclContext *DC,
+ DeclarationName Name) {
+ llvm::SmallVector<NamedDecl *, 1> Decls;
+ llvm::SmallVector<Candidate, 4> Candidates;
+
+ auto FilterFoundDecl = [&Candidates](const Candidate &C) {
+ if (!HasDeclOfSameType(Candidates, C))
+ Candidates.push_back(C);
+ };
+
+ ForEachMatchingDC(DC, [&](ASTImporter &Forward, ASTImporter &Reverse,
+ Source<const DeclContext *> SourceDC) -> bool {
+ DeclarationName FromName = Reverse.Import(Name);
+ DeclContextLookupResult Result = SourceDC.get()->lookup(FromName);
+ for (NamedDecl *FromD : Result) {
+ FilterFoundDecl(std::make_pair(FromD, &Forward));
+ }
+ return false;
+ });
- Decls.reserve(DeclsToReport.size());
- for (const Candidate &C : DeclsToReport) {
+ if (Candidates.empty())
+ return false;
+
+ Decls.reserve(Candidates.size());
+ for (const Candidate &C : Candidates) {
NamedDecl *d = cast<NamedDecl>(C.second->Import(C.first.get()));
assert(d);
Decls.push_back(d);
@@ -166,17 +387,16 @@ bool ExternalASTMerger::FindExternalVisibleDeclsByName(const DeclContext *DC,
void ExternalASTMerger::FindExternalLexicalDecls(
const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
SmallVectorImpl<Decl *> &Result) {
- ForEachMatchingDC(
- DC, Importers,
- [&](const ImporterPair &IP, Source<const DeclContext *> SourceDC) {
- for (const Decl *SourceDecl : SourceDC.get()->decls()) {
- if (IsKindWeWant(SourceDecl->getKind())) {
- Decl *ImportedDecl =
- IP.Forward->Import(const_cast<Decl *>(SourceDecl));
- assert(ImportedDecl->getDeclContext() == DC);
- (void)ImportedDecl;
- }
- }
- });
+ ForEachMatchingDC(DC, [&](ASTImporter &Forward, ASTImporter &Reverse,
+ Source<const DeclContext *> SourceDC) -> bool {
+ for (const Decl *SourceDecl : SourceDC.get()->decls()) {
+ if (IsKindWeWant(SourceDecl->getKind())) {
+ Decl *ImportedDecl = Forward.Import(const_cast<Decl *>(SourceDecl));
+ assert(!ImportedDecl || IsSameDC(ImportedDecl->getDeclContext(), DC));
+ (void)ImportedDecl;
+ }
+ }
+ return false;
+ });
}
diff --git a/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp b/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp
index 182d38242f596..198ba9d4fbdba 100644
--- a/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp
@@ -1,4 +1,4 @@
-//===- ExternalASTSource.cpp - Abstract External AST Interface --*- C++ -*-===//
+//===- ExternalASTSource.cpp - Abstract External AST Interface ------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,12 +16,16 @@
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclarationName.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/Module.h"
+#include "llvm/ADT/None.h"
#include "llvm/Support/ErrorHandling.h"
+#include <cstdint>
using namespace clang;
-ExternalASTSource::~ExternalASTSource() { }
+ExternalASTSource::~ExternalASTSource() = default;
llvm::Optional<ExternalASTSource::ASTSourceDescriptor>
ExternalASTSource::getSourceDescriptor(unsigned ID) {
@@ -66,7 +70,7 @@ void ExternalASTSource::FinishedDeserializing() {}
void ExternalASTSource::StartTranslationUnit(ASTConsumer *Consumer) {}
-void ExternalASTSource::PrintStats() { }
+void ExternalASTSource::PrintStats() {}
bool ExternalASTSource::layoutRecordType(
const RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,
diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp
index 692a455eafc08..d6bc16b6350fc 100644
--- a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp
@@ -101,15 +101,17 @@ protected:
public:
ItaniumCXXABI(ASTContext &Ctx) : Context(Ctx) { }
- std::pair<uint64_t, unsigned>
- getMemberPointerWidthAndAlign(const MemberPointerType *MPT) const override {
+ MemberPointerInfo
+ getMemberPointerInfo(const MemberPointerType *MPT) const override {
const TargetInfo &Target = Context.getTargetInfo();
TargetInfo::IntType PtrDiff = Target.getPtrDiffType(0);
- uint64_t Width = Target.getTypeWidth(PtrDiff);
- unsigned Align = Target.getTypeAlign(PtrDiff);
+ MemberPointerInfo MPI;
+ MPI.Width = Target.getTypeWidth(PtrDiff);
+ MPI.Align = Target.getTypeAlign(PtrDiff);
+ MPI.HasPadding = false;
if (MPT->isMemberFunctionPointer())
- Width = 2 * Width;
- return std::make_pair(Width, Align);
+ MPI.Width *= 2;
+ return MPI;
}
CallingConv getDefaultMethodCallConv(bool isVariadic) const override {
diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp
index 4e7c6c4edf370..f95dc8458e8a8 100644
--- a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp
@@ -11,7 +11,7 @@
// which is used in GCC 3.2 and newer (and many compilers that are
// ABI-compatible with GCC):
//
-// http://mentorembedded.github.io/cxx-abi/abi.html#mangling
+// http://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling
//
//===----------------------------------------------------------------------===//
#include "clang/AST/Mangle.h"
@@ -381,6 +381,7 @@ class CXXNameMangler {
AbiTagState AbiTagsRoot;
llvm::DenseMap<uintptr_t, unsigned> Substitutions;
+ llvm::DenseMap<StringRef, unsigned> ModuleSubstitutions;
ASTContext &getASTContext() const { return Context.getASTContext(); }
@@ -475,6 +476,8 @@ private:
void mangleNameWithAbiTags(const NamedDecl *ND,
const AbiTagList *AdditionalAbiTags);
+ void mangleModuleName(const Module *M);
+ void mangleModuleNamePrefix(StringRef Name);
void mangleTemplateName(const TemplateDecl *TD,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs);
@@ -517,7 +520,7 @@ private:
void mangleOperatorName(DeclarationName Name, unsigned Arity);
void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity);
void mangleVendorQualifier(StringRef qualifier);
- void mangleQualifiers(Qualifiers Quals);
+ void mangleQualifiers(Qualifiers Quals, const DependentAddressSpaceType *DAST = nullptr);
void mangleRefQualifier(RefQualifierKind RefQualifier);
void mangleObjCMethodName(const ObjCMethodDecl *MD);
@@ -845,9 +848,9 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) {
void CXXNameMangler::mangleNameWithAbiTags(const NamedDecl *ND,
const AbiTagList *AdditionalAbiTags) {
- // <name> ::= <nested-name>
- // ::= <unscoped-name>
- // ::= <unscoped-template-name> <template-args>
+ // <name> ::= [<module-name>] <nested-name>
+ // ::= [<module-name>] <unscoped-name>
+ // ::= [<module-name>] <unscoped-template-name> <template-args>
// ::= <local-name>
//
const DeclContext *DC = getEffectiveDeclContext(ND);
@@ -866,6 +869,19 @@ void CXXNameMangler::mangleNameWithAbiTags(const NamedDecl *ND,
DC = IgnoreLinkageSpecDecls(DC);
+ if (isLocalContainerContext(DC)) {
+ mangleLocalName(ND, AdditionalAbiTags);
+ return;
+ }
+
+ // Do not mangle the owning module for an external linkage declaration.
+ // This enables backwards-compatibility with non-modular code, and is
+ // a valid choice since conflicts are not permitted by C++ Modules TS
+ // [basic.def.odr]/6.2.
+ if (!ND->hasExternalFormalLinkage())
+ if (Module *M = ND->getOwningModuleForLinkage())
+ mangleModuleName(M);
+
if (DC->isTranslationUnit() || isStdNamespace(DC)) {
// Check if we have a template.
const TemplateArgumentList *TemplateArgs = nullptr;
@@ -879,12 +895,42 @@ void CXXNameMangler::mangleNameWithAbiTags(const NamedDecl *ND,
return;
}
- if (isLocalContainerContext(DC)) {
- mangleLocalName(ND, AdditionalAbiTags);
+ mangleNestedName(ND, DC, AdditionalAbiTags);
+}
+
+void CXXNameMangler::mangleModuleName(const Module *M) {
+ // Implement the C++ Modules TS name mangling proposal; see
+ // https://gcc.gnu.org/wiki/cxx-modules?action=AttachFile
+ //
+ // <module-name> ::= W <unscoped-name>+ E
+ // ::= W <module-subst> <unscoped-name>* E
+ Out << 'W';
+ mangleModuleNamePrefix(M->Name);
+ Out << 'E';
+}
+
+void CXXNameMangler::mangleModuleNamePrefix(StringRef Name) {
+ // <module-subst> ::= _ <seq-id> # 0 < seq-id < 10
+ // ::= W <seq-id - 10> _ # otherwise
+ auto It = ModuleSubstitutions.find(Name);
+ if (It != ModuleSubstitutions.end()) {
+ if (It->second < 10)
+ Out << '_' << static_cast<char>('0' + It->second);
+ else
+ Out << 'W' << (It->second - 10) << '_';
return;
}
- mangleNestedName(ND, DC, AdditionalAbiTags);
+ // FIXME: Preserve hierarchy in module names rather than flattening
+ // them to strings; use Module*s as substitution keys.
+ auto Parts = Name.rsplit('.');
+ if (Parts.second.empty())
+ Parts.second = Parts.first;
+ else
+ mangleModuleNamePrefix(Parts.first);
+
+ Out << Parts.second.size() << Parts.second;
+ ModuleSubstitutions.insert({Name, ModuleSubstitutions.size()});
}
void CXXNameMangler::mangleTemplateName(const TemplateDecl *TD,
@@ -1233,14 +1279,23 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
}
if (II) {
- // We must avoid conflicts between internally- and externally-
- // linked variable and function declaration names in the same TU:
+ // Match GCC's naming convention for internal linkage symbols, for
+ // symbols that are not actually visible outside of this TU. GCC
+ // distinguishes between internal and external linkage symbols in
+ // its mangling, to support cases like this that were valid C++ prior
+ // to DR426:
+ //
// void test() { extern void foo(); }
// static void foo();
- // This naming convention is the same as that followed by GCC,
- // though it shouldn't actually matter.
+ //
+ // Don't bother with the L marker for names in anonymous namespaces; the
+ // 12_GLOBAL__N_1 mangling is quite sufficient there, and this better
+ // matches GCC anyway, because GCC does not treat anonymous namespaces as
+ // implying internal linkage.
if (ND && ND->getFormalLinkage() == InternalLinkage &&
- getEffectiveDeclContext(ND)->isFileContext())
+ !ND->isExternallyVisible() &&
+ getEffectiveDeclContext(ND)->isFileContext() &&
+ !ND->isInAnonymousNamespace())
Out << 'L';
auto *FD = dyn_cast<FunctionDecl>(ND);
@@ -1620,6 +1675,10 @@ void CXXNameMangler::mangleUnqualifiedBlock(const BlockDecl *Block) {
// the symbol in question isn't externally visible.
if (!Number)
Number = Context.getBlockId(Block, false);
+ else {
+ // Stored mangling numbers are 1-based.
+ --Number;
+ }
Out << "Ub";
if (Number > 0)
Out << Number - 1;
@@ -1638,10 +1697,15 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) {
// to emit that last part of the prefix here.
if (Decl *Context = Lambda->getLambdaContextDecl()) {
if ((isa<VarDecl>(Context) || isa<FieldDecl>(Context)) &&
- Context->getDeclContext()->isRecord()) {
+ !isa<ParmVarDecl>(Context)) {
+ // FIXME: 'inline auto [a, b] = []{ return ... };' does not get a
+ // reasonable mangling here.
if (const IdentifierInfo *Name
= cast<NamedDecl>(Context)->getIdentifier()) {
mangleSourceName(Name);
+ const TemplateArgumentList *TemplateArgs = nullptr;
+ if (isTemplate(cast<NamedDecl>(Context), TemplateArgs))
+ mangleTemplateArgs(*TemplateArgs);
Out << 'M';
}
}
@@ -1866,6 +1930,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
case Type::IncompleteArray:
case Type::VariableArray:
case Type::DependentSizedArray:
+ case Type::DependentAddressSpace:
case Type::DependentSizedExtVector:
case Type::Vector:
case Type::ExtVector:
@@ -2130,6 +2195,9 @@ CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) {
// Proposal on cxx-abi-dev, 2015-10-21.
// ::= aw # co_await
case OO_Coawait: Out << "aw"; break;
+ // Proposed in cxx-abi github issue 43.
+ // ::= ss # <=>
+ case OO_Spaceship: Out << "ss"; break;
case OO_None:
case NUM_OVERLOADED_OPERATORS:
@@ -2137,10 +2205,17 @@ CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) {
}
}
-void CXXNameMangler::mangleQualifiers(Qualifiers Quals) {
+void CXXNameMangler::mangleQualifiers(Qualifiers Quals, const DependentAddressSpaceType *DAST) {
// Vendor qualifiers come first and if they are order-insensitive they must
// be emitted in reversed alphabetical order, see Itanium ABI 5.1.5.
+ // <type> ::= U <addrspace-expr>
+ if (DAST) {
+ Out << "U2ASI";
+ mangleExpression(DAST->getAddrSpaceExpr());
+ Out << "E";
+ }
+
// Address space qualifiers start with an ordinary letter.
if (Quals.hasAddressSpace()) {
// Address space extension:
@@ -2150,20 +2225,22 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals) {
// <type> ::= U <CUDA-addrspace>
SmallString<64> ASString;
- unsigned AS = Quals.getAddressSpace();
+ LangAS AS = Quals.getAddressSpace();
if (Context.getASTContext().addressSpaceMapManglingFor(AS)) {
// <target-addrspace> ::= "AS" <address-space-number>
unsigned TargetAS = Context.getASTContext().getTargetAddressSpace(AS);
- ASString = "AS" + llvm::utostr(TargetAS);
+ if (TargetAS != 0)
+ ASString = "AS" + llvm::utostr(TargetAS);
} else {
switch (AS) {
default: llvm_unreachable("Not a language specific address space");
- // <OpenCL-addrspace> ::= "CL" [ "global" | "local" | "constant |
- // "generic" ]
+ // <OpenCL-addrspace> ::= "CL" [ "global" | "local" | "constant" |
+ // "private"| "generic" ]
case LangAS::opencl_global: ASString = "CLglobal"; break;
case LangAS::opencl_local: ASString = "CLlocal"; break;
case LangAS::opencl_constant: ASString = "CLconstant"; break;
+ case LangAS::opencl_private: ASString = "CLprivate"; break;
case LangAS::opencl_generic: ASString = "CLgeneric"; break;
// <CUDA-addrspace> ::= "CU" [ "device" | "constant" | "shared" ]
case LangAS::cuda_device: ASString = "CUdevice"; break;
@@ -2171,7 +2248,8 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals) {
case LangAS::cuda_shared: ASString = "CUshared"; break;
}
}
- mangleVendorQualifier(ASString);
+ if (!ASString.empty())
+ mangleVendorQualifier(ASString);
}
// The ARC ownership qualifiers start with underscores.
@@ -2336,11 +2414,19 @@ void CXXNameMangler::mangleType(QualType T) {
// substitution at the original type.
}
- if (quals) {
- mangleQualifiers(quals);
- // Recurse: even if the qualified type isn't yet substitutable,
- // the unqualified type might be.
- mangleType(QualType(ty, 0));
+ if (quals || ty->isDependentAddressSpaceType()) {
+ if (const DependentAddressSpaceType *DAST =
+ dyn_cast<DependentAddressSpaceType>(ty)) {
+ SplitQualType splitDAST = DAST->getPointeeType().split();
+ mangleQualifiers(splitDAST.Quals, DAST);
+ mangleType(QualType(splitDAST.Ty, 0));
+ } else {
+ mangleQualifiers(quals);
+
+ // Recurse: even if the qualified type isn't yet substitutable,
+ // the unqualified type might be.
+ mangleType(QualType(ty, 0));
+ }
} else {
switch (ty->getTypeClass()) {
#define ABSTRACT_TYPE(CLASS, PARENT)
@@ -2392,6 +2478,7 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
// UNSUPPORTED: ::= De # IEEE 754r decimal floating point (128 bits)
// UNSUPPORTED: ::= Df # IEEE 754r decimal floating point (32 bits)
// ::= Dh # IEEE 754r half-precision floating point (16 bits)
+ // ::= DF <number> _ # ISO/IEC TS 18661 binary floating point type _FloatN (N bits);
// ::= Di # char32_t
// ::= Ds # char16_t
// ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
@@ -2454,6 +2541,9 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
case BuiltinType::Int128:
Out << 'n';
break;
+ case BuiltinType::Float16:
+ Out << "DF16_";
+ break;
case BuiltinType::Half:
Out << "Dh";
break;
@@ -2586,6 +2676,9 @@ CXXNameMangler::mangleExtParameterInfo(FunctionProtoType::ExtParameterInfo PI) {
if (PI.isConsumed())
mangleVendorQualifier("ns_consumed");
+
+ if (PI.isNoEscape())
+ mangleVendorQualifier("noescape");
}
// <type> ::= <function-type>
@@ -2981,6 +3074,12 @@ void CXXNameMangler::mangleType(const DependentSizedExtVectorType *T) {
mangleType(T->getElementType());
}
+void CXXNameMangler::mangleType(const DependentAddressSpaceType *T) {
+ SplitQualType split = T->getPointeeType().split();
+ mangleQualifiers(split.Quals, T);
+ mangleType(QualType(split.Ty, 0));
+}
+
void CXXNameMangler::mangleType(const PackExpansionType *T) {
// <type> ::= Dp <type> # pack expansion (C++0x)
Out << "Dp";
@@ -3343,7 +3442,6 @@ recurse:
case Expr::BlockExprClass:
case Expr::ChooseExprClass:
case Expr::CompoundLiteralExprClass:
- case Expr::DesignatedInitExprClass:
case Expr::ExtVectorElementExprClass:
case Expr::GenericSelectionExprClass:
case Expr::ObjCEncodeExprClass:
@@ -3421,6 +3519,27 @@ recurse:
break;
}
+ case Expr::DesignatedInitExprClass: {
+ auto *DIE = cast<DesignatedInitExpr>(E);
+ for (const auto &Designator : DIE->designators()) {
+ if (Designator.isFieldDesignator()) {
+ Out << "di";
+ mangleSourceName(Designator.getFieldName());
+ } else if (Designator.isArrayDesignator()) {
+ Out << "dx";
+ mangleExpression(DIE->getArrayIndex(Designator));
+ } else {
+ assert(Designator.isArrayRangeDesignator() &&
+ "unknown designator kind");
+ Out << "dX";
+ mangleExpression(DIE->getArrayRangeStart(Designator));
+ mangleExpression(DIE->getArrayRangeEnd(Designator));
+ }
+ }
+ mangleExpression(DIE->getInit());
+ break;
+ }
+
case Expr::CXXDefaultArgExprClass:
mangleExpression(cast<CXXDefaultArgExpr>(E)->getExpr(), Arity);
break;
@@ -3512,7 +3631,6 @@ recurse:
if (const Expr *Base = PDE->getBase())
mangleMemberExprBase(Base, PDE->isArrow());
NestedNameSpecifier *Qualifier = PDE->getQualifier();
- QualType ScopeType;
if (TypeSourceInfo *ScopeInfo = PDE->getScopeTypeInfo()) {
if (Qualifier) {
mangleUnresolvedPrefix(Qualifier,
@@ -3578,6 +3696,16 @@ recurse:
const CXXUnresolvedConstructExpr *CE = cast<CXXUnresolvedConstructExpr>(E);
unsigned N = CE->arg_size();
+ if (CE->isListInitialization()) {
+ assert(N == 1 && "unexpected form for list initialization");
+ auto *IL = cast<InitListExpr>(CE->getArg(0));
+ Out << "tl";
+ mangleType(CE->getType());
+ mangleInitListElements(IL);
+ Out << "E";
+ return;
+ }
+
Out << "cv";
mangleType(CE->getType());
if (N != 1) Out << '_';
@@ -4114,7 +4242,13 @@ void CXXNameMangler::mangleFunctionParam(const ParmVarDecl *parm) {
// get mangled if used as an rvalue of a known non-class type?
assert(!parm->getType()->isArrayType()
&& "parameter's type is still an array type?");
- mangleQualifiers(parm->getType().getQualifiers());
+
+ if (const DependentAddressSpaceType *DAST =
+ dyn_cast<DependentAddressSpaceType>(parm->getType())) {
+ mangleQualifiers(DAST->getPointeeType().getQualifiers(), DAST);
+ } else {
+ mangleQualifiers(parm->getType().getQualifiers());
+ }
// Parameter index.
if (parmIndex != 0) {
diff --git a/contrib/llvm/tools/clang/lib/AST/Linkage.h b/contrib/llvm/tools/clang/lib/AST/Linkage.h
new file mode 100644
index 0000000000000..e6489c7ef2b31
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/Linkage.h
@@ -0,0 +1,159 @@
+//===----- Linkage.h - Linkage calculation-related utilities ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides AST-internal utilities for linkage and visibility
+// calculation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_AST_LINKAGE_H
+#define LLVM_CLANG_LIB_AST_LINKAGE_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Type.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Optional.h"
+
+namespace clang {
+/// Kinds of LV computation. The linkage side of the computation is
+/// always the same, but different things can change how visibility is
+/// computed.
+struct LVComputationKind {
+ /// The kind of entity whose visibility is ultimately being computed;
+ /// visibility computations for types and non-types follow different rules.
+ unsigned ExplicitKind : 1;
+ /// Whether explicit visibility attributes should be ignored. When set,
+ /// visibility may only be restricted by the visibility of template arguments.
+ unsigned IgnoreExplicitVisibility : 1;
+ /// Whether all visibility should be ignored. When set, we're only interested
+ /// in computing linkage.
+ unsigned IgnoreAllVisibility : 1;
+
+ explicit LVComputationKind(NamedDecl::ExplicitVisibilityKind EK)
+ : ExplicitKind(EK), IgnoreExplicitVisibility(false),
+ IgnoreAllVisibility(false) {}
+
+ NamedDecl::ExplicitVisibilityKind getExplicitVisibilityKind() const {
+ return static_cast<NamedDecl::ExplicitVisibilityKind>(ExplicitKind);
+ }
+
+ bool isTypeVisibility() const {
+ return getExplicitVisibilityKind() == NamedDecl::VisibilityForType;
+ }
+ bool isValueVisibility() const {
+ return getExplicitVisibilityKind() == NamedDecl::VisibilityForValue;
+ }
+
+ /// Do an LV computation when we only care about the linkage.
+ static LVComputationKind forLinkageOnly() {
+ LVComputationKind Result(NamedDecl::VisibilityForValue);
+ Result.IgnoreExplicitVisibility = true;
+ Result.IgnoreAllVisibility = true;
+ return Result;
+ }
+
+ unsigned toBits() {
+ unsigned Bits = 0;
+ Bits = (Bits << 1) | ExplicitKind;
+ Bits = (Bits << 1) | IgnoreExplicitVisibility;
+ Bits = (Bits << 1) | IgnoreAllVisibility;
+ return Bits;
+ }
+};
+
+class LinkageComputer {
+ // We have a cache for repeated linkage/visibility computations. This saves us
+ // from exponential behavior in heavily templated code, such as:
+ //
+ // template <typename T, typename V> struct {};
+ // using A = int;
+ // using B = Foo<A, A>;
+ // using C = Foo<B, B>;
+ // using D = Foo<C, C>;
+ //
+ // The unsigned represents an LVComputationKind.
+ using QueryType = std::pair<const NamedDecl *, unsigned>;
+ llvm::SmallDenseMap<QueryType, LinkageInfo, 8> CachedLinkageInfo;
+
+ static QueryType makeCacheKey(const NamedDecl *ND, LVComputationKind Kind) {
+ return std::make_pair(ND, Kind.toBits());
+ }
+
+ llvm::Optional<LinkageInfo> lookup(const NamedDecl *ND,
+ LVComputationKind Kind) const {
+ auto Iter = CachedLinkageInfo.find(makeCacheKey(ND, Kind));
+ if (Iter == CachedLinkageInfo.end())
+ return None;
+ return Iter->second;
+ }
+
+ void cache(const NamedDecl *ND, LVComputationKind Kind, LinkageInfo Info) {
+ CachedLinkageInfo[makeCacheKey(ND, Kind)] = Info;
+ }
+
+ LinkageInfo getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args,
+ LVComputationKind computation);
+
+ LinkageInfo getLVForTemplateArgumentList(const TemplateArgumentList &TArgs,
+ LVComputationKind computation);
+
+ void mergeTemplateLV(LinkageInfo &LV, const FunctionDecl *fn,
+ const FunctionTemplateSpecializationInfo *specInfo,
+ LVComputationKind computation);
+
+ void mergeTemplateLV(LinkageInfo &LV,
+ const ClassTemplateSpecializationDecl *spec,
+ LVComputationKind computation);
+
+ void mergeTemplateLV(LinkageInfo &LV,
+ const VarTemplateSpecializationDecl *spec,
+ LVComputationKind computation);
+
+ LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
+ LVComputationKind computation,
+ bool IgnoreVarTypeLinkage);
+
+ LinkageInfo getLVForClassMember(const NamedDecl *D,
+ LVComputationKind computation,
+ bool IgnoreVarTypeLinkage);
+
+ LinkageInfo getLVForClosure(const DeclContext *DC, Decl *ContextDecl,
+ LVComputationKind computation);
+
+ LinkageInfo getLVForLocalDecl(const NamedDecl *D,
+ LVComputationKind computation);
+
+ LinkageInfo getLVForType(const Type &T, LVComputationKind computation);
+
+ LinkageInfo getLVForTemplateParameterList(const TemplateParameterList *Params,
+ LVComputationKind computation);
+
+public:
+ LinkageInfo computeLVForDecl(const NamedDecl *D,
+ LVComputationKind computation,
+ bool IgnoreVarTypeLinkage = false);
+
+ LinkageInfo getLVForDecl(const NamedDecl *D, LVComputationKind computation);
+
+ LinkageInfo computeTypeLinkageInfo(const Type *T);
+ LinkageInfo computeTypeLinkageInfo(QualType T) {
+ return computeTypeLinkageInfo(T.getTypePtr());
+ }
+
+ LinkageInfo getDeclLinkageAndVisibility(const NamedDecl *D);
+
+ LinkageInfo getTypeLinkageAndVisibility(const Type *T);
+ LinkageInfo getTypeLinkageAndVisibility(QualType T) {
+ return getTypeLinkageAndVisibility(T.getTypePtr());
+ }
+};
+} // namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/AST/Mangle.cpp b/contrib/llvm/tools/clang/lib/AST/Mangle.cpp
index 00d50c0e3bdf4..56a2500274a72 100644
--- a/contrib/llvm/tools/clang/lib/AST/Mangle.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Mangle.cpp
@@ -103,6 +103,11 @@ bool MangleContext::shouldMangleDeclName(const NamedDecl *D) {
if (CC != CCM_Other)
return true;
+ // If the declaration has an owning module for linkage purposes that needs to
+ // be mangled, we must mangle its name.
+ if (!D->hasExternalFormalLinkage() && D->getOwningModuleForLinkage())
+ return true;
+
// In C, functions with no attributes never need to be mangled. Fastpath them.
if (!getASTContext().getLangOpts().CPlusPlus && !D->hasAttrs())
return false;
diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp
index 73324e40f3b10..b19491f313047 100644
--- a/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp
@@ -76,8 +76,8 @@ class MicrosoftCXXABI : public CXXABI {
public:
MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { }
- std::pair<uint64_t, unsigned>
- getMemberPointerWidthAndAlign(const MemberPointerType *MPT) const override;
+ MemberPointerInfo
+ getMemberPointerInfo(const MemberPointerType *MPT) const override;
CallingConv getDefaultMethodCallConv(bool isVariadic) const override {
if (!isVariadic &&
@@ -227,7 +227,7 @@ getMSMemberPointerSlots(const MemberPointerType *MPT) {
return std::make_pair(Ptrs, Ints);
}
-std::pair<uint64_t, unsigned> MicrosoftCXXABI::getMemberPointerWidthAndAlign(
+CXXABI::MemberPointerInfo MicrosoftCXXABI::getMemberPointerInfo(
const MemberPointerType *MPT) const {
// The nominal struct is laid out with pointers followed by ints and aligned
// to a pointer width if any are present and an int width otherwise.
@@ -237,22 +237,25 @@ std::pair<uint64_t, unsigned> MicrosoftCXXABI::getMemberPointerWidthAndAlign(
unsigned Ptrs, Ints;
std::tie(Ptrs, Ints) = getMSMemberPointerSlots(MPT);
- uint64_t Width = Ptrs * PtrSize + Ints * IntSize;
- unsigned Align;
+ MemberPointerInfo MPI;
+ MPI.HasPadding = false;
+ MPI.Width = Ptrs * PtrSize + Ints * IntSize;
// When MSVC does x86_32 record layout, it aligns aggregate member pointers to
// 8 bytes. However, __alignof usually returns 4 for data memptrs and 8 for
// function memptrs.
if (Ptrs + Ints > 1 && Target.getTriple().isArch32Bit())
- Align = 64;
+ MPI.Align = 64;
else if (Ptrs)
- Align = Target.getPointerAlign(0);
+ MPI.Align = Target.getPointerAlign(0);
else
- Align = Target.getIntAlign();
+ MPI.Align = Target.getIntAlign();
- if (Target.getTriple().isArch64Bit())
- Width = llvm::alignTo(Width, Align);
- return std::make_pair(Width, Align);
+ if (Target.getTriple().isArch64Bit()) {
+ MPI.Width = llvm::alignTo(MPI.Width, MPI.Align);
+ MPI.HasPadding = MPI.Width != (Ptrs * PtrSize + Ints * IntSize);
+ }
+ return MPI;
}
CXXABI *clang::CreateMicrosoftCXXABI(ASTContext &Ctx) {
diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp
index 24b16f892e7a9..0c55c1a922873 100644
--- a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp
@@ -1192,6 +1192,15 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO,
// <operator-name> ::= ?__L # co_await
case OO_Coawait: Out << "?__L"; break;
+ case OO_Spaceship: {
+ // FIXME: Once MS picks a mangling, use it.
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle this three-way comparison operator yet");
+ Diags.Report(Loc, DiagID);
+ break;
+ }
+
case OO_Conditional: {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
@@ -1866,6 +1875,7 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers,
Out << "$$T";
break;
+ case BuiltinType::Float16:
case BuiltinType::Float128:
case BuiltinType::Half: {
DiagnosticsEngine &Diags = Context.getDiags();
@@ -2324,13 +2334,15 @@ void MicrosoftCXXNameMangler::mangleType(const PointerType *T, Qualifiers Quals,
manglePointerExtQualifiers(Quals, PointeeType);
mangleType(PointeeType, Range);
}
+
void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T,
Qualifiers Quals, SourceRange Range) {
+ if (T->isObjCIdType() || T->isObjCClassType())
+ return mangleType(T->getPointeeType(), Range, QMM_Drop);
+
QualType PointeeType = T->getPointeeType();
manglePointerCVQualifiers(Quals);
manglePointerExtQualifiers(Quals, PointeeType);
- // Object pointers never have qualifiers.
- Out << 'A';
mangleType(PointeeType, Range);
}
@@ -2427,6 +2439,15 @@ void MicrosoftCXXNameMangler::mangleType(const DependentSizedExtVectorType *T,
<< Range;
}
+void MicrosoftCXXNameMangler::mangleType(const DependentAddressSpaceType *T,
+ Qualifiers, SourceRange Range) {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(
+ DiagnosticsEngine::Error,
+ "cannot mangle this dependent address space type yet");
+ Diags.Report(Range.getBegin(), DiagID) << Range;
+}
+
void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T, Qualifiers,
SourceRange) {
// ObjC interfaces have structs underlying them.
@@ -2438,7 +2459,7 @@ void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T, Qualifiers,
SourceRange Range) {
// We don't allow overloading by different protocol qualification,
// so mangling them isn't necessary.
- mangleType(T->getBaseType(), Range);
+ mangleType(T->getBaseType(), Range, QMM_Drop);
}
void MicrosoftCXXNameMangler::mangleType(const BlockPointerType *T,
diff --git a/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp b/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp
index e7c8c16b01452..8adaef1fb6402 100644
--- a/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp
@@ -441,6 +441,7 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
case BuiltinType::Int128:
case BuiltinType::LongDouble:
case BuiltinType::UInt128:
+ case BuiltinType::Float16:
case BuiltinType::Float128:
case BuiltinType::NullPtr:
case BuiltinType::ObjCClass:
diff --git a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp
index e2e0dbeec0dd3..889f8308a93c6 100644
--- a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp
@@ -1,4 +1,4 @@
-//===--- NestedNameSpecifier.cpp - C++ nested name specifiers -----*- C++ -*-=//
+//===- NestedNameSpecifier.cpp - C++ nested name specifiers ---------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,16 +11,28 @@
// a C++ nested-name-specifier.
//
//===----------------------------------------------------------------------===//
+
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/PrettyPrinter.h"
+#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
-#include "llvm/Support/AlignOf.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
#include <cassert>
+#include <cstdlib>
+#include <cstring>
using namespace clang;
@@ -314,8 +326,8 @@ NestedNameSpecifier::print(raw_ostream &OS,
SpecType->getTemplateName().print(OS, InnerPolicy, true);
// Print the template argument list.
- TemplateSpecializationType::PrintTemplateArgumentList(
- OS, SpecType->template_arguments(), InnerPolicy);
+ printTemplateArgumentList(OS, SpecType->template_arguments(),
+ InnerPolicy);
} else {
// Print the type normally
QualType(T, 0).print(OS, InnerPolicy);
@@ -375,22 +387,20 @@ NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) {
return Length;
}
-namespace {
- /// \brief Load a (possibly unaligned) source location from a given address
- /// and offset.
- SourceLocation LoadSourceLocation(void *Data, unsigned Offset) {
- unsigned Raw;
- memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(unsigned));
- return SourceLocation::getFromRawEncoding(Raw);
- }
+/// \brief Load a (possibly unaligned) source location from a given address
+/// and offset.
+static SourceLocation LoadSourceLocation(void *Data, unsigned Offset) {
+ unsigned Raw;
+ memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(unsigned));
+ return SourceLocation::getFromRawEncoding(Raw);
+}
- /// \brief Load a (possibly unaligned) pointer from a given address and
- /// offset.
- void *LoadPointer(void *Data, unsigned Offset) {
- void *Result;
- memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*));
- return Result;
- }
+/// \brief Load a (possibly unaligned) pointer from a given address and
+/// offset.
+static void *LoadPointer(void *Data, unsigned Offset) {
+ void *Result;
+ memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*));
+ return Result;
}
SourceRange NestedNameSpecifierLoc::getSourceRange() const {
@@ -446,53 +456,49 @@ TypeLoc NestedNameSpecifierLoc::getTypeLoc() const {
return TypeLoc(Qualifier->getAsType(), TypeData);
}
-namespace {
- void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize,
+static void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize,
unsigned &BufferCapacity) {
- if (Start == End)
- return;
+ if (Start == End)
+ return;
- if (BufferSize + (End - Start) > BufferCapacity) {
- // Reallocate the buffer.
- unsigned NewCapacity = std::max(
- (unsigned)(BufferCapacity ? BufferCapacity * 2 : sizeof(void *) * 2),
- (unsigned)(BufferSize + (End - Start)));
- char *NewBuffer = static_cast<char *>(malloc(NewCapacity));
- if (BufferCapacity) {
- memcpy(NewBuffer, Buffer, BufferSize);
- free(Buffer);
- }
- Buffer = NewBuffer;
- BufferCapacity = NewCapacity;
+ if (BufferSize + (End - Start) > BufferCapacity) {
+ // Reallocate the buffer.
+ unsigned NewCapacity = std::max(
+ (unsigned)(BufferCapacity ? BufferCapacity * 2 : sizeof(void *) * 2),
+ (unsigned)(BufferSize + (End - Start)));
+ char *NewBuffer = static_cast<char *>(malloc(NewCapacity));
+ if (BufferCapacity) {
+ memcpy(NewBuffer, Buffer, BufferSize);
+ free(Buffer);
}
-
- memcpy(Buffer + BufferSize, Start, End - Start);
- BufferSize += End-Start;
+ Buffer = NewBuffer;
+ BufferCapacity = NewCapacity;
}
+
+ memcpy(Buffer + BufferSize, Start, End - Start);
+ BufferSize += End-Start;
+}
- /// \brief Save a source location to the given buffer.
- void SaveSourceLocation(SourceLocation Loc, char *&Buffer,
- unsigned &BufferSize, unsigned &BufferCapacity) {
- unsigned Raw = Loc.getRawEncoding();
- Append(reinterpret_cast<char *>(&Raw),
- reinterpret_cast<char *>(&Raw) + sizeof(unsigned),
- Buffer, BufferSize, BufferCapacity);
- }
+/// \brief Save a source location to the given buffer.
+static void SaveSourceLocation(SourceLocation Loc, char *&Buffer,
+ unsigned &BufferSize, unsigned &BufferCapacity) {
+ unsigned Raw = Loc.getRawEncoding();
+ Append(reinterpret_cast<char *>(&Raw),
+ reinterpret_cast<char *>(&Raw) + sizeof(unsigned),
+ Buffer, BufferSize, BufferCapacity);
+}
- /// \brief Save a pointer to the given buffer.
- void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize,
- unsigned &BufferCapacity) {
- Append(reinterpret_cast<char *>(&Ptr),
- reinterpret_cast<char *>(&Ptr) + sizeof(void *),
- Buffer, BufferSize, BufferCapacity);
- }
+/// \brief Save a pointer to the given buffer.
+static void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize,
+ unsigned &BufferCapacity) {
+ Append(reinterpret_cast<char *>(&Ptr),
+ reinterpret_cast<char *>(&Ptr) + sizeof(void *),
+ Buffer, BufferSize, BufferCapacity);
}
NestedNameSpecifierLocBuilder::
NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other)
- : Representation(Other.Representation), Buffer(nullptr),
- BufferSize(0), BufferCapacity(0)
-{
+ : Representation(Other.Representation) {
if (!Other.Buffer)
return;
diff --git a/contrib/llvm/tools/clang/lib/AST/ODRHash.cpp b/contrib/llvm/tools/clang/lib/AST/ODRHash.cpp
index 121724a731526..17c95f2a0af77 100644
--- a/contrib/llvm/tools/clang/lib/AST/ODRHash.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ODRHash.cpp
@@ -158,7 +158,14 @@ void ODRHash::AddTemplateArgument(TemplateArgument TA) {
}
}
-void ODRHash::AddTemplateParameterList(const TemplateParameterList *TPL) {}
+void ODRHash::AddTemplateParameterList(const TemplateParameterList *TPL) {
+ assert(TPL && "Expecting non-null pointer.");
+
+ ID.AddInteger(TPL->size());
+ for (auto *ND : TPL->asArray()) {
+ AddSubDecl(ND);
+ }
+}
void ODRHash::clear() {
DeclMap.clear();
@@ -199,6 +206,7 @@ unsigned ODRHash::CalculateHash() {
return ID.ComputeHash();
}
+namespace {
// Process a Decl pointer. Add* methods call back into ODRHash while Visit*
// methods process the relevant parts of the Decl.
class ODRDeclVisitor : public ConstDeclVisitor<ODRDeclVisitor> {
@@ -235,6 +243,10 @@ public:
}
}
+ void AddTemplateArgument(TemplateArgument TA) {
+ Hash.AddTemplateArgument(TA);
+ }
+
void Visit(const Decl *D) {
ID.AddInteger(D->getKind());
Inherited::Visit(D);
@@ -342,7 +354,44 @@ public:
AddDecl(D->getFriendDecl());
}
}
+
+ void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
+ // Only care about default arguments as part of the definition.
+ const bool hasDefaultArgument =
+ D->hasDefaultArgument() && !D->defaultArgumentWasInherited();
+ Hash.AddBoolean(hasDefaultArgument);
+ if (hasDefaultArgument) {
+ AddTemplateArgument(D->getDefaultArgument());
+ }
+
+ Inherited::VisitTemplateTypeParmDecl(D);
+ }
+
+ void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) {
+ // Only care about default arguments as part of the definition.
+ const bool hasDefaultArgument =
+ D->hasDefaultArgument() && !D->defaultArgumentWasInherited();
+ Hash.AddBoolean(hasDefaultArgument);
+ if (hasDefaultArgument) {
+ AddStmt(D->getDefaultArgument());
+ }
+
+ Inherited::VisitNonTypeTemplateParmDecl(D);
+ }
+
+ void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D) {
+ // Only care about default arguments as part of the definition.
+ const bool hasDefaultArgument =
+ D->hasDefaultArgument() && !D->defaultArgumentWasInherited();
+ Hash.AddBoolean(hasDefaultArgument);
+ if (hasDefaultArgument) {
+ AddTemplateArgument(D->getDefaultArgument().getArgument());
+ }
+
+ Inherited::VisitTemplateTemplateParmDecl(D);
+ }
};
+} // namespace
// Only allow a small portion of Decl's to be processed. Remove this once
// all Decl's can be handled.
@@ -401,6 +450,20 @@ void ODRHash::AddCXXRecordDecl(const CXXRecordDecl *Record) {
for (auto SubDecl : Decls) {
AddSubDecl(SubDecl);
}
+
+ const ClassTemplateDecl *TD = Record->getDescribedClassTemplate();
+ AddBoolean(TD);
+ if (TD) {
+ AddTemplateParameterList(TD->getTemplateParameters());
+ }
+
+ ID.AddInteger(Record->getNumBases());
+ auto Bases = Record->bases();
+ for (auto Base : Bases) {
+ AddQualType(Base.getType());
+ ID.AddInteger(Base.isVirtual());
+ ID.AddInteger(Base.getAccessSpecifierAsWritten());
+ }
}
void ODRHash::AddDecl(const Decl *D) {
@@ -420,6 +483,7 @@ void ODRHash::AddDecl(const Decl *D) {
}
}
+namespace {
// Process a Type pointer. Add* methods call back into ODRHash while Visit*
// methods process the relevant parts of the Type.
class ODRTypeVisitor : public TypeVisitor<ODRTypeVisitor> {
@@ -608,6 +672,7 @@ public:
AddDecl(T->getDecl());
}
};
+} // namespace
void ODRHash::AddType(const Type *T) {
assert(T && "Expecting non-null pointer.");
diff --git a/contrib/llvm/tools/clang/lib/AST/OpenMPClause.cpp b/contrib/llvm/tools/clang/lib/AST/OpenMPClause.cpp
index 2c4d159a1bc82..4feac0cfd0416 100644
--- a/contrib/llvm/tools/clang/lib/AST/OpenMPClause.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/OpenMPClause.cpp
@@ -1,4 +1,4 @@
-//===--- OpenMPClause.cpp - Classes for OpenMP clauses --------------------===//
+//===- OpenMPClause.cpp - Classes for OpenMP clauses ----------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,8 +12,14 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/OpenMPClause.h"
-
#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <algorithm>
+#include <cassert>
using namespace clang;
@@ -48,6 +54,8 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) {
return static_cast<const OMPReductionClause *>(C);
case OMPC_task_reduction:
return static_cast<const OMPTaskReductionClause *>(C);
+ case OMPC_in_reduction:
+ return static_cast<const OMPInReductionClause *>(C);
case OMPC_linear:
return static_cast<const OMPLinearClause *>(C);
case OMPC_if:
@@ -58,6 +66,8 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) {
return static_cast<const OMPNumTeamsClause *>(C);
case OMPC_thread_limit:
return static_cast<const OMPThreadLimitClause *>(C);
+ case OMPC_device:
+ return static_cast<const OMPDeviceClause *>(C);
case OMPC_default:
case OMPC_proc_bind:
case OMPC_final:
@@ -81,7 +91,6 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) {
case OMPC_capture:
case OMPC_seq_cst:
case OMPC_depend:
- case OMPC_device:
case OMPC_threads:
case OMPC_simd:
case OMPC_map:
@@ -116,6 +125,8 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C)
return static_cast<const OMPReductionClause *>(C);
case OMPC_task_reduction:
return static_cast<const OMPTaskReductionClause *>(C);
+ case OMPC_in_reduction:
+ return static_cast<const OMPInReductionClause *>(C);
case OMPC_linear:
return static_cast<const OMPLinearClause *>(C);
case OMPC_schedule:
@@ -562,6 +573,69 @@ OMPTaskReductionClause *OMPTaskReductionClause::CreateEmpty(const ASTContext &C,
return new (Mem) OMPTaskReductionClause(N);
}
+void OMPInReductionClause::setPrivates(ArrayRef<Expr *> Privates) {
+ assert(Privates.size() == varlist_size() &&
+ "Number of private copies is not the same as the preallocated buffer");
+ std::copy(Privates.begin(), Privates.end(), varlist_end());
+}
+
+void OMPInReductionClause::setLHSExprs(ArrayRef<Expr *> LHSExprs) {
+ assert(
+ LHSExprs.size() == varlist_size() &&
+ "Number of LHS expressions is not the same as the preallocated buffer");
+ std::copy(LHSExprs.begin(), LHSExprs.end(), getPrivates().end());
+}
+
+void OMPInReductionClause::setRHSExprs(ArrayRef<Expr *> RHSExprs) {
+ assert(
+ RHSExprs.size() == varlist_size() &&
+ "Number of RHS expressions is not the same as the preallocated buffer");
+ std::copy(RHSExprs.begin(), RHSExprs.end(), getLHSExprs().end());
+}
+
+void OMPInReductionClause::setReductionOps(ArrayRef<Expr *> ReductionOps) {
+ assert(ReductionOps.size() == varlist_size() && "Number of in reduction "
+ "expressions is not the same "
+ "as the preallocated buffer");
+ std::copy(ReductionOps.begin(), ReductionOps.end(), getRHSExprs().end());
+}
+
+void OMPInReductionClause::setTaskgroupDescriptors(
+ ArrayRef<Expr *> TaskgroupDescriptors) {
+ assert(TaskgroupDescriptors.size() == varlist_size() &&
+ "Number of in reduction descriptors is not the same as the "
+ "preallocated buffer");
+ std::copy(TaskgroupDescriptors.begin(), TaskgroupDescriptors.end(),
+ getReductionOps().end());
+}
+
+OMPInReductionClause *OMPInReductionClause::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL,
+ NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo,
+ ArrayRef<Expr *> Privates, ArrayRef<Expr *> LHSExprs,
+ ArrayRef<Expr *> RHSExprs, ArrayRef<Expr *> ReductionOps,
+ ArrayRef<Expr *> TaskgroupDescriptors, Stmt *PreInit, Expr *PostUpdate) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(6 * VL.size()));
+ OMPInReductionClause *Clause = new (Mem) OMPInReductionClause(
+ StartLoc, LParenLoc, EndLoc, ColonLoc, VL.size(), QualifierLoc, NameInfo);
+ Clause->setVarRefs(VL);
+ Clause->setPrivates(Privates);
+ Clause->setLHSExprs(LHSExprs);
+ Clause->setRHSExprs(RHSExprs);
+ Clause->setReductionOps(ReductionOps);
+ Clause->setTaskgroupDescriptors(TaskgroupDescriptors);
+ Clause->setPreInitStmt(PreInit);
+ Clause->setPostUpdateExpr(PostUpdate);
+ return Clause;
+}
+
+OMPInReductionClause *OMPInReductionClause::CreateEmpty(const ASTContext &C,
+ unsigned N) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(6 * N));
+ return new (Mem) OMPInReductionClause(N);
+}
+
OMPFlushClause *OMPFlushClause::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation LParenLoc,
@@ -648,7 +722,6 @@ OMPMapClause::Create(const ASTContext &C, SourceLocation StartLoc,
MappableExprComponentListsRef ComponentLists,
OpenMPMapClauseKind TypeModifier, OpenMPMapClauseKind Type,
bool TypeIsImplicit, SourceLocation TypeLoc) {
-
unsigned NumVars = Vars.size();
unsigned NumUniqueDeclarations =
getUniqueDeclarationsTotalNumber(Declarations);
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Core/QualTypeNames.cpp b/contrib/llvm/tools/clang/lib/AST/QualTypeNames.cpp
index 721c2c92fc274..86c0eff9f78c3 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/Core/QualTypeNames.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/QualTypeNames.cpp
@@ -9,11 +9,11 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Tooling/Core/QualTypeNames.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/GlobalDecl.h"
#include "clang/AST/Mangle.h"
+#include "clang/AST/QualTypeNames.h"
#include <stdio.h>
#include <memory>
@@ -21,17 +21,6 @@
namespace clang {
namespace TypeName {
-/// \brief Generates a QualType that can be used to name the same type
-/// if used at the end of the current translation unit. This ignores
-/// issues such as type shadowing.
-///
-/// \param[in] QT - the type for which the fully qualified type will be
-/// returned.
-/// \param[in] Ctx - the ASTContext to be used.
-/// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace
-/// specifier "::" should be prepended or not.
-static QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx,
- bool WithGlobalNsPrefix);
/// \brief Create a NestedNameSpecifier for Namesp and its enclosing
/// scopes.
diff --git a/contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp b/contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp
index 299fd111bf6a6..37fe029f53bd3 100644
--- a/contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp
@@ -1,4 +1,4 @@
-//===-- RecordLayout.cpp - Layout information for a struct/union -*- C++ -*-==//
+//===- RecordLayout.cpp - Layout information for a struct/union -----------===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,9 +11,11 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/AST/ASTContext.h"
#include "clang/AST/RecordLayout.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Basic/TargetCXXABI.h"
#include "clang/Basic/TargetInfo.h"
+#include <cassert>
using namespace clang;
@@ -32,7 +34,7 @@ ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx, CharUnits size,
CharUnits datasize,
ArrayRef<uint64_t> fieldoffsets)
: Size(size), DataSize(datasize), Alignment(alignment),
- RequiredAlignment(requiredAlignment), CXXInfo(nullptr) {
+ RequiredAlignment(requiredAlignment) {
FieldOffsets.append(Ctx, fieldoffsets.begin(), fieldoffsets.end());
}
@@ -73,7 +75,6 @@ ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx,
CXXInfo->EndsWithZeroSizedObject = EndsWithZeroSizedObject;
CXXInfo->LeadsWithZeroSizedBase = LeadsWithZeroSizedBase;
-
#ifndef NDEBUG
if (const CXXRecordDecl *PrimaryBase = getPrimaryBase()) {
if (isPrimaryBaseVirtual()) {
diff --git a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp
index c0b9cadca4227..a9d43dfa80c54 100644
--- a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -632,6 +632,9 @@ protected:
/// pointer, as opposed to inheriting one from a primary base class.
bool HasOwnVFPtr;
+ /// \brief the flag of field offset changing due to packed attribute.
+ bool HasPackedField;
+
typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
/// Bases - base classes and their offsets in the record.
@@ -666,7 +669,7 @@ protected:
NonVirtualSize(CharUnits::Zero()),
NonVirtualAlignment(CharUnits::One()), PrimaryBase(nullptr),
PrimaryBaseIsVirtual(false), HasOwnVFPtr(false),
- FirstNearlyEmptyVBase(nullptr) {}
+ HasPackedField(false), FirstNearlyEmptyVBase(nullptr) {}
void Layout(const RecordDecl *D);
void Layout(const CXXRecordDecl *D);
@@ -1166,7 +1169,6 @@ ItaniumRecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {
// Query the external layout to see if it provides an offset.
bool HasExternalLayout = false;
if (UseExternalLayout) {
- llvm::DenseMap<const CXXRecordDecl *, CharUnits>::iterator Known;
if (Base->IsVirtual)
HasExternalLayout = External.getExternalNVBaseOffset(Base->Class, Offset);
else
@@ -1729,7 +1731,7 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D,
const ArrayType* ATy = Context.getAsArrayType(D->getType());
FieldAlign = Context.getTypeAlignInChars(ATy->getElementType());
} else if (const ReferenceType *RT = D->getType()->getAs<ReferenceType>()) {
- unsigned AS = RT->getPointeeType().getAddressSpace();
+ unsigned AS = Context.getTargetAddressSpace(RT->getPointeeType());
FieldSize =
Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(AS));
FieldAlign =
@@ -1847,7 +1849,6 @@ void ItaniumRecordLayoutBuilder::FinishLayout(const NamedDecl *D) {
uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastUnit;
uint64_t UnpackedSizeInBits =
llvm::alignTo(getSizeInBits(), Context.toBits(UnpackedAlignment));
- CharUnits UnpackedSize = Context.toCharUnitsFromBits(UnpackedSizeInBits);
uint64_t RoundedSize =
llvm::alignTo(getSizeInBits(), Context.toBits(Alignment));
@@ -1882,10 +1883,11 @@ void ItaniumRecordLayoutBuilder::FinishLayout(const NamedDecl *D) {
<< (InBits ? 1 : 0); // (byte|bit)
}
- // Warn if we packed it unnecessarily. If the alignment is 1 byte don't
- // bother since there won't be alignment issues.
- if (Packed && UnpackedAlignment > CharUnits::One() &&
- getSize() == UnpackedSize)
+ // Warn if we packed it unnecessarily, when the unpacked alignment is not
+ // greater than the one after packing, the size in bits doesn't change and
+ // the offset of each field is identical.
+ if (Packed && UnpackedAlignment <= Alignment &&
+ UnpackedSizeInBits == getSizeInBits() && !HasPackedField)
Diag(D->getLocation(), diag::warn_unnecessary_packed)
<< Context.getTypeDeclType(RD);
}
@@ -1977,13 +1979,10 @@ void ItaniumRecordLayoutBuilder::CheckFieldPadding(
<< Context.getTypeDeclType(D->getParent())
<< PadSize
<< (InBits ? 1 : 0); // (byte|bit)
- }
-
- // Warn if we packed it unnecessarily. If the alignment is 1 byte don't
- // bother since there won't be alignment issues.
- if (isPacked && UnpackedAlign > CharBitNum && Offset == UnpackedOffset)
- Diag(D->getLocation(), diag::warn_unnecessary_packed)
- << D->getIdentifier();
+ }
+ if (isPacked && Offset != UnpackedOffset) {
+ HasPackedField = true;
+ }
}
static const CXXMethodDecl *computeKeyFunction(ASTContext &Context,
@@ -2084,7 +2083,7 @@ static bool mustSkipTailPadding(TargetCXXABI ABI, const CXXRecordDecl *RD) {
// rules, we should implement the restrictions about over-sized
// bitfields:
//
- // http://mentorembedded.github.com/cxx-abi/abi.html#POD :
+ // http://itanium-cxx-abi.github.io/cxx-abi/abi.html#POD :
// In general, a type is considered a POD for the purposes of
// layout if it is a POD type (in the sense of ISO C++
// [basic.types]). However, a POD-struct or POD-union (in the
@@ -2896,13 +2895,12 @@ void MicrosoftRecordLayoutBuilder::computeVtorDispSet(
Work.insert(MD);
while (!Work.empty()) {
const CXXMethodDecl *MD = *Work.begin();
- CXXMethodDecl::method_iterator i = MD->begin_overridden_methods(),
- e = MD->end_overridden_methods();
+ auto MethodRange = MD->overridden_methods();
// If a virtual method has no-overrides it lives in its parent's vtable.
- if (i == e)
+ if (MethodRange.begin() == MethodRange.end())
BasesWithOverriddenMethods.insert(MD->getParent());
else
- Work.insert(i, e);
+ Work.insert(MethodRange.begin(), MethodRange.end());
// We've finished processing this element, remove it from the working set.
Work.erase(MD);
}
diff --git a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp
index 2367cadf645c6..8d240c1336abd 100644
--- a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp
@@ -1,4 +1,4 @@
-//===--- Stmt.cpp - Statement AST Node Implementation ---------------------===//
+//===- Stmt.cpp - Statement AST Node Implementation -----------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,6 +13,8 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclGroup.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExprOpenMP.h"
@@ -22,10 +24,24 @@
#include "clang/AST/StmtOpenMP.h"
#include "clang/AST/Type.h"
#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Token.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cstring>
+#include <string>
+#include <utility>
+
using namespace clang;
static struct StmtClassNameTable {
@@ -150,6 +166,7 @@ const Stmt *Stmt::stripLabelLikeStatements() const {
}
namespace {
+
struct good {};
struct bad {};
@@ -191,7 +208,8 @@ namespace {
(void) is_good(implements_getLocStart(&type::getLocStart))
#define ASSERT_IMPLEMENTS_getLocEnd(type) \
(void) is_good(implements_getLocEnd(&type::getLocEnd))
-}
+
+} // namespace
/// Check whether the various Stmt classes implement their member
/// functions.
@@ -222,6 +240,7 @@ Stmt::child_range Stmt::children() {
//
// See also Expr.cpp:getExprLoc().
namespace {
+
/// This implementation is used when a class provides a custom
/// implementation of getSourceRange.
template <class S, class T>
@@ -240,7 +259,8 @@ namespace {
return SourceRange(static_cast<const S*>(stmt)->getLocStart(),
static_cast<const S*>(stmt)->getLocEnd());
}
-}
+
+} // namespace
SourceRange Stmt::getSourceRange() const {
switch (getStmtClass()) {
@@ -286,7 +306,7 @@ CompoundStmt::CompoundStmt(const ASTContext &C, ArrayRef<Stmt*> Stmts,
assert(CompoundStmtBits.NumStmts == Stmts.size() &&
"NumStmts doesn't fit in bits of CompoundStmtBits.NumStmts!");
- if (Stmts.size() == 0) {
+ if (Stmts.empty()) {
Body = nullptr;
return;
}
@@ -408,6 +428,7 @@ StringRef GCCAsmStmt::getOutputConstraint(unsigned i) const {
Expr *GCCAsmStmt::getInputExpr(unsigned i) {
return cast<Expr>(Exprs[i + NumOutputs]);
}
+
void GCCAsmStmt::setInputExpr(unsigned i, Expr *E) {
Exprs[i + NumOutputs] = E;
}
@@ -506,7 +527,7 @@ unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces,
unsigned LastAsmStringToken = 0;
unsigned LastAsmStringOffset = 0;
- while (1) {
+ while (true) {
// Done with the string?
if (CurPtr == StrEnd) {
if (!CurStringPiece.empty())
@@ -682,6 +703,7 @@ Expr *MSAsmStmt::getOutputExpr(unsigned i) {
Expr *MSAsmStmt::getInputExpr(unsigned i) {
return cast<Expr>(Exprs[i + NumOutputs]);
}
+
void MSAsmStmt::setInputExpr(unsigned i, Expr *E) {
Exprs[i + NumOutputs] = E;
}
@@ -696,9 +718,8 @@ GCCAsmStmt::GCCAsmStmt(const ASTContext &C, SourceLocation asmloc,
StringLiteral **constraints, Expr **exprs,
StringLiteral *asmstr, unsigned numclobbers,
StringLiteral **clobbers, SourceLocation rparenloc)
- : AsmStmt(GCCAsmStmtClass, asmloc, issimple, isvolatile, numoutputs,
- numinputs, numclobbers), RParenLoc(rparenloc), AsmStr(asmstr) {
-
+ : AsmStmt(GCCAsmStmtClass, asmloc, issimple, isvolatile, numoutputs,
+ numinputs, numclobbers), RParenLoc(rparenloc), AsmStr(asmstr) {
unsigned NumExprs = NumOutputs + NumInputs;
Names = new (C) IdentifierInfo*[NumExprs];
@@ -721,10 +742,9 @@ MSAsmStmt::MSAsmStmt(const ASTContext &C, SourceLocation asmloc,
ArrayRef<StringRef> constraints, ArrayRef<Expr*> exprs,
StringRef asmstr, ArrayRef<StringRef> clobbers,
SourceLocation endloc)
- : AsmStmt(MSAsmStmtClass, asmloc, issimple, isvolatile, numoutputs,
- numinputs, clobbers.size()), LBraceLoc(lbraceloc),
- EndLoc(endloc), NumAsmToks(asmtoks.size()) {
-
+ : AsmStmt(MSAsmStmtClass, asmloc, issimple, isvolatile, numoutputs,
+ numinputs, clobbers.size()), LBraceLoc(lbraceloc),
+ EndLoc(endloc), NumAsmToks(asmtoks.size()) {
initialize(C, asmstr, asmtoks, constraints, exprs, clobbers);
}
@@ -909,14 +929,9 @@ Expr* ReturnStmt::getRetValue() {
return cast_or_null<Expr>(RetExpr);
}
-SEHTryStmt::SEHTryStmt(bool IsCXXTry,
- SourceLocation TryLoc,
- Stmt *TryBlock,
+SEHTryStmt::SEHTryStmt(bool IsCXXTry, SourceLocation TryLoc, Stmt *TryBlock,
Stmt *Handler)
- : Stmt(SEHTryStmtClass),
- IsCXXTry(IsCXXTry),
- TryLoc(TryLoc)
-{
+ : Stmt(SEHTryStmtClass), IsCXXTry(IsCXXTry), TryLoc(TryLoc) {
Children[TRY] = TryBlock;
Children[HANDLER] = Handler;
}
@@ -935,12 +950,8 @@ SEHFinallyStmt* SEHTryStmt::getFinallyHandler() const {
return dyn_cast<SEHFinallyStmt>(getHandler());
}
-SEHExceptStmt::SEHExceptStmt(SourceLocation Loc,
- Expr *FilterExpr,
- Stmt *Block)
- : Stmt(SEHExceptStmtClass),
- Loc(Loc)
-{
+SEHExceptStmt::SEHExceptStmt(SourceLocation Loc, Expr *FilterExpr, Stmt *Block)
+ : Stmt(SEHExceptStmtClass), Loc(Loc) {
Children[FILTER_EXPR] = FilterExpr;
Children[BLOCK] = Block;
}
@@ -950,12 +961,8 @@ SEHExceptStmt* SEHExceptStmt::Create(const ASTContext &C, SourceLocation Loc,
return new(C) SEHExceptStmt(Loc,FilterExpr,Block);
}
-SEHFinallyStmt::SEHFinallyStmt(SourceLocation Loc,
- Stmt *Block)
- : Stmt(SEHFinallyStmtClass),
- Loc(Loc),
- Block(Block)
-{}
+SEHFinallyStmt::SEHFinallyStmt(SourceLocation Loc, Stmt *Block)
+ : Stmt(SEHFinallyStmtClass), Loc(Loc), Block(Block) {}
SEHFinallyStmt* SEHFinallyStmt::Create(const ASTContext &C, SourceLocation Loc,
Stmt *Block) {
@@ -1037,7 +1044,7 @@ CapturedStmt::CapturedStmt(Stmt *S, CapturedRegionKind Kind,
CapturedStmt::CapturedStmt(EmptyShell Empty, unsigned NumCaptures)
: Stmt(CapturedStmtClass, Empty), NumCaptures(NumCaptures),
- CapDeclAndKind(nullptr, CR_Default), TheRecordDecl(nullptr) {
+ CapDeclAndKind(nullptr, CR_Default) {
getStoredStmts()[NumCaptures] = nullptr;
}
@@ -1090,6 +1097,7 @@ Stmt::child_range CapturedStmt::children() {
CapturedDecl *CapturedStmt::getCapturedDecl() {
return CapDeclAndKind.getPointer();
}
+
const CapturedDecl *CapturedStmt::getCapturedDecl() const {
return CapDeclAndKind.getPointer();
}
@@ -1114,11 +1122,7 @@ bool CapturedStmt::capturesVariable(const VarDecl *Var) const {
for (const auto &I : captures()) {
if (!I.capturesVariable() && !I.capturesVariableByCopy())
continue;
-
- // This does not handle variable redeclarations. This should be
- // extended to capture variables with redeclarations, for example
- // a thread-private variable in OpenMP.
- if (I.getCapturedVar() == Var)
+ if (I.getCapturedVar()->getCanonicalDecl() == Var->getCanonicalDecl())
return true;
}
diff --git a/contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp b/contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp
index 861d0908209dc..00056e83af2c0 100644
--- a/contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp
@@ -1,4 +1,4 @@
-//===--- StmtIterator.cpp - Iterators for Statements ------------------------===//
+//===- StmtIterator.cpp - Iterators for Statements ------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,6 +13,11 @@
#include "clang/AST/StmtIterator.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/Support/Casting.h"
+#include <cassert>
+#include <cstdint>
using namespace clang;
@@ -31,7 +36,7 @@ static inline const VariableArrayType *FindVA(const Type* t) {
}
void StmtIteratorBase::NextVA() {
- assert (getVAPtr());
+ assert(getVAPtr());
const VariableArrayType *p = getVAPtr();
p = FindVA(p->getElementType().getTypePtr());
@@ -93,22 +98,22 @@ bool StmtIteratorBase::HandleDecl(Decl* D) {
}
StmtIteratorBase::StmtIteratorBase(Decl** dgi, Decl** dge)
- : DGI(dgi), RawVAPtr(DeclGroupMode), DGE(dge) {
+ : DGI(dgi), RawVAPtr(DeclGroupMode), DGE(dge) {
NextDecl(false);
}
StmtIteratorBase::StmtIteratorBase(const VariableArrayType* t)
- : DGI(nullptr), RawVAPtr(SizeOfTypeVAMode) {
+ : DGI(nullptr), RawVAPtr(SizeOfTypeVAMode) {
RawVAPtr |= reinterpret_cast<uintptr_t>(t);
}
Stmt*& StmtIteratorBase::GetDeclExpr() const {
if (const VariableArrayType* VAPtr = getVAPtr()) {
- assert (VAPtr->SizeExpr);
+ assert(VAPtr->SizeExpr);
return const_cast<Stmt*&>(VAPtr->SizeExpr);
}
- assert (inDeclGroup());
+ assert(inDeclGroup());
VarDecl* VD = cast<VarDecl>(*DGI);
return *VD->getInitAddress();
}
diff --git a/contrib/llvm/tools/clang/lib/AST/StmtOpenMP.cpp b/contrib/llvm/tools/clang/lib/AST/StmtOpenMP.cpp
index 1dcb4fd5196be..87bf5aaaa585d 100644
--- a/contrib/llvm/tools/clang/lib/AST/StmtOpenMP.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/StmtOpenMP.cpp
@@ -524,14 +524,15 @@ OMPTaskwaitDirective *OMPTaskwaitDirective::CreateEmpty(const ASTContext &C,
OMPTaskgroupDirective *OMPTaskgroupDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
- ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) {
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *ReductionRef) {
unsigned Size = llvm::alignTo(sizeof(OMPTaskgroupDirective) +
sizeof(OMPClause *) * Clauses.size(),
alignof(Stmt *));
- void *Mem = C.Allocate(Size + sizeof(Stmt *));
+ void *Mem = C.Allocate(Size + sizeof(Stmt *) + sizeof(Expr *));
OMPTaskgroupDirective *Dir =
new (Mem) OMPTaskgroupDirective(StartLoc, EndLoc, Clauses.size());
Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setReductionRef(ReductionRef);
Dir->setClauses(Clauses);
return Dir;
}
@@ -542,7 +543,7 @@ OMPTaskgroupDirective *OMPTaskgroupDirective::CreateEmpty(const ASTContext &C,
unsigned Size = llvm::alignTo(sizeof(OMPTaskgroupDirective) +
sizeof(OMPClause *) * NumClauses,
alignof(Stmt *));
- void *Mem = C.Allocate(Size + sizeof(Stmt *));
+ void *Mem = C.Allocate(Size + sizeof(Stmt *) + sizeof(Expr *));
return new (Mem) OMPTaskgroupDirective(NumClauses);
}
@@ -794,13 +795,14 @@ OMPTargetDataDirective *OMPTargetDataDirective::CreateEmpty(const ASTContext &C,
OMPTargetEnterDataDirective *OMPTargetEnterDataDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
- ArrayRef<OMPClause *> Clauses) {
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) {
void *Mem = C.Allocate(
llvm::alignTo(sizeof(OMPTargetEnterDataDirective), alignof(OMPClause *)) +
- sizeof(OMPClause *) * Clauses.size());
+ sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
OMPTargetEnterDataDirective *Dir =
new (Mem) OMPTargetEnterDataDirective(StartLoc, EndLoc, Clauses.size());
Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
return Dir;
}
@@ -809,20 +811,20 @@ OMPTargetEnterDataDirective::CreateEmpty(const ASTContext &C, unsigned N,
EmptyShell) {
void *Mem = C.Allocate(
llvm::alignTo(sizeof(OMPTargetEnterDataDirective), alignof(OMPClause *)) +
- sizeof(OMPClause *) * N);
+ sizeof(OMPClause *) * N + sizeof(Stmt *));
return new (Mem) OMPTargetEnterDataDirective(N);
}
-OMPTargetExitDataDirective *
-OMPTargetExitDataDirective::Create(const ASTContext &C, SourceLocation StartLoc,
- SourceLocation EndLoc,
- ArrayRef<OMPClause *> Clauses) {
+OMPTargetExitDataDirective *OMPTargetExitDataDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) {
void *Mem = C.Allocate(
llvm::alignTo(sizeof(OMPTargetExitDataDirective), alignof(OMPClause *)) +
- sizeof(OMPClause *) * Clauses.size());
+ sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
OMPTargetExitDataDirective *Dir =
new (Mem) OMPTargetExitDataDirective(StartLoc, EndLoc, Clauses.size());
Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
return Dir;
}
@@ -831,7 +833,7 @@ OMPTargetExitDataDirective::CreateEmpty(const ASTContext &C, unsigned N,
EmptyShell) {
void *Mem = C.Allocate(
llvm::alignTo(sizeof(OMPTargetExitDataDirective), alignof(OMPClause *)) +
- sizeof(OMPClause *) * N);
+ sizeof(OMPClause *) * N + sizeof(Stmt *));
return new (Mem) OMPTargetExitDataDirective(N);
}
@@ -1006,16 +1008,17 @@ OMPDistributeDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses,
return new (Mem) OMPDistributeDirective(CollapsedNum, NumClauses);
}
-OMPTargetUpdateDirective *
-OMPTargetUpdateDirective::Create(const ASTContext &C, SourceLocation StartLoc,
- SourceLocation EndLoc,
- ArrayRef<OMPClause *> Clauses) {
+OMPTargetUpdateDirective *OMPTargetUpdateDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) {
unsigned Size =
llvm::alignTo(sizeof(OMPTargetUpdateDirective), alignof(OMPClause *));
- void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
OMPTargetUpdateDirective *Dir =
new (Mem) OMPTargetUpdateDirective(StartLoc, EndLoc, Clauses.size());
Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
return Dir;
}
@@ -1024,14 +1027,15 @@ OMPTargetUpdateDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses,
EmptyShell) {
unsigned Size =
llvm::alignTo(sizeof(OMPTargetUpdateDirective), alignof(OMPClause *));
- void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses);
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
return new (Mem) OMPTargetUpdateDirective(NumClauses);
}
OMPDistributeParallelForDirective *OMPDistributeParallelForDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
- const HelperExprs &Exprs) {
+ const HelperExprs &Exprs, bool HasCancel) {
unsigned Size = llvm::alignTo(sizeof(OMPDistributeParallelForDirective),
alignof(OMPClause *));
void *Mem = C.Allocate(
@@ -1075,6 +1079,7 @@ OMPDistributeParallelForDirective *OMPDistributeParallelForDirective::Create(
Dir->setCombinedCond(Exprs.DistCombinedFields.Cond);
Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB);
Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB);
+ Dir->HasCancel = HasCancel;
return Dir;
}
@@ -1475,7 +1480,7 @@ OMPTeamsDistributeParallelForDirective *
OMPTeamsDistributeParallelForDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
- const HelperExprs &Exprs) {
+ const HelperExprs &Exprs, bool HasCancel) {
auto Size = llvm::alignTo(sizeof(OMPTeamsDistributeParallelForDirective),
alignof(OMPClause *));
void *Mem = C.Allocate(
@@ -1519,6 +1524,7 @@ OMPTeamsDistributeParallelForDirective::Create(
Dir->setCombinedCond(Exprs.DistCombinedFields.Cond);
Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB);
Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB);
+ Dir->HasCancel = HasCancel;
return Dir;
}
@@ -1618,7 +1624,7 @@ OMPTargetTeamsDistributeParallelForDirective *
OMPTargetTeamsDistributeParallelForDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
- const HelperExprs &Exprs) {
+ const HelperExprs &Exprs, bool HasCancel) {
auto Size =
llvm::alignTo(sizeof(OMPTargetTeamsDistributeParallelForDirective),
alignof(OMPClause *));
@@ -1664,6 +1670,7 @@ OMPTargetTeamsDistributeParallelForDirective::Create(
Dir->setCombinedCond(Exprs.DistCombinedFields.Cond);
Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB);
Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB);
+ Dir->HasCancel = HasCancel;
return Dir;
}
diff --git a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp
index 5ebaa32b49c80..d7e668a832809 100644
--- a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp
@@ -24,6 +24,7 @@
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/CharInfo.h"
+#include "clang/Lex/Lexer.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Format.h"
using namespace clang;
@@ -38,12 +39,14 @@ namespace {
unsigned IndentLevel;
clang::PrinterHelper* Helper;
PrintingPolicy Policy;
+ const ASTContext *Context;
public:
- StmtPrinter(raw_ostream &os, PrinterHelper* helper,
- const PrintingPolicy &Policy,
- unsigned Indentation = 0)
- : OS(os), IndentLevel(Indentation), Helper(helper), Policy(Policy) {}
+ StmtPrinter(raw_ostream &os, PrinterHelper *helper,
+ const PrintingPolicy &Policy, unsigned Indentation = 0,
+ const ASTContext *Context = nullptr)
+ : OS(os), IndentLevel(Indentation), Helper(helper), Policy(Policy),
+ Context(Context) {}
void PrintStmt(Stmt *S) {
PrintStmt(S, Policy.Indentation);
@@ -72,7 +75,8 @@ namespace {
void PrintCallArgs(CallExpr *E);
void PrintRawSEHExceptHandler(SEHExceptStmt *S);
void PrintRawSEHFinallyStmt(SEHFinallyStmt *S);
- void PrintOMPExecutableDirective(OMPExecutableDirective *S);
+ void PrintOMPExecutableDirective(OMPExecutableDirective *S,
+ bool ForceNoStmt = false);
void PrintExpr(Expr *E) {
if (E)
@@ -859,6 +863,28 @@ void OMPClausePrinter::VisitOMPTaskReductionClause(
}
}
+void OMPClausePrinter::VisitOMPInReductionClause(OMPInReductionClause *Node) {
+ if (!Node->varlist_empty()) {
+ OS << "in_reduction(";
+ NestedNameSpecifier *QualifierLoc =
+ Node->getQualifierLoc().getNestedNameSpecifier();
+ OverloadedOperatorKind OOK =
+ Node->getNameInfo().getName().getCXXOverloadedOperator();
+ if (QualifierLoc == nullptr && OOK != OO_None) {
+ // Print reduction identifier in C format
+ OS << getOperatorSpelling(OOK);
+ } else {
+ // Use C++ format
+ if (QualifierLoc != nullptr)
+ QualifierLoc->print(OS, Policy);
+ OS << Node->getNameInfo();
+ }
+ OS << ":";
+ VisitOMPClauseList(Node, ' ');
+ OS << ")";
+ }
+}
+
void OMPClausePrinter::VisitOMPLinearClause(OMPLinearClause *Node) {
if (!Node->varlist_empty()) {
OS << "linear";
@@ -997,7 +1023,8 @@ void OMPClausePrinter::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *Node) {
// OpenMP directives printing methods
//===----------------------------------------------------------------------===//
-void StmtPrinter::PrintOMPExecutableDirective(OMPExecutableDirective *S) {
+void StmtPrinter::PrintOMPExecutableDirective(OMPExecutableDirective *S,
+ bool ForceNoStmt) {
OMPClausePrinter Printer(OS, Policy);
ArrayRef<OMPClause *> Clauses = S->clauses();
for (ArrayRef<OMPClause *>::iterator I = Clauses.begin(), E = Clauses.end();
@@ -1007,7 +1034,7 @@ void StmtPrinter::PrintOMPExecutableDirective(OMPExecutableDirective *S) {
OS << ' ';
}
OS << "\n";
- if (S->hasAssociatedStmt() && S->getAssociatedStmt()) {
+ if (S->hasAssociatedStmt() && S->getAssociatedStmt() && !ForceNoStmt) {
assert(isa<CapturedStmt>(S->getAssociatedStmt()) &&
"Expected captured statement!");
Stmt *CS = cast<CapturedStmt>(S->getAssociatedStmt())->getCapturedStmt();
@@ -1136,13 +1163,13 @@ void StmtPrinter::VisitOMPTargetDataDirective(OMPTargetDataDirective *Node) {
void StmtPrinter::VisitOMPTargetEnterDataDirective(
OMPTargetEnterDataDirective *Node) {
Indent() << "#pragma omp target enter data ";
- PrintOMPExecutableDirective(Node);
+ PrintOMPExecutableDirective(Node, /*ForceNoStmt=*/true);
}
void StmtPrinter::VisitOMPTargetExitDataDirective(
OMPTargetExitDataDirective *Node) {
Indent() << "#pragma omp target exit data ";
- PrintOMPExecutableDirective(Node);
+ PrintOMPExecutableDirective(Node, /*ForceNoStmt=*/true);
}
void StmtPrinter::VisitOMPTargetParallelDirective(
@@ -1194,7 +1221,7 @@ void StmtPrinter::VisitOMPDistributeDirective(OMPDistributeDirective *Node) {
void StmtPrinter::VisitOMPTargetUpdateDirective(
OMPTargetUpdateDirective *Node) {
Indent() << "#pragma omp target update ";
- PrintOMPExecutableDirective(Node);
+ PrintOMPExecutableDirective(Node, /*ForceNoStmt=*/true);
}
void StmtPrinter::VisitOMPDistributeParallelForDirective(
@@ -1294,8 +1321,7 @@ void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
OS << "template ";
OS << Node->getNameInfo();
if (Node->hasExplicitTemplateArgs())
- TemplateSpecializationType::PrintTemplateArgumentList(
- OS, Node->template_arguments(), Policy);
+ printTemplateArgumentList(OS, Node->template_arguments(), Policy);
}
void StmtPrinter::VisitDependentScopeDeclRefExpr(
@@ -1306,8 +1332,7 @@ void StmtPrinter::VisitDependentScopeDeclRefExpr(
OS << "template ";
OS << Node->getNameInfo();
if (Node->hasExplicitTemplateArgs())
- TemplateSpecializationType::PrintTemplateArgumentList(
- OS, Node->template_arguments(), Policy);
+ printTemplateArgumentList(OS, Node->template_arguments(), Policy);
}
void StmtPrinter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) {
@@ -1317,14 +1342,28 @@ void StmtPrinter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) {
OS << "template ";
OS << Node->getNameInfo();
if (Node->hasExplicitTemplateArgs())
- TemplateSpecializationType::PrintTemplateArgumentList(
- OS, Node->template_arguments(), Policy);
+ printTemplateArgumentList(OS, Node->template_arguments(), Policy);
+}
+
+static bool isImplicitSelf(const Expr *E) {
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
+ if (const ImplicitParamDecl *PD =
+ dyn_cast<ImplicitParamDecl>(DRE->getDecl())) {
+ if (PD->getParameterKind() == ImplicitParamDecl::ObjCSelf &&
+ DRE->getLocStart().isInvalid())
+ return true;
+ }
+ }
+ return false;
}
void StmtPrinter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
if (Node->getBase()) {
- PrintExpr(Node->getBase());
- OS << (Node->isArrow() ? "->" : ".");
+ if (!Policy.SuppressImplicitBase ||
+ !isImplicitSelf(Node->getBase()->IgnoreImpCasts())) {
+ PrintExpr(Node->getBase());
+ OS << (Node->isArrow() ? "->" : ".");
+ }
}
OS << *Node->getDecl();
}
@@ -1419,7 +1458,26 @@ void StmtPrinter::VisitCharacterLiteral(CharacterLiteral *Node) {
}
}
+/// Prints the given expression using the original source text. Returns true on
+/// success, false otherwise.
+static bool printExprAsWritten(raw_ostream &OS, Expr *E,
+ const ASTContext *Context) {
+ if (!Context)
+ return false;
+ bool Invalid = false;
+ StringRef Source = Lexer::getSourceText(
+ CharSourceRange::getTokenRange(E->getSourceRange()),
+ Context->getSourceManager(), Context->getLangOpts(), &Invalid);
+ if (!Invalid) {
+ OS << Source;
+ return true;
+ }
+ return false;
+}
+
void StmtPrinter::VisitIntegerLiteral(IntegerLiteral *Node) {
+ if (Policy.ConstantsAsWritten && printExprAsWritten(OS, Node, Context))
+ return;
bool isSigned = Node->getType()->isSignedIntegerType();
OS << Node->getValue().toString(10, isSigned);
@@ -1456,6 +1514,7 @@ static void PrintFloatingLiteral(raw_ostream &OS, FloatingLiteral *Node,
default: llvm_unreachable("Unexpected type for float literal!");
case BuiltinType::Half: break; // FIXME: suffix?
case BuiltinType::Double: break; // no suffix.
+ case BuiltinType::Float16: OS << "F16"; break;
case BuiltinType::Float: OS << 'F'; break;
case BuiltinType::LongDouble: OS << 'L'; break;
case BuiltinType::Float128: OS << 'Q'; break;
@@ -1463,6 +1522,8 @@ static void PrintFloatingLiteral(raw_ostream &OS, FloatingLiteral *Node,
}
void StmtPrinter::VisitFloatingLiteral(FloatingLiteral *Node) {
+ if (Policy.ConstantsAsWritten && printExprAsWritten(OS, Node, Context))
+ return;
PrintFloatingLiteral(OS, Node, /*PrintSuffix=*/true);
}
@@ -1623,16 +1684,25 @@ void StmtPrinter::VisitCallExpr(CallExpr *Call) {
PrintCallArgs(Call);
OS << ")";
}
+
+static bool isImplicitThis(const Expr *E) {
+ if (const auto *TE = dyn_cast<CXXThisExpr>(E))
+ return TE->isImplicit();
+ return false;
+}
+
void StmtPrinter::VisitMemberExpr(MemberExpr *Node) {
- // FIXME: Suppress printing implicit bases (like "this")
- PrintExpr(Node->getBase());
+ if (!Policy.SuppressImplicitBase || !isImplicitThis(Node->getBase())) {
+ PrintExpr(Node->getBase());
- MemberExpr *ParentMember = dyn_cast<MemberExpr>(Node->getBase());
- FieldDecl *ParentDecl = ParentMember
- ? dyn_cast<FieldDecl>(ParentMember->getMemberDecl()) : nullptr;
+ MemberExpr *ParentMember = dyn_cast<MemberExpr>(Node->getBase());
+ FieldDecl *ParentDecl =
+ ParentMember ? dyn_cast<FieldDecl>(ParentMember->getMemberDecl())
+ : nullptr;
- if (!ParentDecl || !ParentDecl->isAnonymousStructOrUnion())
- OS << (Node->isArrow() ? "->" : ".");
+ if (!ParentDecl || !ParentDecl->isAnonymousStructOrUnion())
+ OS << (Node->isArrow() ? "->" : ".");
+ }
if (FieldDecl *FD = dyn_cast<FieldDecl>(Node->getMemberDecl()))
if (FD->isAnonymousStructOrUnion())
@@ -1644,8 +1714,7 @@ void StmtPrinter::VisitMemberExpr(MemberExpr *Node) {
OS << "template ";
OS << Node->getMemberNameInfo();
if (Node->hasExplicitTemplateArgs())
- TemplateSpecializationType::PrintTemplateArgumentList(
- OS, Node->template_arguments(), Policy);
+ printTemplateArgumentList(OS, Node->template_arguments(), Policy);
}
void StmtPrinter::VisitObjCIsaExpr(ObjCIsaExpr *Node) {
PrintExpr(Node->getBase());
@@ -1869,7 +1938,8 @@ void StmtPrinter::VisitAtomicExpr(AtomicExpr *Node) {
// AtomicExpr stores its subexpressions in a permuted order.
PrintExpr(Node->getPtr());
if (Node->getOp() != AtomicExpr::AO__c11_atomic_load &&
- Node->getOp() != AtomicExpr::AO__atomic_load_n) {
+ Node->getOp() != AtomicExpr::AO__atomic_load_n &&
+ Node->getOp() != AtomicExpr::AO__opencl_atomic_load) {
OS << ", ";
PrintExpr(Node->getVal1());
}
@@ -1883,7 +1953,8 @@ void StmtPrinter::VisitAtomicExpr(AtomicExpr *Node) {
OS << ", ";
PrintExpr(Node->getWeak());
}
- if (Node->getOp() != AtomicExpr::AO__c11_atomic_init) {
+ if (Node->getOp() != AtomicExpr::AO__c11_atomic_init &&
+ Node->getOp() != AtomicExpr::AO__opencl_atomic_init) {
OS << ", ";
PrintExpr(Node->getOrder());
}
@@ -2036,8 +2107,7 @@ void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) {
if (Args->size() != 1) {
OS << "operator\"\"" << Node->getUDSuffix()->getName();
- TemplateSpecializationType::PrintTemplateArgumentList(
- OS, Args->asArray(), Policy);
+ printTemplateArgumentList(OS, Args->asArray(), Policy);
OS << "()";
return;
}
@@ -2159,6 +2229,9 @@ void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) {
CEnd = Node->explicit_capture_end();
C != CEnd;
++C) {
+ if (C->capturesVLAType())
+ continue;
+
if (NeedComma)
OS << ", ";
NeedComma = true;
@@ -2361,8 +2434,7 @@ void StmtPrinter::VisitCXXDependentScopeMemberExpr(
OS << "template ";
OS << Node->getMemberNameInfo();
if (Node->hasExplicitTemplateArgs())
- TemplateSpecializationType::PrintTemplateArgumentList(
- OS, Node->template_arguments(), Policy);
+ printTemplateArgumentList(OS, Node->template_arguments(), Policy);
}
void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) {
@@ -2376,8 +2448,7 @@ void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) {
OS << "template ";
OS << Node->getMemberNameInfo();
if (Node->hasExplicitTemplateArgs())
- TemplateSpecializationType::PrintTemplateArgumentList(
- OS, Node->template_arguments(), Policy);
+ printTemplateArgumentList(OS, Node->template_arguments(), Policy);
}
static const char *getTypeTraitName(TypeTrait TT) {
@@ -2672,11 +2743,10 @@ void Stmt::dumpPretty(const ASTContext &Context) const {
printPretty(llvm::errs(), nullptr, PrintingPolicy(Context.getLangOpts()));
}
-void Stmt::printPretty(raw_ostream &OS,
- PrinterHelper *Helper,
- const PrintingPolicy &Policy,
- unsigned Indentation) const {
- StmtPrinter P(OS, Helper, Policy, Indentation);
+void Stmt::printPretty(raw_ostream &OS, PrinterHelper *Helper,
+ const PrintingPolicy &Policy, unsigned Indentation,
+ const ASTContext *Context) const {
+ StmtPrinter P(OS, Helper, Policy, Indentation, Context);
P.Visit(const_cast<Stmt*>(this));
}
diff --git a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp
index 7ec0d1d5e0176..00ef0da18bbbf 100644
--- a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp
@@ -573,6 +573,34 @@ void OMPClauseProfiler::VisitOMPTaskReductionClause(
Profiler->VisitStmt(E);
}
}
+void OMPClauseProfiler::VisitOMPInReductionClause(
+ const OMPInReductionClause *C) {
+ Profiler->VisitNestedNameSpecifier(
+ C->getQualifierLoc().getNestedNameSpecifier());
+ Profiler->VisitName(C->getNameInfo().getName());
+ VisitOMPClauseList(C);
+ VistOMPClauseWithPostUpdate(C);
+ for (auto *E : C->privates()) {
+ if (E)
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->lhs_exprs()) {
+ if (E)
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->rhs_exprs()) {
+ if (E)
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->reduction_ops()) {
+ if (E)
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->taskgroup_descriptors()) {
+ if (E)
+ Profiler->VisitStmt(E);
+ }
+}
void OMPClauseProfiler::VisitOMPLinearClause(const OMPLinearClause *C) {
VisitOMPClauseList(C);
VistOMPClauseWithPostUpdate(C);
@@ -774,6 +802,8 @@ void StmtProfiler::VisitOMPTaskwaitDirective(const OMPTaskwaitDirective *S) {
void StmtProfiler::VisitOMPTaskgroupDirective(const OMPTaskgroupDirective *S) {
VisitOMPExecutableDirective(S);
+ if (const Expr *E = S->getReductionRef())
+ VisitStmt(E);
}
void StmtProfiler::VisitOMPFlushDirective(const OMPFlushDirective *S) {
@@ -1354,6 +1384,10 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S,
case OO_GreaterEqual:
BinaryOp = BO_GE;
return Stmt::BinaryOperatorClass;
+
+ case OO_Spaceship:
+ // FIXME: Update this once we support <=> expressions.
+ llvm_unreachable("<=> expressions not supported yet");
case OO_AmpAmp:
BinaryOp = BO_LAnd;
@@ -1388,7 +1422,7 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S,
llvm_unreachable("Invalid overloaded operator expression");
}
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) && !defined(__clang__)
#if _MSC_VER == 1911
// Work around https://developercommunity.visualstudio.com/content/problem/84002/clang-cl-when-built-with-vc-2017-crashes-cause-vc.html
// MSVC 2017 update 3 miscompiles this function, and a clang built with it
@@ -1429,7 +1463,7 @@ void StmtProfiler::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) {
ID.AddInteger(S->getOperator());
}
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) && !defined(__clang__)
#if _MSC_VER == 1911
#pragma optimize("", on)
#endif
@@ -1560,6 +1594,9 @@ StmtProfiler::VisitLambdaExpr(const LambdaExpr *S) {
for (LambdaExpr::capture_iterator C = S->explicit_capture_begin(),
CEnd = S->explicit_capture_end();
C != CEnd; ++C) {
+ if (C->capturesVLAType())
+ continue;
+
ID.AddInteger(C->getCaptureKind());
switch (C->getCaptureKind()) {
case LCK_StarThis:
@@ -1671,6 +1708,7 @@ void StmtProfiler::VisitCXXUnresolvedConstructExpr(
const CXXUnresolvedConstructExpr *S) {
VisitExpr(S);
VisitType(S->getTypeAsWritten());
+ ID.AddInteger(S->isListInitialization());
}
void StmtProfiler::VisitCXXDependentScopeMemberExpr(
diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp
index e4998c37a4ef0..e81c11a778255 100644
--- a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp
@@ -1,4 +1,4 @@
-//===--- TemplateBase.cpp - Common template AST class implementation ------===//
+//===- TemplateBase.cpp - Common template AST class implementation --------===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,17 +14,32 @@
#include "clang/AST/TemplateBase.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/PrettyPrinter.h"
+#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/None.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
using namespace clang;
@@ -37,7 +52,7 @@ using namespace clang;
/// \param Policy the printing policy for EnumConstantDecl printing.
static void printIntegral(const TemplateArgument &TemplArg,
raw_ostream &Out, const PrintingPolicy& Policy) {
- const ::clang::Type *T = TemplArg.getIntegralType().getTypePtr();
+ const Type *T = TemplArg.getIntegralType().getTypePtr();
const llvm::APSInt &Val = TemplArg.getAsIntegral();
if (const EnumType *ET = T->getAs<EnumType>()) {
@@ -415,10 +430,9 @@ void TemplateArgument::print(const PrintingPolicy &Policy,
Out << "...";
break;
- case Integral: {
+ case Integral:
printIntegral(*this, Out, Policy);
break;
- }
case Expression:
getAsExpr()->printPretty(Out, nullptr, Policy);
diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp
index 47a7d47e7a489..bd04fd8366b3f 100644
--- a/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp
@@ -1,4 +1,4 @@
-//===--- TemplateName.cpp - C++ Template Name Representation---------------===//
+//===- TemplateName.cpp - C++ Template Name Representation ----------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,15 +12,24 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/TemplateName.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/TemplateBase.h"
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/OperatorKinds.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <string>
+
using namespace clang;
-using namespace llvm;
TemplateArgument
SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
@@ -131,6 +140,23 @@ DependentTemplateName *TemplateName::getAsDependentTemplateName() const {
return Storage.dyn_cast<DependentTemplateName *>();
}
+TemplateName TemplateName::getNameToSubstitute() const {
+ TemplateDecl *Decl = getAsTemplateDecl();
+
+ // Substituting a dependent template name: preserve it as written.
+ if (!Decl)
+ return *this;
+
+ // If we have a template declaration, use the most recent non-friend
+ // declaration of that template.
+ Decl = cast<TemplateDecl>(Decl->getMostRecentDecl());
+ while (Decl->getFriendObjectKind()) {
+ Decl = cast<TemplateDecl>(Decl->getPreviousDecl());
+ assert(Decl && "all declarations of template are friends");
+ }
+ return TemplateName(Decl);
+}
+
bool TemplateName::isDependent() const {
if (TemplateDecl *Template = getAsTemplateDecl()) {
if (isa<TemplateTemplateParmDecl>(Template))
@@ -209,7 +235,7 @@ TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
TemplateName N) {
std::string NameStr;
- raw_string_ostream OS(NameStr);
+ llvm::raw_string_ostream OS(NameStr);
LangOptions LO;
LO.CPlusPlus = true;
LO.Bool = true;
diff --git a/contrib/llvm/tools/clang/lib/AST/Type.cpp b/contrib/llvm/tools/clang/lib/AST/Type.cpp
index d21781dc38992..38f2a16fa16ff 100644
--- a/contrib/llvm/tools/clang/lib/AST/Type.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Type.cpp
@@ -1,4 +1,4 @@
-//===--- Type.cpp - Type representation and manipulation ------------------===//
+//===- Type.cpp - Type representation and manipulation --------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,20 +12,44 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/Type.h"
+#include "Linkage.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/CharUnits.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/PrettyPrinter.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/TemplateName.h"
#include "clang/AST/TypeVisitor.h"
+#include "clang/Basic/AddressSpaces.h"
+#include "clang/Basic/ExceptionSpecificationType.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/Linkage.h"
#include "clang/Basic/Specifiers.h"
+#include "clang/Basic/TargetCXXABI.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/Visibility.h"
+#include "llvm/ADT/APInt.h"
#include "llvm/ADT/APSInt.h"
-#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <cstring>
+
using namespace clang;
bool Qualifiers::isStrictSupersetOf(Qualifiers Other) const {
@@ -125,12 +149,10 @@ DependentSizedArrayType::DependentSizedArrayType(const ASTContext &Context,
Expr *e, ArraySizeModifier sm,
unsigned tq,
SourceRange brackets)
- : ArrayType(DependentSizedArray, et, can, sm, tq,
+ : ArrayType(DependentSizedArray, et, can, sm, tq,
(et->containsUnexpandedParameterPack() ||
(e && e->containsUnexpandedParameterPack()))),
- Context(Context), SizeExpr((Stmt*) e), Brackets(brackets)
-{
-}
+ Context(Context), SizeExpr((Stmt*) e), Brackets(brackets) {}
void DependentSizedArrayType::Profile(llvm::FoldingSetNodeID &ID,
const ASTContext &Context,
@@ -152,13 +174,11 @@ DependentSizedExtVectorType::DependentSizedExtVectorType(const
SourceLocation loc)
: Type(DependentSizedExtVector, can, /*Dependent=*/true,
/*InstantiationDependent=*/true,
- ElementType->isVariablyModifiedType(),
+ ElementType->isVariablyModifiedType(),
(ElementType->containsUnexpandedParameterPack() ||
(SizeExpr && SizeExpr->containsUnexpandedParameterPack()))),
Context(Context), SizeExpr(SizeExpr), ElementType(ElementType),
- loc(loc)
-{
-}
+ loc(loc) {}
void
DependentSizedExtVectorType::Profile(llvm::FoldingSetNodeID &ID,
@@ -168,18 +188,37 @@ DependentSizedExtVectorType::Profile(llvm::FoldingSetNodeID &ID,
SizeExpr->Profile(ID, Context, true);
}
+DependentAddressSpaceType::DependentAddressSpaceType(
+ const ASTContext &Context, QualType PointeeType, QualType can,
+ Expr *AddrSpaceExpr, SourceLocation loc)
+ : Type(DependentAddressSpace, can, /*Dependent=*/true,
+ /*InstantiationDependent=*/true,
+ PointeeType->isVariablyModifiedType(),
+ (PointeeType->containsUnexpandedParameterPack() ||
+ (AddrSpaceExpr &&
+ AddrSpaceExpr->containsUnexpandedParameterPack()))),
+ Context(Context), AddrSpaceExpr(AddrSpaceExpr), PointeeType(PointeeType),
+ loc(loc) {}
+
+void DependentAddressSpaceType::Profile(llvm::FoldingSetNodeID &ID,
+ const ASTContext &Context,
+ QualType PointeeType,
+ Expr *AddrSpaceExpr) {
+ ID.AddPointer(PointeeType.getAsOpaquePtr());
+ AddrSpaceExpr->Profile(ID, Context, true);
+}
+
VectorType::VectorType(QualType vecType, unsigned nElements, QualType canonType,
VectorKind vecKind)
: VectorType(Vector, vecType, nElements, canonType, vecKind) {}
VectorType::VectorType(TypeClass tc, QualType vecType, unsigned nElements,
QualType canonType, VectorKind vecKind)
- : Type(tc, canonType, vecType->isDependentType(),
- vecType->isInstantiationDependentType(),
- vecType->isVariablyModifiedType(),
- vecType->containsUnexpandedParameterPack()),
- ElementType(vecType)
-{
+ : Type(tc, canonType, vecType->isDependentType(),
+ vecType->isInstantiationDependentType(),
+ vecType->isVariablyModifiedType(),
+ vecType->containsUnexpandedParameterPack()),
+ ElementType(vecType) {
VectorTypeBits.VecKind = vecKind;
VectorTypeBits.NumElements = nElements;
}
@@ -354,11 +393,13 @@ const Type *Type::getUnqualifiedDesugaredType() const {
}
}
}
+
bool Type::isClassType() const {
if (const RecordType *RT = getAs<RecordType>())
return RT->getDecl()->isClass();
return false;
}
+
bool Type::isStructureType() const {
if (const RecordType *RT = getAs<RecordType>())
return RT->getDecl()->isStruct();
@@ -381,6 +422,7 @@ bool Type::isStructureOrClassType() const {
}
return false;
}
+
bool Type::isVoidPointerType() const {
if (const PointerType *PT = getAs<PointerType>())
return PT->getPointeeType()->isVoidType();
@@ -534,12 +576,11 @@ bool Type::isObjCInertUnsafeUnretainedType() const {
ObjCTypeParamType::ObjCTypeParamType(const ObjCTypeParamDecl *D,
QualType can,
ArrayRef<ObjCProtocolDecl *> protocols)
- : Type(ObjCTypeParam, can, can->isDependentType(),
- can->isInstantiationDependentType(),
- can->isVariablyModifiedType(),
- /*ContainsUnexpandedParameterPack=*/false),
- OTPDecl(const_cast<ObjCTypeParamDecl*>(D))
-{
+ : Type(ObjCTypeParam, can, can->isDependentType(),
+ can->isInstantiationDependentType(),
+ can->isVariablyModifiedType(),
+ /*ContainsUnexpandedParameterPack=*/false),
+ OTPDecl(const_cast<ObjCTypeParamDecl*>(D)) {
initialize(protocols);
}
@@ -547,12 +588,11 @@ ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base,
ArrayRef<QualType> typeArgs,
ArrayRef<ObjCProtocolDecl *> protocols,
bool isKindOf)
- : Type(ObjCObject, Canonical, Base->isDependentType(),
- Base->isInstantiationDependentType(),
- Base->isVariablyModifiedType(),
- Base->containsUnexpandedParameterPack()),
- BaseType(Base)
-{
+ : Type(ObjCObject, Canonical, Base->isDependentType(),
+ Base->isInstantiationDependentType(),
+ Base->isVariablyModifiedType(),
+ Base->containsUnexpandedParameterPack()),
+ BaseType(Base) {
ObjCObjectTypeBits.IsKindOf = isKindOf;
ObjCObjectTypeBits.NumTypeArgs = typeArgs.size();
@@ -603,13 +643,13 @@ ArrayRef<QualType> ObjCObjectType::getTypeArgs() const {
if (auto objcObject = getBaseType()->getAs<ObjCObjectType>()) {
// Terminate when we reach an interface type.
if (isa<ObjCInterfaceType>(objcObject))
- return { };
+ return {};
return objcObject->getTypeArgs();
}
// No type arguments.
- return { };
+ return {};
}
bool ObjCObjectType::isKindOfType() const {
@@ -645,7 +685,7 @@ QualType ObjCObjectType::stripObjCKindOfTypeAndQuals(
return ctx.getObjCObjectType(ctx.getQualifiedType(baseType,
splitBaseType.Quals),
getTypeArgsAsWritten(),
- /*protocols=*/{ },
+ /*protocols=*/{},
/*isKindOf=*/false);
}
@@ -658,10 +698,10 @@ const ObjCObjectPointerType *ObjCObjectPointerType::stripObjCKindOfTypeAndQuals(
return ctx.getObjCObjectPointerType(obj)->castAs<ObjCObjectPointerType>();
}
-namespace {
-
template<typename F>
-QualType simpleTransform(ASTContext &ctx, QualType type, F &&f);
+static QualType simpleTransform(ASTContext &ctx, QualType type, F &&f);
+
+namespace {
/// Visitor used by simpleTransform() to perform the transformation.
template<typename F>
@@ -675,7 +715,8 @@ struct SimpleTransformVisitor
}
public:
- SimpleTransformVisitor(ASTContext &ctx, F &&f) : Ctx(ctx), TheFunc(std::move(f)) { }
+ SimpleTransformVisitor(ASTContext &ctx, F &&f)
+ : Ctx(ctx), TheFunc(std::move(f)) {}
// None of the clients of this transformation can occur where
// there are dependent types, so skip dependent types.
@@ -1044,10 +1085,12 @@ public:
#undef TRIVIAL_TYPE_CLASS
};
+} // namespace
+
/// Perform a simple type transformation that does not change the
/// semantics of the type.
template<typename F>
-QualType simpleTransform(ASTContext &ctx, QualType type, F &&f) {
+static QualType simpleTransform(ASTContext &ctx, QualType type, F &&f) {
// Transform the type. If it changed, return the transformed result.
QualType transformed = f(type);
if (transformed.getAsOpaquePtr() != type.getAsOpaquePtr())
@@ -1067,8 +1110,6 @@ QualType simpleTransform(ASTContext &ctx, QualType type, F &&f) {
return ctx.getQualifiedType(result, splitType.Quals);
}
-} // end anonymous namespace
-
/// Substitute the given type arguments for Objective-C type
/// parameters within the given type, recursively.
QualType QualType::substObjCTypeArgs(
@@ -1233,7 +1274,7 @@ QualType QualType::substObjCTypeArgs(
if (typeArgs.empty() &&
context != ObjCSubstitutionContext::Superclass) {
return ctx.getObjCObjectType(
- objcObjectType->getBaseType(), { },
+ objcObjectType->getBaseType(), {},
protocols,
objcObjectType->isKindOfTypeAsWritten());
}
@@ -1343,7 +1384,7 @@ Optional<ArrayRef<QualType>> Type::getObjCSubstitutions(
objectType = objectPointerType->getObjectType();
} else if (getAs<BlockPointerType>()) {
ASTContext &ctx = dc->getParentASTContext();
- objectType = ctx.getObjCObjectType(ctx.ObjCBuiltinIdTy, { }, { })
+ objectType = ctx.getObjCObjectType(ctx.ObjCBuiltinIdTy, {}, {})
->castAs<ObjCObjectType>();
} else {
objectType = getAs<ObjCObjectType>();
@@ -1522,6 +1563,7 @@ const ObjCObjectType *Type::getAsObjCInterfaceType() const {
}
return nullptr;
}
+
const ObjCObjectPointerType *Type::getAsObjCInterfacePointerType() const {
if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) {
if (OPT->getInterfaceType())
@@ -1559,14 +1601,17 @@ TagDecl *Type::getAsTagDecl() const {
}
namespace {
+
class GetContainedDeducedTypeVisitor :
public TypeVisitor<GetContainedDeducedTypeVisitor, Type*> {
bool Syntactic;
+
public:
GetContainedDeducedTypeVisitor(bool Syntactic = false)
: Syntactic(Syntactic) {}
using TypeVisitor<GetContainedDeducedTypeVisitor, Type*>::Visit;
+
Type *Visit(QualType T) {
if (T.isNull())
return nullptr;
@@ -1579,50 +1624,64 @@ namespace {
}
// Only these types can contain the desired 'auto' type.
+
Type *VisitElaboratedType(const ElaboratedType *T) {
return Visit(T->getNamedType());
}
+
Type *VisitPointerType(const PointerType *T) {
return Visit(T->getPointeeType());
}
+
Type *VisitBlockPointerType(const BlockPointerType *T) {
return Visit(T->getPointeeType());
}
+
Type *VisitReferenceType(const ReferenceType *T) {
return Visit(T->getPointeeTypeAsWritten());
}
+
Type *VisitMemberPointerType(const MemberPointerType *T) {
return Visit(T->getPointeeType());
}
+
Type *VisitArrayType(const ArrayType *T) {
return Visit(T->getElementType());
}
+
Type *VisitDependentSizedExtVectorType(
const DependentSizedExtVectorType *T) {
return Visit(T->getElementType());
}
+
Type *VisitVectorType(const VectorType *T) {
return Visit(T->getElementType());
}
+
Type *VisitFunctionProtoType(const FunctionProtoType *T) {
if (Syntactic && T->hasTrailingReturn())
return const_cast<FunctionProtoType*>(T);
return VisitFunctionType(T);
}
+
Type *VisitFunctionType(const FunctionType *T) {
return Visit(T->getReturnType());
}
+
Type *VisitParenType(const ParenType *T) {
return Visit(T->getInnerType());
}
+
Type *VisitAttributedType(const AttributedType *T) {
return Visit(T->getModifiedType());
}
+
Type *VisitAdjustedType(const AdjustedType *T) {
return Visit(T->getOriginalType());
}
};
-}
+
+} // namespace
DeducedType *Type::getContainedDeducedType() const {
return cast_or_null<DeducedType>(
@@ -1673,7 +1732,6 @@ bool Type::isIntegralType(const ASTContext &Ctx) const {
return false;
}
-
bool Type::isIntegralOrUnscopedEnumerationType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
@@ -1689,8 +1747,6 @@ bool Type::isIntegralOrUnscopedEnumerationType() const {
return false;
}
-
-
bool Type::isCharType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() == BuiltinType::Char_U ||
@@ -2015,7 +2071,7 @@ bool QualType::isCXX98PODType(const ASTContext &Context) const {
// We return false for that case. Except for incomplete arrays of PODs, which
// are PODs according to the standard.
if (isNull())
- return 0;
+ return false;
if ((*this)->isIncompleteArrayType())
return Context.getBaseElementType(*this).isCXX98PODType(Context);
@@ -2063,7 +2119,7 @@ bool QualType::isTrivialType(const ASTContext &Context) const {
// We return false for that case. Except for incomplete arrays of PODs, which
// are PODs according to the standard.
if (isNull())
- return 0;
+ return false;
if ((*this)->isArrayType())
return Context.getBaseElementType(*this).isTrivialType(Context);
@@ -2563,6 +2619,8 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const {
return "double";
case LongDouble:
return "long double";
+ case Float16:
+ return "_Float16";
case Float128:
return "__float128";
case WChar_S:
@@ -2835,7 +2893,6 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
const QualType *ArgTys, unsigned NumParams,
const ExtProtoInfo &epi,
const ASTContext &Context, bool Canonical) {
-
// We have to be careful not to get ambiguous profile encodings.
// Note that valid type pointers are never ambiguous with anything else.
//
@@ -2897,12 +2954,11 @@ QualType TypedefType::desugar() const {
}
TypeOfExprType::TypeOfExprType(Expr *E, QualType can)
- : Type(TypeOfExpr, can, E->isTypeDependent(),
- E->isInstantiationDependent(),
- E->getType()->isVariablyModifiedType(),
- E->containsUnexpandedParameterPack()),
- TOExpr(E) {
-}
+ : Type(TypeOfExpr, can, E->isTypeDependent(),
+ E->isInstantiationDependent(),
+ E->getType()->isVariablyModifiedType(),
+ E->containsUnexpandedParameterPack()),
+ TOExpr(E) {}
bool TypeOfExprType::isSugared() const {
return !TOExpr->isTypeDependent();
@@ -2924,13 +2980,11 @@ DecltypeType::DecltypeType(Expr *E, QualType underlyingType, QualType can)
// C++11 [temp.type]p2: "If an expression e involves a template parameter,
// decltype(e) denotes a unique dependent type." Hence a decltype type is
// type-dependent even if its expression is only instantiation-dependent.
- : Type(Decltype, can, E->isInstantiationDependent(),
- E->isInstantiationDependent(),
- E->getType()->isVariablyModifiedType(),
- E->containsUnexpandedParameterPack()),
- E(E),
- UnderlyingType(underlyingType) {
-}
+ : Type(Decltype, can, E->isInstantiationDependent(),
+ E->isInstantiationDependent(),
+ E->getType()->isVariablyModifiedType(),
+ E->containsUnexpandedParameterPack()),
+ E(E), UnderlyingType(underlyingType) {}
bool DecltypeType::isSugared() const { return !E->isInstantiationDependent(); }
@@ -2942,7 +2996,7 @@ QualType DecltypeType::desugar() const {
}
DependentDecltypeType::DependentDecltypeType(const ASTContext &Context, Expr *E)
- : DecltypeType(E, Context.DependentTy), Context(Context) { }
+ : DecltypeType(E, Context.DependentTy), Context(Context) {}
void DependentDecltypeType::Profile(llvm::FoldingSetNodeID &ID,
const ASTContext &Context, Expr *E) {
@@ -2953,26 +3007,23 @@ UnaryTransformType::UnaryTransformType(QualType BaseType,
QualType UnderlyingType,
UTTKind UKind,
QualType CanonicalType)
- : Type(UnaryTransform, CanonicalType, BaseType->isDependentType(),
- BaseType->isInstantiationDependentType(),
- BaseType->isVariablyModifiedType(),
- BaseType->containsUnexpandedParameterPack())
- , BaseType(BaseType), UnderlyingType(UnderlyingType), UKind(UKind)
-{}
+ : Type(UnaryTransform, CanonicalType, BaseType->isDependentType(),
+ BaseType->isInstantiationDependentType(),
+ BaseType->isVariablyModifiedType(),
+ BaseType->containsUnexpandedParameterPack()),
+ BaseType(BaseType), UnderlyingType(UnderlyingType), UKind(UKind) {}
DependentUnaryTransformType::DependentUnaryTransformType(const ASTContext &C,
QualType BaseType,
UTTKind UKind)
- : UnaryTransformType(BaseType, C.DependentTy, UKind, QualType())
-{}
-
+ : UnaryTransformType(BaseType, C.DependentTy, UKind, QualType()) {}
TagType::TagType(TypeClass TC, const TagDecl *D, QualType can)
- : Type(TC, can, D->isDependentType(),
- /*InstantiationDependent=*/D->isDependentType(),
- /*VariablyModified=*/false,
- /*ContainsUnexpandedParameterPack=*/false),
- decl(const_cast<TagDecl*>(D)) {}
+ : Type(TC, can, D->isDependentType(),
+ /*InstantiationDependent=*/D->isDependentType(),
+ /*VariablyModified=*/false,
+ /*ContainsUnexpandedParameterPack=*/false),
+ decl(const_cast<TagDecl*>(D)) {}
static TagDecl *getInterestingTagDecl(TagDecl *decl) {
for (auto I : decl->redecls()) {
@@ -2991,6 +3042,19 @@ bool TagType::isBeingDefined() const {
return getDecl()->isBeingDefined();
}
+bool RecordType::hasConstFields() const {
+ for (FieldDecl *FD : getDecl()->fields()) {
+ QualType FieldTy = FD->getType();
+ if (FieldTy.isConstQualified())
+ return true;
+ FieldTy = FieldTy.getCanonicalType();
+ if (const RecordType *FieldRecTy = FieldTy->getAs<RecordType>())
+ if (FieldRecTy->hasConstFields())
+ return true;
+ }
+ return false;
+}
+
bool AttributedType::isQualifier() const {
switch (getAttrKind()) {
// These are type qualifiers in the traditional C sense: they annotate
@@ -3104,11 +3168,9 @@ SubstTemplateTypeParmPackType::
SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param,
QualType Canon,
const TemplateArgument &ArgPack)
- : Type(SubstTemplateTypeParmPack, Canon, true, true, false, true),
- Replaced(Param),
- Arguments(ArgPack.pack_begin()), NumArguments(ArgPack.pack_size())
-{
-}
+ : Type(SubstTemplateTypeParmPack, Canon, true, true, false, true),
+ Replaced(Param),
+ Arguments(ArgPack.pack_begin()), NumArguments(ArgPack.pack_size()) {}
TemplateArgument SubstTemplateTypeParmPackType::getArgumentPack() const {
return TemplateArgument(llvm::makeArrayRef(Arguments, NumArguments));
@@ -3275,11 +3337,13 @@ public:
L.hasLocalOrUnnamedType() | R.hasLocalOrUnnamedType());
}
};
-}
+
+} // namespace
static CachedProperties computeCachedProperties(const Type *T);
namespace clang {
+
/// The type-property cache. This is templated so as to be
/// instantiated at an internal type to prevent unnecessary symbol
/// leakage.
@@ -3317,13 +3381,19 @@ public:
T->TypeBits.CachedLocalOrUnnamed = Result.hasLocalOrUnnamedType();
}
};
-}
+
+} // namespace clang
// Instantiate the friend template at a private class. In a
// reasonable implementation, these symbols will be internal.
// It is terrible that this is the best way to accomplish this.
-namespace { class Private {}; }
-typedef TypePropertyCache<Private> Cache;
+namespace {
+
+class Private {};
+
+} // namespace
+
+using Cache = TypePropertyCache<Private>;
static CachedProperties computeCachedProperties(const Type *T) {
switch (T->getTypeClass()) {
@@ -3428,9 +3498,7 @@ bool Type::hasUnnamedOrLocalType() const {
return TypeBits.hasLocalOrUnnamedType();
}
-static LinkageInfo computeLinkageInfo(QualType T);
-
-static LinkageInfo computeLinkageInfo(const Type *T) {
+LinkageInfo LinkageComputer::computeTypeLinkageInfo(const Type *T) {
switch (T->getTypeClass()) {
#define TYPE(Class,Base)
#define NON_CANONICAL_TYPE(Class,Base) case Type::Class:
@@ -3454,75 +3522,78 @@ static LinkageInfo computeLinkageInfo(const Type *T) {
case Type::Record:
case Type::Enum:
- return cast<TagType>(T)->getDecl()->getLinkageAndVisibility();
+ return getDeclLinkageAndVisibility(cast<TagType>(T)->getDecl());
case Type::Complex:
- return computeLinkageInfo(cast<ComplexType>(T)->getElementType());
+ return computeTypeLinkageInfo(cast<ComplexType>(T)->getElementType());
case Type::Pointer:
- return computeLinkageInfo(cast<PointerType>(T)->getPointeeType());
+ return computeTypeLinkageInfo(cast<PointerType>(T)->getPointeeType());
case Type::BlockPointer:
- return computeLinkageInfo(cast<BlockPointerType>(T)->getPointeeType());
+ return computeTypeLinkageInfo(cast<BlockPointerType>(T)->getPointeeType());
case Type::LValueReference:
case Type::RValueReference:
- return computeLinkageInfo(cast<ReferenceType>(T)->getPointeeType());
+ return computeTypeLinkageInfo(cast<ReferenceType>(T)->getPointeeType());
case Type::MemberPointer: {
const MemberPointerType *MPT = cast<MemberPointerType>(T);
- LinkageInfo LV = computeLinkageInfo(MPT->getClass());
- LV.merge(computeLinkageInfo(MPT->getPointeeType()));
+ LinkageInfo LV = computeTypeLinkageInfo(MPT->getClass());
+ LV.merge(computeTypeLinkageInfo(MPT->getPointeeType()));
return LV;
}
case Type::ConstantArray:
case Type::IncompleteArray:
case Type::VariableArray:
- return computeLinkageInfo(cast<ArrayType>(T)->getElementType());
+ return computeTypeLinkageInfo(cast<ArrayType>(T)->getElementType());
case Type::Vector:
case Type::ExtVector:
- return computeLinkageInfo(cast<VectorType>(T)->getElementType());
+ return computeTypeLinkageInfo(cast<VectorType>(T)->getElementType());
case Type::FunctionNoProto:
- return computeLinkageInfo(cast<FunctionType>(T)->getReturnType());
+ return computeTypeLinkageInfo(cast<FunctionType>(T)->getReturnType());
case Type::FunctionProto: {
const FunctionProtoType *FPT = cast<FunctionProtoType>(T);
- LinkageInfo LV = computeLinkageInfo(FPT->getReturnType());
+ LinkageInfo LV = computeTypeLinkageInfo(FPT->getReturnType());
for (const auto &ai : FPT->param_types())
- LV.merge(computeLinkageInfo(ai));
+ LV.merge(computeTypeLinkageInfo(ai));
return LV;
}
case Type::ObjCInterface:
- return cast<ObjCInterfaceType>(T)->getDecl()->getLinkageAndVisibility();
+ return getDeclLinkageAndVisibility(cast<ObjCInterfaceType>(T)->getDecl());
case Type::ObjCObject:
- return computeLinkageInfo(cast<ObjCObjectType>(T)->getBaseType());
+ return computeTypeLinkageInfo(cast<ObjCObjectType>(T)->getBaseType());
case Type::ObjCObjectPointer:
- return computeLinkageInfo(cast<ObjCObjectPointerType>(T)->getPointeeType());
+ return computeTypeLinkageInfo(
+ cast<ObjCObjectPointerType>(T)->getPointeeType());
case Type::Atomic:
- return computeLinkageInfo(cast<AtomicType>(T)->getValueType());
+ return computeTypeLinkageInfo(cast<AtomicType>(T)->getValueType());
case Type::Pipe:
- return computeLinkageInfo(cast<PipeType>(T)->getElementType());
+ return computeTypeLinkageInfo(cast<PipeType>(T)->getElementType());
}
llvm_unreachable("unhandled type class");
}
-static LinkageInfo computeLinkageInfo(QualType T) {
- return computeLinkageInfo(T.getTypePtr());
-}
-
bool Type::isLinkageValid() const {
if (!TypeBits.isCacheValid())
return true;
- return computeLinkageInfo(getCanonicalTypeInternal()).getLinkage() ==
- TypeBits.getLinkage();
+ Linkage L = LinkageComputer{}
+ .computeTypeLinkageInfo(getCanonicalTypeInternal())
+ .getLinkage();
+ return L == TypeBits.getLinkage();
}
-LinkageInfo Type::getLinkageAndVisibility() const {
- if (!isCanonicalUnqualified())
- return computeLinkageInfo(getCanonicalTypeInternal());
+LinkageInfo LinkageComputer::getTypeLinkageAndVisibility(const Type *T) {
+ if (!T->isCanonicalUnqualified())
+ return computeTypeLinkageInfo(T->getCanonicalTypeInternal());
- LinkageInfo LV = computeLinkageInfo(this);
- assert(LV.getLinkage() == getLinkage());
+ LinkageInfo LV = computeTypeLinkageInfo(T);
+ assert(LV.getLinkage() == T->getLinkage());
return LV;
}
+LinkageInfo Type::getLinkageAndVisibility() const {
+ return LinkageComputer{}.getTypeLinkageAndVisibility(this);
+}
+
Optional<NullabilityKind> Type::getNullability(const ASTContext &context) const {
QualType type(this, 0);
do {
@@ -3634,6 +3705,7 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
case Type::DependentSizedExtVector:
case Type::Vector:
case Type::ExtVector:
+ case Type::DependentAddressSpace:
case Type::FunctionProto:
case Type::FunctionNoProto:
case Type::Record:
@@ -3748,11 +3820,13 @@ bool Type::isObjCIndependentClassType() const {
return typedefType->getDecl()->hasAttr<ObjCIndependentClassAttr>();
return false;
}
+
bool Type::isObjCRetainableType() const {
return isObjCObjectPointerType() ||
isBlockPointerType() ||
isObjCNSObjectType();
}
+
bool Type::isObjCIndirectLifetimeType() const {
if (isObjCLifetimeType())
return true;
diff --git a/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp
index c9a268655723b..b05c5fc680962 100644
--- a/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp
@@ -1,4 +1,4 @@
-//===--- TypeLoc.cpp - Type Source Info Wrapper -----------------*- C++ -*-===//
+//===- TypeLoc.cpp - Type Source Info Wrapper -----------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,8 +14,19 @@
#include "clang/AST/TypeLoc.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/TemplateName.h"
#include "clang/AST/TypeLocVisitor.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <cstring>
+
using namespace clang;
static const unsigned TypeLocMaxDataAlign = alignof(void *);
@@ -25,16 +36,18 @@ static const unsigned TypeLocMaxDataAlign = alignof(void *);
//===----------------------------------------------------------------------===//
namespace {
- class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
- public:
+
+class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
+public:
#define ABSTRACT_TYPELOC(CLASS, PARENT)
#define TYPELOC(CLASS, PARENT) \
- SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
- return TyLoc.getLocalSourceRange(); \
- }
+ SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
+ return TyLoc.getLocalSourceRange(); \
+ }
#include "clang/AST/TypeLocNodes.def"
- };
-}
+};
+
+} // namespace
SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {
if (TL.isNull()) return SourceRange();
@@ -42,16 +55,18 @@ SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {
}
namespace {
- class TypeAligner : public TypeLocVisitor<TypeAligner, unsigned> {
- public:
+
+class TypeAligner : public TypeLocVisitor<TypeAligner, unsigned> {
+public:
#define ABSTRACT_TYPELOC(CLASS, PARENT)
#define TYPELOC(CLASS, PARENT) \
- unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
- return TyLoc.getLocalDataAlignment(); \
- }
+ unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
+ return TyLoc.getLocalDataAlignment(); \
+ }
#include "clang/AST/TypeLocNodes.def"
- };
-}
+};
+
+} // namespace
/// \brief Returns the alignment of the type source info data block.
unsigned TypeLoc::getLocalAlignmentForType(QualType Ty) {
@@ -60,16 +75,18 @@ unsigned TypeLoc::getLocalAlignmentForType(QualType Ty) {
}
namespace {
- class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
- public:
+
+class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
+public:
#define ABSTRACT_TYPELOC(CLASS, PARENT)
#define TYPELOC(CLASS, PARENT) \
- unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
- return TyLoc.getLocalDataSize(); \
- }
+ unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
+ return TyLoc.getLocalDataSize(); \
+ }
#include "clang/AST/TypeLocNodes.def"
- };
-}
+};
+
+} // namespace
/// \brief Returns the size of the type source info data block.
unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
@@ -88,16 +105,18 @@ unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
}
namespace {
- class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
- public:
+
+class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
+public:
#define ABSTRACT_TYPELOC(CLASS, PARENT)
#define TYPELOC(CLASS, PARENT) \
- TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
- return TyLoc.getNextTypeLoc(); \
- }
+ TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
+ return TyLoc.getNextTypeLoc(); \
+ }
#include "clang/AST/TypeLocNodes.def"
- };
-}
+};
+
+} // namespace
/// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
/// TypeLoc is a PointerLoc and next TypeLoc is for "int".
@@ -127,20 +146,22 @@ void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL,
}
namespace {
- class TypeLocCopier : public TypeLocVisitor<TypeLocCopier> {
- TypeLoc Source;
- public:
- TypeLocCopier(TypeLoc source) : Source(source) { }
+
+class TypeLocCopier : public TypeLocVisitor<TypeLocCopier> {
+ TypeLoc Source;
+
+public:
+ TypeLocCopier(TypeLoc source) : Source(source) {}
#define ABSTRACT_TYPELOC(CLASS, PARENT)
#define TYPELOC(CLASS, PARENT) \
- void Visit##CLASS##TypeLoc(CLASS##TypeLoc dest) { \
- dest.copyLocal(Source.castAs<CLASS##TypeLoc>()); \
- }
+ void Visit##CLASS##TypeLoc(CLASS##TypeLoc dest) { \
+ dest.copyLocal(Source.castAs<CLASS##TypeLoc>()); \
+ }
#include "clang/AST/TypeLocNodes.def"
- };
-}
+};
+} // namespace
void TypeLoc::copy(TypeLoc other) {
assert(getFullDataSize() == other.getFullDataSize());
@@ -243,22 +264,22 @@ SourceLocation TypeLoc::getEndLoc() const {
}
}
-
namespace {
- struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
- // Overload resolution does the real work for us.
- static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
- static bool isTypeSpec(TypeLoc _) { return false; }
+
+struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
+ // Overload resolution does the real work for us.
+ static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
+ static bool isTypeSpec(TypeLoc _) { return false; }
#define ABSTRACT_TYPELOC(CLASS, PARENT)
#define TYPELOC(CLASS, PARENT) \
- bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
- return isTypeSpec(TyLoc); \
- }
+ bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
+ return isTypeSpec(TyLoc); \
+ }
#include "clang/AST/TypeLocNodes.def"
- };
-}
+};
+} // namespace
/// \brief Determines if the given type loc corresponds to a
/// TypeSpecTypeLoc. Since there is not actually a TypeSpecType in
@@ -319,6 +340,7 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
case BuiltinType::Float:
case BuiltinType::Double:
case BuiltinType::LongDouble:
+ case BuiltinType::Float16:
case BuiltinType::Float128:
llvm_unreachable("Builtin type needs extra local data!");
// Fall through, if the impossible happens.
@@ -363,7 +385,7 @@ SourceLocation TypeLoc::findNullabilityLoc() const {
return attributedLoc.getAttrNameLoc();
}
- return SourceLocation();
+ return {};
}
TypeLoc TypeLoc::findExplicitQualifierLoc() const {
@@ -384,7 +406,7 @@ TypeLoc TypeLoc::findExplicitQualifierLoc() const {
return atomic;
}
- return TypeLoc();
+ return {};
}
void ObjCTypeParamTypeLoc::initializeLocal(ASTContext &Context,
@@ -422,6 +444,15 @@ void TypeOfTypeLoc::initializeLocal(ASTContext &Context,
getUnderlyingType(), Loc);
}
+void UnaryTransformTypeLoc::initializeLocal(ASTContext &Context,
+ SourceLocation Loc) {
+ setKWLoc(Loc);
+ setRParenLoc(Loc);
+ setLParenLoc(Loc);
+ this->setUnderlyingTInfo(
+ Context.getTrivialTypeSourceInfo(getTypePtr()->getBaseType(), Loc));
+}
+
void ElaboratedTypeLoc::initializeLocal(ASTContext &Context,
SourceLocation Loc) {
setElaboratedKeywordLoc(Loc);
diff --git a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp
index 15c63bf4ed988..35e0b75f3c22e 100644
--- a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp
@@ -222,6 +222,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T,
case Type::LValueReference:
case Type::RValueReference:
case Type::MemberPointer:
+ case Type::DependentAddressSpace:
case Type::DependentSizedExtVector:
case Type::Vector:
case Type::ExtVector:
@@ -527,6 +528,19 @@ void TypePrinter::printDependentSizedArrayAfter(
printAfter(T->getElementType(), OS);
}
+void TypePrinter::printDependentAddressSpaceBefore(
+ const DependentAddressSpaceType *T, raw_ostream &OS) {
+ printBefore(T->getPointeeType(), OS);
+}
+void TypePrinter::printDependentAddressSpaceAfter(
+ const DependentAddressSpaceType *T, raw_ostream &OS) {
+ OS << " __attribute__((address_space(";
+ if (T->getAddrSpaceExpr())
+ T->getAddrSpaceExpr()->printPretty(OS, nullptr, Policy);
+ OS << ")))";
+ printAfter(T->getPointeeType(), OS);
+}
+
void TypePrinter::printDependentSizedExtVectorBefore(
const DependentSizedExtVectorType *T,
raw_ostream &OS) {
@@ -665,6 +679,8 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,
auto EPI = T->getExtParameterInfo(i);
if (EPI.isConsumed()) OS << "__attribute__((ns_consumed)) ";
+ if (EPI.isNoEscape())
+ OS << "__attribute__((noescape)) ";
auto ABI = EPI.getABI();
if (ABI != ParameterABI::Ordinary)
OS << "__attribute__((" << getParameterABISpelling(ABI) << ")) ";
@@ -966,8 +982,7 @@ void TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
OS << Spec->getIdentifier()->getName();
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
- TemplateSpecializationType::PrintTemplateArgumentList(
- OS, TemplateArgs.asArray(), Policy);
+ printTemplateArgumentList(OS, TemplateArgs.asArray(), Policy);
OS << "::";
} else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
if (TypedefNameDecl *Typedef = Tag->getTypedefNameForAnonDecl())
@@ -1054,7 +1069,7 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) {
Args = TemplateArgs.asArray();
}
IncludeStrongLifetimeRAII Strong(Policy);
- TemplateSpecializationType::PrintTemplateArgumentList(OS, Args, Policy);
+ printTemplateArgumentList(OS, Args, Policy);
}
spaceBeforePlaceHolder(OS);
@@ -1113,8 +1128,7 @@ void TypePrinter::printTemplateSpecializationBefore(
IncludeStrongLifetimeRAII Strong(Policy);
T->getTemplateName().print(OS, Policy);
- TemplateSpecializationType::PrintTemplateArgumentList(
- OS, T->template_arguments(), Policy);
+ printTemplateArgumentList(OS, T->template_arguments(), Policy);
spaceBeforePlaceHolder(OS);
}
void TypePrinter::printTemplateSpecializationAfter(
@@ -1182,19 +1196,18 @@ void TypePrinter::printDependentNameAfter(const DependentNameType *T,
void TypePrinter::printDependentTemplateSpecializationBefore(
const DependentTemplateSpecializationType *T, raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
-
+
OS << TypeWithKeyword::getKeywordName(T->getKeyword());
if (T->getKeyword() != ETK_None)
OS << " ";
-
+
if (T->getQualifier())
- T->getQualifier()->print(OS, Policy);
+ T->getQualifier()->print(OS, Policy);
OS << T->getIdentifier()->getName();
- TemplateSpecializationType::PrintTemplateArgumentList(OS,
- T->template_arguments(),
- Policy);
+ printTemplateArgumentList(OS, T->template_arguments(), Policy);
spaceBeforePlaceHolder(OS);
}
+
void TypePrinter::printDependentTemplateSpecializationAfter(
const DependentTemplateSpecializationType *T, raw_ostream &OS) { }
@@ -1304,7 +1317,9 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
default: llvm_unreachable("This attribute should have been handled already");
case AttributedType::attr_address_space:
OS << "address_space(";
- OS << T->getEquivalentType().getAddressSpace();
+ // FIXME: printing the raw LangAS value is wrong. This should probably
+ // use the same code as Qualifiers::print()
+ OS << (unsigned)T->getEquivalentType().getAddressSpace();
OS << ')';
break;
@@ -1503,41 +1518,39 @@ void TypePrinter::printObjCObjectPointerBefore(const ObjCObjectPointerType *T,
OS << '*';
}
}
+
void TypePrinter::printObjCObjectPointerAfter(const ObjCObjectPointerType *T,
raw_ostream &OS) { }
-void TemplateSpecializationType::
- PrintTemplateArgumentList(raw_ostream &OS,
- const TemplateArgumentListInfo &Args,
- const PrintingPolicy &Policy) {
- return PrintTemplateArgumentList(OS,
- Args.arguments(),
- Policy);
+static
+const TemplateArgument &getArgument(const TemplateArgument &A) { return A; }
+
+static const TemplateArgument &getArgument(const TemplateArgumentLoc &A) {
+ return A.getArgument();
}
-void TemplateSpecializationType::PrintTemplateArgumentList(
- raw_ostream &OS, ArrayRef<TemplateArgument> Args,
- const PrintingPolicy &Policy, bool SkipBrackets) {
+template<typename TA>
+static void printTo(raw_ostream &OS, ArrayRef<TA> Args,
+ const PrintingPolicy &Policy, bool SkipBrackets) {
const char *Comma = Policy.MSVCFormatting ? "," : ", ";
if (!SkipBrackets)
OS << '<';
- bool needSpace = false;
+ bool NeedSpace = false;
bool FirstArg = true;
- for (const TemplateArgument &Arg : Args) {
+ for (const auto &Arg : Args) {
// Print the argument into a string.
SmallString<128> Buf;
llvm::raw_svector_ostream ArgOS(Buf);
- if (Arg.getKind() == TemplateArgument::Pack) {
- if (Arg.pack_size() && !FirstArg)
+ const TemplateArgument &Argument = getArgument(Arg);
+ if (Argument.getKind() == TemplateArgument::Pack) {
+ if (Argument.pack_size() && !FirstArg)
OS << Comma;
- PrintTemplateArgumentList(ArgOS,
- Arg.getPackAsArray(),
- Policy, true);
+ printTo(ArgOS, Argument.getPackAsArray(), Policy, true);
} else {
if (!FirstArg)
OS << Comma;
- Arg.print(Policy, ArgOS);
+ Argument.print(Policy, ArgOS);
}
StringRef ArgString = ArgOS.str();
@@ -1549,65 +1562,36 @@ void TemplateSpecializationType::PrintTemplateArgumentList(
OS << ArgString;
- needSpace = (!ArgString.empty() && ArgString.back() == '>');
+ NeedSpace = (!ArgString.empty() && ArgString.back() == '>');
FirstArg = false;
}
// If the last character of our string is '>', add another space to
// keep the two '>''s separate tokens. We don't *have* to do this in
// C++0x, but it's still good hygiene.
- if (needSpace)
+ if (NeedSpace)
OS << ' ';
if (!SkipBrackets)
OS << '>';
}
-// Sadly, repeat all that with TemplateArgLoc.
-void TemplateSpecializationType::
-PrintTemplateArgumentList(raw_ostream &OS,
- ArrayRef<TemplateArgumentLoc> Args,
- const PrintingPolicy &Policy) {
- OS << '<';
- const char *Comma = Policy.MSVCFormatting ? "," : ", ";
-
- bool needSpace = false;
- bool FirstArg = true;
- for (const TemplateArgumentLoc &Arg : Args) {
- if (!FirstArg)
- OS << Comma;
-
- // Print the argument into a string.
- SmallString<128> Buf;
- llvm::raw_svector_ostream ArgOS(Buf);
- if (Arg.getArgument().getKind() == TemplateArgument::Pack) {
- PrintTemplateArgumentList(ArgOS,
- Arg.getArgument().getPackAsArray(),
- Policy, true);
- } else {
- Arg.getArgument().print(Policy, ArgOS);
- }
- StringRef ArgString = ArgOS.str();
-
- // If this is the first argument and its string representation
- // begins with the global scope specifier ('::foo'), add a space
- // to avoid printing the diagraph '<:'.
- if (FirstArg && !ArgString.empty() && ArgString[0] == ':')
- OS << ' ';
-
- OS << ArgString;
-
- needSpace = (!ArgString.empty() && ArgString.back() == '>');
- FirstArg = false;
- }
+void clang::printTemplateArgumentList(raw_ostream &OS,
+ const TemplateArgumentListInfo &Args,
+ const PrintingPolicy &Policy) {
+ return printTo(OS, Args.arguments(), Policy, false);
+}
- // If the last character of our string is '>', add another space to
- // keep the two '>''s separate tokens. We don't *have* to do this in
- // C++0x, but it's still good hygiene.
- if (needSpace)
- OS << ' ';
+void clang::printTemplateArgumentList(raw_ostream &OS,
+ ArrayRef<TemplateArgument> Args,
+ const PrintingPolicy &Policy) {
+ printTo(OS, Args, Policy, false);
+}
- OS << '>';
+void clang::printTemplateArgumentList(raw_ostream &OS,
+ ArrayRef<TemplateArgumentLoc> Args,
+ const PrintingPolicy &Policy) {
+ printTo(OS, Args, Policy, false);
}
std::string Qualifiers::getAsString() const {
@@ -1629,7 +1613,7 @@ bool Qualifiers::isEmptyWhenPrinted(const PrintingPolicy &Policy) const {
if (getCVRQualifiers())
return false;
- if (getAddressSpace())
+ if (getAddressSpace() != LangAS::Default)
return false;
if (getObjCGCAttr())
@@ -1660,17 +1644,21 @@ void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy,
OS << "__unaligned";
addSpace = true;
}
- if (unsigned addrspace = getAddressSpace()) {
- if (addSpace)
- OS << ' ';
- addSpace = true;
- switch (addrspace) {
+ LangAS addrspace = getAddressSpace();
+ if (addrspace != LangAS::Default) {
+ if (addrspace != LangAS::opencl_private) {
+ if (addSpace)
+ OS << ' ';
+ addSpace = true;
+ switch (addrspace) {
case LangAS::opencl_global:
OS << "__global";
break;
case LangAS::opencl_local:
OS << "__local";
break;
+ case LangAS::opencl_private:
+ break;
case LangAS::opencl_constant:
case LangAS::cuda_constant:
OS << "__constant";
@@ -1685,10 +1673,10 @@ void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy,
OS << "__shared";
break;
default:
- assert(addrspace >= LangAS::FirstTargetAddressSpace);
OS << "__attribute__((address_space(";
- OS << addrspace - LangAS::FirstTargetAddressSpace;
+ OS << toTargetAddressSpace(addrspace);
OS << ")))";
+ }
}
}
if (Qualifiers::GC gc = getObjCGCAttr()) {
diff --git a/contrib/llvm/tools/clang/lib/AST/VTTBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/VTTBuilder.cpp
index 53461ebbb8120..b946f10105f42 100644
--- a/contrib/llvm/tools/clang/lib/AST/VTTBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/VTTBuilder.cpp
@@ -1,4 +1,4 @@
-//===--- VTTBuilder.cpp - C++ VTT layout builder --------------------------===//
+//===- VTTBuilder.cpp - C++ VTT layout builder ----------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,12 +14,16 @@
#include "clang/AST/VTTBuilder.h"
#include "clang/AST/ASTContext.h"
-#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/BaseSubobject.h"
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/RecordLayout.h"
-#include "clang/Basic/TargetInfo.h"
-#include "llvm/Support/Format.h"
-#include <algorithm>
-#include <cstdio>
+#include "clang/AST/Type.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/Support/Casting.h"
+#include <cassert>
+#include <cstdint>
using namespace clang;
@@ -28,9 +32,9 @@ using namespace clang;
VTTBuilder::VTTBuilder(ASTContext &Ctx,
const CXXRecordDecl *MostDerivedClass,
bool GenerateDefinition)
- : Ctx(Ctx), MostDerivedClass(MostDerivedClass),
- MostDerivedClassLayout(Ctx.getASTRecordLayout(MostDerivedClass)),
- GenerateDefinition(GenerateDefinition) {
+ : Ctx(Ctx), MostDerivedClass(MostDerivedClass),
+ MostDerivedClassLayout(Ctx.getASTRecordLayout(MostDerivedClass)),
+ GenerateDefinition(GenerateDefinition) {
// Lay out this VTT.
LayoutVTT(BaseSubobject(MostDerivedClass, CharUnits::Zero()),
/*BaseIsVirtual=*/false);
@@ -56,7 +60,7 @@ void VTTBuilder::AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex,
void VTTBuilder::LayoutSecondaryVTTs(BaseSubobject Base) {
const CXXRecordDecl *RD = Base.getBase();
- for (const auto &I : RD->bases()) {
+ for (const auto &I : RD->bases()) {
// Don't layout virtual bases.
if (I.isVirtual())
continue;
diff --git a/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp
index e60ae33f2e5c0..347c516ef6a5e 100644
--- a/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp
@@ -1079,9 +1079,7 @@ static void
visitAllOverriddenMethods(const CXXMethodDecl *MD, VisitorTy &Visitor) {
assert(MD->isVirtual() && "Method is not virtual!");
- for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
- E = MD->end_overridden_methods(); I != E; ++I) {
- const CXXMethodDecl *OverriddenMD = *I;
+ for (const CXXMethodDecl *OverriddenMD : MD->overridden_methods()) {
if (!Visitor(OverriddenMD))
continue;
visitAllOverriddenMethods(OverriddenMD, Visitor);
@@ -1329,11 +1327,8 @@ static bool OverridesIndirectMethodInBases(
ItaniumVTableBuilder::PrimaryBasesSetVectorTy &Bases) {
if (Bases.count(MD->getParent()))
return true;
-
- for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
- E = MD->end_overridden_methods(); I != E; ++I) {
- const CXXMethodDecl *OverriddenMD = *I;
-
+
+ for (const CXXMethodDecl *OverriddenMD : MD->overridden_methods()) {
// Check "indirect overriders".
if (OverridesIndirectMethodInBases(OverriddenMD, Bases))
return true;
@@ -2963,6 +2958,9 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
CalculateVtordispAdjustment(FinalOverrider, ThisOffset,
ThisAdjustmentOffset);
+ unsigned VBIndex =
+ LastVBase ? VTables.getVBTableIndex(MostDerivedClass, LastVBase) : 0;
+
if (OverriddenMD) {
// If MD overrides anything in this vftable, we need to update the
// entries.
@@ -2975,6 +2973,8 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
MethodInfo &OverriddenMethodInfo = OverriddenMDIterator->second;
+ VBIndex = OverriddenMethodInfo.VBTableIndex;
+
// Let's check if the overrider requires any return adjustments.
// We must create a new slot if the MD's return type is not trivially
// convertible to the OverriddenMD's one.
@@ -2987,8 +2987,7 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
if (!ReturnAdjustingThunk) {
// No return adjustment needed - just replace the overridden method info
// with the current info.
- MethodInfo MI(OverriddenMethodInfo.VBTableIndex,
- OverriddenMethodInfo.VFTableIndex);
+ MethodInfo MI(VBIndex, OverriddenMethodInfo.VFTableIndex);
MethodInfoMap.erase(OverriddenMDIterator);
assert(!MethodInfoMap.count(MD) &&
@@ -3015,8 +3014,6 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
// If we got here, MD is a method not seen in any of the sub-bases or
// it requires return adjustment. Insert the method info for this method.
- unsigned VBIndex =
- LastVBase ? VTables.getVBTableIndex(MostDerivedClass, LastVBase) : 0;
MethodInfo MI(VBIndex,
HasRTTIComponent ? Components.size() - 1 : Components.size(),
ReturnAdjustingThunk);
diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp
index 49b15ee68500a..02aee4b46ddd1 100644
--- a/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp
+++ b/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -734,7 +734,10 @@ private:
BoundNodesTreeBuilder *Builder) {
const Type *const CanonicalType =
ActiveASTContext->getCanonicalType(TypeNode);
- for (const TypedefNameDecl *Alias : TypeAliases.lookup(CanonicalType)) {
+ auto Aliases = TypeAliases.find(CanonicalType);
+ if (Aliases == TypeAliases.end())
+ return false;
+ for (const TypedefNameDecl *Alias : Aliases->second) {
BoundNodesTreeBuilder Result(*Builder);
if (Matcher.matches(*Alias, this, &Result)) {
*Builder = std::move(Result);
diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
index f0bfbf9e32d87..0bcdd8e328048 100644
--- a/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -1,4 +1,4 @@
-//===--- ASTMatchersInternal.cpp - Structural query framework -------------===//
+//===- ASTMatchersInternal.cpp - Structural query framework ---------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,11 +11,30 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchersInternal.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTTypeTraits.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/PrettyPrinter.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/None.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <string>
+#include <utility>
+#include <vector>
namespace clang {
namespace ast_matchers {
@@ -40,7 +59,6 @@ bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode,
BoundNodesTreeBuilder *Builder,
ArrayRef<DynTypedMatcher> InnerMatchers);
-
void BoundNodesTreeBuilder::visitMatches(Visitor *ResultVisitor) {
if (Bindings.empty())
Bindings.push_back(BoundNodesMap());
@@ -51,7 +69,7 @@ void BoundNodesTreeBuilder::visitMatches(Visitor *ResultVisitor) {
namespace {
-typedef bool (*VariadicOperatorFunction)(
+using VariadicOperatorFunction = bool (*)(
const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder, ArrayRef<DynTypedMatcher> InnerMatchers);
@@ -100,20 +118,22 @@ public:
TrueMatcherImpl() {
Retain(); // Reference count will never become zero.
}
+
bool dynMatches(const ast_type_traits::DynTypedNode &, ASTMatchFinder *,
BoundNodesTreeBuilder *) const override {
return true;
}
};
-static llvm::ManagedStatic<TrueMatcherImpl> TrueMatcherInstance;
-} // namespace
+} // namespace
+
+static llvm::ManagedStatic<TrueMatcherImpl> TrueMatcherInstance;
DynTypedMatcher DynTypedMatcher::constructVariadic(
DynTypedMatcher::VariadicOperator Op,
ast_type_traits::ASTNodeKind SupportedKind,
std::vector<DynTypedMatcher> InnerMatchers) {
- assert(InnerMatchers.size() > 0 && "Array must not be empty.");
+ assert(!InnerMatchers.empty() && "Array must not be empty.");
assert(std::all_of(InnerMatchers.begin(), InnerMatchers.end(),
[SupportedKind](const DynTypedMatcher &M) {
return M.canConvertTo(SupportedKind);
@@ -314,9 +334,7 @@ HasNameMatcher::HasNameMatcher(std::vector<std::string> N)
#endif
}
-namespace {
-
-bool consumeNameSuffix(StringRef &FullName, StringRef Suffix) {
+static bool consumeNameSuffix(StringRef &FullName, StringRef Suffix) {
StringRef Name = FullName;
if (!Name.endswith(Suffix))
return false;
@@ -330,7 +348,8 @@ bool consumeNameSuffix(StringRef &FullName, StringRef Suffix) {
return true;
}
-StringRef getNodeName(const NamedDecl &Node, llvm::SmallString<128> &Scratch) {
+static StringRef getNodeName(const NamedDecl &Node,
+ llvm::SmallString<128> &Scratch) {
// Simple name.
if (Node.getIdentifier())
return Node.getName();
@@ -346,7 +365,8 @@ StringRef getNodeName(const NamedDecl &Node, llvm::SmallString<128> &Scratch) {
return "(anonymous)";
}
-StringRef getNodeName(const RecordDecl &Node, llvm::SmallString<128> &Scratch) {
+static StringRef getNodeName(const RecordDecl &Node,
+ llvm::SmallString<128> &Scratch) {
if (Node.getIdentifier()) {
return Node.getName();
}
@@ -354,11 +374,12 @@ StringRef getNodeName(const RecordDecl &Node, llvm::SmallString<128> &Scratch) {
return ("(anonymous " + Node.getKindName() + ")").toStringRef(Scratch);
}
-StringRef getNodeName(const NamespaceDecl &Node,
- llvm::SmallString<128> &Scratch) {
+static StringRef getNodeName(const NamespaceDecl &Node,
+ llvm::SmallString<128> &Scratch) {
return Node.isAnonymousNamespace() ? "(anonymous namespace)" : Node.getName();
}
+namespace {
class PatternSet {
public:
@@ -397,10 +418,11 @@ private:
StringRef P;
bool IsFullyQualified;
};
+
llvm::SmallVector<Pattern, 8> Patterns;
};
-} // namespace
+} // namespace
bool HasNameMatcher::matchesNodeUnqualified(const NamedDecl &Node) const {
assert(UseUnqualifiedMatch);
@@ -504,5 +526,282 @@ bool HasNameMatcher::matchesNode(const NamedDecl &Node) const {
}
} // end namespace internal
+
+const internal::VariadicDynCastAllOfMatcher<Decl, TranslationUnitDecl>
+ translationUnitDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, TypedefDecl> typedefDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, TypedefNameDecl>
+ typedefNameDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasDecl> typeAliasDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasTemplateDecl>
+ typeAliasTemplateDecl;
+const internal::VariadicAllOfMatcher<Decl> decl;
+const internal::VariadicDynCastAllOfMatcher<Decl, LinkageSpecDecl>
+ linkageSpecDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, NamedDecl> namedDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, LabelDecl> labelDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceDecl> namespaceDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceAliasDecl>
+ namespaceAliasDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, RecordDecl> recordDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, CXXRecordDecl> cxxRecordDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, ClassTemplateDecl>
+ classTemplateDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl,
+ ClassTemplateSpecializationDecl>
+ classTemplateSpecializationDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, DeclaratorDecl>
+ declaratorDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, ParmVarDecl> parmVarDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, AccessSpecDecl>
+ accessSpecDecl;
+const internal::VariadicAllOfMatcher<CXXCtorInitializer> cxxCtorInitializer;
+const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument;
+const internal::VariadicAllOfMatcher<TemplateName> templateName;
+const internal::VariadicDynCastAllOfMatcher<Decl, NonTypeTemplateParmDecl>
+ nonTypeTemplateParmDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, TemplateTypeParmDecl>
+ templateTypeParmDecl;
+const internal::VariadicAllOfMatcher<QualType> qualType;
+const internal::VariadicAllOfMatcher<Type> type;
+const internal::VariadicAllOfMatcher<TypeLoc> typeLoc;
+const internal::VariadicDynCastAllOfMatcher<Stmt, UnaryExprOrTypeTraitExpr>
+ unaryExprOrTypeTraitExpr;
+const internal::VariadicDynCastAllOfMatcher<Decl, ValueDecl> valueDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, CXXConstructorDecl>
+ cxxConstructorDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, CXXDestructorDecl>
+ cxxDestructorDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, EnumDecl> enumDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, EnumConstantDecl>
+ enumConstantDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl> cxxMethodDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, CXXConversionDecl>
+ cxxConversionDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, VarDecl> varDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, FieldDecl> fieldDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, FunctionDecl> functionDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, FunctionTemplateDecl>
+ functionTemplateDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, FriendDecl> friendDecl;
+const internal::VariadicAllOfMatcher<Stmt> stmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, DeclStmt> declStmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, MemberExpr> memberExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> callExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, LambdaExpr> lambdaExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXMemberCallExpr>
+ cxxMemberCallExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCMessageExpr>
+ objcMessageExpr;
+const internal::VariadicDynCastAllOfMatcher<Decl, ObjCInterfaceDecl>
+ objcInterfaceDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, ObjCImplementationDecl>
+ objcImplementationDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, ObjCProtocolDecl>
+ objcProtocolDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, ObjCCategoryDecl>
+ objcCategoryDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, ObjCCategoryImplDecl>
+ objcCategoryImplDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, ObjCMethodDecl>
+ objcMethodDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, ObjCIvarDecl> objcIvarDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, ObjCPropertyDecl>
+ objcPropertyDecl;
+const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtThrowStmt>
+ objcThrowStmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtTryStmt> objcTryStmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtCatchStmt>
+ objcCatchStmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtFinallyStmt>
+ objcFinallyStmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, ExprWithCleanups>
+ exprWithCleanups;
+const internal::VariadicDynCastAllOfMatcher<Stmt, InitListExpr> initListExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXStdInitializerListExpr>
+ cxxStdInitializerListExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, ImplicitValueInitExpr>
+ implicitValueInitExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, ParenListExpr> parenListExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, SubstNonTypeTemplateParmExpr>
+ substNonTypeTemplateParmExpr;
+const internal::VariadicDynCastAllOfMatcher<Decl, UsingDecl> usingDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, UsingDirectiveDecl>
+ usingDirectiveDecl;
+const internal::VariadicDynCastAllOfMatcher<Stmt, UnresolvedLookupExpr>
+ unresolvedLookupExpr;
+const internal::VariadicDynCastAllOfMatcher<Decl, UnresolvedUsingValueDecl>
+ unresolvedUsingValueDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, UnresolvedUsingTypenameDecl>
+ unresolvedUsingTypenameDecl;
+const internal::VariadicDynCastAllOfMatcher<Stmt, ParenExpr> parenExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXConstructExpr>
+ cxxConstructExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXUnresolvedConstructExpr>
+ cxxUnresolvedConstructExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThisExpr> cxxThisExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXBindTemporaryExpr>
+ cxxBindTemporaryExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, MaterializeTemporaryExpr>
+ materializeTemporaryExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNewExpr> cxxNewExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDeleteExpr> cxxDeleteExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, ArraySubscriptExpr>
+ arraySubscriptExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDefaultArgExpr>
+ cxxDefaultArgExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXOperatorCallExpr>
+ cxxOperatorCallExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, Expr> expr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, DeclRefExpr> declRefExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, IfStmt> ifStmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, ForStmt> forStmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXForRangeStmt>
+ cxxForRangeStmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, WhileStmt> whileStmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, DoStmt> doStmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, BreakStmt> breakStmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, ContinueStmt> continueStmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, ReturnStmt> returnStmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, GotoStmt> gotoStmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, LabelStmt> labelStmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, AddrLabelExpr> addrLabelExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchStmt> switchStmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchCase> switchCase;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CaseStmt> caseStmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, DefaultStmt> defaultStmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundStmt> compoundStmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXCatchStmt> cxxCatchStmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTryStmt> cxxTryStmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThrowExpr> cxxThrowExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, NullStmt> nullStmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, AsmStmt> asmStmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXBoolLiteralExpr>
+ cxxBoolLiteral;
+const internal::VariadicDynCastAllOfMatcher<Stmt, StringLiteral> stringLiteral;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CharacterLiteral>
+ characterLiteral;
+const internal::VariadicDynCastAllOfMatcher<Stmt, IntegerLiteral>
+ integerLiteral;
+const internal::VariadicDynCastAllOfMatcher<Stmt, FloatingLiteral> floatLiteral;
+const internal::VariadicDynCastAllOfMatcher<Stmt, UserDefinedLiteral>
+ userDefinedLiteral;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundLiteralExpr>
+ compoundLiteralExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNullPtrLiteralExpr>
+ cxxNullPtrLiteralExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, GNUNullExpr> gnuNullExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, AtomicExpr> atomicExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, StmtExpr> stmtExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, BinaryOperator>
+ binaryOperator;
+const internal::VariadicDynCastAllOfMatcher<Stmt, UnaryOperator> unaryOperator;
+const internal::VariadicDynCastAllOfMatcher<Stmt, ConditionalOperator>
+ conditionalOperator;
+const internal::VariadicDynCastAllOfMatcher<Stmt, BinaryConditionalOperator>
+ binaryConditionalOperator;
+const internal::VariadicDynCastAllOfMatcher<Stmt, OpaqueValueExpr>
+ opaqueValueExpr;
+const internal::VariadicDynCastAllOfMatcher<Decl, StaticAssertDecl>
+ staticAssertDecl;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXReinterpretCastExpr>
+ cxxReinterpretCastExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXStaticCastExpr>
+ cxxStaticCastExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDynamicCastExpr>
+ cxxDynamicCastExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXConstCastExpr>
+ cxxConstCastExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CStyleCastExpr>
+ cStyleCastExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, ExplicitCastExpr>
+ explicitCastExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, ImplicitCastExpr>
+ implicitCastExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CastExpr> castExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXFunctionalCastExpr>
+ cxxFunctionalCastExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTemporaryObjectExpr>
+ cxxTemporaryObjectExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, PredefinedExpr>
+ predefinedExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, DesignatedInitExpr>
+ designatedInitExpr;
+const internal::VariadicOperatorMatcherFunc<
+ 2, std::numeric_limits<unsigned>::max()>
+ eachOf = {internal::DynTypedMatcher::VO_EachOf};
+const internal::VariadicOperatorMatcherFunc<
+ 2, std::numeric_limits<unsigned>::max()>
+ anyOf = {internal::DynTypedMatcher::VO_AnyOf};
+const internal::VariadicOperatorMatcherFunc<
+ 2, std::numeric_limits<unsigned>::max()>
+ allOf = {internal::DynTypedMatcher::VO_AllOf};
+const internal::VariadicFunction<internal::Matcher<NamedDecl>, StringRef,
+ internal::hasAnyNameFunc>
+ hasAnyName = {};
+const internal::ArgumentAdaptingMatcherFunc<internal::HasMatcher> has = {};
+const internal::ArgumentAdaptingMatcherFunc<internal::HasDescendantMatcher>
+ hasDescendant = {};
+const internal::ArgumentAdaptingMatcherFunc<internal::ForEachMatcher> forEach =
+ {};
+const internal::ArgumentAdaptingMatcherFunc<internal::ForEachDescendantMatcher>
+ forEachDescendant = {};
+const internal::ArgumentAdaptingMatcherFunc<
+ internal::HasParentMatcher,
+ internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>,
+ internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>>
+ hasParent = {};
+const internal::ArgumentAdaptingMatcherFunc<
+ internal::HasAncestorMatcher,
+ internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>,
+ internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>>
+ hasAncestor = {};
+const internal::VariadicOperatorMatcherFunc<1, 1> unless = {
+ internal::DynTypedMatcher::VO_UnaryNot};
+const internal::VariadicAllOfMatcher<NestedNameSpecifier> nestedNameSpecifier;
+const internal::VariadicAllOfMatcher<NestedNameSpecifierLoc>
+ nestedNameSpecifierLoc;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CUDAKernelCallExpr>
+ cudaKernelCallExpr;
+const AstTypeMatcher<BuiltinType> builtinType;
+const AstTypeMatcher<ArrayType> arrayType;
+const AstTypeMatcher<ComplexType> complexType;
+const AstTypeMatcher<ConstantArrayType> constantArrayType;
+const AstTypeMatcher<DependentSizedArrayType> dependentSizedArrayType;
+const AstTypeMatcher<IncompleteArrayType> incompleteArrayType;
+const AstTypeMatcher<VariableArrayType> variableArrayType;
+const AstTypeMatcher<AtomicType> atomicType;
+const AstTypeMatcher<AutoType> autoType;
+const AstTypeMatcher<FunctionType> functionType;
+const AstTypeMatcher<FunctionProtoType> functionProtoType;
+const AstTypeMatcher<ParenType> parenType;
+const AstTypeMatcher<BlockPointerType> blockPointerType;
+const AstTypeMatcher<MemberPointerType> memberPointerType;
+const AstTypeMatcher<PointerType> pointerType;
+const AstTypeMatcher<ObjCObjectPointerType> objcObjectPointerType;
+const AstTypeMatcher<ReferenceType> referenceType;
+const AstTypeMatcher<LValueReferenceType> lValueReferenceType;
+const AstTypeMatcher<RValueReferenceType> rValueReferenceType;
+const AstTypeMatcher<TypedefType> typedefType;
+const AstTypeMatcher<EnumType> enumType;
+const AstTypeMatcher<TemplateSpecializationType> templateSpecializationType;
+const AstTypeMatcher<UnaryTransformType> unaryTransformType;
+const AstTypeMatcher<RecordType> recordType;
+const AstTypeMatcher<TagType> tagType;
+const AstTypeMatcher<ElaboratedType> elaboratedType;
+const AstTypeMatcher<SubstTemplateTypeParmType> substTemplateTypeParmType;
+const AstTypeMatcher<TemplateTypeParmType> templateTypeParmType;
+const AstTypeMatcher<InjectedClassNameType> injectedClassNameType;
+const AstTypeMatcher<DecayedType> decayedType;
+AST_TYPELOC_TRAVERSE_MATCHER_DEF(hasElementType,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(ArrayType,
+ ComplexType));
+AST_TYPELOC_TRAVERSE_MATCHER_DEF(hasValueType,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(AtomicType));
+AST_TYPELOC_TRAVERSE_MATCHER_DEF(
+ pointee,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(BlockPointerType, MemberPointerType,
+ PointerType, ReferenceType));
+
} // end namespace ast_matchers
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Marshallers.h b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Marshallers.h
index c557ff162691a..af90e2c7eca1d 100644
--- a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Marshallers.h
+++ b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Marshallers.h
@@ -1,4 +1,4 @@
-//===--- Marshallers.h - Generic matcher function marshallers ---*- C++ -*-===//
+//===- Marshallers.h - Generic matcher function marshallers -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,7 +6,7 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
/// \brief Functions templates and classes to wrap matcher construct functions.
///
@@ -14,18 +14,33 @@
/// marshalling layer on top of matcher construct functions.
/// These are used by the registry to export all marshaller constructors with
/// the same generic interface.
-///
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LIB_ASTMATCHERS_DYNAMIC_MARSHALLERS_H
#define LLVM_CLANG_LIB_ASTMATCHERS_DYNAMIC_MARSHALLERS_H
-#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/AST/ASTTypeTraits.h"
+#include "clang/AST/OperationKinds.h"
+#include "clang/ASTMatchers/ASTMatchersInternal.h"
#include "clang/ASTMatchers/Dynamic/Diagnostics.h"
#include "clang/ASTMatchers/Dynamic/VariantValue.h"
+#include "clang/Basic/AttrKinds.h"
#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/None.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Twine.h"
+#include <cassert>
+#include <cstddef>
+#include <iterator>
+#include <limits>
+#include <memory>
#include <string>
+#include <utility>
+#include <vector>
namespace clang {
namespace ast_matchers {
@@ -41,9 +56,11 @@ template <class T> struct ArgTypeTraits<const T &> : public ArgTypeTraits<T> {
template <> struct ArgTypeTraits<std::string> {
static bool is(const VariantValue &Value) { return Value.isString(); }
+
static const std::string &get(const VariantValue &Value) {
return Value.getString();
}
+
static ArgKind getKind() {
return ArgKind(ArgKind::AK_String);
}
@@ -53,13 +70,15 @@ template <>
struct ArgTypeTraits<StringRef> : public ArgTypeTraits<std::string> {
};
-template <class T> struct ArgTypeTraits<ast_matchers::internal::Matcher<T> > {
+template <class T> struct ArgTypeTraits<ast_matchers::internal::Matcher<T>> {
static bool is(const VariantValue &Value) {
return Value.isMatcher() && Value.getMatcher().hasTypedMatcher<T>();
}
+
static ast_matchers::internal::Matcher<T> get(const VariantValue &Value) {
return Value.getMatcher().getTypedMatcher<T>();
}
+
static ArgKind getKind() {
return ArgKind(ast_type_traits::ASTNodeKind::getFromNodeKind<T>());
}
@@ -67,9 +86,11 @@ template <class T> struct ArgTypeTraits<ast_matchers::internal::Matcher<T> > {
template <> struct ArgTypeTraits<bool> {
static bool is(const VariantValue &Value) { return Value.isBoolean(); }
+
static bool get(const VariantValue &Value) {
return Value.getBoolean();
}
+
static ArgKind getKind() {
return ArgKind(ArgKind::AK_Boolean);
}
@@ -77,9 +98,11 @@ template <> struct ArgTypeTraits<bool> {
template <> struct ArgTypeTraits<double> {
static bool is(const VariantValue &Value) { return Value.isDouble(); }
+
static double get(const VariantValue &Value) {
return Value.getDouble();
}
+
static ArgKind getKind() {
return ArgKind(ArgKind::AK_Double);
}
@@ -87,9 +110,11 @@ template <> struct ArgTypeTraits<double> {
template <> struct ArgTypeTraits<unsigned> {
static bool is(const VariantValue &Value) { return Value.isUnsigned(); }
+
static unsigned get(const VariantValue &Value) {
return Value.getUnsigned();
}
+
static ArgKind getKind() {
return ArgKind(ArgKind::AK_Unsigned);
}
@@ -97,42 +122,45 @@ template <> struct ArgTypeTraits<unsigned> {
template <> struct ArgTypeTraits<attr::Kind> {
private:
- static attr::Kind getAttrKind(llvm::StringRef AttrKind) {
- return llvm::StringSwitch<attr::Kind>(AttrKind)
+ static Optional<attr::Kind> getAttrKind(llvm::StringRef AttrKind) {
+ return llvm::StringSwitch<Optional<attr::Kind>>(AttrKind)
#define ATTR(X) .Case("attr::" #X, attr:: X)
#include "clang/Basic/AttrList.inc"
- .Default(attr::Kind(-1));
+ .Default(llvm::None);
}
+
public:
static bool is(const VariantValue &Value) {
- return Value.isString() &&
- getAttrKind(Value.getString()) != attr::Kind(-1);
+ return Value.isString() && getAttrKind(Value.getString());
}
+
static attr::Kind get(const VariantValue &Value) {
- return getAttrKind(Value.getString());
+ return *getAttrKind(Value.getString());
}
+
static ArgKind getKind() {
return ArgKind(ArgKind::AK_String);
}
};
-template <> struct ArgTypeTraits<clang::CastKind> {
+template <> struct ArgTypeTraits<CastKind> {
private:
- static clang::CastKind getCastKind(llvm::StringRef AttrKind) {
- return llvm::StringSwitch<clang::CastKind>(AttrKind)
+ static Optional<CastKind> getCastKind(llvm::StringRef AttrKind) {
+ return llvm::StringSwitch<Optional<CastKind>>(AttrKind)
#define CAST_OPERATION(Name) .Case( #Name, CK_##Name)
#include "clang/AST/OperationKinds.def"
- .Default(CK_Invalid);
+ .Default(llvm::None);
}
public:
static bool is(const VariantValue &Value) {
- return Value.isString() &&
- getCastKind(Value.getString()) != CK_Invalid;
+ return Value.isString() && getCastKind(Value.getString());
}
- static clang::CastKind get(const VariantValue &Value) {
- return getCastKind(Value.getString());
+
+ static CastKind get(const VariantValue &Value) {
+ return *getCastKind(Value.getString());
}
+
static ArgKind getKind() {
return ArgKind(ArgKind::AK_String);
}
@@ -144,7 +172,8 @@ public:
/// arguments, and various other methods for type introspection.
class MatcherDescriptor {
public:
- virtual ~MatcherDescriptor() {}
+ virtual ~MatcherDescriptor() = default;
+
virtual VariantMatcher create(SourceRange NameRange,
ArrayRef<ParserValue> Args,
Diagnostics *Error) const = 0;
@@ -201,11 +230,11 @@ inline bool isRetKindConvertibleTo(
/// their types, unpacking them and calling the underlying function.
class FixedArgCountMatcherDescriptor : public MatcherDescriptor {
public:
- typedef VariantMatcher (*MarshallerType)(void (*Func)(),
- StringRef MatcherName,
- SourceRange NameRange,
- ArrayRef<ParserValue> Args,
- Diagnostics *Error);
+ using MarshallerType = VariantMatcher (*)(void (*Func)(),
+ StringRef MatcherName,
+ SourceRange NameRange,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error);
/// \param Marshaller Function to unpack the arguments and call \c Func
/// \param Func Matcher construct function. This is the function that
@@ -229,10 +258,12 @@ public:
bool isVariadic() const override { return false; }
unsigned getNumArgs() const override { return ArgKinds.size(); }
+
void getArgKinds(ast_type_traits::ASTNodeKind ThisKind, unsigned ArgNo,
std::vector<ArgKind> &Kinds) const override {
Kinds.push_back(ArgKinds[ArgNo]);
}
+
bool isConvertibleTo(
ast_type_traits::ASTNodeKind Kind, unsigned *Specificity,
ast_type_traits::ASTNodeKind *LeastDerivedKind) const override {
@@ -303,14 +334,14 @@ struct BuildReturnTypeVector {
};
template <typename T>
-struct BuildReturnTypeVector<ast_matchers::internal::Matcher<T> > {
+struct BuildReturnTypeVector<ast_matchers::internal::Matcher<T>> {
static void build(std::vector<ast_type_traits::ASTNodeKind> &RetTypes) {
RetTypes.push_back(ast_type_traits::ASTNodeKind::getFromNodeKind<T>());
}
};
template <typename T>
-struct BuildReturnTypeVector<ast_matchers::internal::BindableMatcher<T> > {
+struct BuildReturnTypeVector<ast_matchers::internal::BindableMatcher<T>> {
static void build(std::vector<ast_type_traits::ASTNodeKind> &RetTypes) {
RetTypes.push_back(ast_type_traits::ASTNodeKind::getFromNodeKind<T>());
}
@@ -326,7 +357,8 @@ variadicMatcherDescriptor(StringRef MatcherName, SourceRange NameRange,
bool HasError = false;
for (size_t i = 0, e = Args.size(); i != e; ++i) {
- typedef ArgTypeTraits<ArgT> ArgTraits;
+ using ArgTraits = ArgTypeTraits<ArgT>;
+
const ParserValue &Arg = Args[i];
const VariantValue &Value = Arg.Value;
if (!ArgTraits::is(Value)) {
@@ -360,10 +392,10 @@ variadicMatcherDescriptor(StringRef MatcherName, SourceRange NameRange,
/// object file.
class VariadicFuncMatcherDescriptor : public MatcherDescriptor {
public:
- typedef VariantMatcher (*RunFunc)(StringRef MatcherName,
- SourceRange NameRange,
- ArrayRef<ParserValue> Args,
- Diagnostics *Error);
+ using RunFunc = VariantMatcher (*)(StringRef MatcherName,
+ SourceRange NameRange,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error);
template <typename ResultT, typename ArgT,
ResultT (*F)(ArrayRef<const ArgT *>)>
@@ -384,10 +416,12 @@ public:
bool isVariadic() const override { return true; }
unsigned getNumArgs() const override { return 0; }
+
void getArgKinds(ast_type_traits::ASTNodeKind ThisKind, unsigned ArgNo,
std::vector<ArgKind> &Kinds) const override {
Kinds.push_back(ArgsKind);
}
+
bool isConvertibleTo(
ast_type_traits::ASTNodeKind Kind, unsigned *Specificity,
ast_type_traits::ASTNodeKind *LeastDerivedKind) const override {
@@ -458,7 +492,7 @@ static VariantMatcher matcherMarshall0(void (*Func)(), StringRef MatcherName,
SourceRange NameRange,
ArrayRef<ParserValue> Args,
Diagnostics *Error) {
- typedef ReturnType (*FuncType)();
+ using FuncType = ReturnType (*)();
CHECK_ARG_COUNT(0);
return outvalueToVariantMatcher(reinterpret_cast<FuncType>(Func)());
}
@@ -469,7 +503,7 @@ static VariantMatcher matcherMarshall1(void (*Func)(), StringRef MatcherName,
SourceRange NameRange,
ArrayRef<ParserValue> Args,
Diagnostics *Error) {
- typedef ReturnType (*FuncType)(ArgType1);
+ using FuncType = ReturnType (*)(ArgType1);
CHECK_ARG_COUNT(1);
CHECK_ARG_TYPE(0, ArgType1);
return outvalueToVariantMatcher(reinterpret_cast<FuncType>(Func)(
@@ -482,7 +516,7 @@ static VariantMatcher matcherMarshall2(void (*Func)(), StringRef MatcherName,
SourceRange NameRange,
ArrayRef<ParserValue> Args,
Diagnostics *Error) {
- typedef ReturnType (*FuncType)(ArgType1, ArgType2);
+ using FuncType = ReturnType (*)(ArgType1, ArgType2);
CHECK_ARG_COUNT(2);
CHECK_ARG_TYPE(0, ArgType1);
CHECK_ARG_TYPE(1, ArgType2);
@@ -507,8 +541,8 @@ public:
}
private:
- typedef ast_matchers::internal::ArgumentAdaptingMatcherFunc<
- ArgumentAdapterT, FromTypes, ToTypes> AdaptativeFunc;
+ using AdaptativeFunc = ast_matchers::internal::ArgumentAdaptingMatcherFunc<
+ ArgumentAdapterT, FromTypes, ToTypes>;
/// \brief End case for the recursion
static void collect(ast_matchers::internal::EmptyTypeList) {}
@@ -534,7 +568,7 @@ public:
: Overloads(std::make_move_iterator(Callbacks.begin()),
std::make_move_iterator(Callbacks.end())) {}
- ~OverloadedMatcherDescriptor() override {}
+ ~OverloadedMatcherDescriptor() override = default;
VariantMatcher create(SourceRange NameRange,
ArrayRef<ParserValue> Args,
@@ -604,7 +638,8 @@ private:
/// \brief Variadic operator marshaller function.
class VariadicOperatorMatcherDescriptor : public MatcherDescriptor {
public:
- typedef DynTypedMatcher::VariadicOperator VarOp;
+ using VarOp = DynTypedMatcher::VariadicOperator;
+
VariadicOperatorMatcherDescriptor(unsigned MinCount, unsigned MaxCount,
VarOp Op, StringRef MatcherName)
: MinCount(MinCount), MaxCount(MaxCount), Op(Op),
@@ -615,7 +650,9 @@ public:
Diagnostics *Error) const override {
if (Args.size() < MinCount || MaxCount < Args.size()) {
const std::string MaxStr =
- (MaxCount == UINT_MAX ? "" : Twine(MaxCount)).str();
+ (MaxCount == std::numeric_limits<unsigned>::max() ? ""
+ : Twine(MaxCount))
+ .str();
Error->addError(NameRange, Error->ET_RegistryWrongArgCount)
<< ("(" + Twine(MinCount) + ", " + MaxStr + ")") << Args.size();
return VariantMatcher();
@@ -637,10 +674,12 @@ public:
bool isVariadic() const override { return true; }
unsigned getNumArgs() const override { return 0; }
+
void getArgKinds(ast_type_traits::ASTNodeKind ThisKind, unsigned ArgNo,
std::vector<ArgKind> &Kinds) const override {
Kinds.push_back(ThisKind);
}
+
bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, unsigned *Specificity,
ast_type_traits::ASTNodeKind *LeastDerivedKind) const override {
if (Specificity)
@@ -649,6 +688,7 @@ public:
*LeastDerivedKind = Kind;
return true;
}
+
bool isPolymorphic() const override { return true; }
private:
diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Parser.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Parser.cpp
index f5bd296689951..89e1a2695860c 100644
--- a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Parser.cpp
+++ b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Parser.cpp
@@ -1,4 +1,4 @@
-//===--- Parser.cpp - Matcher expression parser -----*- C++ -*-===//
+//===- Parser.cpp - Matcher expression parser -----------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,11 +13,21 @@
//===----------------------------------------------------------------------===//
#include "clang/ASTMatchers/Dynamic/Parser.h"
+#include "clang/ASTMatchers/ASTMatchersInternal.h"
+#include "clang/ASTMatchers/Dynamic/Diagnostics.h"
#include "clang/ASTMatchers/Dynamic/Registry.h"
#include "clang/Basic/CharInfo.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
+#include <algorithm>
+#include <cassert>
+#include <cerrno>
+#include <cstddef>
+#include <cstdlib>
#include <string>
+#include <utility>
#include <vector>
namespace clang {
@@ -43,10 +53,10 @@ struct Parser::TokenInfo {
/// \brief Some known identifiers.
static const char* const ID_Bind;
- TokenInfo() : Text(), Kind(TK_Eof), Range(), Value() {}
+ TokenInfo() = default;
StringRef Text;
- TokenKind Kind;
+ TokenKind Kind = TK_Eof;
SourceRange Range;
VariantValue Value;
};
@@ -57,14 +67,13 @@ const char* const Parser::TokenInfo::ID_Bind = "bind";
class Parser::CodeTokenizer {
public:
explicit CodeTokenizer(StringRef MatcherCode, Diagnostics *Error)
- : Code(MatcherCode), StartOfLine(MatcherCode), Line(1), Error(Error),
- CodeCompletionLocation(nullptr) {
+ : Code(MatcherCode), StartOfLine(MatcherCode), Error(Error) {
NextToken = getNextToken();
}
CodeTokenizer(StringRef MatcherCode, Diagnostics *Error,
unsigned CodeCompletionOffset)
- : Code(MatcherCode), StartOfLine(MatcherCode), Line(1), Error(Error),
+ : Code(MatcherCode), StartOfLine(MatcherCode), Error(Error),
CodeCompletionLocation(MatcherCode.data() + CodeCompletionOffset) {
NextToken = getNextToken();
}
@@ -138,7 +147,7 @@ private:
if (isAlphanumeric(Code[0])) {
// Parse an identifier
size_t TokenLength = 1;
- while (1) {
+ while (true) {
// A code completion location in/immediately after an identifier will
// cause the portion of the identifier before the code completion
// location to become a code completion token.
@@ -283,22 +292,22 @@ private:
StringRef Code;
StringRef StartOfLine;
- unsigned Line;
+ unsigned Line = 1;
Diagnostics *Error;
TokenInfo NextToken;
- const char *CodeCompletionLocation;
+ const char *CodeCompletionLocation = nullptr;
};
-Parser::Sema::~Sema() {}
+Parser::Sema::~Sema() = default;
std::vector<ArgKind> Parser::Sema::getAcceptedCompletionTypes(
llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context) {
- return std::vector<ArgKind>();
+ return {};
}
std::vector<MatcherCompletion>
Parser::Sema::getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes) {
- return std::vector<MatcherCompletion>();
+ return {};
}
struct Parser::ScopedContextEntry {
@@ -384,7 +393,7 @@ bool Parser::parseMatcherExpressionImpl(const TokenInfo &NameToken,
EndToken = Tokenizer->consumeNextToken();
break;
}
- if (Args.size() > 0) {
+ if (!Args.empty()) {
// We must find a , token to continue.
const TokenInfo CommaToken = Tokenizer->consumeNextToken();
if (CommaToken.Kind != TokenInfo::TK_Comma) {
@@ -558,7 +567,7 @@ Parser::Parser(CodeTokenizer *Tokenizer, Sema *S,
: Tokenizer(Tokenizer), S(S ? S : &*DefaultRegistrySema),
NamedValues(NamedValues), Error(Error) {}
-Parser::RegistrySema::~RegistrySema() {}
+Parser::RegistrySema::~RegistrySema() = default;
llvm::Optional<MatcherCtor>
Parser::RegistrySema::lookupMatcherCtor(StringRef MatcherName) {
@@ -640,6 +649,6 @@ Parser::parseMatcherExpression(StringRef Code, Sema *S,
return Result;
}
-} // namespace dynamic
-} // namespace ast_matchers
-} // namespace clang
+} // namespace dynamic
+} // namespace ast_matchers
+} // namespace clang
diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Registry.cpp
index 031ceb320306d..2b7bb7a2120d1 100644
--- a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -1,37 +1,49 @@
-//===--- Registry.cpp - Matcher registry -------------------------===//
+//===- Registry.cpp - Matcher registry ------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
-//===------------------------------------------------------------===//
-///
+//===----------------------------------------------------------------------===//
+//
/// \file
/// \brief Registry map populated at static initialization time.
-///
-//===------------------------------------------------------------===//
+//
+//===----------------------------------------------------------------------===//
#include "clang/ASTMatchers/Dynamic/Registry.h"
#include "Marshallers.h"
+#include "clang/AST/ASTTypeTraits.h"
#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/Dynamic/Diagnostics.h"
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <iterator>
+#include <memory>
#include <set>
+#include <string>
#include <utility>
+#include <vector>
using namespace clang::ast_type_traits;
namespace clang {
namespace ast_matchers {
namespace dynamic {
+
namespace {
using internal::MatcherDescriptor;
-typedef llvm::StringMap<std::unique_ptr<const MatcherDescriptor>> ConstructorMap;
+using ConstructorMap = llvm::StringMap<std::unique_ptr<const MatcherDescriptor>>;
+
class RegistryMaps {
public:
RegistryMaps();
@@ -46,6 +58,8 @@ private:
ConstructorMap Constructors;
};
+} // namespace
+
void RegistryMaps::registerMatcher(
StringRef MatcherName, std::unique_ptr<MatcherDescriptor> Callback) {
assert(Constructors.find(MatcherName) == Constructors.end());
@@ -74,7 +88,7 @@ void RegistryMaps::registerMatcher(
MATCHER_OVERLOAD_ENTRY(name, 0), \
MATCHER_OVERLOAD_ENTRY(name, 1)}; \
REGISTER_MATCHER_OVERLOAD(name); \
- } while (0)
+ } while (false)
/// \brief Generate a registry map with all the known matchers.
RegistryMaps::RegistryMaps() {
@@ -196,6 +210,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(forEachArgumentWithParam);
REGISTER_MATCHER(forEachConstructorInitializer);
REGISTER_MATCHER(forEachDescendant);
+ REGISTER_MATCHER(forEachOverridden);
REGISTER_MATCHER(forEachSwitchCase);
REGISTER_MATCHER(forField);
REGISTER_MATCHER(forFunction);
@@ -219,6 +234,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasAnyUsingShadowDecl);
REGISTER_MATCHER(hasArgument);
REGISTER_MATCHER(hasArgumentOfType);
+ REGISTER_MATCHER(hasArraySize);
REGISTER_MATCHER(hasAttr);
REGISTER_MATCHER(hasAutomaticStorageDuration);
REGISTER_MATCHER(hasBase);
@@ -233,6 +249,8 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasDeclaration);
REGISTER_MATCHER(hasDeclContext);
REGISTER_MATCHER(hasDeducedType);
+ REGISTER_MATCHER(hasDefaultArgument);
+ REGISTER_MATCHER(hasDefinition);
REGISTER_MATCHER(hasDescendant);
REGISTER_MATCHER(hasDestinationType);
REGISTER_MATCHER(hasDynamicExceptionSpec);
@@ -301,6 +319,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(isAnonymous);
REGISTER_MATCHER(isAnyCharacter);
REGISTER_MATCHER(isAnyPointer);
+ REGISTER_MATCHER(isArray);
REGISTER_MATCHER(isArrow);
REGISTER_MATCHER(isBaseInitializer);
REGISTER_MATCHER(isBitField);
@@ -355,6 +374,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(labelDecl);
REGISTER_MATCHER(labelStmt);
REGISTER_MATCHER(lambdaExpr);
+ REGISTER_MATCHER(linkageSpecDecl);
REGISTER_MATCHER(lValueReferenceType);
REGISTER_MATCHER(matchesName);
REGISTER_MATCHER(matchesSelector);
@@ -372,7 +392,11 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(nullStmt);
REGISTER_MATCHER(numSelectorArgs);
REGISTER_MATCHER(ofClass);
+ REGISTER_MATCHER(objcCatchStmt);
REGISTER_MATCHER(objcCategoryDecl);
+ REGISTER_MATCHER(objcCategoryImplDecl);
+ REGISTER_MATCHER(objcFinallyStmt);
+ REGISTER_MATCHER(objcImplementationDecl);
REGISTER_MATCHER(objcInterfaceDecl);
REGISTER_MATCHER(objcIvarDecl);
REGISTER_MATCHER(objcMessageExpr);
@@ -380,6 +404,8 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(objcObjectPointerType);
REGISTER_MATCHER(objcPropertyDecl);
REGISTER_MATCHER(objcProtocolDecl);
+ REGISTER_MATCHER(objcThrowStmt);
+ REGISTER_MATCHER(objcTryStmt);
REGISTER_MATCHER(on);
REGISTER_MATCHER(onImplicitObjectArgument);
REGISTER_MATCHER(opaqueValueExpr);
@@ -450,12 +476,10 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(withInitializer);
}
-RegistryMaps::~RegistryMaps() {}
+RegistryMaps::~RegistryMaps() = default;
static llvm::ManagedStatic<RegistryMaps> RegistryData;
-} // anonymous namespace
-
// static
llvm::Optional<MatcherCtor> Registry::lookupMatcherCtor(StringRef MatcherName) {
auto it = RegistryData->constructors().find(MatcherName);
@@ -464,10 +488,8 @@ llvm::Optional<MatcherCtor> Registry::lookupMatcherCtor(StringRef MatcherName) {
: it->second.get();
}
-namespace {
-
-llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
- const std::set<ASTNodeKind> &KS) {
+static llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ const std::set<ASTNodeKind> &KS) {
unsigned Count = 0;
for (std::set<ASTNodeKind>::const_iterator I = KS.begin(), E = KS.end();
I != E; ++I) {
@@ -482,8 +504,6 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
return OS;
}
-} // namespace
-
std::vector<ArgKind> Registry::getAcceptedCompletionTypes(
ArrayRef<std::pair<MatcherCtor, unsigned>> Context) {
ASTNodeKind InitialTypes[] = {
@@ -593,7 +613,6 @@ Registry::getMatcherCompletions(ArrayRef<ArgKind> AcceptedTypes) {
return Completions;
}
-// static
VariantMatcher Registry::constructMatcher(MatcherCtor Ctor,
SourceRange NameRange,
ArrayRef<ParserValue> Args,
@@ -601,7 +620,6 @@ VariantMatcher Registry::constructMatcher(MatcherCtor Ctor,
return Ctor->create(NameRange, Args, Error);
}
-// static
VariantMatcher Registry::constructBoundMatcher(MatcherCtor Ctor,
SourceRange NameRange,
StringRef BindID,
@@ -621,6 +639,6 @@ VariantMatcher Registry::constructBoundMatcher(MatcherCtor Ctor,
return VariantMatcher();
}
-} // namespace dynamic
-} // namespace ast_matchers
-} // namespace clang
+} // namespace dynamic
+} // namespace ast_matchers
+} // namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Analysis/AnalysisDeclContext.cpp b/contrib/llvm/tools/clang/lib/Analysis/AnalysisDeclContext.cpp
index ec15f34fb231d..181edff0a03f5 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/AnalysisDeclContext.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/AnalysisDeclContext.cpp
@@ -12,8 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Analysis/AnalysisContext.h"
-#include "BodyFarm.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
@@ -23,6 +22,7 @@
#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Analysis/Analyses/PseudoConstantAnalysis.h"
+#include "clang/Analysis/BodyFarm.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/CFGStmtMap.h"
#include "clang/Analysis/Support/BumpVector.h"
@@ -63,33 +63,25 @@ AnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
}
-AnalysisDeclContextManager::AnalysisDeclContextManager(bool useUnoptimizedCFG,
- bool addImplicitDtors,
- bool addInitializers,
- bool addTemporaryDtors,
- bool addLifetime,
- bool synthesizeBodies,
- bool addStaticInitBranch,
- bool addCXXNewAllocator,
- CodeInjector *injector)
- : Injector(injector), SynthesizeBodies(synthesizeBodies)
-{
+AnalysisDeclContextManager::AnalysisDeclContextManager(
+ ASTContext &ASTCtx, bool useUnoptimizedCFG, bool addImplicitDtors,
+ bool addInitializers, bool addTemporaryDtors, bool addLifetime,
+ bool addLoopExit, bool synthesizeBodies, bool addStaticInitBranch,
+ bool addCXXNewAllocator, CodeInjector *injector)
+ : Injector(injector), FunctionBodyFarm(ASTCtx, injector),
+ SynthesizeBodies(synthesizeBodies) {
cfgBuildOptions.PruneTriviallyFalseEdges = !useUnoptimizedCFG;
cfgBuildOptions.AddImplicitDtors = addImplicitDtors;
cfgBuildOptions.AddInitializers = addInitializers;
cfgBuildOptions.AddTemporaryDtors = addTemporaryDtors;
cfgBuildOptions.AddLifetime = addLifetime;
+ cfgBuildOptions.AddLoopExit = addLoopExit;
cfgBuildOptions.AddStaticInitBranches = addStaticInitBranch;
cfgBuildOptions.AddCXXNewAllocator = addCXXNewAllocator;
}
void AnalysisDeclContextManager::clear() { Contexts.clear(); }
-static BodyFarm &getBodyFarm(ASTContext &C, CodeInjector *injector = nullptr) {
- static BodyFarm *BF = new BodyFarm(C, injector);
- return *BF;
-}
-
Stmt *AnalysisDeclContext::getBody(bool &IsAutosynthesized) const {
IsAutosynthesized = false;
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
@@ -97,8 +89,7 @@ Stmt *AnalysisDeclContext::getBody(bool &IsAutosynthesized) const {
if (auto *CoroBody = dyn_cast_or_null<CoroutineBodyStmt>(Body))
Body = CoroBody->getBody();
if (Manager && Manager->synthesizeBodies()) {
- Stmt *SynthesizedBody =
- getBodyFarm(getASTContext(), Manager->Injector.get()).getBody(FD);
+ Stmt *SynthesizedBody = Manager->getBodyFarm().getBody(FD);
if (SynthesizedBody) {
Body = SynthesizedBody;
IsAutosynthesized = true;
@@ -109,8 +100,7 @@ Stmt *AnalysisDeclContext::getBody(bool &IsAutosynthesized) const {
else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
Stmt *Body = MD->getBody();
if (Manager && Manager->synthesizeBodies()) {
- Stmt *SynthesizedBody =
- getBodyFarm(getASTContext(), Manager->Injector.get()).getBody(MD);
+ Stmt *SynthesizedBody = Manager->getBodyFarm().getBody(MD);
if (SynthesizedBody) {
Body = SynthesizedBody;
IsAutosynthesized = true;
@@ -315,6 +305,8 @@ AnalysisDeclContext *AnalysisDeclContextManager::getContext(const Decl *D) {
return AC.get();
}
+BodyFarm &AnalysisDeclContextManager::getBodyFarm() { return FunctionBodyFarm; }
+
const StackFrameContext *
AnalysisDeclContext::getStackFrame(LocationContext const *Parent, const Stmt *S,
const CFGBlock *Blk, unsigned Idx) {
@@ -608,8 +600,6 @@ AnalysisDeclContext::~AnalysisDeclContext() {
}
}
-AnalysisDeclContextManager::~AnalysisDeclContextManager() {}
-
LocationContext::~LocationContext() {}
LocationContextManager::~LocationContextManager() {
diff --git a/contrib/llvm/tools/clang/lib/Analysis/BodyFarm.cpp b/contrib/llvm/tools/clang/lib/Analysis/BodyFarm.cpp
index 59127246105d3..e5d3c5ce5bc2a 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/BodyFarm.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/BodyFarm.cpp
@@ -12,13 +12,20 @@
//
//===----------------------------------------------------------------------===//
-#include "BodyFarm.h"
+#include "clang/Analysis/BodyFarm.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/CXXInheritance.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/NestedNameSpecifier.h"
#include "clang/Analysis/CodeInjector.h"
+#include "clang/Basic/OperatorKinds.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/Debug.h"
+
+#define DEBUG_TYPE "body-farm"
using namespace clang;
@@ -55,7 +62,8 @@ public:
CompoundStmt *makeCompound(ArrayRef<Stmt*>);
/// Create a new DeclRefExpr for the referenced variable.
- DeclRefExpr *makeDeclRefExpr(const VarDecl *D);
+ DeclRefExpr *makeDeclRefExpr(const VarDecl *D,
+ bool RefersToEnclosingVariableOrCapture = false);
/// Create a new UnaryOperator representing a dereference.
UnaryOperator *makeDereference(const Expr *Arg, QualType Ty);
@@ -66,9 +74,19 @@ public:
/// Create an implicit cast to a builtin boolean type.
ImplicitCastExpr *makeIntegralCastToBoolean(const Expr *Arg);
- // Create an implicit cast for lvalue-to-rvaluate conversions.
+ /// Create an implicit cast for lvalue-to-rvaluate conversions.
ImplicitCastExpr *makeLvalueToRvalue(const Expr *Arg, QualType Ty);
+ /// Make RValue out of variable declaration, creating a temporary
+ /// DeclRefExpr in the process.
+ ImplicitCastExpr *
+ makeLvalueToRvalue(const VarDecl *Decl,
+ bool RefersToEnclosingVariableOrCapture = false);
+
+ /// Create an implicit cast of the given type.
+ ImplicitCastExpr *makeImplicitCast(const Expr *Arg, QualType Ty,
+ CastKind CK = CK_LValueToRValue);
+
/// Create an Objective-C bool literal.
ObjCBoolLiteralExpr *makeObjCBool(bool Val);
@@ -78,6 +96,18 @@ public:
/// Create a Return statement.
ReturnStmt *makeReturn(const Expr *RetVal);
+ /// Create an integer literal expression of the given type.
+ IntegerLiteral *makeIntegerLiteral(uint64_t Value, QualType Ty);
+
+ /// Create a member expression.
+ MemberExpr *makeMemberExpression(Expr *base, ValueDecl *MemberDecl,
+ bool IsArrow = false,
+ ExprValueKind ValueKind = VK_LValue);
+
+ /// Returns a *first* member field of a record declaration with a given name.
+ /// \return an nullptr if no member with such a name exists.
+ ValueDecl *findMemberField(const RecordDecl *RD, StringRef Name);
+
private:
ASTContext &C;
};
@@ -106,16 +136,14 @@ CompoundStmt *ASTMaker::makeCompound(ArrayRef<Stmt *> Stmts) {
return new (C) CompoundStmt(C, Stmts, SourceLocation(), SourceLocation());
}
-DeclRefExpr *ASTMaker::makeDeclRefExpr(const VarDecl *D) {
- DeclRefExpr *DR =
- DeclRefExpr::Create(/* Ctx = */ C,
- /* QualifierLoc = */ NestedNameSpecifierLoc(),
- /* TemplateKWLoc = */ SourceLocation(),
- /* D = */ const_cast<VarDecl*>(D),
- /* RefersToEnclosingVariableOrCapture = */ false,
- /* NameLoc = */ SourceLocation(),
- /* T = */ D->getType(),
- /* VK = */ VK_LValue);
+DeclRefExpr *ASTMaker::makeDeclRefExpr(
+ const VarDecl *D,
+ bool RefersToEnclosingVariableOrCapture) {
+ QualType Type = D->getType().getNonReferenceType();
+
+ DeclRefExpr *DR = DeclRefExpr::Create(
+ C, NestedNameSpecifierLoc(), SourceLocation(), const_cast<VarDecl *>(D),
+ RefersToEnclosingVariableOrCapture, SourceLocation(), Type, VK_LValue);
return DR;
}
@@ -125,8 +153,25 @@ UnaryOperator *ASTMaker::makeDereference(const Expr *Arg, QualType Ty) {
}
ImplicitCastExpr *ASTMaker::makeLvalueToRvalue(const Expr *Arg, QualType Ty) {
- return ImplicitCastExpr::Create(C, Ty, CK_LValueToRValue,
- const_cast<Expr*>(Arg), nullptr, VK_RValue);
+ return makeImplicitCast(Arg, Ty, CK_LValueToRValue);
+}
+
+ImplicitCastExpr *
+ASTMaker::makeLvalueToRvalue(const VarDecl *Arg,
+ bool RefersToEnclosingVariableOrCapture) {
+ QualType Type = Arg->getType().getNonReferenceType();
+ return makeLvalueToRvalue(makeDeclRefExpr(Arg,
+ RefersToEnclosingVariableOrCapture),
+ Type);
+}
+
+ImplicitCastExpr *ASTMaker::makeImplicitCast(const Expr *Arg, QualType Ty,
+ CastKind CK) {
+ return ImplicitCastExpr::Create(C, Ty,
+ /* CastKind=*/ CK,
+ /* Expr=*/ const_cast<Expr *>(Arg),
+ /* CXXCastPath=*/ nullptr,
+ /* ExprValueKind=*/ VK_RValue);
}
Expr *ASTMaker::makeIntegralCast(const Expr *Arg, QualType Ty) {
@@ -161,12 +206,259 @@ ReturnStmt *ASTMaker::makeReturn(const Expr *RetVal) {
nullptr);
}
+IntegerLiteral *ASTMaker::makeIntegerLiteral(uint64_t Value, QualType Ty) {
+ llvm::APInt APValue = llvm::APInt(C.getTypeSize(Ty), Value);
+ return IntegerLiteral::Create(C, APValue, Ty, SourceLocation());
+}
+
+MemberExpr *ASTMaker::makeMemberExpression(Expr *base, ValueDecl *MemberDecl,
+ bool IsArrow,
+ ExprValueKind ValueKind) {
+
+ DeclAccessPair FoundDecl = DeclAccessPair::make(MemberDecl, AS_public);
+ return MemberExpr::Create(
+ C, base, IsArrow, SourceLocation(), NestedNameSpecifierLoc(),
+ SourceLocation(), MemberDecl, FoundDecl,
+ DeclarationNameInfo(MemberDecl->getDeclName(), SourceLocation()),
+ /* TemplateArgumentListInfo=*/ nullptr, MemberDecl->getType(), ValueKind,
+ OK_Ordinary);
+}
+
+ValueDecl *ASTMaker::findMemberField(const RecordDecl *RD, StringRef Name) {
+
+ CXXBasePaths Paths(
+ /* FindAmbiguities=*/false,
+ /* RecordPaths=*/false,
+ /* DetectVirtual=*/ false);
+ const IdentifierInfo &II = C.Idents.get(Name);
+ DeclarationName DeclName = C.DeclarationNames.getIdentifier(&II);
+
+ DeclContextLookupResult Decls = RD->lookup(DeclName);
+ for (NamedDecl *FoundDecl : Decls)
+ if (!FoundDecl->getDeclContext()->isFunctionOrMethod())
+ return cast<ValueDecl>(FoundDecl);
+
+ return nullptr;
+}
+
//===----------------------------------------------------------------------===//
// Creation functions for faux ASTs.
//===----------------------------------------------------------------------===//
typedef Stmt *(*FunctionFarmer)(ASTContext &C, const FunctionDecl *D);
+static CallExpr *create_call_once_funcptr_call(ASTContext &C, ASTMaker M,
+ const ParmVarDecl *Callback,
+ ArrayRef<Expr *> CallArgs) {
+
+ QualType Ty = Callback->getType();
+ DeclRefExpr *Call = M.makeDeclRefExpr(Callback);
+ CastKind CK;
+ if (Ty->isRValueReferenceType()) {
+ CK = CK_LValueToRValue;
+ } else {
+ assert(Ty->isLValueReferenceType());
+ CK = CK_FunctionToPointerDecay;
+ Ty = C.getPointerType(Ty.getNonReferenceType());
+ }
+
+ return new (C)
+ CallExpr(C, M.makeImplicitCast(Call, Ty.getNonReferenceType(), CK),
+ /*args=*/CallArgs,
+ /*QualType=*/C.VoidTy,
+ /*ExprValueType=*/VK_RValue,
+ /*SourceLocation=*/SourceLocation());
+}
+
+static CallExpr *create_call_once_lambda_call(ASTContext &C, ASTMaker M,
+ const ParmVarDecl *Callback,
+ CXXRecordDecl *CallbackDecl,
+ ArrayRef<Expr *> CallArgs) {
+ assert(CallbackDecl != nullptr);
+ assert(CallbackDecl->isLambda());
+ FunctionDecl *callOperatorDecl = CallbackDecl->getLambdaCallOperator();
+ assert(callOperatorDecl != nullptr);
+
+ DeclRefExpr *callOperatorDeclRef =
+ DeclRefExpr::Create(/* Ctx =*/ C,
+ /* QualifierLoc =*/ NestedNameSpecifierLoc(),
+ /* TemplateKWLoc =*/ SourceLocation(),
+ const_cast<FunctionDecl *>(callOperatorDecl),
+ /* RefersToEnclosingVariableOrCapture=*/ false,
+ /* NameLoc =*/ SourceLocation(),
+ /* T =*/ callOperatorDecl->getType(),
+ /* VK =*/ VK_LValue);
+
+ return new (C)
+ CXXOperatorCallExpr(/*AstContext=*/C, OO_Call, callOperatorDeclRef,
+ /*args=*/CallArgs,
+ /*QualType=*/C.VoidTy,
+ /*ExprValueType=*/VK_RValue,
+ /*SourceLocation=*/SourceLocation(), FPOptions());
+}
+
+/// Create a fake body for std::call_once.
+/// Emulates the following function body:
+///
+/// \code
+/// typedef struct once_flag_s {
+/// unsigned long __state = 0;
+/// } once_flag;
+/// template<class Callable>
+/// void call_once(once_flag& o, Callable func) {
+/// if (!o.__state) {
+/// func();
+/// }
+/// o.__state = 1;
+/// }
+/// \endcode
+static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) {
+ DEBUG(llvm::dbgs() << "Generating body for call_once\n");
+
+ // We need at least two parameters.
+ if (D->param_size() < 2)
+ return nullptr;
+
+ ASTMaker M(C);
+
+ const ParmVarDecl *Flag = D->getParamDecl(0);
+ const ParmVarDecl *Callback = D->getParamDecl(1);
+
+ if (!Callback->getType()->isReferenceType()) {
+ llvm::dbgs() << "libcxx03 std::call_once implementation, skipping.\n";
+ return nullptr;
+ }
+ if (!Flag->getType()->isReferenceType()) {
+ llvm::dbgs() << "unknown std::call_once implementation, skipping.\n";
+ return nullptr;
+ }
+
+ QualType CallbackType = Callback->getType().getNonReferenceType();
+
+ // Nullable pointer, non-null iff function is a CXXRecordDecl.
+ CXXRecordDecl *CallbackRecordDecl = CallbackType->getAsCXXRecordDecl();
+ QualType FlagType = Flag->getType().getNonReferenceType();
+ auto *FlagRecordDecl = dyn_cast_or_null<RecordDecl>(FlagType->getAsTagDecl());
+
+ if (!FlagRecordDecl) {
+ DEBUG(llvm::dbgs() << "Flag field is not a record: "
+ << "unknown std::call_once implementation, "
+ << "ignoring the call.\n");
+ return nullptr;
+ }
+
+ // We initially assume libc++ implementation of call_once,
+ // where the once_flag struct has a field `__state_`.
+ ValueDecl *FlagFieldDecl = M.findMemberField(FlagRecordDecl, "__state_");
+
+ // Otherwise, try libstdc++ implementation, with a field
+ // `_M_once`
+ if (!FlagFieldDecl) {
+ FlagFieldDecl = M.findMemberField(FlagRecordDecl, "_M_once");
+ }
+
+ if (!FlagFieldDecl) {
+ DEBUG(llvm::dbgs() << "No field _M_once or __state_ found on "
+ << "std::once_flag struct: unknown std::call_once "
+ << "implementation, ignoring the call.");
+ return nullptr;
+ }
+
+ bool isLambdaCall = CallbackRecordDecl && CallbackRecordDecl->isLambda();
+ if (CallbackRecordDecl && !isLambdaCall) {
+ DEBUG(llvm::dbgs() << "Not supported: synthesizing body for functors when "
+ << "body farming std::call_once, ignoring the call.");
+ return nullptr;
+ }
+
+ SmallVector<Expr *, 5> CallArgs;
+ const FunctionProtoType *CallbackFunctionType;
+ if (isLambdaCall) {
+
+ // Lambda requires callback itself inserted as a first parameter.
+ CallArgs.push_back(
+ M.makeDeclRefExpr(Callback,
+ /* RefersToEnclosingVariableOrCapture=*/ true));
+ CallbackFunctionType = CallbackRecordDecl->getLambdaCallOperator()
+ ->getType()
+ ->getAs<FunctionProtoType>();
+ } else if (!CallbackType->getPointeeType().isNull()) {
+ CallbackFunctionType =
+ CallbackType->getPointeeType()->getAs<FunctionProtoType>();
+ } else {
+ CallbackFunctionType = CallbackType->getAs<FunctionProtoType>();
+ }
+
+ if (!CallbackFunctionType)
+ return nullptr;
+
+ // First two arguments are used for the flag and for the callback.
+ if (D->getNumParams() != CallbackFunctionType->getNumParams() + 2) {
+ DEBUG(llvm::dbgs() << "Types of params of the callback do not match "
+ << "params passed to std::call_once, "
+ << "ignoring the call\n");
+ return nullptr;
+ }
+
+ // All arguments past first two ones are passed to the callback,
+ // and we turn lvalues into rvalues if the argument is not passed by
+ // reference.
+ for (unsigned int ParamIdx = 2; ParamIdx < D->getNumParams(); ParamIdx++) {
+ const ParmVarDecl *PDecl = D->getParamDecl(ParamIdx);
+ Expr *ParamExpr = M.makeDeclRefExpr(PDecl);
+ if (!CallbackFunctionType->getParamType(ParamIdx - 2)->isReferenceType()) {
+ QualType PTy = PDecl->getType().getNonReferenceType();
+ ParamExpr = M.makeLvalueToRvalue(ParamExpr, PTy);
+ }
+ CallArgs.push_back(ParamExpr);
+ }
+
+ CallExpr *CallbackCall;
+ if (isLambdaCall) {
+
+ CallbackCall = create_call_once_lambda_call(C, M, Callback,
+ CallbackRecordDecl, CallArgs);
+ } else {
+
+ // Function pointer case.
+ CallbackCall = create_call_once_funcptr_call(C, M, Callback, CallArgs);
+ }
+
+ DeclRefExpr *FlagDecl =
+ M.makeDeclRefExpr(Flag,
+ /* RefersToEnclosingVariableOrCapture=*/true);
+
+
+ MemberExpr *Deref = M.makeMemberExpression(FlagDecl, FlagFieldDecl);
+ assert(Deref->isLValue());
+ QualType DerefType = Deref->getType();
+
+ // Negation predicate.
+ UnaryOperator *FlagCheck = new (C) UnaryOperator(
+ /* input=*/
+ M.makeImplicitCast(M.makeLvalueToRvalue(Deref, DerefType), DerefType,
+ CK_IntegralToBoolean),
+ /* opc=*/ UO_LNot,
+ /* QualType=*/ C.IntTy,
+ /* ExprValueKind=*/ VK_RValue,
+ /* ExprObjectKind=*/ OK_Ordinary, SourceLocation());
+
+ // Create assignment.
+ BinaryOperator *FlagAssignment = M.makeAssignment(
+ Deref, M.makeIntegralCast(M.makeIntegerLiteral(1, C.IntTy), DerefType),
+ DerefType);
+
+ IfStmt *Out = new (C)
+ IfStmt(C, SourceLocation(),
+ /* IsConstexpr=*/ false,
+ /* init=*/ nullptr,
+ /* var=*/ nullptr,
+ /* cond=*/ FlagCheck,
+ /* then=*/ M.makeCompound({CallbackCall, FlagAssignment}));
+
+ return Out;
+}
+
/// Create a fake body for dispatch_once.
static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) {
// Check if we have at least two parameters.
@@ -193,8 +485,8 @@ static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) {
// sets it, and calls the block. Basically, an AST dump of:
//
// void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block) {
- // if (!*predicate) {
- // *predicate = 1;
+ // if (*predicate != ~0l) {
+ // *predicate = ~0l;
// block();
// }
// }
@@ -202,22 +494,26 @@ static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) {
ASTMaker M(C);
// (1) Create the call.
- DeclRefExpr *DR = M.makeDeclRefExpr(Block);
- ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty);
- CallExpr *CE = new (C) CallExpr(C, ICE, None, C.VoidTy, VK_RValue,
- SourceLocation());
+ CallExpr *CE = new (C) CallExpr(
+ /*ASTContext=*/C,
+ /*StmtClass=*/M.makeLvalueToRvalue(/*Expr=*/Block),
+ /*args=*/None,
+ /*QualType=*/C.VoidTy,
+ /*ExprValueType=*/VK_RValue,
+ /*SourceLocation=*/SourceLocation());
// (2) Create the assignment to the predicate.
- IntegerLiteral *IL =
- IntegerLiteral::Create(C, llvm::APInt(C.getTypeSize(C.IntTy), (uint64_t) 1),
- C.IntTy, SourceLocation());
+ Expr *DoneValue =
+ new (C) UnaryOperator(M.makeIntegerLiteral(0, C.LongTy), UO_Not, C.LongTy,
+ VK_RValue, OK_Ordinary, SourceLocation());
+
BinaryOperator *B =
M.makeAssignment(
M.makeDereference(
M.makeLvalueToRvalue(
M.makeDeclRefExpr(Predicate), PredicateQPtrTy),
PredicateTy),
- M.makeIntegralCast(IL, PredicateTy),
+ M.makeIntegralCast(DoneValue, PredicateTy),
PredicateTy);
// (3) Create the compound statement.
@@ -233,14 +529,15 @@ static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) {
PredicateQPtrTy),
PredicateTy),
PredicateTy);
-
- UnaryOperator *UO = new (C) UnaryOperator(LValToRval, UO_LNot, C.IntTy,
- VK_RValue, OK_Ordinary,
- SourceLocation());
-
+
+ Expr *GuardCondition = M.makeComparison(LValToRval, DoneValue, BO_NE);
// (5) Create the 'if' statement.
- IfStmt *If = new (C) IfStmt(C, SourceLocation(), false, nullptr, nullptr,
- UO, CS);
+ IfStmt *If = new (C) IfStmt(C, SourceLocation(),
+ /* IsConstexpr=*/ false,
+ /* init=*/ nullptr,
+ /* var=*/ nullptr,
+ /* cond=*/ GuardCondition,
+ /* then=*/ CS);
return If;
}
@@ -370,8 +667,9 @@ Stmt *BodyFarm::getBody(const FunctionDecl *D) {
if (Name.startswith("OSAtomicCompareAndSwap") ||
Name.startswith("objc_atomicCompareAndSwap")) {
FF = create_OSAtomicCompareAndSwap;
- }
- else {
+ } else if (Name == "call_once" && D->getDeclContext()->isStdNamespace()) {
+ FF = create_call_once;
+ } else {
FF = llvm::StringSwitch<FunctionFarmer>(Name)
.Case("dispatch_sync", create_dispatch_sync)
.Case("dispatch_once", create_dispatch_once)
diff --git a/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp b/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp
index 6a77455edeef6..714b85d3a9fff 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp
@@ -1,4 +1,4 @@
-//===--- CFG.cpp - Classes for representing and building CFGs----*- C++ -*-===//
+//===- CFG.cpp - Classes for representing and building CFGs ---------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,23 +15,53 @@
#include "clang/Analysis/CFG.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
-#include "clang/AST/CharUnits.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclGroup.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/OperationKinds.h"
#include "clang/AST/PrettyPrinter.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtObjC.h"
#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/Support/BumpVector.h"
#include "clang/Basic/Builtins.h"
+#include "clang/Basic/ExceptionSpecificationType.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
-#include <memory>
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/DOTGraphTraits.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/Support/SaveAndRestore.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <memory>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
using namespace clang;
-namespace {
-
static SourceLocation GetEndLoc(Decl *D) {
if (VarDecl *VD = dyn_cast<VarDecl>(D))
if (Expr *Ex = VD->getInit())
@@ -41,7 +71,7 @@ static SourceLocation GetEndLoc(Decl *D) {
/// Helper for tryNormalizeBinaryOperator. Attempts to extract an IntegerLiteral
/// or EnumConstantDecl from the given Expr. If it fails, returns nullptr.
-const Expr *tryTransformToIntOrEnumConstant(const Expr *E) {
+static const Expr *tryTransformToIntOrEnumConstant(const Expr *E) {
E = E->IgnoreParens();
if (isa<IntegerLiteral>(E))
return E;
@@ -111,6 +141,8 @@ static bool areExprTypesCompatible(const Expr *E1, const Expr *E2) {
return DC1 == DC2;
}
+namespace {
+
class CFGBuilder;
/// The CFG builder uses a recursive algorithm to build the CFG. When
@@ -125,7 +157,6 @@ class CFGBuilder;
/// contextual information. If AddStmtChoice is 'NotAlwaysAdd', then
/// the builder has an option not to add a subexpression as a
/// block-level expression.
-///
class AddStmtChoice {
public:
enum Kind { NotAlwaysAdd = 0, AlwaysAdd = 1 };
@@ -168,23 +199,24 @@ private:
///
class LocalScope {
public:
- typedef BumpVector<VarDecl*> AutomaticVarsTy;
+ friend class const_iterator;
+
+ using AutomaticVarsTy = BumpVector<VarDecl *>;
/// const_iterator - Iterates local scope backwards and jumps to previous
/// scope on reaching the beginning of currently iterated scope.
class const_iterator {
- const LocalScope* Scope;
+ const LocalScope* Scope = nullptr;
/// VarIter is guaranteed to be greater then 0 for every valid iterator.
/// Invalid iterator (with null Scope) has VarIter equal to 0.
- unsigned VarIter;
+ unsigned VarIter = 0;
public:
/// Create invalid iterator. Dereferencing invalid iterator is not allowed.
/// Incrementing invalid iterator is allowed and will result in invalid
/// iterator.
- const_iterator()
- : Scope(nullptr), VarIter(0) {}
+ const_iterator() = default;
/// Create valid iterator. In case when S.Prev is an invalid iterator and
/// I is equal to 0, this will create invalid iterator.
@@ -197,8 +229,8 @@ public:
}
VarDecl *const* operator->() const {
- assert (Scope && "Dereferencing invalid iterator is not allowed");
- assert (VarIter != 0 && "Iterator has invalid value of VarIter member");
+ assert(Scope && "Dereferencing invalid iterator is not allowed");
+ assert(VarIter != 0 && "Iterator has invalid value of VarIter member");
return &Scope->Vars[VarIter - 1];
}
VarDecl *operator*() const {
@@ -209,7 +241,7 @@ public:
if (!Scope)
return *this;
- assert (VarIter != 0 && "Iterator has invalid value of VarIter member");
+ assert(VarIter != 0 && "Iterator has invalid value of VarIter member");
--VarIter;
if (VarIter == 0)
*this = Scope->Prev;
@@ -236,13 +268,12 @@ public:
const_iterator shared_parent(const_iterator L);
};
- friend class const_iterator;
-
private:
BumpVectorContext ctx;
/// Automatic variables in order of declaration.
AutomaticVarsTy Vars;
+
/// Iterator to variable in previous scope that was declared just before
/// begin of this scope.
const_iterator Prev;
@@ -260,6 +291,8 @@ public:
}
};
+} // namespace
+
/// distance - Calculates distance from this to L. L must be reachable from this
/// (with use of ++ operator). Cost of calculating the distance is linear w.r.t.
/// number of scopes between this and L.
@@ -267,8 +300,8 @@ int LocalScope::const_iterator::distance(LocalScope::const_iterator L) {
int D = 0;
const_iterator F = *this;
while (F.Scope != L.Scope) {
- assert (F != const_iterator()
- && "L iterator is not reachable from F iterator.");
+ assert(F != const_iterator() &&
+ "L iterator is not reachable from F iterator.");
D += F.VarIter;
F = F.Scope->Prev;
}
@@ -300,16 +333,18 @@ LocalScope::const_iterator::shared_parent(LocalScope::const_iterator L) {
}
}
+namespace {
+
/// Structure for specifying position in CFG during its build process. It
/// consists of CFGBlock that specifies position in CFG and
/// LocalScope::const_iterator that specifies position in LocalScope graph.
struct BlockScopePosPair {
- BlockScopePosPair() : block(nullptr) {}
+ CFGBlock *block = nullptr;
+ LocalScope::const_iterator scopePosition;
+
+ BlockScopePosPair() = default;
BlockScopePosPair(CFGBlock *b, LocalScope::const_iterator scopePos)
: block(b), scopePosition(scopePos) {}
-
- CFGBlock *block;
- LocalScope::const_iterator scopePosition;
};
/// TryResult - a class representing a variant over the values
@@ -317,37 +352,46 @@ struct BlockScopePosPair {
/// and is used by the CFGBuilder to decide if a branch condition
/// can be decided up front during CFG construction.
class TryResult {
- int X;
+ int X = -1;
+
public:
+ TryResult() = default;
TryResult(bool b) : X(b ? 1 : 0) {}
- TryResult() : X(-1) {}
bool isTrue() const { return X == 1; }
bool isFalse() const { return X == 0; }
bool isKnown() const { return X >= 0; }
+
void negate() {
assert(isKnown());
X ^= 0x1;
}
};
-TryResult bothKnownTrue(TryResult R1, TryResult R2) {
+} // namespace
+
+static TryResult bothKnownTrue(TryResult R1, TryResult R2) {
if (!R1.isKnown() || !R2.isKnown())
return TryResult();
return TryResult(R1.isTrue() && R2.isTrue());
}
+namespace {
+
class reverse_children {
llvm::SmallVector<Stmt *, 12> childrenBuf;
- ArrayRef<Stmt*> children;
+ ArrayRef<Stmt *> children;
+
public:
reverse_children(Stmt *S);
- typedef ArrayRef<Stmt*>::reverse_iterator iterator;
+ using iterator = ArrayRef<Stmt *>::reverse_iterator;
+
iterator begin() const { return children.rbegin(); }
iterator end() const { return children.rend(); }
};
+} // namespace
reverse_children::reverse_children(Stmt *S) {
if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
@@ -374,6 +418,8 @@ reverse_children::reverse_children(Stmt *S) {
children = childrenBuf;
}
+namespace {
+
/// CFGBuilder - This class implements CFG construction from an AST.
/// The builder is stateful: an instance of the builder should be used to only
/// construct a single CFG.
@@ -387,62 +433,65 @@ reverse_children::reverse_children(Stmt *S) {
/// the AST in reverse order so that the successor of a basic block is
/// constructed prior to its predecessor. This allows us to nicely capture
/// implicit fall-throughs without extra basic blocks.
-///
class CFGBuilder {
- typedef BlockScopePosPair JumpTarget;
- typedef BlockScopePosPair JumpSource;
+ using JumpTarget = BlockScopePosPair;
+ using JumpSource = BlockScopePosPair;
ASTContext *Context;
std::unique_ptr<CFG> cfg;
- CFGBlock *Block;
- CFGBlock *Succ;
+ // Current block.
+ CFGBlock *Block = nullptr;
+
+ // Block after the current block.
+ CFGBlock *Succ = nullptr;
+
JumpTarget ContinueJumpTarget;
JumpTarget BreakJumpTarget;
- CFGBlock *SwitchTerminatedBlock;
- CFGBlock *DefaultCaseBlock;
- CFGBlock *TryTerminatedBlock;
+ JumpTarget SEHLeaveJumpTarget;
+ CFGBlock *SwitchTerminatedBlock = nullptr;
+ CFGBlock *DefaultCaseBlock = nullptr;
+
+ // This can point either to a try or a __try block. The frontend forbids
+ // mixing both kinds in one function, so having one for both is enough.
+ CFGBlock *TryTerminatedBlock = nullptr;
// Current position in local scope.
LocalScope::const_iterator ScopePos;
// LabelMap records the mapping from Label expressions to their jump targets.
- typedef llvm::DenseMap<LabelDecl*, JumpTarget> LabelMapTy;
+ using LabelMapTy = llvm::DenseMap<LabelDecl *, JumpTarget>;
LabelMapTy LabelMap;
// A list of blocks that end with a "goto" that must be backpatched to their
// resolved targets upon completion of CFG construction.
- typedef std::vector<JumpSource> BackpatchBlocksTy;
+ using BackpatchBlocksTy = std::vector<JumpSource>;
BackpatchBlocksTy BackpatchBlocks;
// A list of labels whose address has been taken (for indirect gotos).
- typedef llvm::SmallPtrSet<LabelDecl*, 5> LabelSetTy;
+ using LabelSetTy = llvm::SmallSetVector<LabelDecl *, 8>;
LabelSetTy AddressTakenLabels;
- bool badCFG;
+ bool badCFG = false;
const CFG::BuildOptions &BuildOpts;
// State to track for building switch statements.
- bool switchExclusivelyCovered;
- Expr::EvalResult *switchCond;
+ bool switchExclusivelyCovered = false;
+ Expr::EvalResult *switchCond = nullptr;
- CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry;
- const Stmt *lastLookup;
+ CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry = nullptr;
+ const Stmt *lastLookup = nullptr;
// Caches boolean evaluations of expressions to avoid multiple re-evaluations
// during construction of branches for chained logical operators.
- typedef llvm::DenseMap<Expr *, TryResult> CachedBoolEvalsTy;
+ using CachedBoolEvalsTy = llvm::DenseMap<Expr *, TryResult>;
CachedBoolEvalsTy CachedBoolEvals;
public:
explicit CFGBuilder(ASTContext *astContext,
- const CFG::BuildOptions &buildOpts)
- : Context(astContext), cfg(new CFG()), // crew a new CFG
- Block(nullptr), Succ(nullptr),
- SwitchTerminatedBlock(nullptr), DefaultCaseBlock(nullptr),
- TryTerminatedBlock(nullptr), badCFG(false), BuildOpts(buildOpts),
- switchExclusivelyCovered(false), switchCond(nullptr),
- cachedEntry(nullptr), lastLookup(nullptr) {}
+ const CFG::BuildOptions &buildOpts)
+ : Context(astContext), cfg(new CFG()), // crew a new CFG
+ BuildOpts(buildOpts) {}
// buildCFG - Used by external clients to construct the CFG.
std::unique_ptr<CFG> buildCFG(const Decl *D, Stmt *Statement);
@@ -501,6 +550,10 @@ private:
CFGBlock *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S);
CFGBlock *VisitPseudoObjectExpr(PseudoObjectExpr *E);
CFGBlock *VisitReturnStmt(ReturnStmt *R);
+ CFGBlock *VisitSEHExceptStmt(SEHExceptStmt *S);
+ CFGBlock *VisitSEHFinallyStmt(SEHFinallyStmt *S);
+ CFGBlock *VisitSEHLeaveStmt(SEHLeaveStmt *S);
+ CFGBlock *VisitSEHTryStmt(SEHTryStmt *S);
CFGBlock *VisitStmtExpr(StmtExpr *S, AddStmtChoice asc);
CFGBlock *VisitSwitchStmt(SwitchStmt *S);
CFGBlock *VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E,
@@ -542,13 +595,9 @@ private:
/// if the CXXBindTemporaryExpr was marked executed, and otherwise
/// branches to the stored successor.
struct TempDtorContext {
- TempDtorContext()
- : IsConditional(false), KnownExecuted(true), Succ(nullptr),
- TerminatorExpr(nullptr) {}
-
+ TempDtorContext() = default;
TempDtorContext(TryResult KnownExecuted)
- : IsConditional(true), KnownExecuted(KnownExecuted), Succ(nullptr),
- TerminatorExpr(nullptr) {}
+ : IsConditional(true), KnownExecuted(KnownExecuted) {}
/// Returns whether we need to start a new branch for a temporary destructor
/// call. This is the case when the temporary destructor is
@@ -567,10 +616,10 @@ private:
TerminatorExpr = E;
}
- const bool IsConditional;
- const TryResult KnownExecuted;
- CFGBlock *Succ;
- CXXBindTemporaryExpr *TerminatorExpr;
+ const bool IsConditional = false;
+ const TryResult KnownExecuted = true;
+ CFGBlock *Succ = nullptr;
+ CXXBindTemporaryExpr *TerminatorExpr = nullptr;
};
// Visitors to walk an AST and generate destructors of temporaries in
@@ -601,7 +650,9 @@ private:
CFGBlock *addStmt(Stmt *S) {
return Visit(S, AddStmtChoice::AlwaysAdd);
}
+
CFGBlock *addInitializer(CXXCtorInitializer *I);
+ void addLoopExit(const Stmt *LoopStmt);
void addAutomaticObjDtors(LocalScope::const_iterator B,
LocalScope::const_iterator E, Stmt *S);
void addLifetimeEnds(LocalScope::const_iterator B,
@@ -621,6 +672,7 @@ private:
void addLocalScopeAndDtors(Stmt *S);
// Interface to CFGBlock - adding CFGElements.
+
void appendStmt(CFGBlock *B, const Stmt *S) {
if (alwaysAdd(S) && cachedEntry)
cachedEntry->second = B;
@@ -629,21 +681,27 @@ private:
assert(!isa<Expr>(S) || cast<Expr>(S)->IgnoreParens() == S);
B->appendStmt(const_cast<Stmt*>(S), cfg->getBumpVectorContext());
}
+
void appendInitializer(CFGBlock *B, CXXCtorInitializer *I) {
B->appendInitializer(I, cfg->getBumpVectorContext());
}
+
void appendNewAllocator(CFGBlock *B, CXXNewExpr *NE) {
B->appendNewAllocator(NE, cfg->getBumpVectorContext());
}
+
void appendBaseDtor(CFGBlock *B, const CXXBaseSpecifier *BS) {
B->appendBaseDtor(BS, cfg->getBumpVectorContext());
}
+
void appendMemberDtor(CFGBlock *B, FieldDecl *FD) {
B->appendMemberDtor(FD, cfg->getBumpVectorContext());
}
+
void appendTemporaryDtor(CFGBlock *B, CXXBindTemporaryExpr *E) {
B->appendTemporaryDtor(E, cfg->getBumpVectorContext());
}
+
void appendAutomaticObjDtor(CFGBlock *B, VarDecl *VD, Stmt *S) {
B->appendAutomaticObjDtor(VD, S, cfg->getBumpVectorContext());
}
@@ -652,6 +710,10 @@ private:
B->appendLifetimeEnds(VD, S, cfg->getBumpVectorContext());
}
+ void appendLoopExit(CFGBlock *B, const Stmt *LoopStmt) {
+ B->appendLoopExit(LoopStmt, cfg->getBumpVectorContext());
+ }
+
void appendDeleteDtor(CFGBlock *B, CXXRecordDecl *RD, CXXDeleteExpr *DE) {
B->appendDeleteDtor(RD, DE, cfg->getBumpVectorContext());
}
@@ -799,10 +861,10 @@ private:
const BinaryOperator *RHS =
dyn_cast<BinaryOperator>(B->getRHS()->IgnoreParens());
if (!LHS || !RHS)
- return TryResult();
+ return {};
if (!LHS->isComparisonOp() || !RHS->isComparisonOp())
- return TryResult();
+ return {};
const DeclRefExpr *Decl1;
const Expr *Expr1;
@@ -810,7 +872,7 @@ private:
std::tie(Decl1, BO1, Expr1) = tryNormalizeBinaryOperator(LHS);
if (!Decl1 || !Expr1)
- return TryResult();
+ return {};
const DeclRefExpr *Decl2;
const Expr *Expr2;
@@ -818,26 +880,26 @@ private:
std::tie(Decl2, BO2, Expr2) = tryNormalizeBinaryOperator(RHS);
if (!Decl2 || !Expr2)
- return TryResult();
+ return {};
// Check that it is the same variable on both sides.
if (Decl1->getDecl() != Decl2->getDecl())
- return TryResult();
+ return {};
// Make sure the user's intent is clear (e.g. they're comparing against two
// int literals, or two things from the same enum)
if (!areExprTypesCompatible(Expr1, Expr2))
- return TryResult();
+ return {};
llvm::APSInt L1, L2;
if (!Expr1->EvaluateAsInt(L1, *Context) ||
!Expr2->EvaluateAsInt(L2, *Context))
- return TryResult();
+ return {};
// Can't compare signed with unsigned or with different bit width.
if (L1.isSigned() != L2.isSigned() || L1.getBitWidth() != L2.getBitWidth())
- return TryResult();
+ return {};
// Values that will be used to determine if result of logical
// operator is always true/false
@@ -868,7 +930,7 @@ private:
Res2 = analyzeLogicOperatorCondition(BO2, Value, L2);
if (!Res1.isKnown() || !Res2.isKnown())
- return TryResult();
+ return {};
if (B->getOpcode() == BO_LAnd) {
AlwaysTrue &= (Res1.isTrue() && Res2.isTrue());
@@ -884,7 +946,7 @@ private:
BuildOpts.Observer->compareAlwaysTrue(B, AlwaysTrue);
return TryResult(AlwaysTrue);
}
- return TryResult();
+ return {};
}
/// Try and evaluate an expression to an integer constant.
@@ -901,7 +963,7 @@ private:
TryResult tryEvaluateBool(Expr *S) {
if (!BuildOpts.PruneTriviallyFalseEdges ||
S->isTypeDependent() || S->isValueDependent())
- return TryResult();
+ return {};
if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(S)) {
if (Bop->isLogicalOp()) {
@@ -976,7 +1038,7 @@ private:
}
}
- return TryResult();
+ return {};
} else if (Bop->isEqualityOp()) {
TryResult BopRes = checkIncorrectEqualityOperator(Bop);
if (BopRes.isKnown())
@@ -992,12 +1054,14 @@ private:
if (E->EvaluateAsBooleanCondition(Result, *Context))
return Result;
- return TryResult();
+ return {};
}
bool hasTrivialDestructor(VarDecl *VD);
};
+} // namespace
+
inline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder,
const Stmt *stmt) const {
return builder.alwaysAdd(stmt) || kind == AlwaysAdd;
@@ -1119,7 +1183,6 @@ std::unique_ptr<CFG> CFGBuilder::buildCFG(const Decl *D, Stmt *Statement) {
if (CFGBlock *B = cfg->getIndirectGotoBlock())
for (LabelSetTy::iterator I = AddressTakenLabels.begin(),
E = AddressTakenLabels.end(); I != E; ++I ) {
-
// Lookup the target block.
LabelMapTy::iterator LI = LabelMap.find(*I);
@@ -1253,6 +1316,15 @@ static QualType getReferenceInitTemporaryType(ASTContext &Context,
return Init->getType();
}
+// TODO: Support adding LoopExit element to the CFG in case where the loop is
+// ended by ReturnStmt, GotoStmt or ThrowExpr.
+void CFGBuilder::addLoopExit(const Stmt *LoopStmt){
+ if(!BuildOpts.AddLoopExit)
+ return;
+ autoCreateBlock();
+ appendLoopExit(Block, LoopStmt);
+}
+
void CFGBuilder::addAutomaticObjHandling(LocalScope::const_iterator B,
LocalScope::const_iterator E,
Stmt *S) {
@@ -1351,8 +1423,8 @@ void CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B,
/// addImplicitDtorsForDestructor - Add implicit destructors generated for
/// base and member objects in destructor.
void CFGBuilder::addImplicitDtorsForDestructor(const CXXDestructorDecl *DD) {
- assert (BuildOpts.AddImplicitDtors
- && "Can be called only when dtors should be added");
+ assert(BuildOpts.AddImplicitDtors &&
+ "Can be called only when dtors should be added");
const CXXRecordDecl *RD = DD->getParent();
// At the end destroy virtual base objects.
@@ -1555,6 +1627,7 @@ void CFGBuilder::prependAutomaticObjLifetimeWithTerminator(
for (LocalScope::const_iterator I = B; I != E; ++I)
InsertPos = Blk->insertLifetimeEnds(InsertPos, *I, Blk->getTerminator());
}
+
/// Visit - Walk the subtree of a statement and add extra
/// blocks for ternary operators, &&, and ||. We also process "," and
/// DeclStmts (which may contain nested control-flow).
@@ -1716,6 +1789,18 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) {
case Stmt::ReturnStmtClass:
return VisitReturnStmt(cast<ReturnStmt>(S));
+ case Stmt::SEHExceptStmtClass:
+ return VisitSEHExceptStmt(cast<SEHExceptStmt>(S));
+
+ case Stmt::SEHFinallyStmtClass:
+ return VisitSEHFinallyStmt(cast<SEHFinallyStmt>(S));
+
+ case Stmt::SEHLeaveStmtClass:
+ return VisitSEHLeaveStmt(cast<SEHLeaveStmt>(S));
+
+ case Stmt::SEHTryStmtClass:
+ return VisitSEHTryStmt(cast<SEHTryStmt>(S));
+
case Stmt::UnaryExprOrTypeTraitExprClass:
return VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S),
asc);
@@ -1797,7 +1882,6 @@ CFGBuilder::VisitLogicalOperator(BinaryOperator *B,
Stmt *Term,
CFGBlock *TrueBlock,
CFGBlock *FalseBlock) {
-
// Introspect the RHS. If it is a nested logical operation, we recursively
// build the CFG using this function. Otherwise, resort to default
// CFG construction behavior.
@@ -1886,7 +1970,6 @@ CFGBuilder::VisitLogicalOperator(BinaryOperator *B,
return std::make_pair(EntryLHSBlock, ExitBlock);
}
-
CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B,
AddStmtChoice asc) {
// && or ||
@@ -1948,7 +2031,6 @@ CFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) {
} else
badCFG = true;
-
return Block;
}
@@ -2072,7 +2154,6 @@ CFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C,
return addStmt(C->getCond());
}
-
CFGBlock *CFGBuilder::VisitCompoundStmt(CompoundStmt *C) {
LocalScope::const_iterator scopeBeginPos = ScopePos;
addLocalScopeForStmt(C);
@@ -2423,7 +2504,6 @@ CFGBlock *CFGBuilder::VisitIfStmt(IfStmt *I) {
return LastBlock;
}
-
CFGBlock *CFGBuilder::VisitReturnStmt(ReturnStmt *R) {
// If we were in the middle of a block we stop processing that block.
//
@@ -2447,6 +2527,117 @@ CFGBlock *CFGBuilder::VisitReturnStmt(ReturnStmt *R) {
return VisitStmt(R, AddStmtChoice::AlwaysAdd);
}
+CFGBlock *CFGBuilder::VisitSEHExceptStmt(SEHExceptStmt *ES) {
+ // SEHExceptStmt are treated like labels, so they are the first statement in a
+ // block.
+
+ // Save local scope position because in case of exception variable ScopePos
+ // won't be restored when traversing AST.
+ SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos);
+
+ addStmt(ES->getBlock());
+ CFGBlock *SEHExceptBlock = Block;
+ if (!SEHExceptBlock)
+ SEHExceptBlock = createBlock();
+
+ appendStmt(SEHExceptBlock, ES);
+
+ // Also add the SEHExceptBlock as a label, like with regular labels.
+ SEHExceptBlock->setLabel(ES);
+
+ // Bail out if the CFG is bad.
+ if (badCFG)
+ return nullptr;
+
+ // We set Block to NULL to allow lazy creation of a new block (if necessary).
+ Block = nullptr;
+
+ return SEHExceptBlock;
+}
+
+CFGBlock *CFGBuilder::VisitSEHFinallyStmt(SEHFinallyStmt *FS) {
+ return VisitCompoundStmt(FS->getBlock());
+}
+
+CFGBlock *CFGBuilder::VisitSEHLeaveStmt(SEHLeaveStmt *LS) {
+ // "__leave" is a control-flow statement. Thus we stop processing the current
+ // block.
+ if (badCFG)
+ return nullptr;
+
+ // Now create a new block that ends with the __leave statement.
+ Block = createBlock(false);
+ Block->setTerminator(LS);
+
+ // If there is no target for the __leave, then we are looking at an incomplete
+ // AST. This means that the CFG cannot be constructed.
+ if (SEHLeaveJumpTarget.block) {
+ addAutomaticObjHandling(ScopePos, SEHLeaveJumpTarget.scopePosition, LS);
+ addSuccessor(Block, SEHLeaveJumpTarget.block);
+ } else
+ badCFG = true;
+
+ return Block;
+}
+
+CFGBlock *CFGBuilder::VisitSEHTryStmt(SEHTryStmt *Terminator) {
+ // "__try"/"__except"/"__finally" is a control-flow statement. Thus we stop
+ // processing the current block.
+ CFGBlock *SEHTrySuccessor = nullptr;
+
+ if (Block) {
+ if (badCFG)
+ return nullptr;
+ SEHTrySuccessor = Block;
+ } else SEHTrySuccessor = Succ;
+
+ // FIXME: Implement __finally support.
+ if (Terminator->getFinallyHandler())
+ return NYS();
+
+ CFGBlock *PrevSEHTryTerminatedBlock = TryTerminatedBlock;
+
+ // Create a new block that will contain the __try statement.
+ CFGBlock *NewTryTerminatedBlock = createBlock(false);
+
+ // Add the terminator in the __try block.
+ NewTryTerminatedBlock->setTerminator(Terminator);
+
+ if (SEHExceptStmt *Except = Terminator->getExceptHandler()) {
+ // The code after the try is the implicit successor if there's an __except.
+ Succ = SEHTrySuccessor;
+ Block = nullptr;
+ CFGBlock *ExceptBlock = VisitSEHExceptStmt(Except);
+ if (!ExceptBlock)
+ return nullptr;
+ // Add this block to the list of successors for the block with the try
+ // statement.
+ addSuccessor(NewTryTerminatedBlock, ExceptBlock);
+ }
+ if (PrevSEHTryTerminatedBlock)
+ addSuccessor(NewTryTerminatedBlock, PrevSEHTryTerminatedBlock);
+ else
+ addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
+
+ // The code after the try is the implicit successor.
+ Succ = SEHTrySuccessor;
+
+ // Save the current "__try" context.
+ SaveAndRestore<CFGBlock *> save_try(TryTerminatedBlock,
+ NewTryTerminatedBlock);
+ cfg->addTryDispatchBlock(TryTerminatedBlock);
+
+ // Save the current value for the __leave target.
+ // All __leaves should go to the code following the __try
+ // (FIXME: or if the __try has a __finally, to the __finally.)
+ SaveAndRestore<JumpTarget> save_break(SEHLeaveJumpTarget);
+ SEHLeaveJumpTarget = JumpTarget(SEHTrySuccessor, ScopePos);
+
+ assert(Terminator->getTryBlock() && "__try must contain a non-NULL body");
+ Block = nullptr;
+ return addStmt(Terminator->getTryBlock());
+}
+
CFGBlock *CFGBuilder::VisitLabelStmt(LabelStmt *L) {
// Get the block of the labeled statement. Add it to our map.
addStmt(L->getSubStmt());
@@ -2543,6 +2734,8 @@ CFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) {
addAutomaticObjHandling(ScopePos, save_scope_pos.get(), F);
+ addLoopExit(F);
+
// "for" is a control-flow statement. Thus we stop processing the current
// block.
if (Block) {
@@ -2668,7 +2861,6 @@ CFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) {
// false branch).
addSuccessor(ExitConditionBlock,
KnownVal.isTrue() ? nullptr : LoopSuccessor);
-
} while (false);
// Link up the loop-back block to the entry condition block.
@@ -2730,7 +2922,6 @@ CFGBlock *CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
// the same with newVariable replaced with existingItem; the binding works
// the same except that for one ObjCForCollectionStmt::getElement() returns
// a DeclStmt and the other returns a DeclRefExpr.
- //
CFGBlock *LoopSuccessor = nullptr;
@@ -2882,6 +3073,7 @@ CFGBlock *CFGBuilder::VisitWhileStmt(WhileStmt *W) {
addLocalScopeForVarDecl(VD);
addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
}
+ addLoopExit(W);
// "while" is a control-flow statement. Thus we stop processing the current
// block.
@@ -2981,7 +3173,6 @@ CFGBlock *CFGBuilder::VisitWhileStmt(WhileStmt *W) {
// false branch).
addSuccessor(ExitConditionBlock,
KnownVal.isTrue() ? nullptr : LoopSuccessor);
-
} while(false);
// Link up the loop-back block to the entry condition block.
@@ -2996,7 +3187,6 @@ CFGBlock *CFGBuilder::VisitWhileStmt(WhileStmt *W) {
return EntryConditionBlock;
}
-
CFGBlock *CFGBuilder::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) {
// FIXME: For now we pretend that @catch and the code it contains does not
// exit.
@@ -3045,6 +3235,8 @@ CFGBlock *CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr *T) {
CFGBlock *CFGBuilder::VisitDoStmt(DoStmt *D) {
CFGBlock *LoopSuccessor = nullptr;
+ addLoopExit(D);
+
// "do...while" is a control-flow statement. Thus we stop processing the
// current block.
if (Block) {
@@ -3167,7 +3359,6 @@ CFGBlock *CFGBuilder::VisitContinueStmt(ContinueStmt *C) {
CFGBlock *CFGBuilder::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E,
AddStmtChoice asc) {
-
if (asc.alwaysAdd(*this, E)) {
autoCreateBlock();
appendStmt(Block, E);
@@ -3688,7 +3879,6 @@ CFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *C,
CFGBlock *CFGBuilder::VisitCXXNewExpr(CXXNewExpr *NE,
AddStmtChoice asc) {
-
autoCreateBlock();
appendStmt(Block, NE);
@@ -3991,8 +4181,6 @@ CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors(
return Block;
}
-} // end anonymous namespace
-
/// createBlock - Constructs and adds a new CFGBlock to the CFG. The block has
/// no successors or predecessors. If this is the first block created in the
/// CFG, it is automatically set to be the Entry and Exit of the CFG.
@@ -4025,6 +4213,7 @@ CFGImplicitDtor::getDestructorDecl(ASTContext &astContext) const {
case CFGElement::Statement:
case CFGElement::Initializer:
case CFGElement::NewAllocator:
+ case CFGElement::LoopExit:
case CFGElement::LifetimeEnds:
llvm_unreachable("getDestructorDecl should only be used with "
"ImplicitDtors");
@@ -4066,7 +4255,6 @@ CFGImplicitDtor::getDestructorDecl(ASTContext &astContext) const {
}
case CFGElement::BaseDtor:
case CFGElement::MemberDtor:
-
// Not yet supported.
return nullptr;
}
@@ -4084,14 +4272,14 @@ bool CFGImplicitDtor::isNoReturn(ASTContext &astContext) const {
//===----------------------------------------------------------------------===//
CFGBlock::AdjacentBlock::AdjacentBlock(CFGBlock *B, bool IsReachable)
- : ReachableBlock(IsReachable ? B : nullptr),
- UnreachableBlock(!IsReachable ? B : nullptr,
- B && IsReachable ? AB_Normal : AB_Unreachable) {}
+ : ReachableBlock(IsReachable ? B : nullptr),
+ UnreachableBlock(!IsReachable ? B : nullptr,
+ B && IsReachable ? AB_Normal : AB_Unreachable) {}
CFGBlock::AdjacentBlock::AdjacentBlock(CFGBlock *B, CFGBlock *AlternateBlock)
- : ReachableBlock(B),
- UnreachableBlock(B == AlternateBlock ? nullptr : AlternateBlock,
- B == AlternateBlock ? AB_Alternate : AB_Normal) {}
+ : ReachableBlock(B),
+ UnreachableBlock(B == AlternateBlock ? nullptr : AlternateBlock,
+ B == AlternateBlock ? AB_Alternate : AB_Normal) {}
void CFGBlock::addSuccessor(AdjacentBlock Succ,
BumpVectorContext &C) {
@@ -4106,7 +4294,6 @@ void CFGBlock::addSuccessor(AdjacentBlock Succ,
bool CFGBlock::FilterEdge(const CFGBlock::FilterOptions &F,
const CFGBlock *From, const CFGBlock *To) {
-
if (F.IgnoreNullPredecessors && !From)
return true;
@@ -4133,18 +4320,18 @@ bool CFGBlock::FilterEdge(const CFGBlock::FilterOptions &F,
namespace {
class StmtPrinterHelper : public PrinterHelper {
- typedef llvm::DenseMap<const Stmt*,std::pair<unsigned,unsigned> > StmtMapTy;
- typedef llvm::DenseMap<const Decl*,std::pair<unsigned,unsigned> > DeclMapTy;
+ using StmtMapTy = llvm::DenseMap<const Stmt *, std::pair<unsigned, unsigned>>;
+ using DeclMapTy = llvm::DenseMap<const Decl *, std::pair<unsigned, unsigned>>;
+
StmtMapTy StmtMap;
DeclMapTy DeclMap;
- signed currentBlock;
- unsigned currStmt;
+ signed currentBlock = 0;
+ unsigned currStmt = 0;
const LangOptions &LangOpts;
-public:
+public:
StmtPrinterHelper(const CFG* cfg, const LangOptions &LO)
- : currentBlock(0), currStmt(0), LangOpts(LO)
- {
+ : LangOpts(LO) {
for (CFG::const_iterator I = cfg->begin(), E = cfg->end(); I != E; ++I ) {
unsigned j = 1;
for (CFGBlock::const_iterator BI = (*I)->begin(), BEnd = (*I)->end() ;
@@ -4199,7 +4386,7 @@ public:
}
}
- ~StmtPrinterHelper() override {}
+ ~StmtPrinterHelper() override = default;
const LangOptions &getLangOpts() const { return LangOpts; }
void setBlockID(signed i) { currentBlock = i; }
@@ -4235,20 +4422,17 @@ public:
return true;
}
};
-} // end anonymous namespace
-
-namespace {
class CFGBlockTerminatorPrint
- : public StmtVisitor<CFGBlockTerminatorPrint,void> {
-
+ : public StmtVisitor<CFGBlockTerminatorPrint,void> {
raw_ostream &OS;
StmtPrinterHelper* Helper;
PrintingPolicy Policy;
+
public:
CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper,
const PrintingPolicy &Policy)
- : OS(os), Helper(helper), Policy(Policy) {
+ : OS(os), Helper(helper), Policy(Policy) {
this->Policy.IncludeNewlines = false;
}
@@ -4302,6 +4486,10 @@ public:
OS << "try ...";
}
+ void VisitSEHTryStmt(SEHTryStmt *CS) {
+ OS << "__try ...";
+ }
+
void VisitAbstractConditionalOperator(AbstractConditionalOperator* C) {
if (Stmt *Cond = C->getCond())
Cond->printPretty(OS, Helper, Policy);
@@ -4353,7 +4541,8 @@ public:
Visit(T.getStmt());
}
};
-} // end anonymous namespace
+
+} // namespace
static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
const CFGElement &E) {
@@ -4403,7 +4592,6 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
// Expressions need a newline.
if (isa<Expr>(S))
OS << '\n';
-
} else if (Optional<CFGInitializer> IE = E.getAs<CFGInitializer>()) {
const CXXCtorInitializer *I = IE->getInitializer();
if (I->isBaseInitializer())
@@ -4422,7 +4610,6 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
else if (I->isDelegatingInitializer())
OS << " (Delegating initializer)\n";
else OS << " (Member initializer)\n";
-
} else if (Optional<CFGAutomaticObjDtor> DE =
E.getAs<CFGAutomaticObjDtor>()) {
const VarDecl *VD = DE->getVarDecl();
@@ -4435,13 +4622,14 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
OS << ".~" << T->getAsCXXRecordDecl()->getName().str() << "()";
OS << " (Implicit destructor)\n";
-
} else if (Optional<CFGLifetimeEnds> DE = E.getAs<CFGLifetimeEnds>()) {
const VarDecl *VD = DE->getVarDecl();
Helper.handleDecl(VD, OS);
OS << " (Lifetime ends)\n";
-
+ } else if (Optional<CFGLoopExit> LE = E.getAs<CFGLoopExit>()) {
+ const Stmt *LoopStmt = LE->getLoopStmt();
+ OS << LoopStmt->getStmtClassName() << " (LoopExit)\n";
} else if (Optional<CFGNewAllocator> NE = E.getAs<CFGNewAllocator>()) {
OS << "CFGNewAllocator(";
if (const CXXNewExpr *AllocExpr = NE->getAllocatorExpr())
@@ -4460,14 +4648,12 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
const CXXBaseSpecifier *BS = BE->getBaseSpecifier();
OS << "~" << BS->getType()->getAsCXXRecordDecl()->getName() << "()";
OS << " (Base object destructor)\n";
-
} else if (Optional<CFGMemberDtor> ME = E.getAs<CFGMemberDtor>()) {
const FieldDecl *FD = ME->getFieldDecl();
const Type *T = FD->getType()->getBaseElementTypeUnsafe();
OS << "this->" << FD->getName();
OS << ".~" << T->getAsCXXRecordDecl()->getName() << "()";
OS << " (Member object destructor)\n";
-
} else if (Optional<CFGTemporaryDtor> TE = E.getAs<CFGTemporaryDtor>()) {
const CXXBindTemporaryExpr *BT = TE->getBindTemporaryExpr();
OS << "~";
@@ -4480,7 +4666,6 @@ static void print_block(raw_ostream &OS, const CFG* cfg,
const CFGBlock &B,
StmtPrinterHelper &Helper, bool print_edges,
bool ShowColors) {
-
Helper.setBlockID(B.getBlockID());
// Print the header.
@@ -4505,7 +4690,6 @@ static void print_block(raw_ostream &OS, const CFG* cfg,
// Print the label of this block.
if (Stmt *Label = const_cast<Stmt*>(B.getLabel())) {
-
if (print_edges)
OS << " ";
@@ -4531,7 +4715,11 @@ static void print_block(raw_ostream &OS, const CFG* cfg,
else
OS << "...";
OS << ")";
-
+ } else if (SEHExceptStmt *ES = dyn_cast<SEHExceptStmt>(Label)) {
+ OS << "__except (";
+ ES->getFilterExpr()->printPretty(OS, &Helper,
+ PrintingPolicy(Helper.getLangOpts()), 0);
+ OS << ")";
} else
llvm_unreachable("Invalid label statement in CFGBlock.");
@@ -4543,7 +4731,6 @@ static void print_block(raw_ostream &OS, const CFG* cfg,
for (CFGBlock::const_iterator I = B.begin(), E = B.end() ;
I != E ; ++I, ++j ) {
-
// Print the statement # in the basic block and the statement itself.
if (print_edges)
OS << " ";
@@ -4590,7 +4777,6 @@ static void print_block(raw_ostream &OS, const CFG* cfg,
for (CFGBlock::const_pred_iterator I = B.pred_begin(), E = B.pred_end();
I != E; ++I, ++i) {
-
if (i % 10 == 8)
OS << "\n ";
@@ -4628,7 +4814,6 @@ static void print_block(raw_ostream &OS, const CFG* cfg,
for (CFGBlock::const_succ_iterator I = B.succ_begin(), E = B.succ_end();
I != E; ++I, ++i) {
-
if (i % 10 == 8)
OS << "\n ";
@@ -4657,7 +4842,6 @@ static void print_block(raw_ostream &OS, const CFG* cfg,
}
}
-
/// dump - A simple pretty printer of a CFG that outputs to stderr.
void CFG::dump(const LangOptions &LO, bool ShowColors) const {
print(llvm::errs(), LO, ShowColors);
@@ -4780,7 +4964,6 @@ Stmt *CFGBlock::getTerminatorCondition(bool StripParens) {
// CFG Graphviz Visualization
//===----------------------------------------------------------------------===//
-
#ifndef NDEBUG
static StmtPrinterHelper* GraphHelper;
#endif
@@ -4795,13 +4978,12 @@ void CFG::viewCFG(const LangOptions &LO) const {
}
namespace llvm {
+
template<>
struct DOTGraphTraits<const CFG*> : public DefaultDOTGraphTraits {
-
- DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
+ DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
static std::string getNodeLabel(const CFGBlock *Node, const CFG* Graph) {
-
#ifndef NDEBUG
std::string OutSStr;
llvm::raw_string_ostream Out(OutSStr);
@@ -4819,8 +5001,9 @@ struct DOTGraphTraits<const CFG*> : public DefaultDOTGraphTraits {
return OutStr;
#else
- return "";
+ return {};
#endif
}
};
-} // end namespace llvm
+
+} // namespace llvm
diff --git a/contrib/llvm/tools/clang/lib/Analysis/CallGraph.cpp b/contrib/llvm/tools/clang/lib/Analysis/CallGraph.cpp
index 6d9530bf0c68d..fb6d7e87a9a31 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/CallGraph.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/CallGraph.cpp
@@ -1,4 +1,4 @@
-//== CallGraph.cpp - AST-based Call graph ----------------------*- C++ -*--==//
+//===- CallGraph.cpp - AST-based Call graph -------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,13 +10,28 @@
// This file defines the AST-based CallGraph.
//
//===----------------------------------------------------------------------===//
+
#include "clang/Analysis/CallGraph.h"
-#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/Stmt.h"
#include "clang/AST/StmtVisitor.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
#include "llvm/ADT/PostOrderIterator.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/DOTGraphTraits.h"
#include "llvm/Support/GraphWriter.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <memory>
+#include <string>
using namespace clang;
@@ -26,6 +41,7 @@ STATISTIC(NumObjCCallEdges, "Number of Objective-C method call edges");
STATISTIC(NumBlockCallEdges, "Number of block call edges");
namespace {
+
/// A helper class, which walks the AST and locates all the call sites in the
/// given function body.
class CGBuilder : public StmtVisitor<CGBuilder> {
@@ -33,8 +49,7 @@ class CGBuilder : public StmtVisitor<CGBuilder> {
CallGraphNode *CallerNode;
public:
- CGBuilder(CallGraph *g, CallGraphNode *N)
- : G(g), CallerNode(N) {}
+ CGBuilder(CallGraph *g, CallGraphNode *N) : G(g), CallerNode(N) {}
void VisitStmt(Stmt *S) { VisitChildren(S); }
@@ -90,7 +105,7 @@ public:
}
};
-} // end anonymous namespace
+} // namespace
void CallGraph::addNodesForBlocks(DeclContext *D) {
if (BlockDecl *BD = dyn_cast<BlockDecl>(D))
@@ -105,7 +120,7 @@ CallGraph::CallGraph() {
Root = getOrInsertNode(nullptr);
}
-CallGraph::~CallGraph() {}
+CallGraph::~CallGraph() = default;
bool CallGraph::includeInGraph(const Decl *D) {
assert(D);
@@ -164,8 +179,8 @@ void CallGraph::print(raw_ostream &OS) const {
// We are going to print the graph in reverse post order, partially, to make
// sure the output is deterministic.
- llvm::ReversePostOrderTraversal<const clang::CallGraph*> RPOT(this);
- for (llvm::ReversePostOrderTraversal<const clang::CallGraph*>::rpo_iterator
+ llvm::ReversePostOrderTraversal<const CallGraph *> RPOT(this);
+ for (llvm::ReversePostOrderTraversal<const CallGraph *>::rpo_iterator
I = RPOT.begin(), E = RPOT.end(); I != E; ++I) {
const CallGraphNode *N = *I;
@@ -209,8 +224,7 @@ namespace llvm {
template <>
struct DOTGraphTraits<const CallGraph*> : public DefaultDOTGraphTraits {
-
- DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
+ DOTGraphTraits (bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
static std::string getNodeLabel(const CallGraphNode *Node,
const CallGraph *CG) {
@@ -222,6 +236,6 @@ struct DOTGraphTraits<const CallGraph*> : public DefaultDOTGraphTraits {
else
return "< >";
}
-
};
-}
+
+} // namespace llvm
diff --git a/contrib/llvm/tools/clang/lib/Analysis/CloneDetection.cpp b/contrib/llvm/tools/clang/lib/Analysis/CloneDetection.cpp
index 5ea74989a7ec9..098803f9a417d 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/CloneDetection.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/CloneDetection.cpp
@@ -13,16 +13,12 @@
#include "clang/Analysis/CloneDetection.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/RecursiveASTVisitor.h"
-#include "clang/AST/Stmt.h"
-#include "clang/Lex/Lexer.h"
+#include "clang/AST/DataCollection.h"
+#include "clang/AST/DeclTemplate.h"
#include "llvm/Support/MD5.h"
-#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Path.h"
using namespace clang;
-using namespace clang::clone_detection;
StmtSequence::StmtSequence(const CompoundStmt *Stmt, const Decl *D,
unsigned StartIndex, unsigned EndIndex)
@@ -91,34 +87,6 @@ SourceRange StmtSequence::getSourceRange() const {
return SourceRange(getStartLoc(), getEndLoc());
}
-/// Prints the macro name that contains the given SourceLocation into the given
-/// raw_string_ostream.
-static void printMacroName(llvm::raw_string_ostream &MacroStack,
- ASTContext &Context, SourceLocation Loc) {
- MacroStack << Lexer::getImmediateMacroName(Loc, Context.getSourceManager(),
- Context.getLangOpts());
-
- // Add an empty space at the end as a padding to prevent
- // that macro names concatenate to the names of other macros.
- MacroStack << " ";
-}
-
-std::string clone_detection::getMacroStack(SourceLocation Loc,
- ASTContext &Context) {
- std::string MacroStack;
- llvm::raw_string_ostream MacroStackStream(MacroStack);
- SourceManager &SM = Context.getSourceManager();
-
- // Iterate over all macros that expanded into the given SourceLocation.
- while (Loc.isMacroID()) {
- // Add the macro name to the stream.
- printMacroName(MacroStackStream, Context, Loc);
- Loc = SM.getImmediateMacroCallerLoc(Loc);
- }
- MacroStackStream.flush();
- return MacroStack;
-}
-
void CloneDetector::analyzeCodeBody(const Decl *D) {
assert(D);
assert(D->hasBody());
@@ -184,16 +152,17 @@ void OnlyLargestCloneConstraint::constrain(
}
}
-bool FilenamePatternConstraint::isAutoGenerated(const CloneDetector::CloneGroup &Group) {
+bool FilenamePatternConstraint::isAutoGenerated(
+ const CloneDetector::CloneGroup &Group) {
std::string Error;
- if (IgnoredFilesPattern.empty() || Group.empty() ||
+ if (IgnoredFilesPattern.empty() || Group.empty() ||
!IgnoredFilesRegex->isValid(Error))
return false;
for (const StmtSequence &S : Group) {
const SourceManager &SM = S.getASTContext().getSourceManager();
- StringRef Filename = llvm::sys::path::filename(SM.getFilename(
- S.getContainingDecl()->getLocation()));
+ StringRef Filename = llvm::sys::path::filename(
+ SM.getFilename(S.getContainingDecl()->getLocation()));
if (IgnoredFilesRegex->match(Filename))
return true;
}
@@ -201,6 +170,59 @@ bool FilenamePatternConstraint::isAutoGenerated(const CloneDetector::CloneGroup
return false;
}
+/// This class defines what a type II code clone is: If it collects for two
+/// statements the same data, then those two statements are considered to be
+/// clones of each other.
+///
+/// All collected data is forwarded to the given data consumer of the type T.
+/// The data consumer class needs to provide a member method with the signature:
+/// update(StringRef Str)
+namespace {
+template <class T>
+class CloneTypeIIStmtDataCollector
+ : public ConstStmtVisitor<CloneTypeIIStmtDataCollector<T>> {
+ ASTContext &Context;
+ /// The data sink to which all data is forwarded.
+ T &DataConsumer;
+
+ template <class Ty> void addData(const Ty &Data) {
+ data_collection::addDataToConsumer(DataConsumer, Data);
+ }
+
+public:
+ CloneTypeIIStmtDataCollector(const Stmt *S, ASTContext &Context,
+ T &DataConsumer)
+ : Context(Context), DataConsumer(DataConsumer) {
+ this->Visit(S);
+ }
+
+// Define a visit method for each class to collect data and subsequently visit
+// all parent classes. This uses a template so that custom visit methods by us
+// take precedence.
+#define DEF_ADD_DATA(CLASS, CODE) \
+ template <class = void> void Visit##CLASS(const CLASS *S) { \
+ CODE; \
+ ConstStmtVisitor<CloneTypeIIStmtDataCollector<T>>::Visit##CLASS(S); \
+ }
+
+#include "clang/AST/StmtDataCollectors.inc"
+
+// Type II clones ignore variable names and literals, so let's skip them.
+#define SKIP(CLASS) \
+ void Visit##CLASS(const CLASS *S) { \
+ ConstStmtVisitor<CloneTypeIIStmtDataCollector<T>>::Visit##CLASS(S); \
+ }
+ SKIP(DeclRefExpr)
+ SKIP(MemberExpr)
+ SKIP(IntegerLiteral)
+ SKIP(FloatingLiteral)
+ SKIP(StringLiteral)
+ SKIP(CXXBoolLiteralExpr)
+ SKIP(CharacterLiteral)
+#undef SKIP
+};
+} // end anonymous namespace
+
static size_t createHash(llvm::MD5 &Hash) {
size_t HashCode;
@@ -216,13 +238,22 @@ static size_t createHash(llvm::MD5 &Hash) {
return HashCode;
}
-size_t RecursiveCloneTypeIIConstraint::saveHash(
- const Stmt *S, const Decl *D,
- std::vector<std::pair<size_t, StmtSequence>> &StmtsByHash) {
+/// Generates and saves a hash code for the given Stmt.
+/// \param S The given Stmt.
+/// \param D The Decl containing S.
+/// \param StmtsByHash Output parameter that will contain the hash codes for
+/// each StmtSequence in the given Stmt.
+/// \return The hash code of the given Stmt.
+///
+/// If the given Stmt is a CompoundStmt, this method will also generate
+/// hashes for all possible StmtSequences in the children of this Stmt.
+static size_t
+saveHash(const Stmt *S, const Decl *D,
+ std::vector<std::pair<size_t, StmtSequence>> &StmtsByHash) {
llvm::MD5 Hash;
ASTContext &Context = D->getASTContext();
- StmtDataCollector<llvm::MD5>(S, Context, Hash);
+ CloneTypeIIStmtDataCollector<llvm::MD5>(S, Context, Hash);
auto CS = dyn_cast<CompoundStmt>(S);
SmallVector<size_t, 8> ChildHashes;
@@ -288,8 +319,8 @@ public:
static void CollectStmtSequenceData(const StmtSequence &Sequence,
FoldingSetNodeIDWrapper &OutputData) {
for (const Stmt *S : Sequence) {
- StmtDataCollector<FoldingSetNodeIDWrapper>(S, Sequence.getASTContext(),
- OutputData);
+ CloneTypeIIStmtDataCollector<FoldingSetNodeIDWrapper>(
+ S, Sequence.getASTContext(), OutputData);
for (const Stmt *Child : S->children()) {
if (!Child)
@@ -318,7 +349,7 @@ static bool areSequencesClones(const StmtSequence &LHS,
return DataLHS == DataRHS;
}
-void RecursiveCloneTypeIIConstraint::constrain(
+void RecursiveCloneTypeIIHashConstraint::constrain(
std::vector<CloneDetector::CloneGroup> &Sequences) {
// FIXME: Maybe we can do this in-place and don't need this additional vector.
std::vector<CloneDetector::CloneGroup> Result;
@@ -339,7 +370,7 @@ void RecursiveCloneTypeIIConstraint::constrain(
// Sort hash_codes in StmtsByHash.
std::stable_sort(StmtsByHash.begin(), StmtsByHash.end(),
[](std::pair<size_t, StmtSequence> LHS,
- std::pair<size_t, StmtSequence> RHS) {
+ std::pair<size_t, StmtSequence> RHS) {
return LHS.first < RHS.first;
});
@@ -359,8 +390,7 @@ void RecursiveCloneTypeIIConstraint::constrain(
for (; i < StmtsByHash.size(); ++i) {
// A different hash value means we have reached the end of the sequence.
- if (PrototypeHash != StmtsByHash[i].first ||
- !areSequencesClones(StmtsByHash[i].second, Current.second)) {
+ if (PrototypeHash != StmtsByHash[i].first) {
// The current sequence could be the start of a new CloneGroup. So we
// decrement i so that we visit it again in the outer loop.
// Note: i can never be 0 at this point because we are just comparing
@@ -383,8 +413,17 @@ void RecursiveCloneTypeIIConstraint::constrain(
Sequences = Result;
}
+void RecursiveCloneTypeIIVerifyConstraint::constrain(
+ std::vector<CloneDetector::CloneGroup> &Sequences) {
+ CloneConstraint::splitCloneGroups(
+ Sequences, [](const StmtSequence &A, const StmtSequence &B) {
+ return areSequencesClones(A, B);
+ });
+}
+
size_t MinComplexityConstraint::calculateStmtComplexity(
- const StmtSequence &Seq, const std::string &ParentMacroStack) {
+ const StmtSequence &Seq, std::size_t Limit,
+ const std::string &ParentMacroStack) {
if (Seq.empty())
return 0;
@@ -393,8 +432,8 @@ size_t MinComplexityConstraint::calculateStmtComplexity(
ASTContext &Context = Seq.getASTContext();
// Look up what macros expanded into the current statement.
- std::string StartMacroStack = getMacroStack(Seq.getStartLoc(), Context);
- std::string EndMacroStack = getMacroStack(Seq.getEndLoc(), Context);
+ std::string MacroStack =
+ data_collection::getMacroStack(Seq.getStartLoc(), Context);
// First, check if ParentMacroStack is not empty which means we are currently
// dealing with a parent statement which was expanded from a macro.
@@ -404,8 +443,7 @@ size_t MinComplexityConstraint::calculateStmtComplexity(
// macro expansion will only increase the total complexity by one.
// Note: This is not the final complexity of this statement as we still
// add the complexity of the child statements to the complexity value.
- if (!ParentMacroStack.empty() && (StartMacroStack == ParentMacroStack &&
- EndMacroStack == ParentMacroStack)) {
+ if (!ParentMacroStack.empty() && MacroStack == ParentMacroStack) {
Complexity = 0;
}
@@ -414,12 +452,16 @@ size_t MinComplexityConstraint::calculateStmtComplexity(
if (Seq.holdsSequence()) {
for (const Stmt *S : Seq) {
Complexity += calculateStmtComplexity(
- StmtSequence(S, Seq.getContainingDecl()), StartMacroStack);
+ StmtSequence(S, Seq.getContainingDecl()), Limit, MacroStack);
+ if (Complexity >= Limit)
+ return Limit;
}
} else {
for (const Stmt *S : Seq.front()->children()) {
Complexity += calculateStmtComplexity(
- StmtSequence(S, Seq.getContainingDecl()), StartMacroStack);
+ StmtSequence(S, Seq.getContainingDecl()), Limit, MacroStack);
+ if (Complexity >= Limit)
+ return Limit;
}
}
return Complexity;
@@ -437,7 +479,8 @@ void MatchingVariablePatternConstraint::constrain(
void CloneConstraint::splitCloneGroups(
std::vector<CloneDetector::CloneGroup> &CloneGroups,
- std::function<bool(const StmtSequence &, const StmtSequence &)> Compare) {
+ llvm::function_ref<bool(const StmtSequence &, const StmtSequence &)>
+ Compare) {
std::vector<CloneDetector::CloneGroup> Result;
for (auto &HashGroup : CloneGroups) {
// Contains all indexes in HashGroup that were already added to a
diff --git a/contrib/llvm/tools/clang/lib/Analysis/CocoaConventions.cpp b/contrib/llvm/tools/clang/lib/Analysis/CocoaConventions.cpp
index be1262dc99108..4d57623e21611 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/CocoaConventions.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/CocoaConventions.cpp
@@ -47,12 +47,19 @@ bool cocoa::isRefType(QualType RetTy, StringRef Prefix,
return Name.startswith(Prefix);
}
+/// Returns true when the passed-in type is a CF-style reference-counted
+/// type from the DiskArbitration framework.
+static bool isDiskArbitrationAPIRefType(QualType T) {
+ return cocoa::isRefType(T, "DADisk") ||
+ cocoa::isRefType(T, "DADissenter") ||
+ cocoa::isRefType(T, "DASessionRef");
+}
+
bool coreFoundation::isCFObjectRef(QualType T) {
return cocoa::isRefType(T, "CF") || // Core Foundation.
cocoa::isRefType(T, "CG") || // Core Graphics.
- cocoa::isRefType(T, "DADisk") || // Disk Arbitration API.
- cocoa::isRefType(T, "DADissenter") ||
- cocoa::isRefType(T, "DASessionRef");
+ cocoa::isRefType(T, "CM") || // Core Media.
+ isDiskArbitrationAPIRefType(T);
}
diff --git a/contrib/llvm/tools/clang/lib/Analysis/Consumed.cpp b/contrib/llvm/tools/clang/lib/Analysis/Consumed.cpp
index f6fe78ac4619c..96edad0c3019f 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/Consumed.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/Consumed.cpp
@@ -22,7 +22,7 @@
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/Type.h"
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
-#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/SourceLocation.h"
@@ -749,8 +749,7 @@ void ConsumedStmtVisitor::VisitCallExpr(const CallExpr *Call) {
// Special case for the std::move function.
// TODO: Make this more specific. (Deferred)
- if (Call->getNumArgs() == 1 && FunDecl->getNameAsString() == "move" &&
- FunDecl->isInStdNamespace()) {
+ if (Call->isCallToStdMove()) {
copyInfo(Call->getArg(0), Call, CS_Consumed);
return;
}
diff --git a/contrib/llvm/tools/clang/lib/Analysis/LiveVariables.cpp b/contrib/llvm/tools/clang/lib/Analysis/LiveVariables.cpp
index cd73a62e6918c..4752c2b020aea 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/LiveVariables.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/LiveVariables.cpp
@@ -15,7 +15,7 @@
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
-#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PostOrderIterator.h"
diff --git a/contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp b/contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp
index 50a3aa20bd195..dfaed26564e6f 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp
@@ -505,9 +505,7 @@ ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64")
: ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
case LengthModifier::AsPtrDiff:
- // FIXME: How to get the corresponding unsigned
- // version of ptrdiff_t?
- return ArgType();
+ return ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t");
case LengthModifier::AsAllocate:
case LengthModifier::AsMAllocate:
case LengthModifier::AsWide:
@@ -654,6 +652,7 @@ bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
case BuiltinType::UInt128:
case BuiltinType::Int128:
case BuiltinType::Half:
+ case BuiltinType::Float16:
case BuiltinType::Float128:
// Various types which are non-trivial to correct.
return false;
diff --git a/contrib/llvm/tools/clang/lib/Analysis/ReachableCode.cpp b/contrib/llvm/tools/clang/lib/Analysis/ReachableCode.cpp
index 60724ea60b25a..7e72795a47f69 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/ReachableCode.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/ReachableCode.cpp
@@ -18,7 +18,7 @@
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ParentMap.h"
#include "clang/AST/StmtCXX.h"
-#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Preprocessor.h"
diff --git a/contrib/llvm/tools/clang/lib/Analysis/ScanfFormatString.cpp b/contrib/llvm/tools/clang/lib/Analysis/ScanfFormatString.cpp
index 534225985460b..8398a4b82d5a3 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/ScanfFormatString.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/ScanfFormatString.cpp
@@ -251,8 +251,7 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const {
case LengthModifier::AsIntMax:
return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
case LengthModifier::AsSizeT:
- // FIXME: ssize_t.
- return ArgType();
+ return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
case LengthModifier::AsPtrDiff:
return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
case LengthModifier::AsLongDouble:
@@ -292,8 +291,8 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const {
case LengthModifier::AsSizeT:
return ArgType::PtrTo(ArgType(Ctx.getSizeType(), "size_t"));
case LengthModifier::AsPtrDiff:
- // FIXME: Unsigned version of ptrdiff_t?
- return ArgType();
+ return ArgType::PtrTo(
+ ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"));
case LengthModifier::AsLongDouble:
// GNU extension.
return ArgType::PtrTo(Ctx.UnsignedLongLongTy);
@@ -386,7 +385,7 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const {
case LengthModifier::AsIntMax:
return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
case LengthModifier::AsSizeT:
- return ArgType(); // FIXME: ssize_t
+ return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
case LengthModifier::AsPtrDiff:
return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
case LengthModifier::AsLongDouble:
diff --git a/contrib/llvm/tools/clang/lib/Analysis/ThreadSafety.cpp b/contrib/llvm/tools/clang/lib/Analysis/ThreadSafety.cpp
index 879a15c9c2a8e..6a9c9a04c55d1 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/ThreadSafety.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/ThreadSafety.cpp
@@ -26,7 +26,7 @@
#include "clang/Analysis/Analyses/ThreadSafetyLogical.h"
#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
#include "clang/Analysis/Analyses/ThreadSafetyTraverse.h"
-#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/CFGStmtMap.h"
#include "clang/Basic/OperatorKinds.h"
@@ -1735,8 +1735,23 @@ void BuildLockset::handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD) {
CapExprSet AssertLocks;
Analyzer->getMutexIDs(AssertLocks, A, Exp, D, VD);
for (const auto &AssertLock : AssertLocks)
- Analyzer->addLock(FSet, llvm::make_unique<LockableFactEntry>(
- AssertLock, LK_Shared, Loc, false, true),
+ Analyzer->addLock(FSet,
+ llvm::make_unique<LockableFactEntry>(
+ AssertLock, LK_Shared, Loc, false, true),
+ ClassifyDiagnostic(A));
+ break;
+ }
+
+ case attr::AssertCapability: {
+ AssertCapabilityAttr *A = cast<AssertCapabilityAttr>(At);
+ CapExprSet AssertLocks;
+ Analyzer->getMutexIDs(AssertLocks, A, Exp, D, VD);
+ for (const auto &AssertLock : AssertLocks)
+ Analyzer->addLock(FSet,
+ llvm::make_unique<LockableFactEntry>(
+ AssertLock,
+ A->isShared() ? LK_Shared : LK_Exclusive, Loc,
+ false, true),
ClassifyDiagnostic(A));
break;
}
diff --git a/contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyCommon.cpp b/contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyCommon.cpp
index cbd5464c34d7c..99284f07b45b3 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyCommon.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyCommon.cpp
@@ -19,7 +19,7 @@
#include "clang/AST/StmtCXX.h"
#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
#include "clang/Analysis/Analyses/ThreadSafetyTraverse.h"
-#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/SourceLocation.h"
@@ -319,11 +319,11 @@ static bool hasCppPointerType(const til::SExpr *E) {
static const CXXMethodDecl *getFirstVirtualDecl(const CXXMethodDecl *D) {
while (true) {
D = D->getCanonicalDecl();
- CXXMethodDecl::method_iterator I = D->begin_overridden_methods(),
- E = D->end_overridden_methods();
- if (I == E)
+ auto OverriddenMethods = D->overridden_methods();
+ if (OverriddenMethods.begin() == OverriddenMethods.end())
return D; // Method does not override anything
- D = *I; // FIXME: this does not work with multiple inheritance.
+ // FIXME: this does not work with multiple inheritance.
+ D = *OverriddenMethods.begin();
}
return nullptr;
}
@@ -505,6 +505,7 @@ til::SExpr *SExprBuilder::translateBinaryOperator(const BinaryOperator *BO,
case BO_GE: return translateBinOp(til::BOP_Leq, BO, Ctx, true);
case BO_EQ: return translateBinOp(til::BOP_Eq, BO, Ctx);
case BO_NE: return translateBinOp(til::BOP_Neq, BO, Ctx);
+ case BO_Cmp: return translateBinOp(til::BOP_Cmp, BO, Ctx);
case BO_And: return translateBinOp(til::BOP_BitAnd, BO, Ctx);
case BO_Xor: return translateBinOp(til::BOP_BitXor, BO, Ctx);
case BO_Or: return translateBinOp(til::BOP_BitOr, BO, Ctx);
diff --git a/contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyTIL.cpp b/contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyTIL.cpp
index 83aa90435e2a5..cd7cdc69ab73a 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyTIL.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyTIL.cpp
@@ -38,6 +38,7 @@ StringRef til::getBinaryOpcodeString(TIL_BinaryOpcode Op) {
case BOP_Neq: return "!=";
case BOP_Lt: return "<";
case BOP_Leq: return "<=";
+ case BOP_Cmp: return "<=>";
case BOP_LogicAnd: return "&&";
case BOP_LogicOr: return "||";
}
diff --git a/contrib/llvm/tools/clang/lib/Analysis/UninitializedValues.cpp b/contrib/llvm/tools/clang/lib/Analysis/UninitializedValues.cpp
index d5289fb9d4271..5f11d8a2a36b5 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/UninitializedValues.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/UninitializedValues.cpp
@@ -18,7 +18,7 @@
#include "clang/AST/StmtVisitor.h"
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
#include "clang/Analysis/Analyses/UninitializedValues.h"
-#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/DomainSpecific/ObjCNoReturn.h"
#include "llvm/ADT/DenseMap.h"
@@ -440,16 +440,11 @@ static bool isPointerToConst(const QualType &QT) {
void ClassifyRefs::VisitCallExpr(CallExpr *CE) {
// Classify arguments to std::move as used.
- if (CE->getNumArgs() == 1) {
- if (FunctionDecl *FD = CE->getDirectCallee()) {
- if (FD->isInStdNamespace() && FD->getIdentifier() &&
- FD->getIdentifier()->isStr("move")) {
- // RecordTypes are handled in SemaDeclCXX.cpp.
- if (!CE->getArg(0)->getType()->isRecordType())
- classify(CE->getArg(0), Use);
- return;
- }
- }
+ if (CE->isCallToStdMove()) {
+ // RecordTypes are handled in SemaDeclCXX.cpp.
+ if (!CE->getArg(0)->getType()->isRecordType())
+ classify(CE->getArg(0), Use);
+ return;
}
// If a value is passed by const pointer or by const reference to a function,
diff --git a/contrib/llvm/tools/clang/lib/Basic/Builtins.cpp b/contrib/llvm/tools/clang/lib/Basic/Builtins.cpp
index 28695d649a867..ed7f87c9b95c7 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Builtins.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Builtins.cpp
@@ -69,9 +69,15 @@ bool Builtin::Context::builtinIsSupported(const Builtin::Info &BuiltinInfo,
bool MSModeUnsupported =
!LangOpts.MicrosoftExt && (BuiltinInfo.Langs & MS_LANG);
bool ObjCUnsupported = !LangOpts.ObjC1 && BuiltinInfo.Langs == OBJC_LANG;
- bool OclCUnsupported = LangOpts.OpenCLVersion != 200 &&
- BuiltinInfo.Langs == OCLC20_LANG;
+ bool OclC1Unsupported = (LangOpts.OpenCLVersion / 100) != 1 &&
+ (BuiltinInfo.Langs & ALL_OCLC_LANGUAGES ) == OCLC1X_LANG;
+ bool OclC2Unsupported = LangOpts.OpenCLVersion != 200 &&
+ (BuiltinInfo.Langs & ALL_OCLC_LANGUAGES) == OCLC20_LANG;
+ bool OclCUnsupported = !LangOpts.OpenCL &&
+ (BuiltinInfo.Langs & ALL_OCLC_LANGUAGES);
+ bool OpenMPUnsupported = !LangOpts.OpenMP && BuiltinInfo.Langs == OMP_LANG;
return !BuiltinsUnsupported && !MathBuiltinsUnsupported && !OclCUnsupported &&
+ !OclC1Unsupported && !OclC2Unsupported && !OpenMPUnsupported &&
!GnuModeUnsupported && !MSModeUnsupported && !ObjCUnsupported;
}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Cuda.cpp b/contrib/llvm/tools/clang/lib/Basic/Cuda.cpp
index 3264078b98f5f..58b99a3b58cbe 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Cuda.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Cuda.cpp
@@ -16,6 +16,8 @@ const char *CudaVersionToString(CudaVersion V) {
return "7.5";
case CudaVersion::CUDA_80:
return "8.0";
+ case CudaVersion::CUDA_90:
+ return "9.0";
}
llvm_unreachable("invalid enum");
}
@@ -48,6 +50,8 @@ const char *CudaArchToString(CudaArch A) {
return "sm_61";
case CudaArch::SM_62:
return "sm_62";
+ case CudaArch::SM_70:
+ return "sm_70";
}
llvm_unreachable("invalid enum");
}
@@ -66,6 +70,7 @@ CudaArch StringToCudaArch(llvm::StringRef S) {
.Case("sm_60", CudaArch::SM_60)
.Case("sm_61", CudaArch::SM_61)
.Case("sm_62", CudaArch::SM_62)
+ .Case("sm_70", CudaArch::SM_70)
.Default(CudaArch::UNKNOWN);
}
@@ -95,6 +100,8 @@ const char *CudaVirtualArchToString(CudaVirtualArch A) {
return "compute_61";
case CudaVirtualArch::COMPUTE_62:
return "compute_62";
+ case CudaVirtualArch::COMPUTE_70:
+ return "compute_70";
}
llvm_unreachable("invalid enum");
}
@@ -112,6 +119,7 @@ CudaVirtualArch StringToCudaVirtualArch(llvm::StringRef S) {
.Case("compute_60", CudaVirtualArch::COMPUTE_60)
.Case("compute_61", CudaVirtualArch::COMPUTE_61)
.Case("compute_62", CudaVirtualArch::COMPUTE_62)
+ .Case("compute_70", CudaVirtualArch::COMPUTE_70)
.Default(CudaVirtualArch::UNKNOWN);
}
@@ -142,6 +150,8 @@ CudaVirtualArch VirtualArchForCudaArch(CudaArch A) {
return CudaVirtualArch::COMPUTE_61;
case CudaArch::SM_62:
return CudaVirtualArch::COMPUTE_62;
+ case CudaArch::SM_70:
+ return CudaVirtualArch::COMPUTE_70;
}
llvm_unreachable("invalid enum");
}
@@ -164,8 +174,22 @@ CudaVersion MinVersionForCudaArch(CudaArch A) {
case CudaArch::SM_61:
case CudaArch::SM_62:
return CudaVersion::CUDA_80;
+ case CudaArch::SM_70:
+ return CudaVersion::CUDA_90;
}
llvm_unreachable("invalid enum");
}
+CudaVersion MaxVersionForCudaArch(CudaArch A) {
+ switch (A) {
+ case CudaArch::UNKNOWN:
+ return CudaVersion::UNKNOWN;
+ case CudaArch::SM_20:
+ case CudaArch::SM_21:
+ return CudaVersion::CUDA_80;
+ default:
+ return CudaVersion::LATEST;
+ }
+}
+
} // namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp b/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp
index c355445dc1e71..640b42c1ca2e6 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp
@@ -11,8 +11,9 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Basic/CharInfo.h"
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/DiagnosticError.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/PartialDiagnostic.h"
@@ -363,7 +364,7 @@ void DiagnosticsEngine::setSeverityForAll(diag::Flavor Flavor,
SourceLocation Loc) {
// Get all the diagnostics.
SmallVector<diag::kind, 64> AllDiags;
- Diags->getAllDiagnostics(Flavor, AllDiags);
+ DiagnosticIDs::getAllDiagnostics(Flavor, AllDiags);
// Set the mapping.
for (diag::kind Diag : AllDiags)
@@ -1050,3 +1051,5 @@ PartialDiagnostic::StorageAllocator::~StorageAllocator() {
llvm::CrashRecoveryContext::isRecoveringFromCrash()) &&
"A partial is on the lam");
}
+
+char DiagnosticError::ID;
diff --git a/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp b/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp
index 0cdaf8e03643f..5c53f35aa68f0 100644
--- a/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp
@@ -43,7 +43,7 @@ struct StaticDiagInfoRec {
unsigned SFINAE : 2;
unsigned WarnNoWerror : 1;
unsigned WarnShowInSystemHeader : 1;
- unsigned Category : 5;
+ unsigned Category : 6;
uint16_t OptionGroupIndex;
@@ -68,6 +68,30 @@ struct StaticDiagInfoRec {
}
};
+#define STRINGIFY_NAME(NAME) #NAME
+#define VALIDATE_DIAG_SIZE(NAME) \
+ static_assert( \
+ static_cast<unsigned>(diag::NUM_BUILTIN_##NAME##_DIAGNOSTICS) < \
+ static_cast<unsigned>(diag::DIAG_START_##NAME) + \
+ static_cast<unsigned>(diag::DIAG_SIZE_##NAME), \
+ STRINGIFY_NAME( \
+ DIAG_SIZE_##NAME) " is insufficient to contain all " \
+ "diagnostics, it may need to be made larger in " \
+ "DiagnosticIDs.h.");
+VALIDATE_DIAG_SIZE(COMMON)
+VALIDATE_DIAG_SIZE(DRIVER)
+VALIDATE_DIAG_SIZE(FRONTEND)
+VALIDATE_DIAG_SIZE(SERIALIZATION)
+VALIDATE_DIAG_SIZE(LEX)
+VALIDATE_DIAG_SIZE(PARSE)
+VALIDATE_DIAG_SIZE(AST)
+VALIDATE_DIAG_SIZE(COMMENT)
+VALIDATE_DIAG_SIZE(SEMA)
+VALIDATE_DIAG_SIZE(ANALYSIS)
+VALIDATE_DIAG_SIZE(REFACTORING)
+#undef VALIDATE_DIAG_SIZE
+#undef STRINGIFY_NAME
+
} // namespace anonymous
static const StaticDiagInfoRec StaticDiagInfo[] = {
@@ -86,8 +110,10 @@ static const StaticDiagInfoRec StaticDiagInfo[] = {
#include "clang/Basic/DiagnosticParseKinds.inc"
#include "clang/Basic/DiagnosticASTKinds.inc"
#include "clang/Basic/DiagnosticCommentKinds.inc"
+#include "clang/Basic/DiagnosticCrossTUKinds.inc"
#include "clang/Basic/DiagnosticSemaKinds.inc"
#include "clang/Basic/DiagnosticAnalysisKinds.inc"
+#include "clang/Basic/DiagnosticRefactoringKinds.inc"
#undef DIAG
};
@@ -96,18 +122,6 @@ static const unsigned StaticDiagInfoSize = llvm::array_lengthof(StaticDiagInfo);
/// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID,
/// or null if the ID is invalid.
static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) {
- // If assertions are enabled, verify that the StaticDiagInfo array is sorted.
-#ifndef NDEBUG
- static bool IsFirst = true; // So the check is only performed on first call.
- if (IsFirst) {
- assert(std::is_sorted(std::begin(StaticDiagInfo),
- std::end(StaticDiagInfo)) &&
- "Diag ID conflict, the enums at the start of clang::diag (in "
- "DiagnosticIDs.h) probably need to be increased");
- IsFirst = false;
- }
-#endif
-
// Out of bounds diag. Can't be in the table.
using namespace diag;
if (DiagID >= DIAG_UPPER_LIMIT || DiagID <= DIAG_START_COMMON)
@@ -135,8 +149,10 @@ CATEGORY(LEX, SERIALIZATION)
CATEGORY(PARSE, LEX)
CATEGORY(AST, PARSE)
CATEGORY(COMMENT, AST)
-CATEGORY(SEMA, COMMENT)
+CATEGORY(CROSSTU, COMMENT)
+CATEGORY(SEMA, CROSSTU)
CATEGORY(ANALYSIS, SEMA)
+CATEGORY(REFACTORING, ANALYSIS)
#undef CATEGORY
// Avoid out of bounds reads.
@@ -567,7 +583,7 @@ DiagnosticIDs::getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group,
}
void DiagnosticIDs::getAllDiagnostics(diag::Flavor Flavor,
- SmallVectorImpl<diag::kind> &Diags) const {
+ SmallVectorImpl<diag::kind> &Diags) {
for (unsigned i = 0; i != StaticDiagInfoSize; ++i)
if (StaticDiagInfo[i].getFlavor() == Flavor)
Diags.push_back(StaticDiagInfo[i].DiagID);
diff --git a/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp b/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp
index 0c10b5f4d14cb..a3e226d6cc964 100644
--- a/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp
@@ -408,7 +408,7 @@ bool FileManager::makeAbsolutePath(SmallVectorImpl<char> &Path) const {
bool Changed = FixupRelativePath(Path);
if (!llvm::sys::path::is_absolute(StringRef(Path.data(), Path.size()))) {
- llvm::sys::fs::make_absolute(Path);
+ FS->makeAbsolute(Path);
Changed = true;
}
diff --git a/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp b/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp
index 372e0c417fd44..2bed531ae3d79 100644
--- a/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp
@@ -1,4 +1,4 @@
-//===--- IdentifierTable.cpp - Hash table for identifier lookup -----------===//
+//===- IdentifierTable.cpp - Hash table for identifier lookup -------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,17 +12,24 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Basic/CharInfo.h"
#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/CharInfo.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/Specifiers.h"
-#include "llvm/ADT/DenseMap.h"
+#include "clang/Basic/TokenKinds.h"
+#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
+#include <cassert>
#include <cstdio>
+#include <cstring>
+#include <string>
using namespace clang;
@@ -46,27 +53,27 @@ IdentifierInfo::IdentifierInfo() {
RevertedTokenID = false;
OutOfDate = false;
IsModulesImport = false;
- FETokenInfo = nullptr;
- Entry = nullptr;
}
//===----------------------------------------------------------------------===//
// IdentifierTable Implementation
//===----------------------------------------------------------------------===//
-IdentifierIterator::~IdentifierIterator() { }
+IdentifierIterator::~IdentifierIterator() = default;
-IdentifierInfoLookup::~IdentifierInfoLookup() {}
+IdentifierInfoLookup::~IdentifierInfoLookup() = default;
namespace {
- /// \brief A simple identifier lookup iterator that represents an
- /// empty sequence of identifiers.
- class EmptyLookupIterator : public IdentifierIterator
- {
- public:
- StringRef Next() override { return StringRef(); }
- };
-}
+
+/// \brief A simple identifier lookup iterator that represents an
+/// empty sequence of identifiers.
+class EmptyLookupIterator : public IdentifierIterator
+{
+public:
+ StringRef Next() override { return StringRef(); }
+};
+
+} // namespace
IdentifierIterator *IdentifierInfoLookup::getIdentifiers() {
return new EmptyLookupIterator();
@@ -76,11 +83,9 @@ IdentifierTable::IdentifierTable(const LangOptions &LangOpts,
IdentifierInfoLookup* externalLookup)
: HashTable(8192), // Start with space for 8K identifiers.
ExternalLookup(externalLookup) {
-
// Populate the identifier table with info about keywords for the current
// language.
AddKeywords(LangOpts);
-
// Add the '_experimental_modules_import' contextual keyword.
get("import").setModulesImport(true);
@@ -92,6 +97,7 @@ IdentifierTable::IdentifierTable(const LangOptions &LangOpts,
// Constants for TokenKinds.def
namespace {
+
enum {
KEYC99 = 0x1,
KEYCXX = 0x2,
@@ -114,7 +120,9 @@ namespace {
KEYZVECTOR = 0x40000,
KEYCOROUTINES = 0x80000,
KEYMODULES = 0x100000,
- KEYALL = (0x1fffff & ~KEYNOMS18 &
+ KEYCXX2A = 0x200000,
+ KEYALLCXX = KEYCXX | KEYCXX11 | KEYCXX2A,
+ KEYALL = (0x3fffff & ~KEYNOMS18 &
~KEYNOOPENCL) // KEYNOMS18 and KEYNOOPENCL are used to exclude.
};
@@ -125,7 +133,8 @@ namespace {
KS_Enabled, // Enabled
KS_Future // Is a keyword in future standard
};
-}
+
+} // namespace
/// \brief Translates flags as specified in TokenKinds.def into keyword status
/// in the given language standard.
@@ -134,6 +143,7 @@ static KeywordStatus getKeywordStatus(const LangOptions &LangOpts,
if (Flags == KEYALL) return KS_Enabled;
if (LangOpts.CPlusPlus && (Flags & KEYCXX)) return KS_Enabled;
if (LangOpts.CPlusPlus11 && (Flags & KEYCXX11)) return KS_Enabled;
+ if (LangOpts.CPlusPlus2a && (Flags & KEYCXX2A)) return KS_Enabled;
if (LangOpts.C99 && (Flags & KEYC99)) return KS_Enabled;
if (LangOpts.GNUKeywords && (Flags & KEYGNU)) return KS_Extension;
if (LangOpts.MicrosoftExt && (Flags & KEYMS)) return KS_Extension;
@@ -152,7 +162,7 @@ static KeywordStatus getKeywordStatus(const LangOptions &LangOpts,
if (LangOpts.ConceptsTS && (Flags & KEYCONCEPTS)) return KS_Enabled;
if (LangOpts.CoroutinesTS && (Flags & KEYCOROUTINES)) return KS_Enabled;
if (LangOpts.ModulesTS && (Flags & KEYMODULES)) return KS_Enabled;
- if (LangOpts.CPlusPlus && (Flags & KEYCXX11)) return KS_Future;
+ if (LangOpts.CPlusPlus && (Flags & KEYALLCXX)) return KS_Future;
return KS_Disabled;
}
@@ -264,6 +274,7 @@ bool IdentifierInfo::isCPlusPlusKeyword(const LangOptions &LangOpts) const {
LangOptions LangOptsNoCPP = LangOpts;
LangOptsNoCPP.CPlusPlus = false;
LangOptsNoCPP.CPlusPlus11 = false;
+ LangOptsNoCPP.CPlusPlus2a = false;
return !isKeyword(LangOptsNoCPP);
}
@@ -362,6 +373,7 @@ unsigned llvm::DenseMapInfo<clang::Selector>::getHashValue(clang::Selector S) {
}
namespace clang {
+
/// MultiKeywordSelector - One of these variable length records is kept for each
/// selector containing more than one keyword. We use a folding set
/// to unique aggregate names (keyword selectors in ObjC parlance). Access to
@@ -371,6 +383,7 @@ class MultiKeywordSelector
MultiKeywordSelector(unsigned nKeys) {
ExtraKindOrNumArgs = NUM_EXTRA_KINDS + nKeys;
}
+
public:
// Constructor for keyword selectors.
MultiKeywordSelector(unsigned nKeys, IdentifierInfo **IIV) {
@@ -388,28 +401,34 @@ public:
unsigned getNumArgs() const { return ExtraKindOrNumArgs - NUM_EXTRA_KINDS; }
- typedef IdentifierInfo *const *keyword_iterator;
+ using keyword_iterator = IdentifierInfo *const *;
+
keyword_iterator keyword_begin() const {
return reinterpret_cast<keyword_iterator>(this+1);
}
+
keyword_iterator keyword_end() const {
return keyword_begin()+getNumArgs();
}
+
IdentifierInfo *getIdentifierInfoForSlot(unsigned i) const {
assert(i < getNumArgs() && "getIdentifierInfoForSlot(): illegal index");
return keyword_begin()[i];
}
+
static void Profile(llvm::FoldingSetNodeID &ID,
keyword_iterator ArgTys, unsigned NumArgs) {
ID.AddInteger(NumArgs);
for (unsigned i = 0; i != NumArgs; ++i)
ID.AddPointer(ArgTys[i]);
}
+
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, keyword_begin(), getNumArgs());
}
};
-} // end namespace clang.
+
+} // namespace clang.
unsigned Selector::getNumArgs() const {
unsigned IIF = getIdentifierInfoFlag();
@@ -427,6 +446,7 @@ IdentifierInfo *Selector::getIdentifierInfoForSlot(unsigned argIndex) const {
assert(argIndex == 0 && "illegal keyword index");
return getAsIdentifierInfo();
}
+
// We point to a MultiKeywordSelector.
MultiKeywordSelector *SI = getMultiKeywordSelector();
return SI->getIdentifierInfoForSlot(argIndex);
@@ -588,11 +608,13 @@ ObjCStringFormatFamily Selector::getStringFormatFamilyImpl(Selector sel) {
}
namespace {
- struct SelectorTableImpl {
- llvm::FoldingSet<MultiKeywordSelector> Table;
- llvm::BumpPtrAllocator Allocator;
- };
-} // end anonymous namespace.
+
+struct SelectorTableImpl {
+ llvm::FoldingSet<MultiKeywordSelector> Table;
+ llvm::BumpPtrAllocator Allocator;
+};
+
+} // namespace
static SelectorTableImpl &getSelectorTableImpl(void *P) {
return *static_cast<SelectorTableImpl*>(P);
diff --git a/contrib/llvm/tools/clang/lib/Basic/Module.cpp b/contrib/llvm/tools/clang/lib/Basic/Module.cpp
index 1d96afd476ef4..7124184865c66 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Module.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Module.cpp
@@ -1,4 +1,4 @@
-//===--- Module.cpp - Describe a module -----------------------------------===//
+//===- Module.cpp - Describe a module -------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,23 +16,33 @@
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <functional>
+#include <string>
+#include <utility>
+#include <vector>
using namespace clang;
Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
bool IsFramework, bool IsExplicit, unsigned VisibilityID)
- : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent), Directory(),
- Umbrella(), ASTFile(nullptr), VisibilityID(VisibilityID),
- IsMissingRequirement(false), HasIncompatibleModuleFile(false),
- IsAvailable(true), IsFromModuleFile(false), IsFramework(IsFramework),
- IsExplicit(IsExplicit), IsSystem(false), IsExternC(false),
- IsInferred(false), InferSubmodules(false), InferExplicitSubmodules(false),
+ : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent),
+ VisibilityID(VisibilityID), IsMissingRequirement(false),
+ HasIncompatibleModuleFile(false), IsAvailable(true),
+ IsFromModuleFile(false), IsFramework(IsFramework), IsExplicit(IsExplicit),
+ IsSystem(false), IsExternC(false), IsInferred(false),
+ InferSubmodules(false), InferExplicitSubmodules(false),
InferExportWildcard(false), ConfigMacrosExhaustive(false),
NoUndeclaredIncludes(false), NameVisibility(Hidden) {
if (Parent) {
@@ -130,6 +140,7 @@ static StringRef getModuleNameFromComponent(
const std::pair<std::string, SourceLocation> &IdComponent) {
return IdComponent.first;
}
+
static StringRef getModuleNameFromComponent(StringRef R) { return R; }
template<typename InputIter>
@@ -440,6 +451,11 @@ void Module::print(raw_ostream &OS, unsigned Indent) const {
}
}
+ if (!ExportAsModule.empty()) {
+ OS.indent(Indent + 2);
+ OS << "export_as" << ExportAsModule << "\n";
+ }
+
for (submodule_const_iterator MI = submodule_begin(), MIEnd = submodule_end();
MI != MIEnd; ++MI)
// Print inferred subframework modules so that we don't need to re-infer
diff --git a/contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp b/contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp
index 050c0cc466db8..09c919e2b0725 100644
--- a/contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp
@@ -139,6 +139,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
case OMPC_shared:
case OMPC_reduction:
case OMPC_task_reduction:
+ case OMPC_in_reduction:
case OMPC_aligned:
case OMPC_copyin:
case OMPC_copyprivate:
@@ -279,6 +280,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
case OMPC_shared:
case OMPC_reduction:
case OMPC_task_reduction:
+ case OMPC_in_reduction:
case OMPC_aligned:
case OMPC_copyin:
case OMPC_copyprivate:
@@ -791,7 +793,7 @@ bool clang::isOpenMPParallelDirective(OpenMPDirectiveKind DKind) {
bool clang::isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind) {
return DKind == OMPD_target || DKind == OMPD_target_parallel ||
- DKind == OMPD_target_parallel_for ||
+ DKind == OMPD_target_parallel_for ||
DKind == OMPD_target_parallel_for_simd || DKind == OMPD_target_simd ||
DKind == OMPD_target_teams || DKind == OMPD_target_teams_distribute ||
DKind == OMPD_target_teams_distribute_parallel_for ||
@@ -827,7 +829,8 @@ bool clang::isOpenMPSimdDirective(OpenMPDirectiveKind DKind) {
DKind == OMPD_teams_distribute_simd ||
DKind == OMPD_teams_distribute_parallel_for_simd ||
DKind == OMPD_target_teams_distribute_parallel_for_simd ||
- DKind == OMPD_target_teams_distribute_simd;
+ DKind == OMPD_target_teams_distribute_simd ||
+ DKind == OMPD_target_parallel_for_simd;
}
bool clang::isOpenMPNestingDistributeDirective(OpenMPDirectiveKind Kind) {
@@ -851,8 +854,8 @@ bool clang::isOpenMPDistributeDirective(OpenMPDirectiveKind Kind) {
bool clang::isOpenMPPrivate(OpenMPClauseKind Kind) {
return Kind == OMPC_private || Kind == OMPC_firstprivate ||
Kind == OMPC_lastprivate || Kind == OMPC_linear ||
- Kind == OMPC_reduction ||
- Kind == OMPC_task_reduction; // TODO add next clauses like 'reduction'.
+ Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
+ Kind == OMPC_in_reduction; // TODO add next clauses like 'reduction'.
}
bool clang::isOpenMPThreadPrivate(OpenMPClauseKind Kind) {
@@ -882,13 +885,45 @@ void clang::getOpenMPCaptureRegions(
case OMPD_parallel_for_simd:
case OMPD_parallel_sections:
case OMPD_distribute_parallel_for:
+ case OMPD_distribute_parallel_for_simd:
CaptureRegions.push_back(OMPD_parallel);
break;
case OMPD_target_teams:
+ case OMPD_target_teams_distribute:
+ case OMPD_target_teams_distribute_simd:
CaptureRegions.push_back(OMPD_target);
CaptureRegions.push_back(OMPD_teams);
break;
case OMPD_teams:
+ case OMPD_teams_distribute:
+ case OMPD_teams_distribute_simd:
+ CaptureRegions.push_back(OMPD_teams);
+ break;
+ case OMPD_target:
+ case OMPD_target_simd:
+ CaptureRegions.push_back(OMPD_target);
+ break;
+ case OMPD_teams_distribute_parallel_for:
+ case OMPD_teams_distribute_parallel_for_simd:
+ CaptureRegions.push_back(OMPD_teams);
+ CaptureRegions.push_back(OMPD_parallel);
+ break;
+ case OMPD_target_parallel:
+ case OMPD_target_parallel_for:
+ case OMPD_target_parallel_for_simd:
+ CaptureRegions.push_back(OMPD_target);
+ CaptureRegions.push_back(OMPD_parallel);
+ break;
+ case OMPD_task:
+ case OMPD_target_enter_data:
+ case OMPD_target_exit_data:
+ case OMPD_target_update:
+ CaptureRegions.push_back(OMPD_task);
+ break;
+ case OMPD_taskloop:
+ case OMPD_taskloop_simd:
+ CaptureRegions.push_back(OMPD_taskloop);
+ break;
case OMPD_simd:
case OMPD_for:
case OMPD_for_simd:
@@ -902,28 +937,10 @@ void clang::getOpenMPCaptureRegions(
case OMPD_ordered:
case OMPD_atomic:
case OMPD_target_data:
- case OMPD_target:
- case OMPD_target_parallel_for:
- case OMPD_target_parallel_for_simd:
- case OMPD_target_simd:
- case OMPD_task:
- case OMPD_taskloop:
- case OMPD_taskloop_simd:
- case OMPD_distribute_parallel_for_simd:
case OMPD_distribute_simd:
- case OMPD_teams_distribute:
- case OMPD_teams_distribute_simd:
- case OMPD_teams_distribute_parallel_for_simd:
- case OMPD_teams_distribute_parallel_for:
- case OMPD_target_teams_distribute:
case OMPD_target_teams_distribute_parallel_for:
case OMPD_target_teams_distribute_parallel_for_simd:
- case OMPD_target_teams_distribute_simd:
- CaptureRegions.push_back(DKind);
- break;
- case OMPD_target_parallel:
- CaptureRegions.push_back(OMPD_target);
- CaptureRegions.push_back(OMPD_parallel);
+ CaptureRegions.push_back(OMPD_unknown);
break;
case OMPD_threadprivate:
case OMPD_taskyield:
@@ -932,13 +949,10 @@ void clang::getOpenMPCaptureRegions(
case OMPD_cancellation_point:
case OMPD_cancel:
case OMPD_flush:
- case OMPD_target_enter_data:
- case OMPD_target_exit_data:
case OMPD_declare_reduction:
case OMPD_declare_simd:
case OMPD_declare_target:
case OMPD_end_declare_target:
- case OMPD_target_update:
llvm_unreachable("OpenMP Directive is not allowed");
case OMPD_unknown:
llvm_unreachable("Unknown OpenMP directive");
diff --git a/contrib/llvm/tools/clang/lib/Basic/OperatorPrecedence.cpp b/contrib/llvm/tools/clang/lib/Basic/OperatorPrecedence.cpp
index 384d23c38af5c..3743b6ad5fefc 100644
--- a/contrib/llvm/tools/clang/lib/Basic/OperatorPrecedence.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/OperatorPrecedence.cpp
@@ -63,6 +63,7 @@ prec::Level getBinOpPrecedence(tok::TokenKind Kind, bool GreaterThanIsOperator,
case tok::lessequal:
case tok::less:
case tok::greaterequal: return prec::Relational;
+ case tok::spaceship: return prec::Spaceship;
case tok::lessless: return prec::Shift;
case tok::plus:
case tok::minus: return prec::Additive;
diff --git a/contrib/llvm/tools/clang/lib/Basic/SanitizerBlacklist.cpp b/contrib/llvm/tools/clang/lib/Basic/SanitizerBlacklist.cpp
index de78c94bc1956..199ded1f317a4 100644
--- a/contrib/llvm/tools/clang/lib/Basic/SanitizerBlacklist.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/SanitizerBlacklist.cpp
@@ -17,30 +17,35 @@ using namespace clang;
SanitizerBlacklist::SanitizerBlacklist(
const std::vector<std::string> &BlacklistPaths, SourceManager &SM)
- : SCL(llvm::SpecialCaseList::createOrDie(BlacklistPaths)), SM(SM) {}
+ : SSCL(SanitizerSpecialCaseList::createOrDie(BlacklistPaths)), SM(SM) {}
-bool SanitizerBlacklist::isBlacklistedGlobal(StringRef GlobalName,
+bool SanitizerBlacklist::isBlacklistedGlobal(SanitizerMask Mask,
+ StringRef GlobalName,
StringRef Category) const {
- return SCL->inSection("global", GlobalName, Category);
+ return SSCL->inSection(Mask, "global", GlobalName, Category);
}
-bool SanitizerBlacklist::isBlacklistedType(StringRef MangledTypeName,
+bool SanitizerBlacklist::isBlacklistedType(SanitizerMask Mask,
+ StringRef MangledTypeName,
StringRef Category) const {
- return SCL->inSection("type", MangledTypeName, Category);
+ return SSCL->inSection(Mask, "type", MangledTypeName, Category);
}
-bool SanitizerBlacklist::isBlacklistedFunction(StringRef FunctionName) const {
- return SCL->inSection("fun", FunctionName);
+bool SanitizerBlacklist::isBlacklistedFunction(SanitizerMask Mask,
+ StringRef FunctionName) const {
+ return SSCL->inSection(Mask, "fun", FunctionName);
}
-bool SanitizerBlacklist::isBlacklistedFile(StringRef FileName,
+bool SanitizerBlacklist::isBlacklistedFile(SanitizerMask Mask,
+ StringRef FileName,
StringRef Category) const {
- return SCL->inSection("src", FileName, Category);
+ return SSCL->inSection(Mask, "src", FileName, Category);
}
-bool SanitizerBlacklist::isBlacklistedLocation(SourceLocation Loc,
+bool SanitizerBlacklist::isBlacklistedLocation(SanitizerMask Mask,
+ SourceLocation Loc,
StringRef Category) const {
return Loc.isValid() &&
- isBlacklistedFile(SM.getFilename(SM.getFileLoc(Loc)), Category);
+ isBlacklistedFile(Mask, SM.getFilename(SM.getFileLoc(Loc)), Category);
}
diff --git a/contrib/llvm/tools/clang/lib/Basic/SanitizerSpecialCaseList.cpp b/contrib/llvm/tools/clang/lib/Basic/SanitizerSpecialCaseList.cpp
new file mode 100644
index 0000000000000..ee8feecbce655
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/SanitizerSpecialCaseList.cpp
@@ -0,0 +1,64 @@
+//===--- SanitizerSpecialCaseList.cpp - SCL for sanitizers ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// An extension of SpecialCaseList to allowing querying sections by
+// SanitizerMask.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/Basic/SanitizerSpecialCaseList.h"
+
+using namespace clang;
+
+std::unique_ptr<SanitizerSpecialCaseList>
+SanitizerSpecialCaseList::create(const std::vector<std::string> &Paths,
+ std::string &Error) {
+ std::unique_ptr<clang::SanitizerSpecialCaseList> SSCL(
+ new SanitizerSpecialCaseList());
+ if (SSCL->createInternal(Paths, Error)) {
+ SSCL->createSanitizerSections();
+ return SSCL;
+ }
+ return nullptr;
+}
+
+std::unique_ptr<SanitizerSpecialCaseList>
+SanitizerSpecialCaseList::createOrDie(const std::vector<std::string> &Paths) {
+ std::string Error;
+ if (auto SSCL = create(Paths, Error))
+ return SSCL;
+ llvm::report_fatal_error(Error);
+}
+
+void SanitizerSpecialCaseList::createSanitizerSections() {
+ for (auto &S : Sections) {
+ SanitizerMask Mask = 0;
+
+#define SANITIZER(NAME, ID) \
+ if (S.SectionMatcher->match(NAME)) \
+ Mask |= SanitizerKind::ID;
+#define SANITIZER_GROUP(NAME, ID, ALIAS) SANITIZER(NAME, ID)
+
+#include "clang/Basic/Sanitizers.def"
+#undef SANITIZER
+#undef SANITIZER_GROUP
+
+ SanitizerSections.emplace_back(Mask, S.Entries);
+ }
+}
+
+bool SanitizerSpecialCaseList::inSection(SanitizerMask Mask, StringRef Prefix,
+ StringRef Query,
+ StringRef Category) const {
+ for (auto &S : SanitizerSections)
+ if ((S.Mask & Mask) &&
+ SpecialCaseList::inSectionBlame(S.Entries, Prefix, Query, Category))
+ return true;
+
+ return false;
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp b/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp
index f0b53b4e48a54..e664879639f3c 100644
--- a/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp
@@ -1,4 +1,4 @@
-//===--- SourceManager.cpp - Track and cache source files -----------------===//
+//===- SourceManager.cpp - Track and cache source files -------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,17 +14,33 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManagerInternals.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/None.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
#include "llvm/Support/Capacity.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
-#include <cstring>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <tuple>
+#include <utility>
+#include <vector>
using namespace clang;
using namespace SrcMgr;
@@ -222,7 +238,6 @@ void LineTableInfo::AddLineNote(FileID FID, unsigned Offset, unsigned LineNo,
IncludeOffset));
}
-
/// FindNearestLineEntry - Find the line entry nearest to FID that is before
/// it. If there is no line entry before Offset in FID, return null.
const LineEntry *LineTableInfo::FindNearestLineEntry(FileID FID,
@@ -250,7 +265,6 @@ void LineTableInfo::AddEntry(FileID FID,
}
/// getLineTableFilenameID - Return the uniqued ID for the specified filename.
-///
unsigned SourceManager::getLineTableFilenameID(StringRef Name) {
return getLineTable().getLineTableFilenameID(Name);
}
@@ -298,10 +312,7 @@ LineTableInfo &SourceManager::getLineTable() {
SourceManager::SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr,
bool UserFilesAreVolatile)
- : Diag(Diag), FileMgr(FileMgr), OverridenFilesKeepOriginalName(true),
- UserFilesAreVolatile(UserFilesAreVolatile), FilesAreTransient(false),
- ExternalSLocEntries(nullptr), LineTable(nullptr), NumLinearScans(0),
- NumBinaryProbes(0) {
+ : Diag(Diag), FileMgr(FileMgr), UserFilesAreVolatile(UserFilesAreVolatile) {
clearIDTables();
Diag.setSourceManager(this);
}
@@ -342,7 +353,7 @@ void SourceManager::clearIDTables() {
// Use up FileID #0 as an invalid expansion.
NextLocalOffset = 0;
CurrentLoadedOffset = MaxLoadedOffset;
- createExpansionLoc(SourceLocation(),SourceLocation(),SourceLocation(), 1);
+ createExpansionLoc(SourceLocation(), SourceLocation(), SourceLocation(), 1);
}
void SourceManager::initializeForReplay(const SourceManager &Old) {
@@ -408,16 +419,16 @@ SourceManager::getOrCreateContentCache(const FileEntry *FileEnt,
return Entry;
}
-
-/// createMemBufferContentCache - Create a new ContentCache for the specified
-/// memory buffer. This does no caching.
-const ContentCache *SourceManager::createMemBufferContentCache(
- std::unique_ptr<llvm::MemoryBuffer> Buffer) {
+/// Create a new ContentCache for the specified memory buffer.
+/// This does no caching.
+const ContentCache *
+SourceManager::createMemBufferContentCache(llvm::MemoryBuffer *Buffer,
+ bool DoNotFree) {
// Add a new ContentCache to the MemBufferInfos list and return it.
ContentCache *Entry = ContentCacheAlloc.Allocate<ContentCache>();
new (Entry) ContentCache();
MemBufferInfos.push_back(Entry);
- Entry->setBuffer(std::move(Buffer));
+ Entry->replaceBuffer(Buffer, DoNotFree);
return Entry;
}
@@ -715,7 +726,7 @@ FileID SourceManager::getFileIDLocal(unsigned SLocOffset) const {
// Find the FileID that contains this. "I" is an iterator that points to a
// FileID whose offset is known to be larger than SLocOffset.
unsigned NumProbes = 0;
- while (1) {
+ while (true) {
--I;
if (I->getOffset() <= SLocOffset) {
FileID Res = FileID::get(int(I - LocalSLocEntryTable.begin()));
@@ -739,7 +750,7 @@ FileID SourceManager::getFileIDLocal(unsigned SLocOffset) const {
// SLocOffset.
unsigned LessIndex = 0;
NumProbes = 0;
- while (1) {
+ while (true) {
bool Invalid = false;
unsigned MiddleIndex = (GreaterIndex-LessIndex)/2+LessIndex;
unsigned MidOffset = getLocalSLocEntry(MiddleIndex, &Invalid).getOffset();
@@ -816,7 +827,7 @@ FileID SourceManager::getFileIDLoaded(unsigned SLocOffset) const {
unsigned GreaterIndex = I;
unsigned LessIndex = LoadedSLocEntryTable.size();
NumProbes = 0;
- while (1) {
+ while (true) {
++NumProbes;
unsigned MiddleIndex = (LessIndex - GreaterIndex) / 2 + GreaterIndex;
const SrcMgr::SLocEntry &E = getLoadedSLocEntry(MiddleIndex);
@@ -934,7 +945,6 @@ SourceLocation SourceManager::getImmediateSpellingLoc(SourceLocation Loc) const{
return Loc.getLocWithOffset(LocInfo.second);
}
-
/// getImmediateExpansionRange - Loc is required to be an expansion location.
/// Return the start/end of the expansion information.
std::pair<SourceLocation,SourceLocation>
@@ -1054,7 +1064,6 @@ bool SourceManager::isAtEndOfImmediateMacroExpansion(SourceLocation Loc,
return true;
}
-
//===----------------------------------------------------------------------===//
// Queries about the code at a SourceLocation.
//===----------------------------------------------------------------------===//
@@ -1083,7 +1092,6 @@ const char *SourceManager::getCharacterData(SourceLocation SL,
return Buffer->getBufferStart() + (CharDataInvalid? 0 : LocInfo.second);
}
-
/// getColumnNumber - Return the column # for the specified file position.
/// this is significantly cheaper to compute than the line number.
unsigned SourceManager::getColumnNumber(FileID FID, unsigned FilePos,
@@ -1188,7 +1196,7 @@ static void ComputeLineNumbers(DiagnosticsEngine &Diag, ContentCache *FI,
const unsigned char *Buf = (const unsigned char *)Buffer->getBufferStart();
const unsigned char *End = (const unsigned char *)Buffer->getBufferEnd();
unsigned Offs = 0;
- while (1) {
+ while (true) {
// Skip over the contents of the line.
const unsigned char *NextBuf = (const unsigned char *)Buf;
@@ -1418,7 +1426,6 @@ StringRef SourceManager::getBufferName(SourceLocation Loc,
return getBuffer(getFileID(Loc), Invalid)->getBufferIdentifier();
}
-
/// getPresumedLoc - This method returns the "presumed" location of a
/// SourceLocation specifies. A "presumed location" can be modified by \#line
/// or GNU line marker directives. This provides a view on the data that a
@@ -1766,7 +1773,7 @@ void SourceManager::computeMacroArgsCache(MacroArgsMap &MacroArgsCache,
MacroArgsCache.insert(std::make_pair(0, SourceLocation()));
int ID = FID.ID;
- while (1) {
+ while (true) {
++ID;
// Stop if there are no more FileIDs to check.
if (ID > 0) {
@@ -1829,7 +1836,7 @@ void SourceManager::associateFileChunkWithMacroArgExp(
FileID SpellFID; // Current FileID in the spelling range.
unsigned SpellRelativeOffs;
std::tie(SpellFID, SpellRelativeOffs) = getDecomposedLoc(SpellLoc);
- while (1) {
+ while (true) {
const SLocEntry &Entry = getSLocEntry(SpellFID);
unsigned SpellFIDBeginOffs = Entry.getOffset();
unsigned SpellFIDSize = getFileIDSize(SpellFID);
@@ -1856,7 +1863,6 @@ void SourceManager::associateFileChunkWithMacroArgExp(
++SpellFID.ID;
SpellRelativeOffs = 0;
}
-
}
assert(SpellLoc.isFileID());
@@ -1936,8 +1942,8 @@ SourceManager::getDecomposedIncludedLoc(FileID FID) const {
// Uses IncludedLocMap to retrieve/cache the decomposed loc.
- typedef std::pair<FileID, unsigned> DecompTy;
- typedef llvm::DenseMap<FileID, DecompTy> MapTy;
+ using DecompTy = std::pair<FileID, unsigned>;
+ using MapTy = llvm::DenseMap<FileID, DecompTy>;
std::pair<MapTy::iterator, bool>
InsertOp = IncludedLocMap.insert(std::make_pair(FID, DecompTy()));
DecompTy &DecompLoc = InsertOp.first->second;
@@ -2084,7 +2090,7 @@ std::pair<bool, bool> SourceManager::isInTheSameTranslationUnit(
// of the other looking for a match.
// We use a map from FileID to Offset to store the chain. Easier than writing
// a custom set hash info that only depends on the first part of a pair.
- typedef llvm::SmallDenseMap<FileID, unsigned, 16> LocSet;
+ using LocSet = llvm::SmallDenseMap<FileID, unsigned, 16>;
LocSet LChain;
do {
LChain.insert(LOffs);
@@ -2196,7 +2202,7 @@ LLVM_DUMP_METHOD void SourceManager::dump() const {
}
}
-ExternalSLocEntrySource::~ExternalSLocEntrySource() { }
+ExternalSLocEntrySource::~ExternalSLocEntrySource() = default;
/// Return the amount of memory used by memory buffers, breaking down
/// by heap-backed versus mmap'ed memory.
diff --git a/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp b/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp
index 4bcebadf458f6..ddd292c1b7435 100644
--- a/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp
@@ -18,10 +18,11 @@
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TargetParser.h"
#include <cstdlib>
using namespace clang;
-static const LangAS::Map DefaultAddrSpaceMap = { 0 };
+static const LangASMap DefaultAddrSpaceMap = {0};
// TargetInfo Constructor.
TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
@@ -29,6 +30,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
// SPARC. These should be overridden by concrete targets as needed.
BigEndian = !T.isLittleEndian();
TLSSupported = true;
+ VLASupported = true;
NoAsmVariants = false;
HasFloat128 = false;
PointerWidth = PointerAlign = 32;
@@ -42,7 +44,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
// From the glibc documentation, on GNU systems, malloc guarantees 16-byte
// alignment on 64-bit systems and 8-byte alignment on 32-bit systems. See
// https://www.gnu.org/software/libc/manual/html_node/Malloc-Examples.html
- if (T.isGNUEnvironment())
+ if (T.isGNUEnvironment() || T.isWindowsMSVCEnvironment())
NewAlign = Triple.isArch64Bit() ? 128 : Triple.isArch32Bit() ? 64 : 0;
else
NewAlign = 0; // Infer from basic type alignment.
@@ -289,8 +291,15 @@ bool TargetInfo::isTypeSigned(IntType T) {
void TargetInfo::adjust(LangOptions &Opts) {
if (Opts.NoBitFieldTypeAlign)
UseBitFieldTypeAlignment = false;
- if (Opts.ShortWChar)
- WCharType = UnsignedShort;
+
+ switch (Opts.WCharSize) {
+ default: llvm_unreachable("invalid wchar_t width");
+ case 0: break;
+ case 1: WCharType = Opts.WCharIsSigned ? SignedChar : UnsignedChar; break;
+ case 2: WCharType = Opts.WCharIsSigned ? SignedShort : UnsignedShort; break;
+ case 4: WCharType = Opts.WCharIsSigned ? SignedInt : UnsignedInt; break;
+ }
+
if (Opts.AlignDouble) {
DoubleAlign = LongLongAlign = 64;
LongDoubleAlign = 64;
@@ -347,6 +356,20 @@ bool TargetInfo::initFeatureMap(
return true;
}
+LangAS TargetInfo::getOpenCLTypeAddrSpace(OpenCLTypeKind TK) const {
+ switch (TK) {
+ case OCLTK_Image:
+ case OCLTK_Pipe:
+ return LangAS::opencl_global;
+
+ case OCLTK_Sampler:
+ return LangAS::opencl_constant;
+
+ default:
+ return LangAS::Default;
+ }
+}
+
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp
index b33ab135816d3..7deebc06c3efa 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp
@@ -12,30 +12,37 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Basic/Builtins.h"
-#include "clang/Basic/Cuda.h"
+#include "Targets.h"
+
+#include "Targets/AArch64.h"
+#include "Targets/AMDGPU.h"
+#include "Targets/ARM.h"
+#include "Targets/AVR.h"
+#include "Targets/BPF.h"
+#include "Targets/Hexagon.h"
+#include "Targets/Lanai.h"
+#include "Targets/Le64.h"
+#include "Targets/MSP430.h"
+#include "Targets/Mips.h"
+#include "Targets/NVPTX.h"
+#include "Targets/Nios2.h"
+#include "Targets/OSTargets.h"
+#include "Targets/PNaCl.h"
+#include "Targets/PPC.h"
+#include "Targets/SPIR.h"
+#include "Targets/Sparc.h"
+#include "Targets/SystemZ.h"
+#include "Targets/TCE.h"
+#include "Targets/WebAssembly.h"
+#include "Targets/X86.h"
+#include "Targets/XCore.h"
#include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/LangOptions.h"
-#include "clang/Basic/MacroBuilder.h"
-#include "clang/Basic/TargetBuiltins.h"
-#include "clang/Basic/TargetInfo.h"
-#include "clang/Basic/TargetOptions.h"
-#include "clang/Basic/Version.h"
-#include "clang/Frontend/CodeGenOptions.h"
-#include "llvm/ADT/APFloat.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
-#include "llvm/MC/MCSectionMachO.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/TargetParser.h"
-#include <algorithm>
-#include <memory>
using namespace clang;
+namespace clang {
+namespace targets {
//===----------------------------------------------------------------------===//
// Common code shared among targets.
//===----------------------------------------------------------------------===//
@@ -43,8 +50,8 @@ using namespace clang;
/// DefineStd - Define a macro name and standard variants. For example if
/// MacroName is "unix", then this will define "__unix", "__unix__", and "unix"
/// when in GNU mode.
-static void DefineStd(MacroBuilder &Builder, StringRef MacroName,
- const LangOptions &Opts) {
+void DefineStd(MacroBuilder &Builder, StringRef MacroName,
+ const LangOptions &Opts) {
assert(MacroName[0] != '_' && "Identifier should be in the user's namespace");
// If in GNU mode (e.g. -std=gnu99 but not -std=c99) define the raw identifier
@@ -59,4636 +66,14 @@ static void DefineStd(MacroBuilder &Builder, StringRef MacroName,
Builder.defineMacro("__" + MacroName + "__");
}
-static void defineCPUMacros(MacroBuilder &Builder, StringRef CPUName,
- bool Tuning = true) {
+void defineCPUMacros(MacroBuilder &Builder, StringRef CPUName, bool Tuning) {
Builder.defineMacro("__" + CPUName);
Builder.defineMacro("__" + CPUName + "__");
if (Tuning)
Builder.defineMacro("__tune_" + CPUName + "__");
}
-static TargetInfo *AllocateTarget(const llvm::Triple &Triple,
- const TargetOptions &Opts);
-
-//===----------------------------------------------------------------------===//
-// Defines specific to certain operating systems.
-//===----------------------------------------------------------------------===//
-
-namespace {
-template<typename TgtInfo>
-class OSTargetInfo : public TgtInfo {
-protected:
- virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const=0;
-public:
- OSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : TgtInfo(Triple, Opts) {}
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- TgtInfo::getTargetDefines(Opts, Builder);
- getOSDefines(Opts, TgtInfo::getTriple(), Builder);
- }
-
-};
-
-// CloudABI Target
-template <typename Target>
-class CloudABITargetInfo : public OSTargetInfo<Target> {
-protected:
- void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const override {
- Builder.defineMacro("__CloudABI__");
- Builder.defineMacro("__ELF__");
-
- // CloudABI uses ISO/IEC 10646:2012 for wchar_t, char16_t and char32_t.
- Builder.defineMacro("__STDC_ISO_10646__", "201206L");
- Builder.defineMacro("__STDC_UTF_16__");
- Builder.defineMacro("__STDC_UTF_32__");
- }
-
-public:
- CloudABITargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : OSTargetInfo<Target>(Triple, Opts) {}
-};
-
-// Ananas target
-template<typename Target>
-class AnanasTargetInfo : public OSTargetInfo<Target> {
-protected:
- void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const override {
- // Ananas defines
- Builder.defineMacro("__Ananas__");
- Builder.defineMacro("__ELF__");
- }
-public:
- AnanasTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : OSTargetInfo<Target>(Triple, Opts) {}
-};
-
-static void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts,
- const llvm::Triple &Triple,
- StringRef &PlatformName,
- VersionTuple &PlatformMinVersion) {
- Builder.defineMacro("__APPLE_CC__", "6000");
- Builder.defineMacro("__APPLE__");
- Builder.defineMacro("__STDC_NO_THREADS__");
- Builder.defineMacro("OBJC_NEW_PROPERTIES");
- // AddressSanitizer doesn't play well with source fortification, which is on
- // by default on Darwin.
- if (Opts.Sanitize.has(SanitizerKind::Address))
- Builder.defineMacro("_FORTIFY_SOURCE", "0");
-
- // Darwin defines __weak, __strong, and __unsafe_unretained even in C mode.
- if (!Opts.ObjC1) {
- // __weak is always defined, for use in blocks and with objc pointers.
- Builder.defineMacro("__weak", "__attribute__((objc_gc(weak)))");
- Builder.defineMacro("__strong", "");
- Builder.defineMacro("__unsafe_unretained", "");
- }
-
- if (Opts.Static)
- Builder.defineMacro("__STATIC__");
- else
- Builder.defineMacro("__DYNAMIC__");
-
- if (Opts.POSIXThreads)
- Builder.defineMacro("_REENTRANT");
-
- // Get the platform type and version number from the triple.
- unsigned Maj, Min, Rev;
- if (Triple.isMacOSX()) {
- Triple.getMacOSXVersion(Maj, Min, Rev);
- PlatformName = "macos";
- } else {
- Triple.getOSVersion(Maj, Min, Rev);
- PlatformName = llvm::Triple::getOSTypeName(Triple.getOS());
- }
-
- // If -target arch-pc-win32-macho option specified, we're
- // generating code for Win32 ABI. No need to emit
- // __ENVIRONMENT_XX_OS_VERSION_MIN_REQUIRED__.
- if (PlatformName == "win32") {
- PlatformMinVersion = VersionTuple(Maj, Min, Rev);
- return;
- }
-
- // Set the appropriate OS version define.
- if (Triple.isiOS()) {
- assert(Maj < 100 && Min < 100 && Rev < 100 && "Invalid version!");
- char Str[7];
- if (Maj < 10) {
- Str[0] = '0' + Maj;
- Str[1] = '0' + (Min / 10);
- Str[2] = '0' + (Min % 10);
- Str[3] = '0' + (Rev / 10);
- Str[4] = '0' + (Rev % 10);
- Str[5] = '\0';
- } else {
- // Handle versions >= 10.
- Str[0] = '0' + (Maj / 10);
- Str[1] = '0' + (Maj % 10);
- Str[2] = '0' + (Min / 10);
- Str[3] = '0' + (Min % 10);
- Str[4] = '0' + (Rev / 10);
- Str[5] = '0' + (Rev % 10);
- Str[6] = '\0';
- }
- if (Triple.isTvOS())
- Builder.defineMacro("__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__", Str);
- else
- Builder.defineMacro("__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__",
- Str);
-
- } else if (Triple.isWatchOS()) {
- assert(Maj < 10 && Min < 100 && Rev < 100 && "Invalid version!");
- char Str[6];
- Str[0] = '0' + Maj;
- Str[1] = '0' + (Min / 10);
- Str[2] = '0' + (Min % 10);
- Str[3] = '0' + (Rev / 10);
- Str[4] = '0' + (Rev % 10);
- Str[5] = '\0';
- Builder.defineMacro("__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__", Str);
- } else if (Triple.isMacOSX()) {
- // Note that the Driver allows versions which aren't representable in the
- // define (because we only get a single digit for the minor and micro
- // revision numbers). So, we limit them to the maximum representable
- // version.
- assert(Maj < 100 && Min < 100 && Rev < 100 && "Invalid version!");
- char Str[7];
- if (Maj < 10 || (Maj == 10 && Min < 10)) {
- Str[0] = '0' + (Maj / 10);
- Str[1] = '0' + (Maj % 10);
- Str[2] = '0' + std::min(Min, 9U);
- Str[3] = '0' + std::min(Rev, 9U);
- Str[4] = '\0';
- } else {
- // Handle versions > 10.9.
- Str[0] = '0' + (Maj / 10);
- Str[1] = '0' + (Maj % 10);
- Str[2] = '0' + (Min / 10);
- Str[3] = '0' + (Min % 10);
- Str[4] = '0' + (Rev / 10);
- Str[5] = '0' + (Rev % 10);
- Str[6] = '\0';
- }
- Builder.defineMacro("__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", Str);
- }
-
- // Tell users about the kernel if there is one.
- if (Triple.isOSDarwin())
- Builder.defineMacro("__MACH__");
-
- // The Watch ABI uses Dwarf EH.
- if(Triple.isWatchABI())
- Builder.defineMacro("__ARM_DWARF_EH__");
-
- PlatformMinVersion = VersionTuple(Maj, Min, Rev);
-}
-
-template<typename Target>
-class DarwinTargetInfo : public OSTargetInfo<Target> {
-protected:
- void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const override {
- getDarwinDefines(Builder, Opts, Triple, this->PlatformName,
- this->PlatformMinVersion);
- }
-
-public:
- DarwinTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : OSTargetInfo<Target>(Triple, Opts) {
- // By default, no TLS, and we whitelist permitted architecture/OS
- // combinations.
- this->TLSSupported = false;
-
- if (Triple.isMacOSX())
- this->TLSSupported = !Triple.isMacOSXVersionLT(10, 7);
- else if (Triple.isiOS()) {
- // 64-bit iOS supported it from 8 onwards, 32-bit from 9 onwards.
- if (Triple.getArch() == llvm::Triple::x86_64 ||
- Triple.getArch() == llvm::Triple::aarch64)
- this->TLSSupported = !Triple.isOSVersionLT(8);
- else if (Triple.getArch() == llvm::Triple::x86 ||
- Triple.getArch() == llvm::Triple::arm ||
- Triple.getArch() == llvm::Triple::thumb)
- this->TLSSupported = !Triple.isOSVersionLT(9);
- } else if (Triple.isWatchOS())
- this->TLSSupported = !Triple.isOSVersionLT(2);
-
- this->MCountName = "\01mcount";
- }
-
- std::string isValidSectionSpecifier(StringRef SR) const override {
- // Let MCSectionMachO validate this.
- StringRef Segment, Section;
- unsigned TAA, StubSize;
- bool HasTAA;
- return llvm::MCSectionMachO::ParseSectionSpecifier(SR, Segment, Section,
- TAA, HasTAA, StubSize);
- }
-
- const char *getStaticInitSectionSpecifier() const override {
- // FIXME: We should return 0 when building kexts.
- return "__TEXT,__StaticInit,regular,pure_instructions";
- }
-
- /// Darwin does not support protected visibility. Darwin's "default"
- /// is very similar to ELF's "protected"; Darwin requires a "weak"
- /// attribute on declarations that can be dynamically replaced.
- bool hasProtectedVisibility() const override {
- return false;
- }
-
- unsigned getExnObjectAlignment() const override {
- // The alignment of an exception object is 8-bytes for darwin since
- // libc++abi doesn't declare _Unwind_Exception with __attribute__((aligned))
- // and therefore doesn't guarantee 16-byte alignment.
- return 64;
- }
-};
-
-
-// DragonFlyBSD Target
-template<typename Target>
-class DragonFlyBSDTargetInfo : public OSTargetInfo<Target> {
-protected:
- void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const override {
- // DragonFly defines; list based off of gcc output
- Builder.defineMacro("__DragonFly__");
- Builder.defineMacro("__DragonFly_cc_version", "100001");
- Builder.defineMacro("__ELF__");
- Builder.defineMacro("__KPRINTF_ATTRIBUTE__");
- Builder.defineMacro("__tune_i386__");
- DefineStd(Builder, "unix", Opts);
- }
-public:
- DragonFlyBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : OSTargetInfo<Target>(Triple, Opts) {
- switch (Triple.getArch()) {
- default:
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- this->MCountName = ".mcount";
- break;
- }
- }
-};
-
-#ifndef FREEBSD_CC_VERSION
-#define FREEBSD_CC_VERSION 0U
-#endif
-
-// FreeBSD Target
-template<typename Target>
-class FreeBSDTargetInfo : public OSTargetInfo<Target> {
-protected:
- void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const override {
- // FreeBSD defines; list based off of gcc output
-
- unsigned Release = Triple.getOSMajorVersion();
- if (Release == 0U)
- Release = 8U;
- unsigned CCVersion = FREEBSD_CC_VERSION;
- if (CCVersion == 0U)
- CCVersion = Release * 100000U + 1U;
-
- Builder.defineMacro("__FreeBSD__", Twine(Release));
- Builder.defineMacro("__FreeBSD_cc_version", Twine(CCVersion));
- Builder.defineMacro("__KPRINTF_ATTRIBUTE__");
- DefineStd(Builder, "unix", Opts);
- Builder.defineMacro("__ELF__");
-
- // On FreeBSD, wchar_t contains the number of the code point as
- // used by the character set of the locale. These character sets are
- // not necessarily a superset of ASCII.
- //
- // FIXME: This is wrong; the macro refers to the numerical values
- // of wchar_t *literals*, which are not locale-dependent. However,
- // FreeBSD systems apparently depend on us getting this wrong, and
- // setting this to 1 is conforming even if all the basic source
- // character literals have the same encoding as char and wchar_t.
- Builder.defineMacro("__STDC_MB_MIGHT_NEQ_WC__", "1");
- }
-public:
- FreeBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : OSTargetInfo<Target>(Triple, Opts) {
- switch (Triple.getArch()) {
- default:
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- this->MCountName = ".mcount";
- break;
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- case llvm::Triple::ppc:
- case llvm::Triple::ppc64:
- case llvm::Triple::ppc64le:
- this->MCountName = "_mcount";
- break;
- case llvm::Triple::arm:
- this->MCountName = "__mcount";
- break;
- }
- }
-};
-
-// GNU/kFreeBSD Target
-template<typename Target>
-class KFreeBSDTargetInfo : public OSTargetInfo<Target> {
-protected:
- void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const override {
- // GNU/kFreeBSD defines; list based off of gcc output
-
- DefineStd(Builder, "unix", Opts);
- Builder.defineMacro("__FreeBSD_kernel__");
- Builder.defineMacro("__GLIBC__");
- Builder.defineMacro("__ELF__");
- if (Opts.POSIXThreads)
- Builder.defineMacro("_REENTRANT");
- if (Opts.CPlusPlus)
- Builder.defineMacro("_GNU_SOURCE");
- }
-public:
- KFreeBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : OSTargetInfo<Target>(Triple, Opts) {}
-};
-
-// Haiku Target
-template<typename Target>
-class HaikuTargetInfo : public OSTargetInfo<Target> {
-protected:
- void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const override {
- // Haiku defines; list based off of gcc output
- Builder.defineMacro("__HAIKU__");
- Builder.defineMacro("__ELF__");
- DefineStd(Builder, "unix", Opts);
- }
-public:
- HaikuTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : OSTargetInfo<Target>(Triple, Opts) {
- this->SizeType = TargetInfo::UnsignedLong;
- this->IntPtrType = TargetInfo::SignedLong;
- this->PtrDiffType = TargetInfo::SignedLong;
- this->ProcessIDType = TargetInfo::SignedLong;
- this->TLSSupported = false;
-
- }
-};
-
-// Minix Target
-template<typename Target>
-class MinixTargetInfo : public OSTargetInfo<Target> {
-protected:
- void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const override {
- // Minix defines
-
- Builder.defineMacro("__minix", "3");
- Builder.defineMacro("_EM_WSIZE", "4");
- Builder.defineMacro("_EM_PSIZE", "4");
- Builder.defineMacro("_EM_SSIZE", "2");
- Builder.defineMacro("_EM_LSIZE", "4");
- Builder.defineMacro("_EM_FSIZE", "4");
- Builder.defineMacro("_EM_DSIZE", "8");
- Builder.defineMacro("__ELF__");
- DefineStd(Builder, "unix", Opts);
- }
-public:
- MinixTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : OSTargetInfo<Target>(Triple, Opts) {}
-};
-
-// Linux target
-template<typename Target>
-class LinuxTargetInfo : public OSTargetInfo<Target> {
-protected:
- void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const override {
- // Linux defines; list based off of gcc output
- DefineStd(Builder, "unix", Opts);
- DefineStd(Builder, "linux", Opts);
- Builder.defineMacro("__gnu_linux__");
- Builder.defineMacro("__ELF__");
- if (Triple.isAndroid()) {
- Builder.defineMacro("__ANDROID__", "1");
- unsigned Maj, Min, Rev;
- Triple.getEnvironmentVersion(Maj, Min, Rev);
- this->PlatformName = "android";
- this->PlatformMinVersion = VersionTuple(Maj, Min, Rev);
- if (Maj)
- Builder.defineMacro("__ANDROID_API__", Twine(Maj));
- }
- if (Opts.POSIXThreads)
- Builder.defineMacro("_REENTRANT");
- if (Opts.CPlusPlus)
- Builder.defineMacro("_GNU_SOURCE");
- if (this->HasFloat128)
- Builder.defineMacro("__FLOAT128__");
- }
-public:
- LinuxTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : OSTargetInfo<Target>(Triple, Opts) {
- this->WIntType = TargetInfo::UnsignedInt;
-
- switch (Triple.getArch()) {
- default:
- break;
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- case llvm::Triple::ppc:
- case llvm::Triple::ppc64:
- case llvm::Triple::ppc64le:
- this->MCountName = "_mcount";
- break;
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- case llvm::Triple::systemz:
- this->HasFloat128 = true;
- break;
- }
- }
-
- const char *getStaticInitSectionSpecifier() const override {
- return ".text.startup";
- }
-};
-
-// NetBSD Target
-template<typename Target>
-class NetBSDTargetInfo : public OSTargetInfo<Target> {
-protected:
- void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const override {
- // NetBSD defines; list based off of gcc output
- Builder.defineMacro("__NetBSD__");
- Builder.defineMacro("__unix__");
- Builder.defineMacro("__ELF__");
- if (Opts.POSIXThreads)
- Builder.defineMacro("_REENTRANT");
-
- switch (Triple.getArch()) {
- default:
- break;
- case llvm::Triple::arm:
- case llvm::Triple::armeb:
- case llvm::Triple::thumb:
- case llvm::Triple::thumbeb:
- Builder.defineMacro("__ARM_DWARF_EH__");
- break;
- }
- }
-public:
- NetBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : OSTargetInfo<Target>(Triple, Opts) {
- this->MCountName = "_mcount";
- }
-};
-
-// OpenBSD Target
-template<typename Target>
-class OpenBSDTargetInfo : public OSTargetInfo<Target> {
-protected:
- void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const override {
- // OpenBSD defines; list based off of gcc output
-
- Builder.defineMacro("__OpenBSD__");
- DefineStd(Builder, "unix", Opts);
- Builder.defineMacro("__ELF__");
- if (Opts.POSIXThreads)
- Builder.defineMacro("_REENTRANT");
- if (this->HasFloat128)
- Builder.defineMacro("__FLOAT128__");
- }
-public:
- OpenBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : OSTargetInfo<Target>(Triple, Opts) {
- switch (Triple.getArch()) {
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- this->HasFloat128 = true;
- // FALLTHROUGH
- default:
- this->MCountName = "__mcount";
- break;
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- case llvm::Triple::ppc:
- case llvm::Triple::sparcv9:
- this->MCountName = "_mcount";
- break;
- }
- }
-};
-
-// Bitrig Target
-template<typename Target>
-class BitrigTargetInfo : public OSTargetInfo<Target> {
-protected:
- void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const override {
- // Bitrig defines; list based off of gcc output
-
- Builder.defineMacro("__Bitrig__");
- DefineStd(Builder, "unix", Opts);
- Builder.defineMacro("__ELF__");
- if (Opts.POSIXThreads)
- Builder.defineMacro("_REENTRANT");
-
- switch (Triple.getArch()) {
- default:
- break;
- case llvm::Triple::arm:
- case llvm::Triple::armeb:
- case llvm::Triple::thumb:
- case llvm::Triple::thumbeb:
- Builder.defineMacro("__ARM_DWARF_EH__");
- break;
- }
- }
-public:
- BitrigTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : OSTargetInfo<Target>(Triple, Opts) {
- this->MCountName = "__mcount";
- }
-};
-
-// PSP Target
-template<typename Target>
-class PSPTargetInfo : public OSTargetInfo<Target> {
-protected:
- void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const override {
- // PSP defines; list based on the output of the pspdev gcc toolchain.
- Builder.defineMacro("PSP");
- Builder.defineMacro("_PSP");
- Builder.defineMacro("__psp__");
- Builder.defineMacro("__ELF__");
- }
-public:
- PSPTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) {}
-};
-
-// PS3 PPU Target
-template<typename Target>
-class PS3PPUTargetInfo : public OSTargetInfo<Target> {
-protected:
- void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const override {
- // PS3 PPU defines.
- Builder.defineMacro("__PPC__");
- Builder.defineMacro("__PPU__");
- Builder.defineMacro("__CELLOS_LV2__");
- Builder.defineMacro("__ELF__");
- Builder.defineMacro("__LP32__");
- Builder.defineMacro("_ARCH_PPC64");
- Builder.defineMacro("__powerpc64__");
- }
-public:
- PS3PPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : OSTargetInfo<Target>(Triple, Opts) {
- this->LongWidth = this->LongAlign = 32;
- this->PointerWidth = this->PointerAlign = 32;
- this->IntMaxType = TargetInfo::SignedLongLong;
- this->Int64Type = TargetInfo::SignedLongLong;
- this->SizeType = TargetInfo::UnsignedInt;
- this->resetDataLayout("E-m:e-p:32:32-i64:64-n32:64");
- }
-};
-
-template <typename Target>
-class PS4OSTargetInfo : public OSTargetInfo<Target> {
-protected:
- void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const override {
- Builder.defineMacro("__FreeBSD__", "9");
- Builder.defineMacro("__FreeBSD_cc_version", "900001");
- Builder.defineMacro("__KPRINTF_ATTRIBUTE__");
- DefineStd(Builder, "unix", Opts);
- Builder.defineMacro("__ELF__");
- Builder.defineMacro("__ORBIS__");
- }
-public:
- PS4OSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : OSTargetInfo<Target>(Triple, Opts) {
- this->WCharType = this->UnsignedShort;
-
- // On PS4, TLS variable cannot be aligned to more than 32 bytes (256 bits).
- this->MaxTLSAlign = 256;
-
- // On PS4, do not honor explicit bit field alignment,
- // as in "__attribute__((aligned(2))) int b : 1;".
- this->UseExplicitBitFieldAlignment = false;
-
- switch (Triple.getArch()) {
- default:
- case llvm::Triple::x86_64:
- this->MCountName = ".mcount";
- break;
- }
- }
-};
-
-// Solaris target
-template<typename Target>
-class SolarisTargetInfo : public OSTargetInfo<Target> {
-protected:
- void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const override {
- DefineStd(Builder, "sun", Opts);
- DefineStd(Builder, "unix", Opts);
- Builder.defineMacro("__ELF__");
- Builder.defineMacro("__svr4__");
- Builder.defineMacro("__SVR4");
- // Solaris headers require _XOPEN_SOURCE to be set to 600 for C99 and
- // newer, but to 500 for everything else. feature_test.h has a check to
- // ensure that you are not using C99 with an old version of X/Open or C89
- // with a new version.
- if (Opts.C99)
- Builder.defineMacro("_XOPEN_SOURCE", "600");
- else
- Builder.defineMacro("_XOPEN_SOURCE", "500");
- if (Opts.CPlusPlus)
- Builder.defineMacro("__C99FEATURES__");
- Builder.defineMacro("_LARGEFILE_SOURCE");
- Builder.defineMacro("_LARGEFILE64_SOURCE");
- Builder.defineMacro("__EXTENSIONS__");
- Builder.defineMacro("_REENTRANT");
- }
-public:
- SolarisTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : OSTargetInfo<Target>(Triple, Opts) {
- this->WCharType = this->SignedInt;
- // FIXME: WIntType should be SignedLong
- }
-};
-
-// Windows target
-template<typename Target>
-class WindowsTargetInfo : public OSTargetInfo<Target> {
-protected:
- void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const override {
- Builder.defineMacro("_WIN32");
- }
- void getVisualStudioDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- if (Opts.CPlusPlus) {
- if (Opts.RTTIData)
- Builder.defineMacro("_CPPRTTI");
-
- if (Opts.CXXExceptions)
- Builder.defineMacro("_CPPUNWIND");
- }
-
- if (Opts.Bool)
- Builder.defineMacro("__BOOL_DEFINED");
-
- if (!Opts.CharIsSigned)
- Builder.defineMacro("_CHAR_UNSIGNED");
-
- // FIXME: POSIXThreads isn't exactly the option this should be defined for,
- // but it works for now.
- if (Opts.POSIXThreads)
- Builder.defineMacro("_MT");
-
- if (Opts.MSCompatibilityVersion) {
- Builder.defineMacro("_MSC_VER",
- Twine(Opts.MSCompatibilityVersion / 100000));
- Builder.defineMacro("_MSC_FULL_VER", Twine(Opts.MSCompatibilityVersion));
- // FIXME We cannot encode the revision information into 32-bits
- Builder.defineMacro("_MSC_BUILD", Twine(1));
-
- if (Opts.CPlusPlus11 && Opts.isCompatibleWithMSVC(LangOptions::MSVC2015))
- Builder.defineMacro("_HAS_CHAR16_T_LANGUAGE_SUPPORT", Twine(1));
-
- if (Opts.isCompatibleWithMSVC(LangOptions::MSVC2015)) {
- if (Opts.CPlusPlus1z)
- Builder.defineMacro("_MSVC_LANG", "201403L");
- else if (Opts.CPlusPlus14)
- Builder.defineMacro("_MSVC_LANG", "201402L");
- }
- }
-
- if (Opts.MicrosoftExt) {
- Builder.defineMacro("_MSC_EXTENSIONS");
-
- if (Opts.CPlusPlus11) {
- Builder.defineMacro("_RVALUE_REFERENCES_V2_SUPPORTED");
- Builder.defineMacro("_RVALUE_REFERENCES_SUPPORTED");
- Builder.defineMacro("_NATIVE_NULLPTR_SUPPORTED");
- }
- }
-
- Builder.defineMacro("_INTEGRAL_MAX_BITS", "64");
- }
-
-public:
- WindowsTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : OSTargetInfo<Target>(Triple, Opts) {}
-};
-
-template <typename Target>
-class NaClTargetInfo : public OSTargetInfo<Target> {
-protected:
- void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const override {
- if (Opts.POSIXThreads)
- Builder.defineMacro("_REENTRANT");
- if (Opts.CPlusPlus)
- Builder.defineMacro("_GNU_SOURCE");
-
- DefineStd(Builder, "unix", Opts);
- Builder.defineMacro("__ELF__");
- Builder.defineMacro("__native_client__");
- }
-
-public:
- NaClTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : OSTargetInfo<Target>(Triple, Opts) {
- this->LongAlign = 32;
- this->LongWidth = 32;
- this->PointerAlign = 32;
- this->PointerWidth = 32;
- this->IntMaxType = TargetInfo::SignedLongLong;
- this->Int64Type = TargetInfo::SignedLongLong;
- this->DoubleAlign = 64;
- this->LongDoubleWidth = 64;
- this->LongDoubleAlign = 64;
- this->LongLongWidth = 64;
- this->LongLongAlign = 64;
- this->SizeType = TargetInfo::UnsignedInt;
- this->PtrDiffType = TargetInfo::SignedInt;
- this->IntPtrType = TargetInfo::SignedInt;
- // RegParmMax is inherited from the underlying architecture.
- this->LongDoubleFormat = &llvm::APFloat::IEEEdouble();
- if (Triple.getArch() == llvm::Triple::arm) {
- // Handled in ARM's setABI().
- } else if (Triple.getArch() == llvm::Triple::x86) {
- this->resetDataLayout("e-m:e-p:32:32-i64:64-n8:16:32-S128");
- } else if (Triple.getArch() == llvm::Triple::x86_64) {
- this->resetDataLayout("e-m:e-p:32:32-i64:64-n8:16:32:64-S128");
- } else if (Triple.getArch() == llvm::Triple::mipsel) {
- // Handled on mips' setDataLayout.
- } else {
- assert(Triple.getArch() == llvm::Triple::le32);
- this->resetDataLayout("e-p:32:32-i64:64");
- }
- }
-};
-
-// Fuchsia Target
-template<typename Target>
-class FuchsiaTargetInfo : public OSTargetInfo<Target> {
-protected:
- void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const override {
- Builder.defineMacro("__Fuchsia__");
- Builder.defineMacro("__ELF__");
- if (Opts.POSIXThreads)
- Builder.defineMacro("_REENTRANT");
- // Required by the libc++ locale support.
- if (Opts.CPlusPlus)
- Builder.defineMacro("_GNU_SOURCE");
- }
-public:
- FuchsiaTargetInfo(const llvm::Triple &Triple,
- const TargetOptions &Opts)
- : OSTargetInfo<Target>(Triple, Opts) {
- this->MCountName = "__mcount";
- }
-};
-
-// WebAssembly target
-template <typename Target>
-class WebAssemblyOSTargetInfo : public OSTargetInfo<Target> {
- void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const final {
- // A common platform macro.
- if (Opts.POSIXThreads)
- Builder.defineMacro("_REENTRANT");
- // Follow g++ convention and predefine _GNU_SOURCE for C++.
- if (Opts.CPlusPlus)
- Builder.defineMacro("_GNU_SOURCE");
- }
-
- // As an optimization, group static init code together in a section.
- const char *getStaticInitSectionSpecifier() const final {
- return ".text.__startup";
- }
-
-public:
- explicit WebAssemblyOSTargetInfo(const llvm::Triple &Triple,
- const TargetOptions &Opts)
- : OSTargetInfo<Target>(Triple, Opts) {
- this->MCountName = "__mcount";
- this->TheCXXABI.set(TargetCXXABI::WebAssembly);
- }
-};
-
-//===----------------------------------------------------------------------===//
-// Specific target implementations.
-//===----------------------------------------------------------------------===//
-
-// PPC abstract base class
-class PPCTargetInfo : public TargetInfo {
- static const Builtin::Info BuiltinInfo[];
- static const char * const GCCRegNames[];
- static const TargetInfo::GCCRegAlias GCCRegAliases[];
- std::string CPU;
-
- // Target cpu features.
- bool HasAltivec;
- bool HasVSX;
- bool HasP8Vector;
- bool HasP8Crypto;
- bool HasDirectMove;
- bool HasQPX;
- bool HasHTM;
- bool HasBPERMD;
- bool HasExtDiv;
- bool HasP9Vector;
-
-protected:
- std::string ABI;
-
-public:
- PPCTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
- : TargetInfo(Triple), HasAltivec(false), HasVSX(false), HasP8Vector(false),
- HasP8Crypto(false), HasDirectMove(false), HasQPX(false), HasHTM(false),
- HasBPERMD(false), HasExtDiv(false), HasP9Vector(false) {
- SuitableAlign = 128;
- SimdDefaultAlign = 128;
- LongDoubleWidth = LongDoubleAlign = 128;
- LongDoubleFormat = &llvm::APFloat::PPCDoubleDouble();
- }
-
- /// \brief Flags for architecture specific defines.
- typedef enum {
- ArchDefineNone = 0,
- ArchDefineName = 1 << 0, // <name> is substituted for arch name.
- ArchDefinePpcgr = 1 << 1,
- ArchDefinePpcsq = 1 << 2,
- ArchDefine440 = 1 << 3,
- ArchDefine603 = 1 << 4,
- ArchDefine604 = 1 << 5,
- ArchDefinePwr4 = 1 << 6,
- ArchDefinePwr5 = 1 << 7,
- ArchDefinePwr5x = 1 << 8,
- ArchDefinePwr6 = 1 << 9,
- ArchDefinePwr6x = 1 << 10,
- ArchDefinePwr7 = 1 << 11,
- ArchDefinePwr8 = 1 << 12,
- ArchDefinePwr9 = 1 << 13,
- ArchDefineA2 = 1 << 14,
- ArchDefineA2q = 1 << 15
- } ArchDefineTypes;
-
- // Set the language option for altivec based on our value.
- void adjust(LangOptions &Opts) override {
- if (HasAltivec)
- Opts.AltiVec = 1;
- TargetInfo::adjust(Opts);
- }
-
- // Note: GCC recognizes the following additional cpus:
- // 401, 403, 405, 405fp, 440fp, 464, 464fp, 476, 476fp, 505, 740, 801,
- // 821, 823, 8540, 8548, e300c2, e300c3, e500mc64, e6500, 860, cell,
- // titan, rs64.
- bool setCPU(const std::string &Name) override {
- bool CPUKnown = llvm::StringSwitch<bool>(Name)
- .Case("generic", true)
- .Case("440", true)
- .Case("450", true)
- .Case("601", true)
- .Case("602", true)
- .Case("603", true)
- .Case("603e", true)
- .Case("603ev", true)
- .Case("604", true)
- .Case("604e", true)
- .Case("620", true)
- .Case("630", true)
- .Case("g3", true)
- .Case("7400", true)
- .Case("g4", true)
- .Case("7450", true)
- .Case("g4+", true)
- .Case("750", true)
- .Case("970", true)
- .Case("g5", true)
- .Case("a2", true)
- .Case("a2q", true)
- .Case("e500mc", true)
- .Case("e5500", true)
- .Case("power3", true)
- .Case("pwr3", true)
- .Case("power4", true)
- .Case("pwr4", true)
- .Case("power5", true)
- .Case("pwr5", true)
- .Case("power5x", true)
- .Case("pwr5x", true)
- .Case("power6", true)
- .Case("pwr6", true)
- .Case("power6x", true)
- .Case("pwr6x", true)
- .Case("power7", true)
- .Case("pwr7", true)
- .Case("power8", true)
- .Case("pwr8", true)
- .Case("power9", true)
- .Case("pwr9", true)
- .Case("powerpc", true)
- .Case("ppc", true)
- .Case("powerpc64", true)
- .Case("ppc64", true)
- .Case("powerpc64le", true)
- .Case("ppc64le", true)
- .Default(false);
-
- if (CPUKnown)
- CPU = Name;
-
- return CPUKnown;
- }
-
-
- StringRef getABI() const override { return ABI; }
-
- ArrayRef<Builtin::Info> getTargetBuiltins() const override {
- return llvm::makeArrayRef(BuiltinInfo,
- clang::PPC::LastTSBuiltin-Builtin::FirstTSBuiltin);
- }
-
- bool isCLZForZeroUndef() const override { return false; }
-
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override;
-
- bool
- initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
- StringRef CPU,
- const std::vector<std::string> &FeaturesVec) const override;
-
- bool handleTargetFeatures(std::vector<std::string> &Features,
- DiagnosticsEngine &Diags) override;
- bool hasFeature(StringRef Feature) const override;
- void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name,
- bool Enabled) const override;
-
- ArrayRef<const char *> getGCCRegNames() const override;
- ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
- bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &Info) const override {
- switch (*Name) {
- default: return false;
- case 'O': // Zero
- break;
- case 'b': // Base register
- case 'f': // Floating point register
- Info.setAllowsRegister();
- break;
- // FIXME: The following are added to allow parsing.
- // I just took a guess at what the actions should be.
- // Also, is more specific checking needed? I.e. specific registers?
- case 'd': // Floating point register (containing 64-bit value)
- case 'v': // Altivec vector register
- Info.setAllowsRegister();
- break;
- case 'w':
- switch (Name[1]) {
- case 'd':// VSX vector register to hold vector double data
- case 'f':// VSX vector register to hold vector float data
- case 's':// VSX vector register to hold scalar float data
- case 'a':// Any VSX register
- case 'c':// An individual CR bit
- break;
- default:
- return false;
- }
- Info.setAllowsRegister();
- Name++; // Skip over 'w'.
- break;
- case 'h': // `MQ', `CTR', or `LINK' register
- case 'q': // `MQ' register
- case 'c': // `CTR' register
- case 'l': // `LINK' register
- case 'x': // `CR' register (condition register) number 0
- case 'y': // `CR' register (condition register)
- case 'z': // `XER[CA]' carry bit (part of the XER register)
- Info.setAllowsRegister();
- break;
- case 'I': // Signed 16-bit constant
- case 'J': // Unsigned 16-bit constant shifted left 16 bits
- // (use `L' instead for SImode constants)
- case 'K': // Unsigned 16-bit constant
- case 'L': // Signed 16-bit constant shifted left 16 bits
- case 'M': // Constant larger than 31
- case 'N': // Exact power of 2
- case 'P': // Constant whose negation is a signed 16-bit constant
- case 'G': // Floating point constant that can be loaded into a
- // register with one instruction per word
- case 'H': // Integer/Floating point constant that can be loaded
- // into a register using three instructions
- break;
- case 'm': // Memory operand. Note that on PowerPC targets, m can
- // include addresses that update the base register. It
- // is therefore only safe to use `m' in an asm statement
- // if that asm statement accesses the operand exactly once.
- // The asm statement must also use `%U<opno>' as a
- // placeholder for the "update" flag in the corresponding
- // load or store instruction. For example:
- // asm ("st%U0 %1,%0" : "=m" (mem) : "r" (val));
- // is correct but:
- // asm ("st %1,%0" : "=m" (mem) : "r" (val));
- // is not. Use es rather than m if you don't want the base
- // register to be updated.
- case 'e':
- if (Name[1] != 's')
- return false;
- // es: A "stable" memory operand; that is, one which does not
- // include any automodification of the base register. Unlike
- // `m', this constraint can be used in asm statements that
- // might access the operand several times, or that might not
- // access it at all.
- Info.setAllowsMemory();
- Name++; // Skip over 'e'.
- break;
- case 'Q': // Memory operand that is an offset from a register (it is
- // usually better to use `m' or `es' in asm statements)
- case 'Z': // Memory operand that is an indexed or indirect from a
- // register (it is usually better to use `m' or `es' in
- // asm statements)
- Info.setAllowsMemory();
- Info.setAllowsRegister();
- break;
- case 'R': // AIX TOC entry
- case 'a': // Address operand that is an indexed or indirect from a
- // register (`p' is preferable for asm statements)
- case 'S': // Constant suitable as a 64-bit mask operand
- case 'T': // Constant suitable as a 32-bit mask operand
- case 'U': // System V Release 4 small data area reference
- case 't': // AND masks that can be performed by two rldic{l, r}
- // instructions
- case 'W': // Vector constant that does not require memory
- case 'j': // Vector constant that is all zeros.
- break;
- // End FIXME.
- }
- return true;
- }
- std::string convertConstraint(const char *&Constraint) const override {
- std::string R;
- switch (*Constraint) {
- case 'e':
- case 'w':
- // Two-character constraint; add "^" hint for later parsing.
- R = std::string("^") + std::string(Constraint, 2);
- Constraint++;
- break;
- default:
- return TargetInfo::convertConstraint(Constraint);
- }
- return R;
- }
- const char *getClobbers() const override {
- return "";
- }
- int getEHDataRegisterNumber(unsigned RegNo) const override {
- if (RegNo == 0) return 3;
- if (RegNo == 1) return 4;
- return -1;
- }
-
- bool hasSjLjLowering() const override {
- return true;
- }
-
- bool useFloat128ManglingForLongDouble() const override {
- return LongDoubleWidth == 128 &&
- LongDoubleFormat == &llvm::APFloat::PPCDoubleDouble() &&
- getTriple().isOSBinFormatELF();
- }
-};
-
-const Builtin::Info PPCTargetInfo::BuiltinInfo[] = {
-#define BUILTIN(ID, TYPE, ATTRS) \
- { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
- { #ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr },
-#include "clang/Basic/BuiltinsPPC.def"
-};
-
-/// handleTargetFeatures - Perform initialization based on the user
-/// configured set of features.
-bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
- DiagnosticsEngine &Diags) {
- for (const auto &Feature : Features) {
- if (Feature == "+altivec") {
- HasAltivec = true;
- } else if (Feature == "+vsx") {
- HasVSX = true;
- } else if (Feature == "+bpermd") {
- HasBPERMD = true;
- } else if (Feature == "+extdiv") {
- HasExtDiv = true;
- } else if (Feature == "+power8-vector") {
- HasP8Vector = true;
- } else if (Feature == "+crypto") {
- HasP8Crypto = true;
- } else if (Feature == "+direct-move") {
- HasDirectMove = true;
- } else if (Feature == "+qpx") {
- HasQPX = true;
- } else if (Feature == "+htm") {
- HasHTM = true;
- } else if (Feature == "+float128") {
- HasFloat128 = true;
- } else if (Feature == "+power9-vector") {
- HasP9Vector = true;
- }
- // TODO: Finish this list and add an assert that we've handled them
- // all.
- }
-
- return true;
-}
-
-/// PPCTargetInfo::getTargetDefines - Return a set of the PowerPC-specific
-/// #defines that are not tied to a specific subtarget.
-void PPCTargetInfo::getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- // Target identification.
- Builder.defineMacro("__ppc__");
- Builder.defineMacro("__PPC__");
- Builder.defineMacro("_ARCH_PPC");
- Builder.defineMacro("__powerpc__");
- Builder.defineMacro("__POWERPC__");
- if (PointerWidth == 64) {
- Builder.defineMacro("_ARCH_PPC64");
- Builder.defineMacro("__powerpc64__");
- Builder.defineMacro("__ppc64__");
- Builder.defineMacro("__PPC64__");
- }
-
- // Target properties.
- if (getTriple().getArch() == llvm::Triple::ppc64le) {
- Builder.defineMacro("_LITTLE_ENDIAN");
- } else {
- if (getTriple().getOS() != llvm::Triple::NetBSD &&
- getTriple().getOS() != llvm::Triple::OpenBSD)
- Builder.defineMacro("_BIG_ENDIAN");
- }
-
- // ABI options.
- if (ABI == "elfv1" || ABI == "elfv1-qpx")
- Builder.defineMacro("_CALL_ELF", "1");
- if (ABI == "elfv2")
- Builder.defineMacro("_CALL_ELF", "2");
-
- // This typically is only for a new enough linker (bfd >= 2.16.2 or gold), but
- // our suppport post-dates this and it should work on all 64-bit ppc linux
- // platforms. It is guaranteed to work on all elfv2 platforms.
- if (getTriple().getOS() == llvm::Triple::Linux && PointerWidth == 64)
- Builder.defineMacro("_CALL_LINUX", "1");
-
- // Subtarget options.
- Builder.defineMacro("__NATURAL_ALIGNMENT__");
- Builder.defineMacro("__REGISTER_PREFIX__", "");
-
- // FIXME: Should be controlled by command line option.
- if (LongDoubleWidth == 128) {
- Builder.defineMacro("__LONG_DOUBLE_128__");
- Builder.defineMacro("__LONGDOUBLE128");
- }
-
- // Define this for elfv2 (64-bit only) or 64-bit darwin.
- if (ABI == "elfv2" ||
- (getTriple().getOS() == llvm::Triple::Darwin && PointerWidth == 64))
- Builder.defineMacro("__STRUCT_PARM_ALIGN__", "16");
-
- // CPU identification.
- ArchDefineTypes defs =
- (ArchDefineTypes)llvm::StringSwitch<int>(CPU)
- .Case("440", ArchDefineName)
- .Case("450", ArchDefineName | ArchDefine440)
- .Case("601", ArchDefineName)
- .Case("602", ArchDefineName | ArchDefinePpcgr)
- .Case("603", ArchDefineName | ArchDefinePpcgr)
- .Case("603e", ArchDefineName | ArchDefine603 | ArchDefinePpcgr)
- .Case("603ev", ArchDefineName | ArchDefine603 | ArchDefinePpcgr)
- .Case("604", ArchDefineName | ArchDefinePpcgr)
- .Case("604e", ArchDefineName | ArchDefine604 | ArchDefinePpcgr)
- .Case("620", ArchDefineName | ArchDefinePpcgr)
- .Case("630", ArchDefineName | ArchDefinePpcgr)
- .Case("7400", ArchDefineName | ArchDefinePpcgr)
- .Case("7450", ArchDefineName | ArchDefinePpcgr)
- .Case("750", ArchDefineName | ArchDefinePpcgr)
- .Case("970", ArchDefineName | ArchDefinePwr4 | ArchDefinePpcgr |
- ArchDefinePpcsq)
- .Case("a2", ArchDefineA2)
- .Case("a2q", ArchDefineName | ArchDefineA2 | ArchDefineA2q)
- .Case("pwr3", ArchDefinePpcgr)
- .Case("pwr4", ArchDefineName | ArchDefinePpcgr | ArchDefinePpcsq)
- .Case("pwr5", ArchDefineName | ArchDefinePwr4 | ArchDefinePpcgr |
- ArchDefinePpcsq)
- .Case("pwr5x", ArchDefineName | ArchDefinePwr5 | ArchDefinePwr4 |
- ArchDefinePpcgr | ArchDefinePpcsq)
- .Case("pwr6", ArchDefineName | ArchDefinePwr5x | ArchDefinePwr5 |
- ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq)
- .Case("pwr6x", ArchDefineName | ArchDefinePwr6 | ArchDefinePwr5x |
- ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr |
- ArchDefinePpcsq)
- .Case("pwr7", ArchDefineName | ArchDefinePwr6x | ArchDefinePwr6 |
- ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 |
- ArchDefinePpcgr | ArchDefinePpcsq)
- .Case("pwr8", ArchDefineName | ArchDefinePwr7 | ArchDefinePwr6x |
- ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 |
- ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq)
- .Case("pwr9", ArchDefineName | ArchDefinePwr8 | ArchDefinePwr7 |
- ArchDefinePwr6x | ArchDefinePwr6 | ArchDefinePwr5x |
- ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr |
- ArchDefinePpcsq)
- .Case("power3", ArchDefinePpcgr)
- .Case("power4", ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq)
- .Case("power5", ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr |
- ArchDefinePpcsq)
- .Case("power5x", ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 |
- ArchDefinePpcgr | ArchDefinePpcsq)
- .Case("power6", ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 |
- ArchDefinePwr4 | ArchDefinePpcgr |
- ArchDefinePpcsq)
- .Case("power6x", ArchDefinePwr6x | ArchDefinePwr6 | ArchDefinePwr5x |
- ArchDefinePwr5 | ArchDefinePwr4 |
- ArchDefinePpcgr | ArchDefinePpcsq)
- .Case("power7", ArchDefinePwr7 | ArchDefinePwr6x | ArchDefinePwr6 |
- ArchDefinePwr5x | ArchDefinePwr5 |
- ArchDefinePwr4 | ArchDefinePpcgr |
- ArchDefinePpcsq)
- .Case("power8", ArchDefinePwr8 | ArchDefinePwr7 | ArchDefinePwr6x |
- ArchDefinePwr6 | ArchDefinePwr5x |
- ArchDefinePwr5 | ArchDefinePwr4 |
- ArchDefinePpcgr | ArchDefinePpcsq)
- .Case("power9", ArchDefinePwr9 | ArchDefinePwr8 | ArchDefinePwr7 |
- ArchDefinePwr6x | ArchDefinePwr6 |
- ArchDefinePwr5x | ArchDefinePwr5 |
- ArchDefinePwr4 | ArchDefinePpcgr |
- ArchDefinePpcsq)
- // powerpc64le automatically defaults to at least power8.
- .Case("ppc64le", ArchDefinePwr8 | ArchDefinePwr7 | ArchDefinePwr6x |
- ArchDefinePwr6 | ArchDefinePwr5x |
- ArchDefinePwr5 | ArchDefinePwr4 |
- ArchDefinePpcgr | ArchDefinePpcsq)
- .Default(ArchDefineNone);
-
- if (defs & ArchDefineName)
- Builder.defineMacro(Twine("_ARCH_", StringRef(CPU).upper()));
- if (defs & ArchDefinePpcgr)
- Builder.defineMacro("_ARCH_PPCGR");
- if (defs & ArchDefinePpcsq)
- Builder.defineMacro("_ARCH_PPCSQ");
- if (defs & ArchDefine440)
- Builder.defineMacro("_ARCH_440");
- if (defs & ArchDefine603)
- Builder.defineMacro("_ARCH_603");
- if (defs & ArchDefine604)
- Builder.defineMacro("_ARCH_604");
- if (defs & ArchDefinePwr4)
- Builder.defineMacro("_ARCH_PWR4");
- if (defs & ArchDefinePwr5)
- Builder.defineMacro("_ARCH_PWR5");
- if (defs & ArchDefinePwr5x)
- Builder.defineMacro("_ARCH_PWR5X");
- if (defs & ArchDefinePwr6)
- Builder.defineMacro("_ARCH_PWR6");
- if (defs & ArchDefinePwr6x)
- Builder.defineMacro("_ARCH_PWR6X");
- if (defs & ArchDefinePwr7)
- Builder.defineMacro("_ARCH_PWR7");
- if (defs & ArchDefinePwr8)
- Builder.defineMacro("_ARCH_PWR8");
- if (defs & ArchDefinePwr9)
- Builder.defineMacro("_ARCH_PWR9");
- if (defs & ArchDefineA2)
- Builder.defineMacro("_ARCH_A2");
- if (defs & ArchDefineA2q) {
- Builder.defineMacro("_ARCH_A2Q");
- Builder.defineMacro("_ARCH_QP");
- }
-
- if (getTriple().getVendor() == llvm::Triple::BGQ) {
- Builder.defineMacro("__bg__");
- Builder.defineMacro("__THW_BLUEGENE__");
- Builder.defineMacro("__bgq__");
- Builder.defineMacro("__TOS_BGQ__");
- }
-
- if (HasAltivec) {
- Builder.defineMacro("__VEC__", "10206");
- Builder.defineMacro("__ALTIVEC__");
- }
- if (HasVSX)
- Builder.defineMacro("__VSX__");
- if (HasP8Vector)
- Builder.defineMacro("__POWER8_VECTOR__");
- if (HasP8Crypto)
- Builder.defineMacro("__CRYPTO__");
- if (HasHTM)
- Builder.defineMacro("__HTM__");
- if (HasFloat128)
- Builder.defineMacro("__FLOAT128__");
- if (HasP9Vector)
- Builder.defineMacro("__POWER9_VECTOR__");
-
- Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
- Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
- Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
- if (PointerWidth == 64)
- Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
-
- // We have support for the bswap intrinsics so we can define this.
- Builder.defineMacro("__HAVE_BSWAP__", "1");
-
- // FIXME: The following are not yet generated here by Clang, but are
- // generated by GCC:
- //
- // _SOFT_FLOAT_
- // __RECIP_PRECISION__
- // __APPLE_ALTIVEC__
- // __RECIP__
- // __RECIPF__
- // __RSQRTE__
- // __RSQRTEF__
- // _SOFT_DOUBLE_
- // __NO_LWSYNC__
- // __CMODEL_MEDIUM__
- // __CMODEL_LARGE__
- // _CALL_SYSV
- // _CALL_DARWIN
- // __NO_FPRS__
-}
-
-// Handle explicit options being passed to the compiler here: if we've
-// explicitly turned off vsx and turned on any of:
-// - power8-vector
-// - direct-move
-// - float128
-// - power9-vector
-// then go ahead and error since the customer has expressed an incompatible
-// set of options.
-static bool ppcUserFeaturesCheck(DiagnosticsEngine &Diags,
- const std::vector<std::string> &FeaturesVec) {
-
- if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "-vsx") !=
- FeaturesVec.end()) {
- if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "+power8-vector") !=
- FeaturesVec.end()) {
- Diags.Report(diag::err_opt_not_valid_with_opt) << "-mpower8-vector"
- << "-mno-vsx";
- return false;
- }
-
- if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "+direct-move") !=
- FeaturesVec.end()) {
- Diags.Report(diag::err_opt_not_valid_with_opt) << "-mdirect-move"
- << "-mno-vsx";
- return false;
- }
-
- if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "+float128") !=
- FeaturesVec.end()) {
- Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfloat128"
- << "-mno-vsx";
- return false;
- }
-
- if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "+power9-vector") !=
- FeaturesVec.end()) {
- Diags.Report(diag::err_opt_not_valid_with_opt) << "-mpower9-vector"
- << "-mno-vsx";
- return false;
- }
- }
-
- return true;
-}
-
-bool PPCTargetInfo::initFeatureMap(
- llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
- const std::vector<std::string> &FeaturesVec) const {
- Features["altivec"] = llvm::StringSwitch<bool>(CPU)
- .Case("7400", true)
- .Case("g4", true)
- .Case("7450", true)
- .Case("g4+", true)
- .Case("970", true)
- .Case("g5", true)
- .Case("pwr6", true)
- .Case("pwr7", true)
- .Case("pwr8", true)
- .Case("pwr9", true)
- .Case("ppc64", true)
- .Case("ppc64le", true)
- .Default(false);
-
- Features["qpx"] = (CPU == "a2q");
- Features["power9-vector"] = (CPU == "pwr9");
- Features["crypto"] = llvm::StringSwitch<bool>(CPU)
- .Case("ppc64le", true)
- .Case("pwr9", true)
- .Case("pwr8", true)
- .Default(false);
- Features["power8-vector"] = llvm::StringSwitch<bool>(CPU)
- .Case("ppc64le", true)
- .Case("pwr9", true)
- .Case("pwr8", true)
- .Default(false);
- Features["bpermd"] = llvm::StringSwitch<bool>(CPU)
- .Case("ppc64le", true)
- .Case("pwr9", true)
- .Case("pwr8", true)
- .Case("pwr7", true)
- .Default(false);
- Features["extdiv"] = llvm::StringSwitch<bool>(CPU)
- .Case("ppc64le", true)
- .Case("pwr9", true)
- .Case("pwr8", true)
- .Case("pwr7", true)
- .Default(false);
- Features["direct-move"] = llvm::StringSwitch<bool>(CPU)
- .Case("ppc64le", true)
- .Case("pwr9", true)
- .Case("pwr8", true)
- .Default(false);
- Features["vsx"] = llvm::StringSwitch<bool>(CPU)
- .Case("ppc64le", true)
- .Case("pwr9", true)
- .Case("pwr8", true)
- .Case("pwr7", true)
- .Default(false);
- Features["htm"] = llvm::StringSwitch<bool>(CPU)
- .Case("ppc64le", true)
- .Case("pwr9", true)
- .Case("pwr8", true)
- .Default(false);
-
- if (!ppcUserFeaturesCheck(Diags, FeaturesVec))
- return false;
-
- return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
-}
-
-bool PPCTargetInfo::hasFeature(StringRef Feature) const {
- return llvm::StringSwitch<bool>(Feature)
- .Case("powerpc", true)
- .Case("altivec", HasAltivec)
- .Case("vsx", HasVSX)
- .Case("power8-vector", HasP8Vector)
- .Case("crypto", HasP8Crypto)
- .Case("direct-move", HasDirectMove)
- .Case("qpx", HasQPX)
- .Case("htm", HasHTM)
- .Case("bpermd", HasBPERMD)
- .Case("extdiv", HasExtDiv)
- .Case("float128", HasFloat128)
- .Case("power9-vector", HasP9Vector)
- .Default(false);
-}
-
-void PPCTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
- StringRef Name, bool Enabled) const {
- if (Enabled) {
- // If we're enabling any of the vsx based features then enable vsx and
- // altivec. We'll diagnose any problems later.
- bool FeatureHasVSX = llvm::StringSwitch<bool>(Name)
- .Case("vsx", true)
- .Case("direct-move", true)
- .Case("power8-vector", true)
- .Case("power9-vector", true)
- .Case("float128", true)
- .Default(false);
- if (FeatureHasVSX)
- Features["vsx"] = Features["altivec"] = true;
- if (Name == "power9-vector")
- Features["power8-vector"] = true;
- Features[Name] = true;
- } else {
- // If we're disabling altivec or vsx go ahead and disable all of the vsx
- // features.
- if ((Name == "altivec") || (Name == "vsx"))
- Features["vsx"] = Features["direct-move"] = Features["power8-vector"] =
- Features["float128"] = Features["power9-vector"] = false;
- if (Name == "power8-vector")
- Features["power9-vector"] = false;
- Features[Name] = false;
- }
-}
-
-const char * const PPCTargetInfo::GCCRegNames[] = {
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
- "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
- "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
- "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
- "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
- "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
- "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
- "mq", "lr", "ctr", "ap",
- "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",
- "xer",
- "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
- "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
- "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
- "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
- "vrsave", "vscr",
- "spe_acc", "spefscr",
- "sfp"
-};
-
-ArrayRef<const char*> PPCTargetInfo::getGCCRegNames() const {
- return llvm::makeArrayRef(GCCRegNames);
-}
-
-const TargetInfo::GCCRegAlias PPCTargetInfo::GCCRegAliases[] = {
- // While some of these aliases do map to different registers
- // they still share the same register name.
- { { "0" }, "r0" },
- { { "1"}, "r1" },
- { { "2" }, "r2" },
- { { "3" }, "r3" },
- { { "4" }, "r4" },
- { { "5" }, "r5" },
- { { "6" }, "r6" },
- { { "7" }, "r7" },
- { { "8" }, "r8" },
- { { "9" }, "r9" },
- { { "10" }, "r10" },
- { { "11" }, "r11" },
- { { "12" }, "r12" },
- { { "13" }, "r13" },
- { { "14" }, "r14" },
- { { "15" }, "r15" },
- { { "16" }, "r16" },
- { { "17" }, "r17" },
- { { "18" }, "r18" },
- { { "19" }, "r19" },
- { { "20" }, "r20" },
- { { "21" }, "r21" },
- { { "22" }, "r22" },
- { { "23" }, "r23" },
- { { "24" }, "r24" },
- { { "25" }, "r25" },
- { { "26" }, "r26" },
- { { "27" }, "r27" },
- { { "28" }, "r28" },
- { { "29" }, "r29" },
- { { "30" }, "r30" },
- { { "31" }, "r31" },
- { { "fr0" }, "f0" },
- { { "fr1" }, "f1" },
- { { "fr2" }, "f2" },
- { { "fr3" }, "f3" },
- { { "fr4" }, "f4" },
- { { "fr5" }, "f5" },
- { { "fr6" }, "f6" },
- { { "fr7" }, "f7" },
- { { "fr8" }, "f8" },
- { { "fr9" }, "f9" },
- { { "fr10" }, "f10" },
- { { "fr11" }, "f11" },
- { { "fr12" }, "f12" },
- { { "fr13" }, "f13" },
- { { "fr14" }, "f14" },
- { { "fr15" }, "f15" },
- { { "fr16" }, "f16" },
- { { "fr17" }, "f17" },
- { { "fr18" }, "f18" },
- { { "fr19" }, "f19" },
- { { "fr20" }, "f20" },
- { { "fr21" }, "f21" },
- { { "fr22" }, "f22" },
- { { "fr23" }, "f23" },
- { { "fr24" }, "f24" },
- { { "fr25" }, "f25" },
- { { "fr26" }, "f26" },
- { { "fr27" }, "f27" },
- { { "fr28" }, "f28" },
- { { "fr29" }, "f29" },
- { { "fr30" }, "f30" },
- { { "fr31" }, "f31" },
- { { "cc" }, "cr0" },
-};
-
-ArrayRef<TargetInfo::GCCRegAlias> PPCTargetInfo::getGCCRegAliases() const {
- return llvm::makeArrayRef(GCCRegAliases);
-}
-
-class PPC32TargetInfo : public PPCTargetInfo {
-public:
- PPC32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : PPCTargetInfo(Triple, Opts) {
- resetDataLayout("E-m:e-p:32:32-i64:64-n32");
-
- switch (getTriple().getOS()) {
- case llvm::Triple::Linux:
- case llvm::Triple::FreeBSD:
- case llvm::Triple::NetBSD:
- SizeType = UnsignedInt;
- PtrDiffType = SignedInt;
- IntPtrType = SignedInt;
- break;
- default:
- break;
- }
-
- if (getTriple().getOS() == llvm::Triple::FreeBSD) {
- LongDoubleWidth = LongDoubleAlign = 64;
- LongDoubleFormat = &llvm::APFloat::IEEEdouble();
- }
-
- // PPC32 supports atomics up to 4 bytes.
- MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;
- }
-
- BuiltinVaListKind getBuiltinVaListKind() const override {
- // This is the ELF definition, and is overridden by the Darwin sub-target
- return TargetInfo::PowerABIBuiltinVaList;
- }
-};
-
-// Note: ABI differences may eventually require us to have a separate
-// TargetInfo for little endian.
-class PPC64TargetInfo : public PPCTargetInfo {
-public:
- PPC64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : PPCTargetInfo(Triple, Opts) {
- LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
- IntMaxType = SignedLong;
- Int64Type = SignedLong;
-
- if ((Triple.getArch() == llvm::Triple::ppc64le)) {
- resetDataLayout("e-m:e-i64:64-n32:64");
- ABI = "elfv2";
- } else {
- resetDataLayout("E-m:e-i64:64-n32:64");
- ABI = "elfv1";
- }
-
- switch (getTriple().getOS()) {
- case llvm::Triple::FreeBSD:
- LongDoubleWidth = LongDoubleAlign = 64;
- LongDoubleFormat = &llvm::APFloat::IEEEdouble();
- break;
- case llvm::Triple::NetBSD:
- IntMaxType = SignedLongLong;
- Int64Type = SignedLongLong;
- break;
- default:
- break;
- }
-
- // PPC64 supports atomics up to 8 bytes.
- MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
- }
- BuiltinVaListKind getBuiltinVaListKind() const override {
- return TargetInfo::CharPtrBuiltinVaList;
- }
- // PPC64 Linux-specific ABI options.
- bool setABI(const std::string &Name) override {
- if (Name == "elfv1" || Name == "elfv1-qpx" || Name == "elfv2") {
- ABI = Name;
- return true;
- }
- return false;
- }
-};
-
-class DarwinPPC32TargetInfo : public DarwinTargetInfo<PPC32TargetInfo> {
-public:
- DarwinPPC32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : DarwinTargetInfo<PPC32TargetInfo>(Triple, Opts) {
- HasAlignMac68kSupport = true;
- BoolWidth = BoolAlign = 32; //XXX support -mone-byte-bool?
- PtrDiffType = SignedInt; // for http://llvm.org/bugs/show_bug.cgi?id=15726
- LongLongAlign = 32;
- resetDataLayout("E-m:o-p:32:32-f64:32:64-n32");
- }
- BuiltinVaListKind getBuiltinVaListKind() const override {
- return TargetInfo::CharPtrBuiltinVaList;
- }
-};
-
-class DarwinPPC64TargetInfo : public DarwinTargetInfo<PPC64TargetInfo> {
-public:
- DarwinPPC64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : DarwinTargetInfo<PPC64TargetInfo>(Triple, Opts) {
- HasAlignMac68kSupport = true;
- resetDataLayout("E-m:o-i64:64-n32:64");
- }
-};
-
-static const unsigned NVPTXAddrSpaceMap[] = {
- 0, // Default
- 1, // opencl_global
- 3, // opencl_local
- 4, // opencl_constant
- // FIXME: generic has to be added to the target
- 0, // opencl_generic
- 1, // cuda_device
- 4, // cuda_constant
- 3, // cuda_shared
-};
-
-class NVPTXTargetInfo : public TargetInfo {
- static const char *const GCCRegNames[];
- static const Builtin::Info BuiltinInfo[];
- CudaArch GPU;
- std::unique_ptr<TargetInfo> HostTarget;
-
-public:
- NVPTXTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts,
- unsigned TargetPointerWidth)
- : TargetInfo(Triple) {
- assert((TargetPointerWidth == 32 || TargetPointerWidth == 64) &&
- "NVPTX only supports 32- and 64-bit modes.");
-
- TLSSupported = false;
- AddrSpaceMap = &NVPTXAddrSpaceMap;
- UseAddrSpaceMapMangling = true;
-
- // Define available target features
- // These must be defined in sorted order!
- NoAsmVariants = true;
- GPU = CudaArch::SM_20;
-
- if (TargetPointerWidth == 32)
- resetDataLayout("e-p:32:32-i64:64-v16:16-v32:32-n16:32:64");
- else
- resetDataLayout("e-i64:64-v16:16-v32:32-n16:32:64");
-
- // If possible, get a TargetInfo for our host triple, so we can match its
- // types.
- llvm::Triple HostTriple(Opts.HostTriple);
- if (!HostTriple.isNVPTX())
- HostTarget.reset(AllocateTarget(llvm::Triple(Opts.HostTriple), Opts));
-
- // If no host target, make some guesses about the data layout and return.
- if (!HostTarget) {
- LongWidth = LongAlign = TargetPointerWidth;
- PointerWidth = PointerAlign = TargetPointerWidth;
- switch (TargetPointerWidth) {
- case 32:
- SizeType = TargetInfo::UnsignedInt;
- PtrDiffType = TargetInfo::SignedInt;
- IntPtrType = TargetInfo::SignedInt;
- break;
- case 64:
- SizeType = TargetInfo::UnsignedLong;
- PtrDiffType = TargetInfo::SignedLong;
- IntPtrType = TargetInfo::SignedLong;
- break;
- default:
- llvm_unreachable("TargetPointerWidth must be 32 or 64");
- }
- return;
- }
-
- // Copy properties from host target.
- PointerWidth = HostTarget->getPointerWidth(/* AddrSpace = */ 0);
- PointerAlign = HostTarget->getPointerAlign(/* AddrSpace = */ 0);
- BoolWidth = HostTarget->getBoolWidth();
- BoolAlign = HostTarget->getBoolAlign();
- IntWidth = HostTarget->getIntWidth();
- IntAlign = HostTarget->getIntAlign();
- HalfWidth = HostTarget->getHalfWidth();
- HalfAlign = HostTarget->getHalfAlign();
- FloatWidth = HostTarget->getFloatWidth();
- FloatAlign = HostTarget->getFloatAlign();
- DoubleWidth = HostTarget->getDoubleWidth();
- DoubleAlign = HostTarget->getDoubleAlign();
- LongWidth = HostTarget->getLongWidth();
- LongAlign = HostTarget->getLongAlign();
- LongLongWidth = HostTarget->getLongLongWidth();
- LongLongAlign = HostTarget->getLongLongAlign();
- MinGlobalAlign = HostTarget->getMinGlobalAlign();
- NewAlign = HostTarget->getNewAlign();
- DefaultAlignForAttributeAligned =
- HostTarget->getDefaultAlignForAttributeAligned();
- SizeType = HostTarget->getSizeType();
- IntMaxType = HostTarget->getIntMaxType();
- PtrDiffType = HostTarget->getPtrDiffType(/* AddrSpace = */ 0);
- IntPtrType = HostTarget->getIntPtrType();
- WCharType = HostTarget->getWCharType();
- WIntType = HostTarget->getWIntType();
- Char16Type = HostTarget->getChar16Type();
- Char32Type = HostTarget->getChar32Type();
- Int64Type = HostTarget->getInt64Type();
- SigAtomicType = HostTarget->getSigAtomicType();
- ProcessIDType = HostTarget->getProcessIDType();
-
- UseBitFieldTypeAlignment = HostTarget->useBitFieldTypeAlignment();
- UseZeroLengthBitfieldAlignment =
- HostTarget->useZeroLengthBitfieldAlignment();
- UseExplicitBitFieldAlignment = HostTarget->useExplicitBitFieldAlignment();
- ZeroLengthBitfieldBoundary = HostTarget->getZeroLengthBitfieldBoundary();
-
- // This is a bit of a lie, but it controls __GCC_ATOMIC_XXX_LOCK_FREE, and
- // we need those macros to be identical on host and device, because (among
- // other things) they affect which standard library classes are defined, and
- // we need all classes to be defined on both the host and device.
- MaxAtomicInlineWidth = HostTarget->getMaxAtomicInlineWidth();
-
- // Properties intentionally not copied from host:
- // - LargeArrayMinWidth, LargeArrayAlign: Not visible across the
- // host/device boundary.
- // - SuitableAlign: Not visible across the host/device boundary, and may
- // correctly be different on host/device, e.g. if host has wider vector
- // types than device.
- // - LongDoubleWidth, LongDoubleAlign: nvptx's long double type is the same
- // as its double type, but that's not necessarily true on the host.
- // TODO: nvcc emits a warning when using long double on device; we should
- // do the same.
- }
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- Builder.defineMacro("__PTX__");
- Builder.defineMacro("__NVPTX__");
- if (Opts.CUDAIsDevice) {
- // Set __CUDA_ARCH__ for the GPU specified.
- std::string CUDAArchCode = [this] {
- switch (GPU) {
- case CudaArch::UNKNOWN:
- assert(false && "No GPU arch when compiling CUDA device code.");
- return "";
- case CudaArch::SM_20:
- return "200";
- case CudaArch::SM_21:
- return "210";
- case CudaArch::SM_30:
- return "300";
- case CudaArch::SM_32:
- return "320";
- case CudaArch::SM_35:
- return "350";
- case CudaArch::SM_37:
- return "370";
- case CudaArch::SM_50:
- return "500";
- case CudaArch::SM_52:
- return "520";
- case CudaArch::SM_53:
- return "530";
- case CudaArch::SM_60:
- return "600";
- case CudaArch::SM_61:
- return "610";
- case CudaArch::SM_62:
- return "620";
- }
- llvm_unreachable("unhandled CudaArch");
- }();
- Builder.defineMacro("__CUDA_ARCH__", CUDAArchCode);
- }
- }
- ArrayRef<Builtin::Info> getTargetBuiltins() const override {
- return llvm::makeArrayRef(BuiltinInfo,
- clang::NVPTX::LastTSBuiltin - Builtin::FirstTSBuiltin);
- }
- bool
- initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
- StringRef CPU,
- const std::vector<std::string> &FeaturesVec) const override {
- Features["satom"] = GPU >= CudaArch::SM_60;
- return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
- }
-
- bool hasFeature(StringRef Feature) const override {
- return llvm::StringSwitch<bool>(Feature)
- .Cases("ptx", "nvptx", true)
- .Case("satom", GPU >= CudaArch::SM_60) // Atomics w/ scope.
- .Default(false);
- }
-
- ArrayRef<const char *> getGCCRegNames() const override;
- ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
- // No aliases.
- return None;
- }
- bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &Info) const override {
- switch (*Name) {
- default:
- return false;
- case 'c':
- case 'h':
- case 'r':
- case 'l':
- case 'f':
- case 'd':
- Info.setAllowsRegister();
- return true;
- }
- }
- const char *getClobbers() const override {
- // FIXME: Is this really right?
- return "";
- }
- BuiltinVaListKind getBuiltinVaListKind() const override {
- // FIXME: implement
- return TargetInfo::CharPtrBuiltinVaList;
- }
- bool setCPU(const std::string &Name) override {
- GPU = StringToCudaArch(Name);
- return GPU != CudaArch::UNKNOWN;
- }
- void setSupportedOpenCLOpts() override {
- auto &Opts = getSupportedOpenCLOpts();
- Opts.support("cl_clang_storage_class_specifiers");
- Opts.support("cl_khr_gl_sharing");
- Opts.support("cl_khr_icd");
-
- Opts.support("cl_khr_fp64");
- Opts.support("cl_khr_byte_addressable_store");
- Opts.support("cl_khr_global_int32_base_atomics");
- Opts.support("cl_khr_global_int32_extended_atomics");
- Opts.support("cl_khr_local_int32_base_atomics");
- Opts.support("cl_khr_local_int32_extended_atomics");
- }
-
- CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
- // CUDA compilations support all of the host's calling conventions.
- //
- // TODO: We should warn if you apply a non-default CC to anything other than
- // a host function.
- if (HostTarget)
- return HostTarget->checkCallingConvention(CC);
- return CCCR_Warning;
- }
-};
-
-const Builtin::Info NVPTXTargetInfo::BuiltinInfo[] = {
-#define BUILTIN(ID, TYPE, ATTRS) \
- { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
- { #ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr },
-#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
- { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE },
-#include "clang/Basic/BuiltinsNVPTX.def"
-};
-
-const char *const NVPTXTargetInfo::GCCRegNames[] = {"r0"};
-
-ArrayRef<const char *> NVPTXTargetInfo::getGCCRegNames() const {
- return llvm::makeArrayRef(GCCRegNames);
-}
-
-static const LangAS::Map AMDGPUPrivIsZeroDefIsGenMap = {
- 4, // Default
- 1, // opencl_global
- 3, // opencl_local
- 2, // opencl_constant
- 4, // opencl_generic
- 1, // cuda_device
- 2, // cuda_constant
- 3 // cuda_shared
-};
-static const LangAS::Map AMDGPUGenIsZeroDefIsGenMap = {
- 0, // Default
- 1, // opencl_global
- 3, // opencl_local
- 2, // opencl_constant
- 0, // opencl_generic
- 1, // cuda_device
- 2, // cuda_constant
- 3 // cuda_shared
-};
-static const LangAS::Map AMDGPUPrivIsZeroDefIsPrivMap = {
- 0, // Default
- 1, // opencl_global
- 3, // opencl_local
- 2, // opencl_constant
- 4, // opencl_generic
- 1, // cuda_device
- 2, // cuda_constant
- 3 // cuda_shared
-};
-static const LangAS::Map AMDGPUGenIsZeroDefIsPrivMap = {
- 5, // Default
- 1, // opencl_global
- 3, // opencl_local
- 2, // opencl_constant
- 0, // opencl_generic
- 1, // cuda_device
- 2, // cuda_constant
- 3 // cuda_shared
-};
-
-// If you edit the description strings, make sure you update
-// getPointerWidthV().
-
-static const char *const DataLayoutStringR600 =
- "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128"
- "-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64";
-
-static const char *const DataLayoutStringSIPrivateIsZero =
- "e-p:32:32-p1:64:64-p2:64:64-p3:32:32-p4:64:64-p5:32:32"
- "-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128"
- "-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64";
-
-static const char *const DataLayoutStringSIGenericIsZero =
- "e-p:64:64-p1:64:64-p2:64:64-p3:32:32-p4:32:32-p5:32:32"
- "-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128"
- "-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-A5";
-
-class AMDGPUTargetInfo final : public TargetInfo {
- static const Builtin::Info BuiltinInfo[];
- static const char * const GCCRegNames[];
-
- struct AddrSpace {
- unsigned Generic, Global, Local, Constant, Private;
- AddrSpace(bool IsGenericZero_ = false){
- if (IsGenericZero_) {
- Generic = 0;
- Global = 1;
- Local = 3;
- Constant = 2;
- Private = 5;
- } else {
- Generic = 4;
- Global = 1;
- Local = 3;
- Constant = 2;
- Private = 0;
- }
- }
- };
-
- /// \brief The GPU profiles supported by the AMDGPU target.
- enum GPUKind {
- GK_NONE,
- GK_R600,
- GK_R600_DOUBLE_OPS,
- GK_R700,
- GK_R700_DOUBLE_OPS,
- GK_EVERGREEN,
- GK_EVERGREEN_DOUBLE_OPS,
- GK_NORTHERN_ISLANDS,
- GK_CAYMAN,
- GK_GFX6,
- GK_GFX7,
- GK_GFX8,
- GK_GFX9
- } GPU;
-
- bool hasFP64:1;
- bool hasFMAF:1;
- bool hasLDEXPF:1;
- const AddrSpace AS;
-
- static bool hasFullSpeedFMAF32(StringRef GPUName) {
- return parseAMDGCNName(GPUName) >= GK_GFX9;
- }
-
- static bool isAMDGCN(const llvm::Triple &TT) {
- return TT.getArch() == llvm::Triple::amdgcn;
- }
-
- static bool isGenericZero(const llvm::Triple &TT) {
- return TT.getEnvironmentName() == "amdgiz" ||
- TT.getEnvironmentName() == "amdgizcl";
- }
-public:
- AMDGPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : TargetInfo(Triple) ,
- GPU(isAMDGCN(Triple) ? GK_GFX6 : parseR600Name(Opts.CPU)),
- hasFP64(false),
- hasFMAF(false),
- hasLDEXPF(false),
- AS(isGenericZero(Triple)){
- if (getTriple().getArch() == llvm::Triple::amdgcn) {
- hasFP64 = true;
- hasFMAF = true;
- hasLDEXPF = true;
- }
- if (getTriple().getArch() == llvm::Triple::r600) {
- if (GPU == GK_EVERGREEN_DOUBLE_OPS || GPU == GK_CAYMAN) {
- hasFMAF = true;
- }
- }
-
- auto IsGenericZero = isGenericZero(Triple);
- resetDataLayout(getTriple().getArch() == llvm::Triple::amdgcn ?
- (IsGenericZero ? DataLayoutStringSIGenericIsZero :
- DataLayoutStringSIPrivateIsZero)
- : DataLayoutStringR600);
- assert(DataLayout->getAllocaAddrSpace() == AS.Private);
-
- setAddressSpaceMap(Triple.getOS() == llvm::Triple::Mesa3D ||
- Triple.getEnvironment() == llvm::Triple::OpenCL ||
- Triple.getEnvironmentName() == "amdgizcl" ||
- !isAMDGCN(Triple));
- UseAddrSpaceMapMangling = true;
-
- // Set pointer width and alignment for target address space 0.
- PointerWidth = PointerAlign = DataLayout->getPointerSizeInBits();
- if (getMaxPointerWidth() == 64) {
- LongWidth = LongAlign = 64;
- SizeType = UnsignedLong;
- PtrDiffType = SignedLong;
- IntPtrType = SignedLong;
- }
- }
-
- void setAddressSpaceMap(bool DefaultIsPrivate) {
- if (isGenericZero(getTriple())) {
- AddrSpaceMap = DefaultIsPrivate ? &AMDGPUGenIsZeroDefIsPrivMap
- : &AMDGPUGenIsZeroDefIsGenMap;
- } else {
- AddrSpaceMap = DefaultIsPrivate ? &AMDGPUPrivIsZeroDefIsPrivMap
- : &AMDGPUPrivIsZeroDefIsGenMap;
- }
- }
-
- void adjust(LangOptions &Opts) override {
- TargetInfo::adjust(Opts);
- setAddressSpaceMap(Opts.OpenCL || !isAMDGCN(getTriple()));
- }
-
- uint64_t getPointerWidthV(unsigned AddrSpace) const override {
- if (GPU <= GK_CAYMAN)
- return 32;
-
- if (AddrSpace == AS.Private || AddrSpace == AS.Local) {
- return 32;
- }
- return 64;
- }
-
- uint64_t getPointerAlignV(unsigned AddrSpace) const override {
- return getPointerWidthV(AddrSpace);
- }
-
- uint64_t getMaxPointerWidth() const override {
- return getTriple().getArch() == llvm::Triple::amdgcn ? 64 : 32;
- }
-
- const char * getClobbers() const override {
- return "";
- }
-
- ArrayRef<const char *> getGCCRegNames() const override;
-
- ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
- return None;
- }
-
- bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &Info) const override {
- switch (*Name) {
- default: break;
- case 'v': // vgpr
- case 's': // sgpr
- Info.setAllowsRegister();
- return true;
- }
- return false;
- }
-
- bool initFeatureMap(llvm::StringMap<bool> &Features,
- DiagnosticsEngine &Diags, StringRef CPU,
- const std::vector<std::string> &FeatureVec) const override;
-
- void adjustTargetOptions(const CodeGenOptions &CGOpts,
- TargetOptions &TargetOpts) const override {
- bool hasFP32Denormals = false;
- bool hasFP64Denormals = false;
- for (auto &I : TargetOpts.FeaturesAsWritten) {
- if (I == "+fp32-denormals" || I == "-fp32-denormals")
- hasFP32Denormals = true;
- if (I == "+fp64-fp16-denormals" || I == "-fp64-fp16-denormals")
- hasFP64Denormals = true;
- }
- if (!hasFP32Denormals)
- TargetOpts.Features.push_back(
- (Twine(hasFullSpeedFMAF32(TargetOpts.CPU) &&
- !CGOpts.FlushDenorm ? '+' : '-') + Twine("fp32-denormals")).str());
- // Always do not flush fp64 or fp16 denorms.
- if (!hasFP64Denormals && hasFP64)
- TargetOpts.Features.push_back("+fp64-fp16-denormals");
- }
-
- ArrayRef<Builtin::Info> getTargetBuiltins() const override {
- return llvm::makeArrayRef(BuiltinInfo,
- clang::AMDGPU::LastTSBuiltin - Builtin::FirstTSBuiltin);
- }
-
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- if (getTriple().getArch() == llvm::Triple::amdgcn)
- Builder.defineMacro("__AMDGCN__");
- else
- Builder.defineMacro("__R600__");
-
- if (hasFMAF)
- Builder.defineMacro("__HAS_FMAF__");
- if (hasLDEXPF)
- Builder.defineMacro("__HAS_LDEXPF__");
- if (hasFP64)
- Builder.defineMacro("__HAS_FP64__");
- }
-
- BuiltinVaListKind getBuiltinVaListKind() const override {
- return TargetInfo::CharPtrBuiltinVaList;
- }
-
- static GPUKind parseR600Name(StringRef Name) {
- return llvm::StringSwitch<GPUKind>(Name)
- .Case("r600" , GK_R600)
- .Case("rv610", GK_R600)
- .Case("rv620", GK_R600)
- .Case("rv630", GK_R600)
- .Case("rv635", GK_R600)
- .Case("rs780", GK_R600)
- .Case("rs880", GK_R600)
- .Case("rv670", GK_R600_DOUBLE_OPS)
- .Case("rv710", GK_R700)
- .Case("rv730", GK_R700)
- .Case("rv740", GK_R700_DOUBLE_OPS)
- .Case("rv770", GK_R700_DOUBLE_OPS)
- .Case("palm", GK_EVERGREEN)
- .Case("cedar", GK_EVERGREEN)
- .Case("sumo", GK_EVERGREEN)
- .Case("sumo2", GK_EVERGREEN)
- .Case("redwood", GK_EVERGREEN)
- .Case("juniper", GK_EVERGREEN)
- .Case("hemlock", GK_EVERGREEN_DOUBLE_OPS)
- .Case("cypress", GK_EVERGREEN_DOUBLE_OPS)
- .Case("barts", GK_NORTHERN_ISLANDS)
- .Case("turks", GK_NORTHERN_ISLANDS)
- .Case("caicos", GK_NORTHERN_ISLANDS)
- .Case("cayman", GK_CAYMAN)
- .Case("aruba", GK_CAYMAN)
- .Default(GK_NONE);
- }
-
- static GPUKind parseAMDGCNName(StringRef Name) {
- return llvm::StringSwitch<GPUKind>(Name)
- .Case("tahiti", GK_GFX6)
- .Case("pitcairn", GK_GFX6)
- .Case("verde", GK_GFX6)
- .Case("oland", GK_GFX6)
- .Case("hainan", GK_GFX6)
- .Case("bonaire", GK_GFX7)
- .Case("kabini", GK_GFX7)
- .Case("kaveri", GK_GFX7)
- .Case("hawaii", GK_GFX7)
- .Case("mullins", GK_GFX7)
- .Case("gfx700", GK_GFX7)
- .Case("gfx701", GK_GFX7)
- .Case("gfx702", GK_GFX7)
- .Case("tonga", GK_GFX8)
- .Case("iceland", GK_GFX8)
- .Case("carrizo", GK_GFX8)
- .Case("fiji", GK_GFX8)
- .Case("stoney", GK_GFX8)
- .Case("polaris10", GK_GFX8)
- .Case("polaris11", GK_GFX8)
- .Case("gfx800", GK_GFX8)
- .Case("gfx801", GK_GFX8)
- .Case("gfx802", GK_GFX8)
- .Case("gfx803", GK_GFX8)
- .Case("gfx804", GK_GFX8)
- .Case("gfx810", GK_GFX8)
- .Case("gfx900", GK_GFX9)
- .Case("gfx901", GK_GFX9)
- .Default(GK_NONE);
- }
-
- bool setCPU(const std::string &Name) override {
- if (getTriple().getArch() == llvm::Triple::amdgcn)
- GPU = parseAMDGCNName(Name);
- else
- GPU = parseR600Name(Name);
-
- return GPU != GK_NONE;
- }
-
- void setSupportedOpenCLOpts() override {
- auto &Opts = getSupportedOpenCLOpts();
- Opts.support("cl_clang_storage_class_specifiers");
- Opts.support("cl_khr_icd");
-
- if (hasFP64)
- Opts.support("cl_khr_fp64");
- if (GPU >= GK_EVERGREEN) {
- Opts.support("cl_khr_byte_addressable_store");
- Opts.support("cl_khr_global_int32_base_atomics");
- Opts.support("cl_khr_global_int32_extended_atomics");
- Opts.support("cl_khr_local_int32_base_atomics");
- Opts.support("cl_khr_local_int32_extended_atomics");
- }
- if (GPU >= GK_GFX6) {
- Opts.support("cl_khr_fp16");
- Opts.support("cl_khr_int64_base_atomics");
- Opts.support("cl_khr_int64_extended_atomics");
- Opts.support("cl_khr_mipmap_image");
- Opts.support("cl_khr_subgroups");
- Opts.support("cl_khr_3d_image_writes");
- Opts.support("cl_amd_media_ops");
- Opts.support("cl_amd_media_ops2");
- }
- }
-
- LangAS::ID getOpenCLImageAddrSpace() const override {
- return LangAS::opencl_constant;
- }
-
- llvm::Optional<unsigned> getConstantAddressSpace() const override {
- return LangAS::FirstTargetAddressSpace + AS.Constant;
- }
-
- /// \returns Target specific vtbl ptr address space.
- unsigned getVtblPtrAddressSpace() const override { return AS.Constant; }
-
- /// \returns If a target requires an address within a target specific address
- /// space \p AddressSpace to be converted in order to be used, then return the
- /// corresponding target specific DWARF address space.
- ///
- /// \returns Otherwise return None and no conversion will be emitted in the
- /// DWARF.
- Optional<unsigned> getDWARFAddressSpace(
- unsigned AddressSpace) const override {
- const unsigned DWARF_Private = 1;
- const unsigned DWARF_Local = 2;
- if (AddressSpace == AS.Private) {
- return DWARF_Private;
- } else if (AddressSpace == AS.Local) {
- return DWARF_Local;
- } else {
- return None;
- }
- }
-
- CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
- switch (CC) {
- default:
- return CCCR_Warning;
- case CC_C:
- case CC_OpenCLKernel:
- return CCCR_OK;
- }
- }
-
- // In amdgcn target the null pointer in global, constant, and generic
- // address space has value 0 but in private and local address space has
- // value ~0.
- uint64_t getNullPointerValue(unsigned AS) const override {
- return AS == LangAS::opencl_local ? ~0 : 0;
- }
-};
-
-const Builtin::Info AMDGPUTargetInfo::BuiltinInfo[] = {
-#define BUILTIN(ID, TYPE, ATTRS) \
- { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
-#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
- { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE },
-#include "clang/Basic/BuiltinsAMDGPU.def"
-};
-const char * const AMDGPUTargetInfo::GCCRegNames[] = {
- "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
- "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
- "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
- "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
- "v32", "v33", "v34", "v35", "v36", "v37", "v38", "v39",
- "v40", "v41", "v42", "v43", "v44", "v45", "v46", "v47",
- "v48", "v49", "v50", "v51", "v52", "v53", "v54", "v55",
- "v56", "v57", "v58", "v59", "v60", "v61", "v62", "v63",
- "v64", "v65", "v66", "v67", "v68", "v69", "v70", "v71",
- "v72", "v73", "v74", "v75", "v76", "v77", "v78", "v79",
- "v80", "v81", "v82", "v83", "v84", "v85", "v86", "v87",
- "v88", "v89", "v90", "v91", "v92", "v93", "v94", "v95",
- "v96", "v97", "v98", "v99", "v100", "v101", "v102", "v103",
- "v104", "v105", "v106", "v107", "v108", "v109", "v110", "v111",
- "v112", "v113", "v114", "v115", "v116", "v117", "v118", "v119",
- "v120", "v121", "v122", "v123", "v124", "v125", "v126", "v127",
- "v128", "v129", "v130", "v131", "v132", "v133", "v134", "v135",
- "v136", "v137", "v138", "v139", "v140", "v141", "v142", "v143",
- "v144", "v145", "v146", "v147", "v148", "v149", "v150", "v151",
- "v152", "v153", "v154", "v155", "v156", "v157", "v158", "v159",
- "v160", "v161", "v162", "v163", "v164", "v165", "v166", "v167",
- "v168", "v169", "v170", "v171", "v172", "v173", "v174", "v175",
- "v176", "v177", "v178", "v179", "v180", "v181", "v182", "v183",
- "v184", "v185", "v186", "v187", "v188", "v189", "v190", "v191",
- "v192", "v193", "v194", "v195", "v196", "v197", "v198", "v199",
- "v200", "v201", "v202", "v203", "v204", "v205", "v206", "v207",
- "v208", "v209", "v210", "v211", "v212", "v213", "v214", "v215",
- "v216", "v217", "v218", "v219", "v220", "v221", "v222", "v223",
- "v224", "v225", "v226", "v227", "v228", "v229", "v230", "v231",
- "v232", "v233", "v234", "v235", "v236", "v237", "v238", "v239",
- "v240", "v241", "v242", "v243", "v244", "v245", "v246", "v247",
- "v248", "v249", "v250", "v251", "v252", "v253", "v254", "v255",
- "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
- "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15",
- "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
- "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
- "s32", "s33", "s34", "s35", "s36", "s37", "s38", "s39",
- "s40", "s41", "s42", "s43", "s44", "s45", "s46", "s47",
- "s48", "s49", "s50", "s51", "s52", "s53", "s54", "s55",
- "s56", "s57", "s58", "s59", "s60", "s61", "s62", "s63",
- "s64", "s65", "s66", "s67", "s68", "s69", "s70", "s71",
- "s72", "s73", "s74", "s75", "s76", "s77", "s78", "s79",
- "s80", "s81", "s82", "s83", "s84", "s85", "s86", "s87",
- "s88", "s89", "s90", "s91", "s92", "s93", "s94", "s95",
- "s96", "s97", "s98", "s99", "s100", "s101", "s102", "s103",
- "s104", "s105", "s106", "s107", "s108", "s109", "s110", "s111",
- "s112", "s113", "s114", "s115", "s116", "s117", "s118", "s119",
- "s120", "s121", "s122", "s123", "s124", "s125", "s126", "s127",
- "exec", "vcc", "scc", "m0", "flat_scratch", "exec_lo", "exec_hi",
- "vcc_lo", "vcc_hi", "flat_scratch_lo", "flat_scratch_hi"
-};
-
-ArrayRef<const char *> AMDGPUTargetInfo::getGCCRegNames() const {
- return llvm::makeArrayRef(GCCRegNames);
-}
-
-bool AMDGPUTargetInfo::initFeatureMap(
- llvm::StringMap<bool> &Features,
- DiagnosticsEngine &Diags, StringRef CPU,
- const std::vector<std::string> &FeatureVec) const {
-
- // XXX - What does the member GPU mean if device name string passed here?
- if (getTriple().getArch() == llvm::Triple::amdgcn) {
- if (CPU.empty())
- CPU = "tahiti";
-
- switch (parseAMDGCNName(CPU)) {
- case GK_GFX6:
- case GK_GFX7:
- break;
-
- case GK_GFX9:
- Features["gfx9-insts"] = true;
- LLVM_FALLTHROUGH;
- case GK_GFX8:
- Features["s-memrealtime"] = true;
- Features["16-bit-insts"] = true;
- Features["dpp"] = true;
- break;
-
- case GK_NONE:
- return false;
- default:
- llvm_unreachable("unhandled subtarget");
- }
- } else {
- if (CPU.empty())
- CPU = "r600";
-
- switch (parseR600Name(CPU)) {
- case GK_R600:
- case GK_R700:
- case GK_EVERGREEN:
- case GK_NORTHERN_ISLANDS:
- break;
- case GK_R600_DOUBLE_OPS:
- case GK_R700_DOUBLE_OPS:
- case GK_EVERGREEN_DOUBLE_OPS:
- case GK_CAYMAN:
- Features["fp64"] = true;
- break;
- case GK_NONE:
- return false;
- default:
- llvm_unreachable("unhandled subtarget");
- }
- }
-
- return TargetInfo::initFeatureMap(Features, Diags, CPU, FeatureVec);
-}
-
-const Builtin::Info BuiltinInfoX86[] = {
-#define BUILTIN(ID, TYPE, ATTRS) \
- { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
-#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
- { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE },
-#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \
- { #ID, TYPE, ATTRS, HEADER, LANGS, FEATURE },
-#include "clang/Basic/BuiltinsX86.def"
-
-#define BUILTIN(ID, TYPE, ATTRS) \
- { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
-#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
- { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE },
-#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \
- { #ID, TYPE, ATTRS, HEADER, LANGS, FEATURE },
-#include "clang/Basic/BuiltinsX86_64.def"
-};
-
-
-static const char* const GCCRegNames[] = {
- "ax", "dx", "cx", "bx", "si", "di", "bp", "sp",
- "st", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)",
- "argp", "flags", "fpcr", "fpsr", "dirflag", "frame",
- "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
- "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
- "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15",
- "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7",
- "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15",
- "xmm16", "xmm17", "xmm18", "xmm19", "xmm20", "xmm21", "xmm22", "xmm23",
- "xmm24", "xmm25", "xmm26", "xmm27", "xmm28", "xmm29", "xmm30", "xmm31",
- "ymm16", "ymm17", "ymm18", "ymm19", "ymm20", "ymm21", "ymm22", "ymm23",
- "ymm24", "ymm25", "ymm26", "ymm27", "ymm28", "ymm29", "ymm30", "ymm31",
- "zmm0", "zmm1", "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7",
- "zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15",
- "zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23",
- "zmm24", "zmm25", "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31",
- "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7",
-};
-
-const TargetInfo::AddlRegName AddlRegNames[] = {
- { { "al", "ah", "eax", "rax" }, 0 },
- { { "bl", "bh", "ebx", "rbx" }, 3 },
- { { "cl", "ch", "ecx", "rcx" }, 2 },
- { { "dl", "dh", "edx", "rdx" }, 1 },
- { { "esi", "rsi" }, 4 },
- { { "edi", "rdi" }, 5 },
- { { "esp", "rsp" }, 7 },
- { { "ebp", "rbp" }, 6 },
- { { "r8d", "r8w", "r8b" }, 38 },
- { { "r9d", "r9w", "r9b" }, 39 },
- { { "r10d", "r10w", "r10b" }, 40 },
- { { "r11d", "r11w", "r11b" }, 41 },
- { { "r12d", "r12w", "r12b" }, 42 },
- { { "r13d", "r13w", "r13b" }, 43 },
- { { "r14d", "r14w", "r14b" }, 44 },
- { { "r15d", "r15w", "r15b" }, 45 },
-};
-
-// X86 target abstract base class; x86-32 and x86-64 are very close, so
-// most of the implementation can be shared.
-class X86TargetInfo : public TargetInfo {
- enum X86SSEEnum {
- NoSSE, SSE1, SSE2, SSE3, SSSE3, SSE41, SSE42, AVX, AVX2, AVX512F
- } SSELevel = NoSSE;
- enum MMX3DNowEnum {
- NoMMX3DNow, MMX, AMD3DNow, AMD3DNowAthlon
- } MMX3DNowLevel = NoMMX3DNow;
- enum XOPEnum {
- NoXOP,
- SSE4A,
- FMA4,
- XOP
- } XOPLevel = NoXOP;
-
- bool HasAES = false;
- bool HasPCLMUL = false;
- bool HasLZCNT = false;
- bool HasRDRND = false;
- bool HasFSGSBASE = false;
- bool HasBMI = false;
- bool HasBMI2 = false;
- bool HasPOPCNT = false;
- bool HasRTM = false;
- bool HasPRFCHW = false;
- bool HasRDSEED = false;
- bool HasADX = false;
- bool HasTBM = false;
- bool HasLWP = false;
- bool HasFMA = false;
- bool HasF16C = false;
- bool HasAVX512CD = false;
- bool HasAVX512VPOPCNTDQ = false;
- bool HasAVX512ER = false;
- bool HasAVX512PF = false;
- bool HasAVX512DQ = false;
- bool HasAVX512BW = false;
- bool HasAVX512VL = false;
- bool HasAVX512VBMI = false;
- bool HasAVX512IFMA = false;
- bool HasSHA = false;
- bool HasMPX = false;
- bool HasSGX = false;
- bool HasCX16 = false;
- bool HasFXSR = false;
- bool HasXSAVE = false;
- bool HasXSAVEOPT = false;
- bool HasXSAVEC = false;
- bool HasXSAVES = false;
- bool HasMWAITX = false;
- bool HasCLZERO = false;
- bool HasPKU = false;
- bool HasCLFLUSHOPT = false;
- bool HasCLWB = false;
- bool HasMOVBE = false;
- bool HasPREFETCHWT1 = false;
-
- /// \brief Enumeration of all of the X86 CPUs supported by Clang.
- ///
- /// Each enumeration represents a particular CPU supported by Clang. These
- /// loosely correspond to the options passed to '-march' or '-mtune' flags.
- enum CPUKind {
- CK_Generic,
-
- /// \name i386
- /// i386-generation processors.
- //@{
- CK_i386,
- //@}
-
- /// \name i486
- /// i486-generation processors.
- //@{
- CK_i486,
- CK_WinChipC6,
- CK_WinChip2,
- CK_C3,
- //@}
-
- /// \name i586
- /// i586-generation processors, P5 microarchitecture based.
- //@{
- CK_i586,
- CK_Pentium,
- CK_PentiumMMX,
- //@}
-
- /// \name i686
- /// i686-generation processors, P6 / Pentium M microarchitecture based.
- //@{
- CK_i686,
- CK_PentiumPro,
- CK_Pentium2,
- CK_Pentium3,
- CK_Pentium3M,
- CK_PentiumM,
- CK_C3_2,
-
- /// This enumerator is a bit odd, as GCC no longer accepts -march=yonah.
- /// Clang however has some logic to support this.
- // FIXME: Warn, deprecate, and potentially remove this.
- CK_Yonah,
- //@}
-
- /// \name Netburst
- /// Netburst microarchitecture based processors.
- //@{
- CK_Pentium4,
- CK_Pentium4M,
- CK_Prescott,
- CK_Nocona,
- //@}
-
- /// \name Core
- /// Core microarchitecture based processors.
- //@{
- CK_Core2,
-
- /// This enumerator, like \see CK_Yonah, is a bit odd. It is another
- /// codename which GCC no longer accepts as an option to -march, but Clang
- /// has some logic for recognizing it.
- // FIXME: Warn, deprecate, and potentially remove this.
- CK_Penryn,
- //@}
-
- /// \name Atom
- /// Atom processors
- //@{
- CK_Bonnell,
- CK_Silvermont,
- CK_Goldmont,
- //@}
-
- /// \name Nehalem
- /// Nehalem microarchitecture based processors.
- CK_Nehalem,
-
- /// \name Westmere
- /// Westmere microarchitecture based processors.
- CK_Westmere,
-
- /// \name Sandy Bridge
- /// Sandy Bridge microarchitecture based processors.
- CK_SandyBridge,
-
- /// \name Ivy Bridge
- /// Ivy Bridge microarchitecture based processors.
- CK_IvyBridge,
-
- /// \name Haswell
- /// Haswell microarchitecture based processors.
- CK_Haswell,
-
- /// \name Broadwell
- /// Broadwell microarchitecture based processors.
- CK_Broadwell,
-
- /// \name Skylake Client
- /// Skylake client microarchitecture based processors.
- CK_SkylakeClient,
-
- /// \name Skylake Server
- /// Skylake server microarchitecture based processors.
- CK_SkylakeServer,
-
- /// \name Cannonlake Client
- /// Cannonlake client microarchitecture based processors.
- CK_Cannonlake,
-
- /// \name Knights Landing
- /// Knights Landing processor.
- CK_KNL,
-
- /// \name Lakemont
- /// Lakemont microarchitecture based processors.
- CK_Lakemont,
-
- /// \name K6
- /// K6 architecture processors.
- //@{
- CK_K6,
- CK_K6_2,
- CK_K6_3,
- //@}
-
- /// \name K7
- /// K7 architecture processors.
- //@{
- CK_Athlon,
- CK_AthlonThunderbird,
- CK_Athlon4,
- CK_AthlonXP,
- CK_AthlonMP,
- //@}
-
- /// \name K8
- /// K8 architecture processors.
- //@{
- CK_Athlon64,
- CK_Athlon64SSE3,
- CK_AthlonFX,
- CK_K8,
- CK_K8SSE3,
- CK_Opteron,
- CK_OpteronSSE3,
- CK_AMDFAM10,
- //@}
-
- /// \name Bobcat
- /// Bobcat architecture processors.
- //@{
- CK_BTVER1,
- CK_BTVER2,
- //@}
-
- /// \name Bulldozer
- /// Bulldozer architecture processors.
- //@{
- CK_BDVER1,
- CK_BDVER2,
- CK_BDVER3,
- CK_BDVER4,
- //@}
-
- /// \name zen
- /// Zen architecture processors.
- //@{
- CK_ZNVER1,
- //@}
-
- /// This specification is deprecated and will be removed in the future.
- /// Users should prefer \see CK_K8.
- // FIXME: Warn on this when the CPU is set to it.
- //@{
- CK_x86_64,
- //@}
-
- /// \name Geode
- /// Geode processors.
- //@{
- CK_Geode
- //@}
- } CPU = CK_Generic;
-
- CPUKind getCPUKind(StringRef CPU) const {
- return llvm::StringSwitch<CPUKind>(CPU)
- .Case("i386", CK_i386)
- .Case("i486", CK_i486)
- .Case("winchip-c6", CK_WinChipC6)
- .Case("winchip2", CK_WinChip2)
- .Case("c3", CK_C3)
- .Case("i586", CK_i586)
- .Case("pentium", CK_Pentium)
- .Case("pentium-mmx", CK_PentiumMMX)
- .Case("i686", CK_i686)
- .Case("pentiumpro", CK_PentiumPro)
- .Case("pentium2", CK_Pentium2)
- .Case("pentium3", CK_Pentium3)
- .Case("pentium3m", CK_Pentium3M)
- .Case("pentium-m", CK_PentiumM)
- .Case("c3-2", CK_C3_2)
- .Case("yonah", CK_Yonah)
- .Case("pentium4", CK_Pentium4)
- .Case("pentium4m", CK_Pentium4M)
- .Case("prescott", CK_Prescott)
- .Case("nocona", CK_Nocona)
- .Case("core2", CK_Core2)
- .Case("penryn", CK_Penryn)
- .Case("bonnell", CK_Bonnell)
- .Case("atom", CK_Bonnell) // Legacy name.
- .Case("silvermont", CK_Silvermont)
- .Case("slm", CK_Silvermont) // Legacy name.
- .Case("goldmont", CK_Goldmont)
- .Case("nehalem", CK_Nehalem)
- .Case("corei7", CK_Nehalem) // Legacy name.
- .Case("westmere", CK_Westmere)
- .Case("sandybridge", CK_SandyBridge)
- .Case("corei7-avx", CK_SandyBridge) // Legacy name.
- .Case("ivybridge", CK_IvyBridge)
- .Case("core-avx-i", CK_IvyBridge) // Legacy name.
- .Case("haswell", CK_Haswell)
- .Case("core-avx2", CK_Haswell) // Legacy name.
- .Case("broadwell", CK_Broadwell)
- .Case("skylake", CK_SkylakeClient)
- .Case("skylake-avx512", CK_SkylakeServer)
- .Case("skx", CK_SkylakeServer) // Legacy name.
- .Case("cannonlake", CK_Cannonlake)
- .Case("knl", CK_KNL)
- .Case("lakemont", CK_Lakemont)
- .Case("k6", CK_K6)
- .Case("k6-2", CK_K6_2)
- .Case("k6-3", CK_K6_3)
- .Case("athlon", CK_Athlon)
- .Case("athlon-tbird", CK_AthlonThunderbird)
- .Case("athlon-4", CK_Athlon4)
- .Case("athlon-xp", CK_AthlonXP)
- .Case("athlon-mp", CK_AthlonMP)
- .Case("athlon64", CK_Athlon64)
- .Case("athlon64-sse3", CK_Athlon64SSE3)
- .Case("athlon-fx", CK_AthlonFX)
- .Case("k8", CK_K8)
- .Case("k8-sse3", CK_K8SSE3)
- .Case("opteron", CK_Opteron)
- .Case("opteron-sse3", CK_OpteronSSE3)
- .Case("barcelona", CK_AMDFAM10)
- .Case("amdfam10", CK_AMDFAM10)
- .Case("btver1", CK_BTVER1)
- .Case("btver2", CK_BTVER2)
- .Case("bdver1", CK_BDVER1)
- .Case("bdver2", CK_BDVER2)
- .Case("bdver3", CK_BDVER3)
- .Case("bdver4", CK_BDVER4)
- .Case("znver1", CK_ZNVER1)
- .Case("x86-64", CK_x86_64)
- .Case("geode", CK_Geode)
- .Default(CK_Generic);
- }
-
- enum FPMathKind {
- FP_Default,
- FP_SSE,
- FP_387
- } FPMath = FP_Default;
-
-public:
- X86TargetInfo(const llvm::Triple &Triple, const TargetOptions &)
- : TargetInfo(Triple) {
- LongDoubleFormat = &llvm::APFloat::x87DoubleExtended();
- }
- unsigned getFloatEvalMethod() const override {
- // X87 evaluates with 80 bits "long double" precision.
- return SSELevel == NoSSE ? 2 : 0;
- }
- ArrayRef<const char *> getGCCRegNames() const override {
- return llvm::makeArrayRef(GCCRegNames);
- }
- ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
- return None;
- }
- ArrayRef<TargetInfo::AddlRegName> getGCCAddlRegNames() const override {
- return llvm::makeArrayRef(AddlRegNames);
- }
- bool validateCpuSupports(StringRef Name) const override;
- bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &info) const override;
-
- bool validateGlobalRegisterVariable(StringRef RegName,
- unsigned RegSize,
- bool &HasSizeMismatch) const override {
- // esp and ebp are the only 32-bit registers the x86 backend can currently
- // handle.
- if (RegName.equals("esp") || RegName.equals("ebp")) {
- // Check that the register size is 32-bit.
- HasSizeMismatch = RegSize != 32;
- return true;
- }
-
- return false;
- }
-
- bool validateOutputSize(StringRef Constraint, unsigned Size) const override;
-
- bool validateInputSize(StringRef Constraint, unsigned Size) const override;
-
- virtual bool validateOperandSize(StringRef Constraint, unsigned Size) const;
-
- std::string convertConstraint(const char *&Constraint) const override;
- const char *getClobbers() const override {
- return "~{dirflag},~{fpsr},~{flags}";
- }
-
- StringRef getConstraintRegister(const StringRef &Constraint,
- const StringRef &Expression) const override {
- StringRef::iterator I, E;
- for (I = Constraint.begin(), E = Constraint.end(); I != E; ++I) {
- if (isalpha(*I))
- break;
- }
- if (I == E)
- return "";
- switch (*I) {
- // For the register constraints, return the matching register name
- case 'a':
- return "ax";
- case 'b':
- return "bx";
- case 'c':
- return "cx";
- case 'd':
- return "dx";
- case 'S':
- return "si";
- case 'D':
- return "di";
- // In case the constraint is 'r' we need to return Expression
- case 'r':
- return Expression;
- default:
- // Default value if there is no constraint for the register
- return "";
- }
- return "";
- }
-
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override;
- static void setSSELevel(llvm::StringMap<bool> &Features, X86SSEEnum Level,
- bool Enabled);
- static void setMMXLevel(llvm::StringMap<bool> &Features, MMX3DNowEnum Level,
- bool Enabled);
- static void setXOPLevel(llvm::StringMap<bool> &Features, XOPEnum Level,
- bool Enabled);
- void setFeatureEnabled(llvm::StringMap<bool> &Features,
- StringRef Name, bool Enabled) const override {
- setFeatureEnabledImpl(Features, Name, Enabled);
- }
- // This exists purely to cut down on the number of virtual calls in
- // initFeatureMap which calls this repeatedly.
- static void setFeatureEnabledImpl(llvm::StringMap<bool> &Features,
- StringRef Name, bool Enabled);
- bool
- initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
- StringRef CPU,
- const std::vector<std::string> &FeaturesVec) const override;
- bool hasFeature(StringRef Feature) const override;
- bool handleTargetFeatures(std::vector<std::string> &Features,
- DiagnosticsEngine &Diags) override;
- StringRef getABI() const override {
- if (getTriple().getArch() == llvm::Triple::x86_64 && SSELevel >= AVX512F)
- return "avx512";
- if (getTriple().getArch() == llvm::Triple::x86_64 && SSELevel >= AVX)
- return "avx";
- if (getTriple().getArch() == llvm::Triple::x86 &&
- MMX3DNowLevel == NoMMX3DNow)
- return "no-mmx";
- return "";
- }
- bool setCPU(const std::string &Name) override {
- CPU = getCPUKind(Name);
-
- // Perform any per-CPU checks necessary to determine if this CPU is
- // acceptable.
- // FIXME: This results in terrible diagnostics. Clang just says the CPU is
- // invalid without explaining *why*.
- switch (CPU) {
- case CK_Generic:
- // No processor selected!
- return false;
-
- case CK_i386:
- case CK_i486:
- case CK_WinChipC6:
- case CK_WinChip2:
- case CK_C3:
- case CK_i586:
- case CK_Pentium:
- case CK_PentiumMMX:
- case CK_i686:
- case CK_PentiumPro:
- case CK_Pentium2:
- case CK_Pentium3:
- case CK_Pentium3M:
- case CK_PentiumM:
- case CK_Yonah:
- case CK_C3_2:
- case CK_Pentium4:
- case CK_Pentium4M:
- case CK_Lakemont:
- case CK_Prescott:
- case CK_K6:
- case CK_K6_2:
- case CK_K6_3:
- case CK_Athlon:
- case CK_AthlonThunderbird:
- case CK_Athlon4:
- case CK_AthlonXP:
- case CK_AthlonMP:
- case CK_Geode:
- // Only accept certain architectures when compiling in 32-bit mode.
- if (getTriple().getArch() != llvm::Triple::x86)
- return false;
-
- // Fallthrough
- case CK_Nocona:
- case CK_Core2:
- case CK_Penryn:
- case CK_Bonnell:
- case CK_Silvermont:
- case CK_Goldmont:
- case CK_Nehalem:
- case CK_Westmere:
- case CK_SandyBridge:
- case CK_IvyBridge:
- case CK_Haswell:
- case CK_Broadwell:
- case CK_SkylakeClient:
- case CK_SkylakeServer:
- case CK_Cannonlake:
- case CK_KNL:
- case CK_Athlon64:
- case CK_Athlon64SSE3:
- case CK_AthlonFX:
- case CK_K8:
- case CK_K8SSE3:
- case CK_Opteron:
- case CK_OpteronSSE3:
- case CK_AMDFAM10:
- case CK_BTVER1:
- case CK_BTVER2:
- case CK_BDVER1:
- case CK_BDVER2:
- case CK_BDVER3:
- case CK_BDVER4:
- case CK_ZNVER1:
- case CK_x86_64:
- return true;
- }
- llvm_unreachable("Unhandled CPU kind");
- }
-
- bool setFPMath(StringRef Name) override;
-
- CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
- // Most of the non-ARM calling conventions are i386 conventions.
- switch (CC) {
- case CC_X86ThisCall:
- case CC_X86FastCall:
- case CC_X86StdCall:
- case CC_X86VectorCall:
- case CC_X86RegCall:
- case CC_C:
- case CC_Swift:
- case CC_X86Pascal:
- case CC_IntelOclBicc:
- case CC_OpenCLKernel:
- return CCCR_OK;
- default:
- return CCCR_Warning;
- }
- }
-
- CallingConv getDefaultCallingConv(CallingConvMethodType MT) const override {
- return MT == CCMT_Member ? CC_X86ThisCall : CC_C;
- }
-
- bool hasSjLjLowering() const override {
- return true;
- }
-
- void setSupportedOpenCLOpts() override {
- getSupportedOpenCLOpts().supportAll();
- }
-};
-
-bool X86TargetInfo::setFPMath(StringRef Name) {
- if (Name == "387") {
- FPMath = FP_387;
- return true;
- }
- if (Name == "sse") {
- FPMath = FP_SSE;
- return true;
- }
- return false;
-}
-
-bool X86TargetInfo::initFeatureMap(
- llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
- const std::vector<std::string> &FeaturesVec) const {
- // FIXME: This *really* should not be here.
- // X86_64 always has SSE2.
- if (getTriple().getArch() == llvm::Triple::x86_64)
- setFeatureEnabledImpl(Features, "sse2", true);
-
- const CPUKind Kind = getCPUKind(CPU);
-
- // Enable X87 for all X86 processors but Lakemont.
- if (Kind != CK_Lakemont)
- setFeatureEnabledImpl(Features, "x87", true);
-
- switch (Kind) {
- case CK_Generic:
- case CK_i386:
- case CK_i486:
- case CK_i586:
- case CK_Pentium:
- case CK_i686:
- case CK_PentiumPro:
- case CK_Lakemont:
- break;
- case CK_PentiumMMX:
- case CK_Pentium2:
- case CK_K6:
- case CK_WinChipC6:
- setFeatureEnabledImpl(Features, "mmx", true);
- break;
- case CK_Pentium3:
- case CK_Pentium3M:
- case CK_C3_2:
- setFeatureEnabledImpl(Features, "sse", true);
- setFeatureEnabledImpl(Features, "fxsr", true);
- break;
- case CK_PentiumM:
- case CK_Pentium4:
- case CK_Pentium4M:
- case CK_x86_64:
- setFeatureEnabledImpl(Features, "sse2", true);
- setFeatureEnabledImpl(Features, "fxsr", true);
- break;
- case CK_Yonah:
- case CK_Prescott:
- case CK_Nocona:
- setFeatureEnabledImpl(Features, "sse3", true);
- setFeatureEnabledImpl(Features, "fxsr", true);
- setFeatureEnabledImpl(Features, "cx16", true);
- break;
- case CK_Core2:
- setFeatureEnabledImpl(Features, "ssse3", true);
- setFeatureEnabledImpl(Features, "fxsr", true);
- setFeatureEnabledImpl(Features, "cx16", true);
- break;
- case CK_Penryn:
- setFeatureEnabledImpl(Features, "sse4.1", true);
- setFeatureEnabledImpl(Features, "fxsr", true);
- setFeatureEnabledImpl(Features, "cx16", true);
- break;
- case CK_Cannonlake:
- setFeatureEnabledImpl(Features, "avx512ifma", true);
- setFeatureEnabledImpl(Features, "avx512vbmi", true);
- setFeatureEnabledImpl(Features, "sha", true);
- LLVM_FALLTHROUGH;
- case CK_SkylakeServer:
- setFeatureEnabledImpl(Features, "avx512f", true);
- setFeatureEnabledImpl(Features, "avx512cd", true);
- setFeatureEnabledImpl(Features, "avx512dq", true);
- setFeatureEnabledImpl(Features, "avx512bw", true);
- setFeatureEnabledImpl(Features, "avx512vl", true);
- setFeatureEnabledImpl(Features, "pku", true);
- setFeatureEnabledImpl(Features, "clwb", true);
- LLVM_FALLTHROUGH;
- case CK_SkylakeClient:
- setFeatureEnabledImpl(Features, "xsavec", true);
- setFeatureEnabledImpl(Features, "xsaves", true);
- setFeatureEnabledImpl(Features, "mpx", true);
- setFeatureEnabledImpl(Features, "sgx", true);
- setFeatureEnabledImpl(Features, "clflushopt", true);
- setFeatureEnabledImpl(Features, "rtm", true);
- LLVM_FALLTHROUGH;
- case CK_Broadwell:
- setFeatureEnabledImpl(Features, "rdseed", true);
- setFeatureEnabledImpl(Features, "adx", true);
- LLVM_FALLTHROUGH;
- case CK_Haswell:
- setFeatureEnabledImpl(Features, "avx2", true);
- setFeatureEnabledImpl(Features, "lzcnt", true);
- setFeatureEnabledImpl(Features, "bmi", true);
- setFeatureEnabledImpl(Features, "bmi2", true);
- setFeatureEnabledImpl(Features, "fma", true);
- setFeatureEnabledImpl(Features, "movbe", true);
- LLVM_FALLTHROUGH;
- case CK_IvyBridge:
- setFeatureEnabledImpl(Features, "rdrnd", true);
- setFeatureEnabledImpl(Features, "f16c", true);
- setFeatureEnabledImpl(Features, "fsgsbase", true);
- LLVM_FALLTHROUGH;
- case CK_SandyBridge:
- setFeatureEnabledImpl(Features, "avx", true);
- setFeatureEnabledImpl(Features, "xsave", true);
- setFeatureEnabledImpl(Features, "xsaveopt", true);
- LLVM_FALLTHROUGH;
- case CK_Westmere:
- setFeatureEnabledImpl(Features, "aes", true);
- setFeatureEnabledImpl(Features, "pclmul", true);
- LLVM_FALLTHROUGH;
- case CK_Nehalem:
- setFeatureEnabledImpl(Features, "sse4.2", true);
- setFeatureEnabledImpl(Features, "fxsr", true);
- setFeatureEnabledImpl(Features, "cx16", true);
- break;
- case CK_Goldmont:
- setFeatureEnabledImpl(Features, "sha", true);
- setFeatureEnabledImpl(Features, "rdrnd", true);
- setFeatureEnabledImpl(Features, "rdseed", true);
- setFeatureEnabledImpl(Features, "xsave", true);
- setFeatureEnabledImpl(Features, "xsaveopt", true);
- setFeatureEnabledImpl(Features, "xsavec", true);
- setFeatureEnabledImpl(Features, "xsaves", true);
- setFeatureEnabledImpl(Features, "clflushopt", true);
- setFeatureEnabledImpl(Features, "mpx", true);
- LLVM_FALLTHROUGH;
- case CK_Silvermont:
- setFeatureEnabledImpl(Features, "aes", true);
- setFeatureEnabledImpl(Features, "pclmul", true);
- setFeatureEnabledImpl(Features, "sse4.2", true);
- LLVM_FALLTHROUGH;
- case CK_Bonnell:
- setFeatureEnabledImpl(Features, "movbe", true);
- setFeatureEnabledImpl(Features, "ssse3", true);
- setFeatureEnabledImpl(Features, "fxsr", true);
- setFeatureEnabledImpl(Features, "cx16", true);
- break;
- case CK_KNL:
- setFeatureEnabledImpl(Features, "avx512f", true);
- setFeatureEnabledImpl(Features, "avx512cd", true);
- setFeatureEnabledImpl(Features, "avx512er", true);
- setFeatureEnabledImpl(Features, "avx512pf", true);
- setFeatureEnabledImpl(Features, "prefetchwt1", true);
- setFeatureEnabledImpl(Features, "fxsr", true);
- setFeatureEnabledImpl(Features, "rdseed", true);
- setFeatureEnabledImpl(Features, "adx", true);
- setFeatureEnabledImpl(Features, "lzcnt", true);
- setFeatureEnabledImpl(Features, "bmi", true);
- setFeatureEnabledImpl(Features, "bmi2", true);
- setFeatureEnabledImpl(Features, "rtm", true);
- setFeatureEnabledImpl(Features, "fma", true);
- setFeatureEnabledImpl(Features, "rdrnd", true);
- setFeatureEnabledImpl(Features, "f16c", true);
- setFeatureEnabledImpl(Features, "fsgsbase", true);
- setFeatureEnabledImpl(Features, "aes", true);
- setFeatureEnabledImpl(Features, "pclmul", true);
- setFeatureEnabledImpl(Features, "cx16", true);
- setFeatureEnabledImpl(Features, "xsaveopt", true);
- setFeatureEnabledImpl(Features, "xsave", true);
- setFeatureEnabledImpl(Features, "movbe", true);
- break;
- case CK_K6_2:
- case CK_K6_3:
- case CK_WinChip2:
- case CK_C3:
- setFeatureEnabledImpl(Features, "3dnow", true);
- break;
- case CK_Athlon:
- case CK_AthlonThunderbird:
- case CK_Geode:
- setFeatureEnabledImpl(Features, "3dnowa", true);
- break;
- case CK_Athlon4:
- case CK_AthlonXP:
- case CK_AthlonMP:
- setFeatureEnabledImpl(Features, "sse", true);
- setFeatureEnabledImpl(Features, "3dnowa", true);
- setFeatureEnabledImpl(Features, "fxsr", true);
- break;
- case CK_K8:
- case CK_Opteron:
- case CK_Athlon64:
- case CK_AthlonFX:
- setFeatureEnabledImpl(Features, "sse2", true);
- setFeatureEnabledImpl(Features, "3dnowa", true);
- setFeatureEnabledImpl(Features, "fxsr", true);
- break;
- case CK_AMDFAM10:
- setFeatureEnabledImpl(Features, "sse4a", true);
- setFeatureEnabledImpl(Features, "lzcnt", true);
- setFeatureEnabledImpl(Features, "popcnt", true);
- LLVM_FALLTHROUGH;
- case CK_K8SSE3:
- case CK_OpteronSSE3:
- case CK_Athlon64SSE3:
- setFeatureEnabledImpl(Features, "sse3", true);
- setFeatureEnabledImpl(Features, "3dnowa", true);
- setFeatureEnabledImpl(Features, "fxsr", true);
- break;
- case CK_BTVER2:
- setFeatureEnabledImpl(Features, "avx", true);
- setFeatureEnabledImpl(Features, "aes", true);
- setFeatureEnabledImpl(Features, "pclmul", true);
- setFeatureEnabledImpl(Features, "bmi", true);
- setFeatureEnabledImpl(Features, "f16c", true);
- setFeatureEnabledImpl(Features, "xsaveopt", true);
- setFeatureEnabledImpl(Features, "movbe", true);
- LLVM_FALLTHROUGH;
- case CK_BTVER1:
- setFeatureEnabledImpl(Features, "ssse3", true);
- setFeatureEnabledImpl(Features, "sse4a", true);
- setFeatureEnabledImpl(Features, "lzcnt", true);
- setFeatureEnabledImpl(Features, "popcnt", true);
- setFeatureEnabledImpl(Features, "prfchw", true);
- setFeatureEnabledImpl(Features, "cx16", true);
- setFeatureEnabledImpl(Features, "fxsr", true);
- break;
- case CK_ZNVER1:
- setFeatureEnabledImpl(Features, "adx", true);
- setFeatureEnabledImpl(Features, "aes", true);
- setFeatureEnabledImpl(Features, "avx2", true);
- setFeatureEnabledImpl(Features, "bmi", true);
- setFeatureEnabledImpl(Features, "bmi2", true);
- setFeatureEnabledImpl(Features, "clflushopt", true);
- setFeatureEnabledImpl(Features, "clzero", true);
- setFeatureEnabledImpl(Features, "cx16", true);
- setFeatureEnabledImpl(Features, "f16c", true);
- setFeatureEnabledImpl(Features, "fma", true);
- setFeatureEnabledImpl(Features, "fsgsbase", true);
- setFeatureEnabledImpl(Features, "fxsr", true);
- setFeatureEnabledImpl(Features, "lzcnt", true);
- setFeatureEnabledImpl(Features, "mwaitx", true);
- setFeatureEnabledImpl(Features, "movbe", true);
- setFeatureEnabledImpl(Features, "pclmul", true);
- setFeatureEnabledImpl(Features, "popcnt", true);
- setFeatureEnabledImpl(Features, "prfchw", true);
- setFeatureEnabledImpl(Features, "rdrnd", true);
- setFeatureEnabledImpl(Features, "rdseed", true);
- setFeatureEnabledImpl(Features, "sha", true);
- setFeatureEnabledImpl(Features, "sse4a", true);
- setFeatureEnabledImpl(Features, "xsave", true);
- setFeatureEnabledImpl(Features, "xsavec", true);
- setFeatureEnabledImpl(Features, "xsaveopt", true);
- setFeatureEnabledImpl(Features, "xsaves", true);
- break;
- case CK_BDVER4:
- setFeatureEnabledImpl(Features, "avx2", true);
- setFeatureEnabledImpl(Features, "bmi2", true);
- setFeatureEnabledImpl(Features, "mwaitx", true);
- LLVM_FALLTHROUGH;
- case CK_BDVER3:
- setFeatureEnabledImpl(Features, "fsgsbase", true);
- setFeatureEnabledImpl(Features, "xsaveopt", true);
- LLVM_FALLTHROUGH;
- case CK_BDVER2:
- setFeatureEnabledImpl(Features, "bmi", true);
- setFeatureEnabledImpl(Features, "fma", true);
- setFeatureEnabledImpl(Features, "f16c", true);
- setFeatureEnabledImpl(Features, "tbm", true);
- LLVM_FALLTHROUGH;
- case CK_BDVER1:
- // xop implies avx, sse4a and fma4.
- setFeatureEnabledImpl(Features, "xop", true);
- setFeatureEnabledImpl(Features, "lwp", true);
- setFeatureEnabledImpl(Features, "lzcnt", true);
- setFeatureEnabledImpl(Features, "aes", true);
- setFeatureEnabledImpl(Features, "pclmul", true);
- setFeatureEnabledImpl(Features, "prfchw", true);
- setFeatureEnabledImpl(Features, "cx16", true);
- setFeatureEnabledImpl(Features, "fxsr", true);
- setFeatureEnabledImpl(Features, "xsave", true);
- break;
- }
- if (!TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec))
- return false;
-
- // Can't do this earlier because we need to be able to explicitly enable
- // or disable these features and the things that they depend upon.
-
- // Enable popcnt if sse4.2 is enabled and popcnt is not explicitly disabled.
- auto I = Features.find("sse4.2");
- if (I != Features.end() && I->getValue() &&
- std::find(FeaturesVec.begin(), FeaturesVec.end(), "-popcnt") ==
- FeaturesVec.end())
- Features["popcnt"] = true;
-
- // Enable prfchw if 3DNow! is enabled and prfchw is not explicitly disabled.
- I = Features.find("3dnow");
- if (I != Features.end() && I->getValue() &&
- std::find(FeaturesVec.begin(), FeaturesVec.end(), "-prfchw") ==
- FeaturesVec.end())
- Features["prfchw"] = true;
-
- // Additionally, if SSE is enabled and mmx is not explicitly disabled,
- // then enable MMX.
- I = Features.find("sse");
- if (I != Features.end() && I->getValue() &&
- std::find(FeaturesVec.begin(), FeaturesVec.end(), "-mmx") ==
- FeaturesVec.end())
- Features["mmx"] = true;
-
- return true;
-}
-
-void X86TargetInfo::setSSELevel(llvm::StringMap<bool> &Features,
- X86SSEEnum Level, bool Enabled) {
- if (Enabled) {
- switch (Level) {
- case AVX512F:
- Features["avx512f"] = true;
- LLVM_FALLTHROUGH;
- case AVX2:
- Features["avx2"] = true;
- LLVM_FALLTHROUGH;
- case AVX:
- Features["avx"] = true;
- Features["xsave"] = true;
- LLVM_FALLTHROUGH;
- case SSE42:
- Features["sse4.2"] = true;
- LLVM_FALLTHROUGH;
- case SSE41:
- Features["sse4.1"] = true;
- LLVM_FALLTHROUGH;
- case SSSE3:
- Features["ssse3"] = true;
- LLVM_FALLTHROUGH;
- case SSE3:
- Features["sse3"] = true;
- LLVM_FALLTHROUGH;
- case SSE2:
- Features["sse2"] = true;
- LLVM_FALLTHROUGH;
- case SSE1:
- Features["sse"] = true;
- LLVM_FALLTHROUGH;
- case NoSSE:
- break;
- }
- return;
- }
-
- switch (Level) {
- case NoSSE:
- case SSE1:
- Features["sse"] = false;
- LLVM_FALLTHROUGH;
- case SSE2:
- Features["sse2"] = Features["pclmul"] = Features["aes"] =
- Features["sha"] = false;
- LLVM_FALLTHROUGH;
- case SSE3:
- Features["sse3"] = false;
- setXOPLevel(Features, NoXOP, false);
- LLVM_FALLTHROUGH;
- case SSSE3:
- Features["ssse3"] = false;
- LLVM_FALLTHROUGH;
- case SSE41:
- Features["sse4.1"] = false;
- LLVM_FALLTHROUGH;
- case SSE42:
- Features["sse4.2"] = false;
- LLVM_FALLTHROUGH;
- case AVX:
- Features["fma"] = Features["avx"] = Features["f16c"] = Features["xsave"] =
- Features["xsaveopt"] = false;
- setXOPLevel(Features, FMA4, false);
- LLVM_FALLTHROUGH;
- case AVX2:
- Features["avx2"] = false;
- LLVM_FALLTHROUGH;
- case AVX512F:
- Features["avx512f"] = Features["avx512cd"] = Features["avx512er"] =
- Features["avx512pf"] = Features["avx512dq"] = Features["avx512bw"] =
- Features["avx512vl"] = Features["avx512vbmi"] =
- Features["avx512ifma"] = Features["avx512vpopcntdq"] = false;
- break;
- }
-}
-
-void X86TargetInfo::setMMXLevel(llvm::StringMap<bool> &Features,
- MMX3DNowEnum Level, bool Enabled) {
- if (Enabled) {
- switch (Level) {
- case AMD3DNowAthlon:
- Features["3dnowa"] = true;
- LLVM_FALLTHROUGH;
- case AMD3DNow:
- Features["3dnow"] = true;
- LLVM_FALLTHROUGH;
- case MMX:
- Features["mmx"] = true;
- LLVM_FALLTHROUGH;
- case NoMMX3DNow:
- break;
- }
- return;
- }
-
- switch (Level) {
- case NoMMX3DNow:
- case MMX:
- Features["mmx"] = false;
- LLVM_FALLTHROUGH;
- case AMD3DNow:
- Features["3dnow"] = false;
- LLVM_FALLTHROUGH;
- case AMD3DNowAthlon:
- Features["3dnowa"] = false;
- break;
- }
-}
-
-void X86TargetInfo::setXOPLevel(llvm::StringMap<bool> &Features, XOPEnum Level,
- bool Enabled) {
- if (Enabled) {
- switch (Level) {
- case XOP:
- Features["xop"] = true;
- LLVM_FALLTHROUGH;
- case FMA4:
- Features["fma4"] = true;
- setSSELevel(Features, AVX, true);
- LLVM_FALLTHROUGH;
- case SSE4A:
- Features["sse4a"] = true;
- setSSELevel(Features, SSE3, true);
- LLVM_FALLTHROUGH;
- case NoXOP:
- break;
- }
- return;
- }
-
- switch (Level) {
- case NoXOP:
- case SSE4A:
- Features["sse4a"] = false;
- LLVM_FALLTHROUGH;
- case FMA4:
- Features["fma4"] = false;
- LLVM_FALLTHROUGH;
- case XOP:
- Features["xop"] = false;
- break;
- }
-}
-
-void X86TargetInfo::setFeatureEnabledImpl(llvm::StringMap<bool> &Features,
- StringRef Name, bool Enabled) {
- // This is a bit of a hack to deal with the sse4 target feature when used
- // as part of the target attribute. We handle sse4 correctly everywhere
- // else. See below for more information on how we handle the sse4 options.
- if (Name != "sse4")
- Features[Name] = Enabled;
-
- if (Name == "mmx") {
- setMMXLevel(Features, MMX, Enabled);
- } else if (Name == "sse") {
- setSSELevel(Features, SSE1, Enabled);
- } else if (Name == "sse2") {
- setSSELevel(Features, SSE2, Enabled);
- } else if (Name == "sse3") {
- setSSELevel(Features, SSE3, Enabled);
- } else if (Name == "ssse3") {
- setSSELevel(Features, SSSE3, Enabled);
- } else if (Name == "sse4.2") {
- setSSELevel(Features, SSE42, Enabled);
- } else if (Name == "sse4.1") {
- setSSELevel(Features, SSE41, Enabled);
- } else if (Name == "3dnow") {
- setMMXLevel(Features, AMD3DNow, Enabled);
- } else if (Name == "3dnowa") {
- setMMXLevel(Features, AMD3DNowAthlon, Enabled);
- } else if (Name == "aes") {
- if (Enabled)
- setSSELevel(Features, SSE2, Enabled);
- } else if (Name == "pclmul") {
- if (Enabled)
- setSSELevel(Features, SSE2, Enabled);
- } else if (Name == "avx") {
- setSSELevel(Features, AVX, Enabled);
- } else if (Name == "avx2") {
- setSSELevel(Features, AVX2, Enabled);
- } else if (Name == "avx512f") {
- setSSELevel(Features, AVX512F, Enabled);
- } else if (Name == "avx512cd" || Name == "avx512er" || Name == "avx512pf" ||
- Name == "avx512dq" || Name == "avx512bw" || Name == "avx512vl" ||
- Name == "avx512vbmi" || Name == "avx512ifma" ||
- Name == "avx512vpopcntdq") {
- if (Enabled)
- setSSELevel(Features, AVX512F, Enabled);
- // Enable BWI instruction if VBMI is being enabled.
- if (Name == "avx512vbmi" && Enabled)
- Features["avx512bw"] = true;
- // Also disable VBMI if BWI is being disabled.
- if (Name == "avx512bw" && !Enabled)
- Features["avx512vbmi"] = false;
- } else if (Name == "fma") {
- if (Enabled)
- setSSELevel(Features, AVX, Enabled);
- } else if (Name == "fma4") {
- setXOPLevel(Features, FMA4, Enabled);
- } else if (Name == "xop") {
- setXOPLevel(Features, XOP, Enabled);
- } else if (Name == "sse4a") {
- setXOPLevel(Features, SSE4A, Enabled);
- } else if (Name == "f16c") {
- if (Enabled)
- setSSELevel(Features, AVX, Enabled);
- } else if (Name == "sha") {
- if (Enabled)
- setSSELevel(Features, SSE2, Enabled);
- } else if (Name == "sse4") {
- // We can get here via the __target__ attribute since that's not controlled
- // via the -msse4/-mno-sse4 command line alias. Handle this the same way
- // here - turn on the sse4.2 if enabled, turn off the sse4.1 level if
- // disabled.
- if (Enabled)
- setSSELevel(Features, SSE42, Enabled);
- else
- setSSELevel(Features, SSE41, Enabled);
- } else if (Name == "xsave") {
- if (!Enabled)
- Features["xsaveopt"] = false;
- } else if (Name == "xsaveopt" || Name == "xsavec" || Name == "xsaves") {
- if (Enabled)
- Features["xsave"] = true;
- }
-}
-
-/// handleTargetFeatures - Perform initialization based on the user
-/// configured set of features.
-bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
- DiagnosticsEngine &Diags) {
- for (const auto &Feature : Features) {
- if (Feature[0] != '+')
- continue;
-
- if (Feature == "+aes") {
- HasAES = true;
- } else if (Feature == "+pclmul") {
- HasPCLMUL = true;
- } else if (Feature == "+lzcnt") {
- HasLZCNT = true;
- } else if (Feature == "+rdrnd") {
- HasRDRND = true;
- } else if (Feature == "+fsgsbase") {
- HasFSGSBASE = true;
- } else if (Feature == "+bmi") {
- HasBMI = true;
- } else if (Feature == "+bmi2") {
- HasBMI2 = true;
- } else if (Feature == "+popcnt") {
- HasPOPCNT = true;
- } else if (Feature == "+rtm") {
- HasRTM = true;
- } else if (Feature == "+prfchw") {
- HasPRFCHW = true;
- } else if (Feature == "+rdseed") {
- HasRDSEED = true;
- } else if (Feature == "+adx") {
- HasADX = true;
- } else if (Feature == "+tbm") {
- HasTBM = true;
- } else if (Feature == "+lwp") {
- HasLWP = true;
- } else if (Feature == "+fma") {
- HasFMA = true;
- } else if (Feature == "+f16c") {
- HasF16C = true;
- } else if (Feature == "+avx512cd") {
- HasAVX512CD = true;
- } else if (Feature == "+avx512vpopcntdq") {
- HasAVX512VPOPCNTDQ = true;
- } else if (Feature == "+avx512er") {
- HasAVX512ER = true;
- } else if (Feature == "+avx512pf") {
- HasAVX512PF = true;
- } else if (Feature == "+avx512dq") {
- HasAVX512DQ = true;
- } else if (Feature == "+avx512bw") {
- HasAVX512BW = true;
- } else if (Feature == "+avx512vl") {
- HasAVX512VL = true;
- } else if (Feature == "+avx512vbmi") {
- HasAVX512VBMI = true;
- } else if (Feature == "+avx512ifma") {
- HasAVX512IFMA = true;
- } else if (Feature == "+sha") {
- HasSHA = true;
- } else if (Feature == "+mpx") {
- HasMPX = true;
- } else if (Feature == "+movbe") {
- HasMOVBE = true;
- } else if (Feature == "+sgx") {
- HasSGX = true;
- } else if (Feature == "+cx16") {
- HasCX16 = true;
- } else if (Feature == "+fxsr") {
- HasFXSR = true;
- } else if (Feature == "+xsave") {
- HasXSAVE = true;
- } else if (Feature == "+xsaveopt") {
- HasXSAVEOPT = true;
- } else if (Feature == "+xsavec") {
- HasXSAVEC = true;
- } else if (Feature == "+xsaves") {
- HasXSAVES = true;
- } else if (Feature == "+mwaitx") {
- HasMWAITX = true;
- } else if (Feature == "+pku") {
- HasPKU = true;
- } else if (Feature == "+clflushopt") {
- HasCLFLUSHOPT = true;
- } else if (Feature == "+clwb") {
- HasCLWB = true;
- } else if (Feature == "+prefetchwt1") {
- HasPREFETCHWT1 = true;
- } else if (Feature == "+clzero") {
- HasCLZERO = true;
- }
-
- X86SSEEnum Level = llvm::StringSwitch<X86SSEEnum>(Feature)
- .Case("+avx512f", AVX512F)
- .Case("+avx2", AVX2)
- .Case("+avx", AVX)
- .Case("+sse4.2", SSE42)
- .Case("+sse4.1", SSE41)
- .Case("+ssse3", SSSE3)
- .Case("+sse3", SSE3)
- .Case("+sse2", SSE2)
- .Case("+sse", SSE1)
- .Default(NoSSE);
- SSELevel = std::max(SSELevel, Level);
-
- MMX3DNowEnum ThreeDNowLevel =
- llvm::StringSwitch<MMX3DNowEnum>(Feature)
- .Case("+3dnowa", AMD3DNowAthlon)
- .Case("+3dnow", AMD3DNow)
- .Case("+mmx", MMX)
- .Default(NoMMX3DNow);
- MMX3DNowLevel = std::max(MMX3DNowLevel, ThreeDNowLevel);
-
- XOPEnum XLevel = llvm::StringSwitch<XOPEnum>(Feature)
- .Case("+xop", XOP)
- .Case("+fma4", FMA4)
- .Case("+sse4a", SSE4A)
- .Default(NoXOP);
- XOPLevel = std::max(XOPLevel, XLevel);
- }
-
- // LLVM doesn't have a separate switch for fpmath, so only accept it if it
- // matches the selected sse level.
- if ((FPMath == FP_SSE && SSELevel < SSE1) ||
- (FPMath == FP_387 && SSELevel >= SSE1)) {
- Diags.Report(diag::err_target_unsupported_fpmath) <<
- (FPMath == FP_SSE ? "sse" : "387");
- return false;
- }
-
- SimdDefaultAlign =
- hasFeature("avx512f") ? 512 : hasFeature("avx") ? 256 : 128;
- return true;
-}
-
-/// X86TargetInfo::getTargetDefines - Return the set of the X86-specific macro
-/// definitions for this particular subtarget.
-void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- // Target identification.
- if (getTriple().getArch() == llvm::Triple::x86_64) {
- Builder.defineMacro("__amd64__");
- Builder.defineMacro("__amd64");
- Builder.defineMacro("__x86_64");
- Builder.defineMacro("__x86_64__");
- if (getTriple().getArchName() == "x86_64h") {
- Builder.defineMacro("__x86_64h");
- Builder.defineMacro("__x86_64h__");
- }
- } else {
- DefineStd(Builder, "i386", Opts);
- }
-
- // Subtarget options.
- // FIXME: We are hard-coding the tune parameters based on the CPU, but they
- // truly should be based on -mtune options.
- switch (CPU) {
- case CK_Generic:
- break;
- case CK_i386:
- // The rest are coming from the i386 define above.
- Builder.defineMacro("__tune_i386__");
- break;
- case CK_i486:
- case CK_WinChipC6:
- case CK_WinChip2:
- case CK_C3:
- defineCPUMacros(Builder, "i486");
- break;
- case CK_PentiumMMX:
- Builder.defineMacro("__pentium_mmx__");
- Builder.defineMacro("__tune_pentium_mmx__");
- LLVM_FALLTHROUGH;
- case CK_i586:
- case CK_Pentium:
- defineCPUMacros(Builder, "i586");
- defineCPUMacros(Builder, "pentium");
- break;
- case CK_Pentium3:
- case CK_Pentium3M:
- case CK_PentiumM:
- Builder.defineMacro("__tune_pentium3__");
- LLVM_FALLTHROUGH;
- case CK_Pentium2:
- case CK_C3_2:
- Builder.defineMacro("__tune_pentium2__");
- LLVM_FALLTHROUGH;
- case CK_PentiumPro:
- Builder.defineMacro("__tune_i686__");
- Builder.defineMacro("__tune_pentiumpro__");
- LLVM_FALLTHROUGH;
- case CK_i686:
- Builder.defineMacro("__i686");
- Builder.defineMacro("__i686__");
- // Strangely, __tune_i686__ isn't defined by GCC when CPU == i686.
- Builder.defineMacro("__pentiumpro");
- Builder.defineMacro("__pentiumpro__");
- break;
- case CK_Pentium4:
- case CK_Pentium4M:
- defineCPUMacros(Builder, "pentium4");
- break;
- case CK_Yonah:
- case CK_Prescott:
- case CK_Nocona:
- defineCPUMacros(Builder, "nocona");
- break;
- case CK_Core2:
- case CK_Penryn:
- defineCPUMacros(Builder, "core2");
- break;
- case CK_Bonnell:
- defineCPUMacros(Builder, "atom");
- break;
- case CK_Silvermont:
- defineCPUMacros(Builder, "slm");
- break;
- case CK_Goldmont:
- defineCPUMacros(Builder, "goldmont");
- break;
- case CK_Nehalem:
- case CK_Westmere:
- case CK_SandyBridge:
- case CK_IvyBridge:
- case CK_Haswell:
- case CK_Broadwell:
- case CK_SkylakeClient:
- // FIXME: Historically, we defined this legacy name, it would be nice to
- // remove it at some point. We've never exposed fine-grained names for
- // recent primary x86 CPUs, and we should keep it that way.
- defineCPUMacros(Builder, "corei7");
- break;
- case CK_SkylakeServer:
- defineCPUMacros(Builder, "skx");
- break;
- case CK_Cannonlake:
- break;
- case CK_KNL:
- defineCPUMacros(Builder, "knl");
- break;
- case CK_Lakemont:
- Builder.defineMacro("__tune_lakemont__");
- break;
- case CK_K6_2:
- Builder.defineMacro("__k6_2__");
- Builder.defineMacro("__tune_k6_2__");
- LLVM_FALLTHROUGH;
- case CK_K6_3:
- if (CPU != CK_K6_2) { // In case of fallthrough
- // FIXME: GCC may be enabling these in cases where some other k6
- // architecture is specified but -m3dnow is explicitly provided. The
- // exact semantics need to be determined and emulated here.
- Builder.defineMacro("__k6_3__");
- Builder.defineMacro("__tune_k6_3__");
- }
- LLVM_FALLTHROUGH;
- case CK_K6:
- defineCPUMacros(Builder, "k6");
- break;
- case CK_Athlon:
- case CK_AthlonThunderbird:
- case CK_Athlon4:
- case CK_AthlonXP:
- case CK_AthlonMP:
- defineCPUMacros(Builder, "athlon");
- if (SSELevel != NoSSE) {
- Builder.defineMacro("__athlon_sse__");
- Builder.defineMacro("__tune_athlon_sse__");
- }
- break;
- case CK_K8:
- case CK_K8SSE3:
- case CK_x86_64:
- case CK_Opteron:
- case CK_OpteronSSE3:
- case CK_Athlon64:
- case CK_Athlon64SSE3:
- case CK_AthlonFX:
- defineCPUMacros(Builder, "k8");
- break;
- case CK_AMDFAM10:
- defineCPUMacros(Builder, "amdfam10");
- break;
- case CK_BTVER1:
- defineCPUMacros(Builder, "btver1");
- break;
- case CK_BTVER2:
- defineCPUMacros(Builder, "btver2");
- break;
- case CK_BDVER1:
- defineCPUMacros(Builder, "bdver1");
- break;
- case CK_BDVER2:
- defineCPUMacros(Builder, "bdver2");
- break;
- case CK_BDVER3:
- defineCPUMacros(Builder, "bdver3");
- break;
- case CK_BDVER4:
- defineCPUMacros(Builder, "bdver4");
- break;
- case CK_ZNVER1:
- defineCPUMacros(Builder, "znver1");
- break;
- case CK_Geode:
- defineCPUMacros(Builder, "geode");
- break;
- }
-
- // Target properties.
- Builder.defineMacro("__REGISTER_PREFIX__", "");
-
- // Define __NO_MATH_INLINES on linux/x86 so that we don't get inline
- // functions in glibc header files that use FP Stack inline asm which the
- // backend can't deal with (PR879).
- Builder.defineMacro("__NO_MATH_INLINES");
-
- if (HasAES)
- Builder.defineMacro("__AES__");
-
- if (HasPCLMUL)
- Builder.defineMacro("__PCLMUL__");
-
- if (HasLZCNT)
- Builder.defineMacro("__LZCNT__");
-
- if (HasRDRND)
- Builder.defineMacro("__RDRND__");
-
- if (HasFSGSBASE)
- Builder.defineMacro("__FSGSBASE__");
-
- if (HasBMI)
- Builder.defineMacro("__BMI__");
-
- if (HasBMI2)
- Builder.defineMacro("__BMI2__");
-
- if (HasPOPCNT)
- Builder.defineMacro("__POPCNT__");
-
- if (HasRTM)
- Builder.defineMacro("__RTM__");
-
- if (HasPRFCHW)
- Builder.defineMacro("__PRFCHW__");
-
- if (HasRDSEED)
- Builder.defineMacro("__RDSEED__");
-
- if (HasADX)
- Builder.defineMacro("__ADX__");
-
- if (HasTBM)
- Builder.defineMacro("__TBM__");
-
- if (HasLWP)
- Builder.defineMacro("__LWP__");
-
- if (HasMWAITX)
- Builder.defineMacro("__MWAITX__");
-
- switch (XOPLevel) {
- case XOP:
- Builder.defineMacro("__XOP__");
- LLVM_FALLTHROUGH;
- case FMA4:
- Builder.defineMacro("__FMA4__");
- LLVM_FALLTHROUGH;
- case SSE4A:
- Builder.defineMacro("__SSE4A__");
- LLVM_FALLTHROUGH;
- case NoXOP:
- break;
- }
-
- if (HasFMA)
- Builder.defineMacro("__FMA__");
-
- if (HasF16C)
- Builder.defineMacro("__F16C__");
-
- if (HasAVX512CD)
- Builder.defineMacro("__AVX512CD__");
- if (HasAVX512VPOPCNTDQ)
- Builder.defineMacro("__AVX512VPOPCNTDQ__");
- if (HasAVX512ER)
- Builder.defineMacro("__AVX512ER__");
- if (HasAVX512PF)
- Builder.defineMacro("__AVX512PF__");
- if (HasAVX512DQ)
- Builder.defineMacro("__AVX512DQ__");
- if (HasAVX512BW)
- Builder.defineMacro("__AVX512BW__");
- if (HasAVX512VL)
- Builder.defineMacro("__AVX512VL__");
- if (HasAVX512VBMI)
- Builder.defineMacro("__AVX512VBMI__");
- if (HasAVX512IFMA)
- Builder.defineMacro("__AVX512IFMA__");
-
- if (HasSHA)
- Builder.defineMacro("__SHA__");
-
- if (HasFXSR)
- Builder.defineMacro("__FXSR__");
- if (HasXSAVE)
- Builder.defineMacro("__XSAVE__");
- if (HasXSAVEOPT)
- Builder.defineMacro("__XSAVEOPT__");
- if (HasXSAVEC)
- Builder.defineMacro("__XSAVEC__");
- if (HasXSAVES)
- Builder.defineMacro("__XSAVES__");
- if (HasPKU)
- Builder.defineMacro("__PKU__");
- if (HasCX16)
- Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16");
- if (HasCLFLUSHOPT)
- Builder.defineMacro("__CLFLUSHOPT__");
- if (HasCLWB)
- Builder.defineMacro("__CLWB__");
- if (HasMPX)
- Builder.defineMacro("__MPX__");
- if (HasSGX)
- Builder.defineMacro("__SGX__");
- if (HasPREFETCHWT1)
- Builder.defineMacro("__PREFETCHWT1__");
- if (HasCLZERO)
- Builder.defineMacro("__CLZERO__");
-
- // Each case falls through to the previous one here.
- switch (SSELevel) {
- case AVX512F:
- Builder.defineMacro("__AVX512F__");
- LLVM_FALLTHROUGH;
- case AVX2:
- Builder.defineMacro("__AVX2__");
- LLVM_FALLTHROUGH;
- case AVX:
- Builder.defineMacro("__AVX__");
- LLVM_FALLTHROUGH;
- case SSE42:
- Builder.defineMacro("__SSE4_2__");
- LLVM_FALLTHROUGH;
- case SSE41:
- Builder.defineMacro("__SSE4_1__");
- LLVM_FALLTHROUGH;
- case SSSE3:
- Builder.defineMacro("__SSSE3__");
- LLVM_FALLTHROUGH;
- case SSE3:
- Builder.defineMacro("__SSE3__");
- LLVM_FALLTHROUGH;
- case SSE2:
- Builder.defineMacro("__SSE2__");
- Builder.defineMacro("__SSE2_MATH__"); // -mfp-math=sse always implied.
- LLVM_FALLTHROUGH;
- case SSE1:
- Builder.defineMacro("__SSE__");
- Builder.defineMacro("__SSE_MATH__"); // -mfp-math=sse always implied.
- LLVM_FALLTHROUGH;
- case NoSSE:
- break;
- }
-
- if (Opts.MicrosoftExt && getTriple().getArch() == llvm::Triple::x86) {
- switch (SSELevel) {
- case AVX512F:
- case AVX2:
- case AVX:
- case SSE42:
- case SSE41:
- case SSSE3:
- case SSE3:
- case SSE2:
- Builder.defineMacro("_M_IX86_FP", Twine(2));
- break;
- case SSE1:
- Builder.defineMacro("_M_IX86_FP", Twine(1));
- break;
- default:
- Builder.defineMacro("_M_IX86_FP", Twine(0));
- break;
- }
- }
-
- // Each case falls through to the previous one here.
- switch (MMX3DNowLevel) {
- case AMD3DNowAthlon:
- Builder.defineMacro("__3dNOW_A__");
- LLVM_FALLTHROUGH;
- case AMD3DNow:
- Builder.defineMacro("__3dNOW__");
- LLVM_FALLTHROUGH;
- case MMX:
- Builder.defineMacro("__MMX__");
- LLVM_FALLTHROUGH;
- case NoMMX3DNow:
- break;
- }
-
- if (CPU >= CK_i486) {
- Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
- Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
- Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
- }
- if (CPU >= CK_i586)
- Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
-
- if (HasFloat128)
- Builder.defineMacro("__SIZEOF_FLOAT128__", "16");
-}
-
-bool X86TargetInfo::hasFeature(StringRef Feature) const {
- return llvm::StringSwitch<bool>(Feature)
- .Case("aes", HasAES)
- .Case("avx", SSELevel >= AVX)
- .Case("avx2", SSELevel >= AVX2)
- .Case("avx512f", SSELevel >= AVX512F)
- .Case("avx512cd", HasAVX512CD)
- .Case("avx512vpopcntdq", HasAVX512VPOPCNTDQ)
- .Case("avx512er", HasAVX512ER)
- .Case("avx512pf", HasAVX512PF)
- .Case("avx512dq", HasAVX512DQ)
- .Case("avx512bw", HasAVX512BW)
- .Case("avx512vl", HasAVX512VL)
- .Case("avx512vbmi", HasAVX512VBMI)
- .Case("avx512ifma", HasAVX512IFMA)
- .Case("bmi", HasBMI)
- .Case("bmi2", HasBMI2)
- .Case("clflushopt", HasCLFLUSHOPT)
- .Case("clwb", HasCLWB)
- .Case("clzero", HasCLZERO)
- .Case("cx16", HasCX16)
- .Case("f16c", HasF16C)
- .Case("fma", HasFMA)
- .Case("fma4", XOPLevel >= FMA4)
- .Case("fsgsbase", HasFSGSBASE)
- .Case("fxsr", HasFXSR)
- .Case("lzcnt", HasLZCNT)
- .Case("mm3dnow", MMX3DNowLevel >= AMD3DNow)
- .Case("mm3dnowa", MMX3DNowLevel >= AMD3DNowAthlon)
- .Case("mmx", MMX3DNowLevel >= MMX)
- .Case("movbe", HasMOVBE)
- .Case("mpx", HasMPX)
- .Case("pclmul", HasPCLMUL)
- .Case("pku", HasPKU)
- .Case("popcnt", HasPOPCNT)
- .Case("prefetchwt1", HasPREFETCHWT1)
- .Case("prfchw", HasPRFCHW)
- .Case("rdrnd", HasRDRND)
- .Case("rdseed", HasRDSEED)
- .Case("rtm", HasRTM)
- .Case("sgx", HasSGX)
- .Case("sha", HasSHA)
- .Case("sse", SSELevel >= SSE1)
- .Case("sse2", SSELevel >= SSE2)
- .Case("sse3", SSELevel >= SSE3)
- .Case("ssse3", SSELevel >= SSSE3)
- .Case("sse4.1", SSELevel >= SSE41)
- .Case("sse4.2", SSELevel >= SSE42)
- .Case("sse4a", XOPLevel >= SSE4A)
- .Case("tbm", HasTBM)
- .Case("lwp", HasLWP)
- .Case("x86", true)
- .Case("x86_32", getTriple().getArch() == llvm::Triple::x86)
- .Case("x86_64", getTriple().getArch() == llvm::Triple::x86_64)
- .Case("xop", XOPLevel >= XOP)
- .Case("xsave", HasXSAVE)
- .Case("xsavec", HasXSAVEC)
- .Case("xsaves", HasXSAVES)
- .Case("xsaveopt", HasXSAVEOPT)
- .Default(false);
-}
-
-// We can't use a generic validation scheme for the features accepted here
-// versus subtarget features accepted in the target attribute because the
-// bitfield structure that's initialized in the runtime only supports the
-// below currently rather than the full range of subtarget features. (See
-// X86TargetInfo::hasFeature for a somewhat comprehensive list).
-bool X86TargetInfo::validateCpuSupports(StringRef FeatureStr) const {
- return llvm::StringSwitch<bool>(FeatureStr)
- .Case("cmov", true)
- .Case("mmx", true)
- .Case("popcnt", true)
- .Case("sse", true)
- .Case("sse2", true)
- .Case("sse3", true)
- .Case("ssse3", true)
- .Case("sse4.1", true)
- .Case("sse4.2", true)
- .Case("avx", true)
- .Case("avx2", true)
- .Case("sse4a", true)
- .Case("fma4", true)
- .Case("xop", true)
- .Case("fma", true)
- .Case("avx512f", true)
- .Case("bmi", true)
- .Case("bmi2", true)
- .Case("aes", true)
- .Case("pclmul", true)
- .Case("avx512vl", true)
- .Case("avx512bw", true)
- .Case("avx512dq", true)
- .Case("avx512cd", true)
- .Case("avx512vpopcntdq", true)
- .Case("avx512er", true)
- .Case("avx512pf", true)
- .Case("avx512vbmi", true)
- .Case("avx512ifma", true)
- .Default(false);
-}
-
-bool
-X86TargetInfo::validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &Info) const {
- switch (*Name) {
- default: return false;
- // Constant constraints.
- case 'e': // 32-bit signed integer constant for use with sign-extending x86_64
- // instructions.
- case 'Z': // 32-bit unsigned integer constant for use with zero-extending
- // x86_64 instructions.
- case 's':
- Info.setRequiresImmediate();
- return true;
- case 'I':
- Info.setRequiresImmediate(0, 31);
- return true;
- case 'J':
- Info.setRequiresImmediate(0, 63);
- return true;
- case 'K':
- Info.setRequiresImmediate(-128, 127);
- return true;
- case 'L':
- Info.setRequiresImmediate({ int(0xff), int(0xffff), int(0xffffffff) });
- return true;
- case 'M':
- Info.setRequiresImmediate(0, 3);
- return true;
- case 'N':
- Info.setRequiresImmediate(0, 255);
- return true;
- case 'O':
- Info.setRequiresImmediate(0, 127);
- return true;
- // Register constraints.
- case 'Y': // 'Y' is the first character for several 2-character constraints.
- // Shift the pointer to the second character of the constraint.
- Name++;
- switch (*Name) {
- default:
- return false;
- case '0': // First SSE register.
- case 't': // Any SSE register, when SSE2 is enabled.
- case 'i': // Any SSE register, when SSE2 and inter-unit moves enabled.
- case 'm': // Any MMX register, when inter-unit moves enabled.
- case 'k': // AVX512 arch mask registers: k1-k7.
- Info.setAllowsRegister();
- return true;
- }
- case 'f': // Any x87 floating point stack register.
- // Constraint 'f' cannot be used for output operands.
- if (Info.ConstraintStr[0] == '=')
- return false;
- Info.setAllowsRegister();
- return true;
- case 'a': // eax.
- case 'b': // ebx.
- case 'c': // ecx.
- case 'd': // edx.
- case 'S': // esi.
- case 'D': // edi.
- case 'A': // edx:eax.
- case 't': // Top of floating point stack.
- case 'u': // Second from top of floating point stack.
- case 'q': // Any register accessible as [r]l: a, b, c, and d.
- case 'y': // Any MMX register.
- case 'v': // Any {X,Y,Z}MM register (Arch & context dependent)
- case 'x': // Any SSE register.
- case 'k': // Any AVX512 mask register (same as Yk, additionaly allows k0
- // for intermideate k reg operations).
- case 'Q': // Any register accessible as [r]h: a, b, c, and d.
- case 'R': // "Legacy" registers: ax, bx, cx, dx, di, si, sp, bp.
- case 'l': // "Index" registers: any general register that can be used as an
- // index in a base+index memory access.
- Info.setAllowsRegister();
- return true;
- // Floating point constant constraints.
- case 'C': // SSE floating point constant.
- case 'G': // x87 floating point constant.
- return true;
- }
-}
-
-bool X86TargetInfo::validateOutputSize(StringRef Constraint,
- unsigned Size) const {
- // Strip off constraint modifiers.
- while (Constraint[0] == '=' ||
- Constraint[0] == '+' ||
- Constraint[0] == '&')
- Constraint = Constraint.substr(1);
-
- return validateOperandSize(Constraint, Size);
-}
-
-bool X86TargetInfo::validateInputSize(StringRef Constraint,
- unsigned Size) const {
- return validateOperandSize(Constraint, Size);
-}
-
-bool X86TargetInfo::validateOperandSize(StringRef Constraint,
- unsigned Size) const {
- switch (Constraint[0]) {
- default: break;
- case 'k':
- // Registers k0-k7 (AVX512) size limit is 64 bit.
- case 'y':
- return Size <= 64;
- case 'f':
- case 't':
- case 'u':
- return Size <= 128;
- case 'v':
- case 'x':
- if (SSELevel >= AVX512F)
- // 512-bit zmm registers can be used if target supports AVX512F.
- return Size <= 512U;
- else if (SSELevel >= AVX)
- // 256-bit ymm registers can be used if target supports AVX.
- return Size <= 256U;
- return Size <= 128U;
- case 'Y':
- // 'Y' is the first character for several 2-character constraints.
- switch (Constraint[1]) {
- default: break;
- case 'm':
- // 'Ym' is synonymous with 'y'.
- case 'k':
- return Size <= 64;
- case 'i':
- case 't':
- // 'Yi' and 'Yt' are synonymous with 'x' when SSE2 is enabled.
- if (SSELevel >= AVX512F)
- return Size <= 512U;
- else if (SSELevel >= AVX)
- return Size <= 256U;
- return SSELevel >= SSE2 && Size <= 128U;
- }
-
- }
-
- return true;
-}
-
-std::string
-X86TargetInfo::convertConstraint(const char *&Constraint) const {
- switch (*Constraint) {
- case 'a': return std::string("{ax}");
- case 'b': return std::string("{bx}");
- case 'c': return std::string("{cx}");
- case 'd': return std::string("{dx}");
- case 'S': return std::string("{si}");
- case 'D': return std::string("{di}");
- case 'p': // address
- return std::string("im");
- case 't': // top of floating point stack.
- return std::string("{st}");
- case 'u': // second from top of floating point stack.
- return std::string("{st(1)}"); // second from top of floating point stack.
- case 'Y':
- switch (Constraint[1]) {
- default:
- // Break from inner switch and fall through (copy single char),
- // continue parsing after copying the current constraint into
- // the return string.
- break;
- case 'k':
- // "^" hints llvm that this is a 2 letter constraint.
- // "Constraint++" is used to promote the string iterator
- // to the next constraint.
- return std::string("^") + std::string(Constraint++, 2);
- }
- LLVM_FALLTHROUGH;
- default:
- return std::string(1, *Constraint);
- }
-}
-
-// X86-32 generic target
-class X86_32TargetInfo : public X86TargetInfo {
-public:
- X86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : X86TargetInfo(Triple, Opts) {
- DoubleAlign = LongLongAlign = 32;
- LongDoubleWidth = 96;
- LongDoubleAlign = 32;
- SuitableAlign = 128;
- resetDataLayout("e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128");
- SizeType = UnsignedInt;
- PtrDiffType = SignedInt;
- IntPtrType = SignedInt;
- RegParmMax = 3;
-
- // Use fpret for all types.
- RealTypeUsesObjCFPRet = ((1 << TargetInfo::Float) |
- (1 << TargetInfo::Double) |
- (1 << TargetInfo::LongDouble));
-
- // x86-32 has atomics up to 8 bytes
- // FIXME: Check that we actually have cmpxchg8b before setting
- // MaxAtomicInlineWidth. (cmpxchg8b is an i586 instruction.)
- MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
- }
- BuiltinVaListKind getBuiltinVaListKind() const override {
- return TargetInfo::CharPtrBuiltinVaList;
- }
-
- int getEHDataRegisterNumber(unsigned RegNo) const override {
- if (RegNo == 0) return 0;
- if (RegNo == 1) return 2;
- return -1;
- }
- bool validateOperandSize(StringRef Constraint,
- unsigned Size) const override {
- switch (Constraint[0]) {
- default: break;
- case 'R':
- case 'q':
- case 'Q':
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'S':
- case 'D':
- return Size <= 32;
- case 'A':
- return Size <= 64;
- }
-
- return X86TargetInfo::validateOperandSize(Constraint, Size);
- }
- ArrayRef<Builtin::Info> getTargetBuiltins() const override {
- return llvm::makeArrayRef(BuiltinInfoX86, clang::X86::LastX86CommonBuiltin -
- Builtin::FirstTSBuiltin + 1);
- }
-};
-
-class NetBSDI386TargetInfo : public NetBSDTargetInfo<X86_32TargetInfo> {
-public:
- NetBSDI386TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : NetBSDTargetInfo<X86_32TargetInfo>(Triple, Opts) {}
-
- unsigned getFloatEvalMethod() const override {
- unsigned Major, Minor, Micro;
- getTriple().getOSVersion(Major, Minor, Micro);
- // New NetBSD uses the default rounding mode.
- if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 26) || Major == 0)
- return X86_32TargetInfo::getFloatEvalMethod();
- // NetBSD before 6.99.26 defaults to "double" rounding.
- return 1;
- }
-};
-
-class OpenBSDI386TargetInfo : public OpenBSDTargetInfo<X86_32TargetInfo> {
-public:
- OpenBSDI386TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : OpenBSDTargetInfo<X86_32TargetInfo>(Triple, Opts) {
- SizeType = UnsignedLong;
- IntPtrType = SignedLong;
- PtrDiffType = SignedLong;
- }
-};
-
-class BitrigI386TargetInfo : public BitrigTargetInfo<X86_32TargetInfo> {
-public:
- BitrigI386TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : BitrigTargetInfo<X86_32TargetInfo>(Triple, Opts) {
- SizeType = UnsignedLong;
- IntPtrType = SignedLong;
- PtrDiffType = SignedLong;
- }
-};
-
-class DarwinI386TargetInfo : public DarwinTargetInfo<X86_32TargetInfo> {
-public:
- DarwinI386TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : DarwinTargetInfo<X86_32TargetInfo>(Triple, Opts) {
- LongDoubleWidth = 128;
- LongDoubleAlign = 128;
- SuitableAlign = 128;
- MaxVectorAlign = 256;
- // The watchOS simulator uses the builtin bool type for Objective-C.
- llvm::Triple T = llvm::Triple(Triple);
- if (T.isWatchOS())
- UseSignedCharForObjCBool = false;
- SizeType = UnsignedLong;
- IntPtrType = SignedLong;
- resetDataLayout("e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128");
- HasAlignMac68kSupport = true;
- }
-
- bool handleTargetFeatures(std::vector<std::string> &Features,
- DiagnosticsEngine &Diags) override {
- if (!DarwinTargetInfo<X86_32TargetInfo>::handleTargetFeatures(Features,
- Diags))
- return false;
- // We now know the features we have: we can decide how to align vectors.
- MaxVectorAlign =
- hasFeature("avx512f") ? 512 : hasFeature("avx") ? 256 : 128;
- return true;
- }
-};
-
-// x86-32 Windows target
-class WindowsX86_32TargetInfo : public WindowsTargetInfo<X86_32TargetInfo> {
-public:
- WindowsX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : WindowsTargetInfo<X86_32TargetInfo>(Triple, Opts) {
- WCharType = UnsignedShort;
- DoubleAlign = LongLongAlign = 64;
- bool IsWinCOFF =
- getTriple().isOSWindows() && getTriple().isOSBinFormatCOFF();
- resetDataLayout(IsWinCOFF
- ? "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
- : "e-m:e-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32");
- }
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- WindowsTargetInfo<X86_32TargetInfo>::getTargetDefines(Opts, Builder);
- }
-};
-
-// x86-32 Windows Visual Studio target
-class MicrosoftX86_32TargetInfo : public WindowsX86_32TargetInfo {
-public:
- MicrosoftX86_32TargetInfo(const llvm::Triple &Triple,
- const TargetOptions &Opts)
- : WindowsX86_32TargetInfo(Triple, Opts) {
- LongDoubleWidth = LongDoubleAlign = 64;
- LongDoubleFormat = &llvm::APFloat::IEEEdouble();
- }
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- WindowsX86_32TargetInfo::getTargetDefines(Opts, Builder);
- WindowsX86_32TargetInfo::getVisualStudioDefines(Opts, Builder);
- // The value of the following reflects processor type.
- // 300=386, 400=486, 500=Pentium, 600=Blend (default)
- // We lost the original triple, so we use the default.
- Builder.defineMacro("_M_IX86", "600");
- }
-};
-
-static void addCygMingDefines(const LangOptions &Opts, MacroBuilder &Builder) {
+void addCygMingDefines(const LangOptions &Opts, MacroBuilder &Builder) {
// Mingw and cygwin define __declspec(a) to __attribute__((a)). Clang
// supports __declspec natively under -fms-extensions, but we define a no-op
// __declspec macro anyway for pre-processor compatibility.
@@ -4712,4819 +97,25 @@ static void addCygMingDefines(const LangOptions &Opts, MacroBuilder &Builder) {
}
}
-static void addMinGWDefines(const LangOptions &Opts, MacroBuilder &Builder) {
- Builder.defineMacro("__MSVCRT__");
- Builder.defineMacro("__MINGW32__");
- addCygMingDefines(Opts, Builder);
-}
-
-// x86-32 MinGW target
-class MinGWX86_32TargetInfo : public WindowsX86_32TargetInfo {
-public:
- MinGWX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : WindowsX86_32TargetInfo(Triple, Opts) {
- HasFloat128 = true;
- }
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- WindowsX86_32TargetInfo::getTargetDefines(Opts, Builder);
- DefineStd(Builder, "WIN32", Opts);
- DefineStd(Builder, "WINNT", Opts);
- Builder.defineMacro("_X86_");
- addMinGWDefines(Opts, Builder);
- }
-};
-
-// x86-32 Cygwin target
-class CygwinX86_32TargetInfo : public X86_32TargetInfo {
-public:
- CygwinX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : X86_32TargetInfo(Triple, Opts) {
- WCharType = UnsignedShort;
- DoubleAlign = LongLongAlign = 64;
- resetDataLayout("e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32");
- }
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- X86_32TargetInfo::getTargetDefines(Opts, Builder);
- Builder.defineMacro("_X86_");
- Builder.defineMacro("__CYGWIN__");
- Builder.defineMacro("__CYGWIN32__");
- addCygMingDefines(Opts, Builder);
- DefineStd(Builder, "unix", Opts);
- if (Opts.CPlusPlus)
- Builder.defineMacro("_GNU_SOURCE");
- }
-};
-
-// x86-32 Haiku target
-class HaikuX86_32TargetInfo : public HaikuTargetInfo<X86_32TargetInfo> {
-public:
- HaikuX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : HaikuTargetInfo<X86_32TargetInfo>(Triple, Opts) {
- }
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- HaikuTargetInfo<X86_32TargetInfo>::getTargetDefines(Opts, Builder);
- Builder.defineMacro("__INTEL__");
- }
-};
-
-// X86-32 MCU target
-class MCUX86_32TargetInfo : public X86_32TargetInfo {
-public:
- MCUX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : X86_32TargetInfo(Triple, Opts) {
- LongDoubleWidth = 64;
- LongDoubleFormat = &llvm::APFloat::IEEEdouble();
- resetDataLayout("e-m:e-p:32:32-i64:32-f64:32-f128:32-n8:16:32-a:0:32-S32");
- WIntType = UnsignedInt;
- }
-
- CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
- // On MCU we support only C calling convention.
- return CC == CC_C ? CCCR_OK : CCCR_Warning;
- }
-
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- X86_32TargetInfo::getTargetDefines(Opts, Builder);
- Builder.defineMacro("__iamcu");
- Builder.defineMacro("__iamcu__");
- }
-
- bool allowsLargerPreferedTypeAlignment() const override {
- return false;
- }
-};
-
-// RTEMS Target
-template<typename Target>
-class RTEMSTargetInfo : public OSTargetInfo<Target> {
-protected:
- void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const override {
- // RTEMS defines; list based off of gcc output
-
- Builder.defineMacro("__rtems__");
- Builder.defineMacro("__ELF__");
- }
-
-public:
- RTEMSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : OSTargetInfo<Target>(Triple, Opts) {
- switch (Triple.getArch()) {
- default:
- case llvm::Triple::x86:
- // this->MCountName = ".mcount";
- break;
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- case llvm::Triple::ppc:
- case llvm::Triple::ppc64:
- case llvm::Triple::ppc64le:
- // this->MCountName = "_mcount";
- break;
- case llvm::Triple::arm:
- // this->MCountName = "__mcount";
- break;
- }
- }
-};
-
-// x86-32 RTEMS target
-class RTEMSX86_32TargetInfo : public X86_32TargetInfo {
-public:
- RTEMSX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : X86_32TargetInfo(Triple, Opts) {
- SizeType = UnsignedLong;
- IntPtrType = SignedLong;
- PtrDiffType = SignedLong;
- }
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- X86_32TargetInfo::getTargetDefines(Opts, Builder);
- Builder.defineMacro("__INTEL__");
- Builder.defineMacro("__rtems__");
- }
-};
-
-// x86-64 generic target
-class X86_64TargetInfo : public X86TargetInfo {
-public:
- X86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : X86TargetInfo(Triple, Opts) {
- const bool IsX32 = getTriple().getEnvironment() == llvm::Triple::GNUX32;
- bool IsWinCOFF =
- getTriple().isOSWindows() && getTriple().isOSBinFormatCOFF();
- LongWidth = LongAlign = PointerWidth = PointerAlign = IsX32 ? 32 : 64;
- LongDoubleWidth = 128;
- LongDoubleAlign = 128;
- LargeArrayMinWidth = 128;
- LargeArrayAlign = 128;
- SuitableAlign = 128;
- SizeType = IsX32 ? UnsignedInt : UnsignedLong;
- PtrDiffType = IsX32 ? SignedInt : SignedLong;
- IntPtrType = IsX32 ? SignedInt : SignedLong;
- IntMaxType = IsX32 ? SignedLongLong : SignedLong;
- Int64Type = IsX32 ? SignedLongLong : SignedLong;
- RegParmMax = 6;
-
- // Pointers are 32-bit in x32.
- resetDataLayout(IsX32
- ? "e-m:e-p:32:32-i64:64-f80:128-n8:16:32:64-S128"
- : IsWinCOFF ? "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
- : "e-m:e-i64:64-f80:128-n8:16:32:64-S128");
-
- // Use fpret only for long double.
- RealTypeUsesObjCFPRet = (1 << TargetInfo::LongDouble);
-
- // Use fp2ret for _Complex long double.
- ComplexLongDoubleUsesFP2Ret = true;
-
- // Make __builtin_ms_va_list available.
- HasBuiltinMSVaList = true;
-
- // x86-64 has atomics up to 16 bytes.
- MaxAtomicPromoteWidth = 128;
- MaxAtomicInlineWidth = 128;
- }
- BuiltinVaListKind getBuiltinVaListKind() const override {
- return TargetInfo::X86_64ABIBuiltinVaList;
- }
-
- int getEHDataRegisterNumber(unsigned RegNo) const override {
- if (RegNo == 0) return 0;
- if (RegNo == 1) return 1;
- return -1;
- }
-
- CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
- switch (CC) {
- case CC_C:
- case CC_Swift:
- case CC_X86VectorCall:
- case CC_IntelOclBicc:
- case CC_Win64:
- case CC_PreserveMost:
- case CC_PreserveAll:
- case CC_X86RegCall:
- case CC_OpenCLKernel:
- return CCCR_OK;
- default:
- return CCCR_Warning;
- }
- }
-
- CallingConv getDefaultCallingConv(CallingConvMethodType MT) const override {
- return CC_C;
- }
-
- // for x32 we need it here explicitly
- bool hasInt128Type() const override { return true; }
- unsigned getUnwindWordWidth() const override { return 64; }
- unsigned getRegisterWidth() const override { return 64; }
-
- bool validateGlobalRegisterVariable(StringRef RegName,
- unsigned RegSize,
- bool &HasSizeMismatch) const override {
- // rsp and rbp are the only 64-bit registers the x86 backend can currently
- // handle.
- if (RegName.equals("rsp") || RegName.equals("rbp")) {
- // Check that the register size is 64-bit.
- HasSizeMismatch = RegSize != 64;
- return true;
- }
-
- // Check if the register is a 32-bit register the backend can handle.
- return X86TargetInfo::validateGlobalRegisterVariable(RegName, RegSize,
- HasSizeMismatch);
- }
- ArrayRef<Builtin::Info> getTargetBuiltins() const override {
- return llvm::makeArrayRef(BuiltinInfoX86,
- X86::LastTSBuiltin - Builtin::FirstTSBuiltin);
- }
-};
-
-// x86-64 Windows target
-class WindowsX86_64TargetInfo : public WindowsTargetInfo<X86_64TargetInfo> {
-public:
- WindowsX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : WindowsTargetInfo<X86_64TargetInfo>(Triple, Opts) {
- WCharType = UnsignedShort;
- LongWidth = LongAlign = 32;
- DoubleAlign = LongLongAlign = 64;
- IntMaxType = SignedLongLong;
- Int64Type = SignedLongLong;
- SizeType = UnsignedLongLong;
- PtrDiffType = SignedLongLong;
- IntPtrType = SignedLongLong;
- }
-
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- WindowsTargetInfo<X86_64TargetInfo>::getTargetDefines(Opts, Builder);
- Builder.defineMacro("_WIN64");
- }
-
- BuiltinVaListKind getBuiltinVaListKind() const override {
- return TargetInfo::CharPtrBuiltinVaList;
- }
-
- CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
- switch (CC) {
- case CC_X86StdCall:
- case CC_X86ThisCall:
- case CC_X86FastCall:
- return CCCR_Ignore;
- case CC_C:
- case CC_X86VectorCall:
- case CC_IntelOclBicc:
- case CC_X86_64SysV:
- case CC_Swift:
- case CC_X86RegCall:
- case CC_OpenCLKernel:
- return CCCR_OK;
- default:
- return CCCR_Warning;
- }
- }
-};
-
-// x86-64 Windows Visual Studio target
-class MicrosoftX86_64TargetInfo : public WindowsX86_64TargetInfo {
-public:
- MicrosoftX86_64TargetInfo(const llvm::Triple &Triple,
- const TargetOptions &Opts)
- : WindowsX86_64TargetInfo(Triple, Opts) {
- LongDoubleWidth = LongDoubleAlign = 64;
- LongDoubleFormat = &llvm::APFloat::IEEEdouble();
- }
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- WindowsX86_64TargetInfo::getTargetDefines(Opts, Builder);
- WindowsX86_64TargetInfo::getVisualStudioDefines(Opts, Builder);
- Builder.defineMacro("_M_X64", "100");
- Builder.defineMacro("_M_AMD64", "100");
- }
-};
-
-// x86-64 MinGW target
-class MinGWX86_64TargetInfo : public WindowsX86_64TargetInfo {
-public:
- MinGWX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : WindowsX86_64TargetInfo(Triple, Opts) {
- // Mingw64 rounds long double size and alignment up to 16 bytes, but sticks
- // with x86 FP ops. Weird.
- LongDoubleWidth = LongDoubleAlign = 128;
- LongDoubleFormat = &llvm::APFloat::x87DoubleExtended();
- HasFloat128 = true;
- }
-
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- WindowsX86_64TargetInfo::getTargetDefines(Opts, Builder);
+void addMinGWDefines(const llvm::Triple &Triple, const LangOptions &Opts,
+ MacroBuilder &Builder) {
+ DefineStd(Builder, "WIN32", Opts);
+ DefineStd(Builder, "WINNT", Opts);
+ if (Triple.isArch64Bit()) {
DefineStd(Builder, "WIN64", Opts);
Builder.defineMacro("__MINGW64__");
- addMinGWDefines(Opts, Builder);
-
- // GCC defines this macro when it is using __gxx_personality_seh0.
- if (!Opts.SjLjExceptions)
- Builder.defineMacro("__SEH__");
- }
-};
-
-// x86-64 Cygwin target
-class CygwinX86_64TargetInfo : public X86_64TargetInfo {
-public:
- CygwinX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : X86_64TargetInfo(Triple, Opts) {
- TLSSupported = false;
- WCharType = UnsignedShort;
- }
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- X86_64TargetInfo::getTargetDefines(Opts, Builder);
- Builder.defineMacro("__x86_64__");
- Builder.defineMacro("__CYGWIN__");
- Builder.defineMacro("__CYGWIN64__");
- addCygMingDefines(Opts, Builder);
- DefineStd(Builder, "unix", Opts);
- if (Opts.CPlusPlus)
- Builder.defineMacro("_GNU_SOURCE");
-
- // GCC defines this macro when it is using __gxx_personality_seh0.
- if (!Opts.SjLjExceptions)
- Builder.defineMacro("__SEH__");
- }
-};
-
-class DarwinX86_64TargetInfo : public DarwinTargetInfo<X86_64TargetInfo> {
-public:
- DarwinX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : DarwinTargetInfo<X86_64TargetInfo>(Triple, Opts) {
- Int64Type = SignedLongLong;
- // The 64-bit iOS simulator uses the builtin bool type for Objective-C.
- llvm::Triple T = llvm::Triple(Triple);
- if (T.isiOS())
- UseSignedCharForObjCBool = false;
- resetDataLayout("e-m:o-i64:64-f80:128-n8:16:32:64-S128");
}
-
- bool handleTargetFeatures(std::vector<std::string> &Features,
- DiagnosticsEngine &Diags) override {
- if (!DarwinTargetInfo<X86_64TargetInfo>::handleTargetFeatures(Features,
- Diags))
- return false;
- // We now know the features we have: we can decide how to align vectors.
- MaxVectorAlign =
- hasFeature("avx512f") ? 512 : hasFeature("avx") ? 256 : 128;
- return true;
- }
-};
-
-class OpenBSDX86_64TargetInfo : public OpenBSDTargetInfo<X86_64TargetInfo> {
-public:
- OpenBSDX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : OpenBSDTargetInfo<X86_64TargetInfo>(Triple, Opts) {
- IntMaxType = SignedLongLong;
- Int64Type = SignedLongLong;
- }
-};
-
-class BitrigX86_64TargetInfo : public BitrigTargetInfo<X86_64TargetInfo> {
-public:
- BitrigX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : BitrigTargetInfo<X86_64TargetInfo>(Triple, Opts) {
- IntMaxType = SignedLongLong;
- Int64Type = SignedLongLong;
- }
-};
-
-class ARMTargetInfo : public TargetInfo {
- // Possible FPU choices.
- enum FPUMode {
- VFP2FPU = (1 << 0),
- VFP3FPU = (1 << 1),
- VFP4FPU = (1 << 2),
- NeonFPU = (1 << 3),
- FPARMV8 = (1 << 4)
- };
-
- // Possible HWDiv features.
- enum HWDivMode {
- HWDivThumb = (1 << 0),
- HWDivARM = (1 << 1)
- };
-
- static bool FPUModeIsVFP(FPUMode Mode) {
- return Mode & (VFP2FPU | VFP3FPU | VFP4FPU | NeonFPU | FPARMV8);
- }
-
- static const TargetInfo::GCCRegAlias GCCRegAliases[];
- static const char * const GCCRegNames[];
-
- std::string ABI, CPU;
-
- StringRef CPUProfile;
- StringRef CPUAttr;
-
- enum {
- FP_Default,
- FP_VFP,
- FP_Neon
- } FPMath;
-
- unsigned ArchISA;
- unsigned ArchKind = llvm::ARM::AK_ARMV4T;
- unsigned ArchProfile;
- unsigned ArchVersion;
-
- unsigned FPU : 5;
-
- unsigned IsAAPCS : 1;
- unsigned HWDiv : 2;
-
- // Initialized via features.
- unsigned SoftFloat : 1;
- unsigned SoftFloatABI : 1;
-
- unsigned CRC : 1;
- unsigned Crypto : 1;
- unsigned DSP : 1;
- unsigned Unaligned : 1;
-
- enum {
- LDREX_B = (1 << 0), /// byte (8-bit)
- LDREX_H = (1 << 1), /// half (16-bit)
- LDREX_W = (1 << 2), /// word (32-bit)
- LDREX_D = (1 << 3), /// double (64-bit)
- };
-
- uint32_t LDREX;
-
- // ACLE 6.5.1 Hardware floating point
- enum {
- HW_FP_HP = (1 << 1), /// half (16-bit)
- HW_FP_SP = (1 << 2), /// single (32-bit)
- HW_FP_DP = (1 << 3), /// double (64-bit)
- };
- uint32_t HW_FP;
-
- static const Builtin::Info BuiltinInfo[];
-
- void setABIAAPCS() {
- IsAAPCS = true;
-
- DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;
- const llvm::Triple &T = getTriple();
-
- // size_t is unsigned long on MachO-derived environments, NetBSD,
- // OpenBSD and Bitrig.
- if (T.isOSBinFormatMachO() || T.getOS() == llvm::Triple::NetBSD ||
- T.getOS() == llvm::Triple::OpenBSD ||
- T.getOS() == llvm::Triple::Bitrig)
- SizeType = UnsignedLong;
- else
- SizeType = UnsignedInt;
-
- switch (T.getOS()) {
- case llvm::Triple::NetBSD:
- case llvm::Triple::OpenBSD:
- WCharType = SignedInt;
- break;
- case llvm::Triple::Win32:
- WCharType = UnsignedShort;
- break;
- case llvm::Triple::Linux:
- default:
- // AAPCS 7.1.1, ARM-Linux ABI 2.4: type of wchar_t is unsigned int.
- WCharType = UnsignedInt;
- break;
- }
-
- UseBitFieldTypeAlignment = true;
-
- ZeroLengthBitfieldBoundary = 0;
-
- // Thumb1 add sp, #imm requires the immediate value be multiple of 4,
- // so set preferred for small types to 32.
- if (T.isOSBinFormatMachO()) {
- resetDataLayout(BigEndian
- ? "E-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
- : "e-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64");
- } else if (T.isOSWindows()) {
- assert(!BigEndian && "Windows on ARM does not support big endian");
- resetDataLayout("e"
- "-m:w"
- "-p:32:32"
- "-i64:64"
- "-v128:64:128"
- "-a:0:32"
- "-n32"
- "-S64");
- } else if (T.isOSNaCl()) {
- assert(!BigEndian && "NaCl on ARM does not support big endian");
- resetDataLayout("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S128");
- } else {
- resetDataLayout(BigEndian
- ? "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
- : "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64");
- }
-
- // FIXME: Enumerated types are variable width in straight AAPCS.
- }
-
- void setABIAPCS(bool IsAAPCS16) {
- const llvm::Triple &T = getTriple();
-
- IsAAPCS = false;
-
- if (IsAAPCS16)
- DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;
- else
- DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 32;
-
- // size_t is unsigned int on FreeBSD.
- if (T.getOS() == llvm::Triple::FreeBSD)
- SizeType = UnsignedInt;
- else
- SizeType = UnsignedLong;
-
- // Revert to using SignedInt on apcs-gnu to comply with existing behaviour.
- WCharType = SignedInt;
-
- // Do not respect the alignment of bit-field types when laying out
- // structures. This corresponds to PCC_BITFIELD_TYPE_MATTERS in gcc.
- UseBitFieldTypeAlignment = false;
-
- /// gcc forces the alignment to 4 bytes, regardless of the type of the
- /// zero length bitfield. This corresponds to EMPTY_FIELD_BOUNDARY in
- /// gcc.
- ZeroLengthBitfieldBoundary = 32;
-
- if (T.isOSBinFormatMachO() && IsAAPCS16) {
- assert(!BigEndian && "AAPCS16 does not support big-endian");
- resetDataLayout("e-m:o-p:32:32-i64:64-a:0:32-n32-S128");
- } else if (T.isOSBinFormatMachO())
- resetDataLayout(
- BigEndian
- ? "E-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
- : "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32");
- else
- resetDataLayout(
- BigEndian
- ? "E-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
- : "e-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32");
-
- // FIXME: Override "preferred align" for double and long long.
- }
-
- void setArchInfo() {
- StringRef ArchName = getTriple().getArchName();
-
- ArchISA = llvm::ARM::parseArchISA(ArchName);
- CPU = llvm::ARM::getDefaultCPU(ArchName);
- unsigned AK = llvm::ARM::parseArch(ArchName);
- if (AK != llvm::ARM::AK_INVALID)
- ArchKind = AK;
- setArchInfo(ArchKind);
- }
-
- void setArchInfo(unsigned Kind) {
- StringRef SubArch;
-
- // cache TargetParser info
- ArchKind = Kind;
- SubArch = llvm::ARM::getSubArch(ArchKind);
- ArchProfile = llvm::ARM::parseArchProfile(SubArch);
- ArchVersion = llvm::ARM::parseArchVersion(SubArch);
-
- // cache CPU related strings
- CPUAttr = getCPUAttr();
- CPUProfile = getCPUProfile();
- }
-
- void setAtomic() {
- // when triple does not specify a sub arch,
- // then we are not using inline atomics
- bool ShouldUseInlineAtomic =
- (ArchISA == llvm::ARM::IK_ARM && ArchVersion >= 6) ||
- (ArchISA == llvm::ARM::IK_THUMB && ArchVersion >= 7);
- // Cortex M does not support 8 byte atomics, while general Thumb2 does.
- if (ArchProfile == llvm::ARM::PK_M) {
- MaxAtomicPromoteWidth = 32;
- if (ShouldUseInlineAtomic)
- MaxAtomicInlineWidth = 32;
- }
- else {
- MaxAtomicPromoteWidth = 64;
- if (ShouldUseInlineAtomic)
- MaxAtomicInlineWidth = 64;
- }
- }
-
- bool isThumb() const {
- return (ArchISA == llvm::ARM::IK_THUMB);
- }
-
- bool supportsThumb() const {
- return CPUAttr.count('T') || ArchVersion >= 6;
- }
-
- bool supportsThumb2() const {
- return CPUAttr.equals("6T2") ||
- (ArchVersion >= 7 && !CPUAttr.equals("8M_BASE"));
- }
-
- StringRef getCPUAttr() const {
- // For most sub-arches, the build attribute CPU name is enough.
- // For Cortex variants, it's slightly different.
- switch(ArchKind) {
- default:
- return llvm::ARM::getCPUAttr(ArchKind);
- case llvm::ARM::AK_ARMV6M:
- return "6M";
- case llvm::ARM::AK_ARMV7S:
- return "7S";
- case llvm::ARM::AK_ARMV7A:
- return "7A";
- case llvm::ARM::AK_ARMV7R:
- return "7R";
- case llvm::ARM::AK_ARMV7M:
- return "7M";
- case llvm::ARM::AK_ARMV7EM:
- return "7EM";
- case llvm::ARM::AK_ARMV7VE:
- return "7VE";
- case llvm::ARM::AK_ARMV8A:
- return "8A";
- case llvm::ARM::AK_ARMV8_1A:
- return "8_1A";
- case llvm::ARM::AK_ARMV8_2A:
- return "8_2A";
- case llvm::ARM::AK_ARMV8MBaseline:
- return "8M_BASE";
- case llvm::ARM::AK_ARMV8MMainline:
- return "8M_MAIN";
- case llvm::ARM::AK_ARMV8R:
- return "8R";
- }
- }
-
- StringRef getCPUProfile() const {
- switch(ArchProfile) {
- case llvm::ARM::PK_A:
- return "A";
- case llvm::ARM::PK_R:
- return "R";
- case llvm::ARM::PK_M:
- return "M";
- default:
- return "";
- }
- }
-
-public:
- ARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : TargetInfo(Triple), FPMath(FP_Default), IsAAPCS(true), LDREX(0),
- HW_FP(0) {
-
- switch (getTriple().getOS()) {
- case llvm::Triple::NetBSD:
- case llvm::Triple::OpenBSD:
- PtrDiffType = SignedLong;
- break;
- default:
- PtrDiffType = SignedInt;
- break;
- }
-
- // Cache arch related info.
- setArchInfo();
-
- // {} in inline assembly are neon specifiers, not assembly variant
- // specifiers.
- NoAsmVariants = true;
-
- // FIXME: This duplicates code from the driver that sets the -target-abi
- // option - this code is used if -target-abi isn't passed and should
- // be unified in some way.
- if (Triple.isOSBinFormatMachO()) {
- // The backend is hardwired to assume AAPCS for M-class processors, ensure
- // the frontend matches that.
- if (Triple.getEnvironment() == llvm::Triple::EABI ||
- Triple.getOS() == llvm::Triple::UnknownOS ||
- ArchProfile == llvm::ARM::PK_M) {
- setABI("aapcs");
- } else if (Triple.isWatchABI()) {
- setABI("aapcs16");
- } else {
- setABI("apcs-gnu");
- }
- } else if (Triple.isOSWindows()) {
- // FIXME: this is invalid for WindowsCE
- setABI("aapcs");
- } else {
- // Select the default based on the platform.
- switch (Triple.getEnvironment()) {
- case llvm::Triple::Android:
- case llvm::Triple::GNUEABI:
- case llvm::Triple::GNUEABIHF:
- case llvm::Triple::MuslEABI:
- case llvm::Triple::MuslEABIHF:
- setABI("aapcs-linux");
- break;
- case llvm::Triple::EABIHF:
- case llvm::Triple::EABI:
- setABI("aapcs");
- break;
- case llvm::Triple::GNU:
- setABI("apcs-gnu");
- break;
- default:
- if (Triple.getOS() == llvm::Triple::NetBSD)
- setABI("apcs-gnu");
- else if (Triple.getOS() == llvm::Triple::OpenBSD)
- setABI("aapcs-linux");
- else
- setABI("aapcs");
- break;
- }
- }
-
- // ARM targets default to using the ARM C++ ABI.
- TheCXXABI.set(TargetCXXABI::GenericARM);
-
- // ARM has atomics up to 8 bytes
- setAtomic();
-
- // Maximum alignment for ARM NEON data types should be 64-bits (AAPCS)
- if (IsAAPCS && (Triple.getEnvironment() != llvm::Triple::Android))
- MaxVectorAlign = 64;
-
- // Do force alignment of members that follow zero length bitfields. If
- // the alignment of the zero-length bitfield is greater than the member
- // that follows it, `bar', `bar' will be aligned as the type of the
- // zero length bitfield.
- UseZeroLengthBitfieldAlignment = true;
-
- if (Triple.getOS() == llvm::Triple::Linux ||
- Triple.getOS() == llvm::Triple::UnknownOS)
- this->MCountName =
- Opts.EABIVersion == llvm::EABI::GNU ? "\01__gnu_mcount_nc" : "\01mcount";
- }
-
- StringRef getABI() const override { return ABI; }
-
- bool setABI(const std::string &Name) override {
- ABI = Name;
-
- // The defaults (above) are for AAPCS, check if we need to change them.
- //
- // FIXME: We need support for -meabi... we could just mangle it into the
- // name.
- if (Name == "apcs-gnu" || Name == "aapcs16") {
- setABIAPCS(Name == "aapcs16");
- return true;
- }
- if (Name == "aapcs" || Name == "aapcs-vfp" || Name == "aapcs-linux") {
- setABIAAPCS();
- return true;
- }
- return false;
- }
-
- // FIXME: This should be based on Arch attributes, not CPU names.
- bool
- initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
- StringRef CPU,
- const std::vector<std::string> &FeaturesVec) const override {
-
- std::vector<StringRef> TargetFeatures;
- unsigned Arch = llvm::ARM::parseArch(getTriple().getArchName());
-
- // get default FPU features
- unsigned FPUKind = llvm::ARM::getDefaultFPU(CPU, Arch);
- llvm::ARM::getFPUFeatures(FPUKind, TargetFeatures);
-
- // get default Extension features
- unsigned Extensions = llvm::ARM::getDefaultExtensions(CPU, Arch);
- llvm::ARM::getExtensionFeatures(Extensions, TargetFeatures);
-
- for (auto Feature : TargetFeatures)
- if (Feature[0] == '+')
- Features[Feature.drop_front(1)] = true;
-
- // Enable or disable thumb-mode explicitly per function to enable mixed
- // ARM and Thumb code generation.
- if (isThumb())
- Features["thumb-mode"] = true;
- else
- Features["thumb-mode"] = false;
-
- // Convert user-provided arm and thumb GNU target attributes to
- // [-|+]thumb-mode target features respectively.
- std::vector<std::string> UpdatedFeaturesVec(FeaturesVec);
- for (auto &Feature : UpdatedFeaturesVec) {
- if (Feature.compare("+arm") == 0)
- Feature = "-thumb-mode";
- else if (Feature.compare("+thumb") == 0)
- Feature = "+thumb-mode";
- }
-
- return TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeaturesVec);
- }
-
- bool handleTargetFeatures(std::vector<std::string> &Features,
- DiagnosticsEngine &Diags) override {
- FPU = 0;
- CRC = 0;
- Crypto = 0;
- DSP = 0;
- Unaligned = 1;
- SoftFloat = SoftFloatABI = false;
- HWDiv = 0;
-
- // This does not diagnose illegal cases like having both
- // "+vfpv2" and "+vfpv3" or having "+neon" and "+fp-only-sp".
- uint32_t HW_FP_remove = 0;
- for (const auto &Feature : Features) {
- if (Feature == "+soft-float") {
- SoftFloat = true;
- } else if (Feature == "+soft-float-abi") {
- SoftFloatABI = true;
- } else if (Feature == "+vfp2") {
- FPU |= VFP2FPU;
- HW_FP |= HW_FP_SP | HW_FP_DP;
- } else if (Feature == "+vfp3") {
- FPU |= VFP3FPU;
- HW_FP |= HW_FP_SP | HW_FP_DP;
- } else if (Feature == "+vfp4") {
- FPU |= VFP4FPU;
- HW_FP |= HW_FP_SP | HW_FP_DP | HW_FP_HP;
- } else if (Feature == "+fp-armv8") {
- FPU |= FPARMV8;
- HW_FP |= HW_FP_SP | HW_FP_DP | HW_FP_HP;
- } else if (Feature == "+neon") {
- FPU |= NeonFPU;
- HW_FP |= HW_FP_SP | HW_FP_DP;
- } else if (Feature == "+hwdiv") {
- HWDiv |= HWDivThumb;
- } else if (Feature == "+hwdiv-arm") {
- HWDiv |= HWDivARM;
- } else if (Feature == "+crc") {
- CRC = 1;
- } else if (Feature == "+crypto") {
- Crypto = 1;
- } else if (Feature == "+dsp") {
- DSP = 1;
- } else if (Feature == "+fp-only-sp") {
- HW_FP_remove |= HW_FP_DP;
- } else if (Feature == "+strict-align") {
- Unaligned = 0;
- } else if (Feature == "+fp16") {
- HW_FP |= HW_FP_HP;
- }
- }
- HW_FP &= ~HW_FP_remove;
-
- switch (ArchVersion) {
- case 6:
- if (ArchProfile == llvm::ARM::PK_M)
- LDREX = 0;
- else if (ArchKind == llvm::ARM::AK_ARMV6K)
- LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B ;
- else
- LDREX = LDREX_W;
- break;
- case 7:
- if (ArchProfile == llvm::ARM::PK_M)
- LDREX = LDREX_W | LDREX_H | LDREX_B ;
- else
- LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B ;
- break;
- case 8:
- LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B ;
- }
-
- if (!(FPU & NeonFPU) && FPMath == FP_Neon) {
- Diags.Report(diag::err_target_unsupported_fpmath) << "neon";
- return false;
- }
-
- if (FPMath == FP_Neon)
- Features.push_back("+neonfp");
- else if (FPMath == FP_VFP)
- Features.push_back("-neonfp");
-
- // Remove front-end specific options which the backend handles differently.
- auto Feature =
- std::find(Features.begin(), Features.end(), "+soft-float-abi");
- if (Feature != Features.end())
- Features.erase(Feature);
-
- return true;
- }
-
- bool hasFeature(StringRef Feature) const override {
- return llvm::StringSwitch<bool>(Feature)
- .Case("arm", true)
- .Case("aarch32", true)
- .Case("softfloat", SoftFloat)
- .Case("thumb", isThumb())
- .Case("neon", (FPU & NeonFPU) && !SoftFloat)
- .Case("vfp", FPU && !SoftFloat)
- .Case("hwdiv", HWDiv & HWDivThumb)
- .Case("hwdiv-arm", HWDiv & HWDivARM)
- .Default(false);
- }
-
- bool setCPU(const std::string &Name) override {
- if (Name != "generic")
- setArchInfo(llvm::ARM::parseCPUArch(Name));
-
- if (ArchKind == llvm::ARM::AK_INVALID)
- return false;
- setAtomic();
- CPU = Name;
- return true;
- }
-
- bool setFPMath(StringRef Name) override;
-
- void getTargetDefinesARMV81A(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
- }
-
- void getTargetDefinesARMV82A(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- // Also include the ARMv8.1-A defines
- getTargetDefinesARMV81A(Opts, Builder);
- }
-
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- // Target identification.
- Builder.defineMacro("__arm");
- Builder.defineMacro("__arm__");
- // For bare-metal none-eabi.
- if (getTriple().getOS() == llvm::Triple::UnknownOS &&
- (getTriple().getEnvironment() == llvm::Triple::EABI ||
- getTriple().getEnvironment() == llvm::Triple::EABIHF))
- Builder.defineMacro("__ELF__");
-
-
- // Target properties.
- Builder.defineMacro("__REGISTER_PREFIX__", "");
-
- // Unfortunately, __ARM_ARCH_7K__ is now more of an ABI descriptor. The CPU
- // happens to be Cortex-A7 though, so it should still get __ARM_ARCH_7A__.
- if (getTriple().isWatchABI())
- Builder.defineMacro("__ARM_ARCH_7K__", "2");
-
- if (!CPUAttr.empty())
- Builder.defineMacro("__ARM_ARCH_" + CPUAttr + "__");
-
- // ACLE 6.4.1 ARM/Thumb instruction set architecture
- // __ARM_ARCH is defined as an integer value indicating the current ARM ISA
- Builder.defineMacro("__ARM_ARCH", Twine(ArchVersion));
-
- if (ArchVersion >= 8) {
- // ACLE 6.5.7 Crypto Extension
- if (Crypto)
- Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
- // ACLE 6.5.8 CRC32 Extension
- if (CRC)
- Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
- // ACLE 6.5.10 Numeric Maximum and Minimum
- Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");
- // ACLE 6.5.9 Directed Rounding
- Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");
- }
-
- // __ARM_ARCH_ISA_ARM is defined to 1 if the core supports the ARM ISA. It
- // is not defined for the M-profile.
- // NOTE that the default profile is assumed to be 'A'
- if (CPUProfile.empty() || ArchProfile != llvm::ARM::PK_M)
- Builder.defineMacro("__ARM_ARCH_ISA_ARM", "1");
-
- // __ARM_ARCH_ISA_THUMB is defined to 1 if the core supports the original
- // Thumb ISA (including v6-M and v8-M Baseline). It is set to 2 if the
- // core supports the Thumb-2 ISA as found in the v6T2 architecture and all
- // v7 and v8 architectures excluding v8-M Baseline.
- if (supportsThumb2())
- Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "2");
- else if (supportsThumb())
- Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "1");
-
- // __ARM_32BIT_STATE is defined to 1 if code is being generated for a 32-bit
- // instruction set such as ARM or Thumb.
- Builder.defineMacro("__ARM_32BIT_STATE", "1");
-
- // ACLE 6.4.2 Architectural Profile (A, R, M or pre-Cortex)
-
- // __ARM_ARCH_PROFILE is defined as 'A', 'R', 'M' or 'S', or unset.
- if (!CPUProfile.empty())
- Builder.defineMacro("__ARM_ARCH_PROFILE", "'" + CPUProfile + "'");
-
- // ACLE 6.4.3 Unaligned access supported in hardware
- if (Unaligned)
- Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
-
- // ACLE 6.4.4 LDREX/STREX
- if (LDREX)
- Builder.defineMacro("__ARM_FEATURE_LDREX", "0x" + llvm::utohexstr(LDREX));
-
- // ACLE 6.4.5 CLZ
- if (ArchVersion == 5 ||
- (ArchVersion == 6 && CPUProfile != "M") ||
- ArchVersion > 6)
- Builder.defineMacro("__ARM_FEATURE_CLZ", "1");
-
- // ACLE 6.5.1 Hardware Floating Point
- if (HW_FP)
- Builder.defineMacro("__ARM_FP", "0x" + llvm::utohexstr(HW_FP));
-
- // ACLE predefines.
- Builder.defineMacro("__ARM_ACLE", "200");
-
- // FP16 support (we currently only support IEEE format).
- Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
- Builder.defineMacro("__ARM_FP16_ARGS", "1");
-
- // ACLE 6.5.3 Fused multiply-accumulate (FMA)
- if (ArchVersion >= 7 && (FPU & VFP4FPU))
- Builder.defineMacro("__ARM_FEATURE_FMA", "1");
-
- // Subtarget options.
-
- // FIXME: It's more complicated than this and we don't really support
- // interworking.
- // Windows on ARM does not "support" interworking
- if (5 <= ArchVersion && ArchVersion <= 8 && !getTriple().isOSWindows())
- Builder.defineMacro("__THUMB_INTERWORK__");
-
- if (ABI == "aapcs" || ABI == "aapcs-linux" || ABI == "aapcs-vfp") {
- // Embedded targets on Darwin follow AAPCS, but not EABI.
- // Windows on ARM follows AAPCS VFP, but does not conform to EABI.
- if (!getTriple().isOSBinFormatMachO() && !getTriple().isOSWindows())
- Builder.defineMacro("__ARM_EABI__");
- Builder.defineMacro("__ARM_PCS", "1");
- }
-
- if ((!SoftFloat && !SoftFloatABI) || ABI == "aapcs-vfp" ||
- ABI == "aapcs16")
- Builder.defineMacro("__ARM_PCS_VFP", "1");
-
- if (SoftFloat)
- Builder.defineMacro("__SOFTFP__");
-
- if (ArchKind == llvm::ARM::AK_XSCALE)
- Builder.defineMacro("__XSCALE__");
-
- if (isThumb()) {
- Builder.defineMacro("__THUMBEL__");
- Builder.defineMacro("__thumb__");
- if (supportsThumb2())
- Builder.defineMacro("__thumb2__");
- }
-
- // ACLE 6.4.9 32-bit SIMD instructions
- if (ArchVersion >= 6 && (CPUProfile != "M" || CPUAttr == "7EM"))
- Builder.defineMacro("__ARM_FEATURE_SIMD32", "1");
-
- // ACLE 6.4.10 Hardware Integer Divide
- if (((HWDiv & HWDivThumb) && isThumb()) ||
- ((HWDiv & HWDivARM) && !isThumb())) {
- Builder.defineMacro("__ARM_FEATURE_IDIV", "1");
- Builder.defineMacro("__ARM_ARCH_EXT_IDIV__", "1");
- }
-
- // Note, this is always on in gcc, even though it doesn't make sense.
- Builder.defineMacro("__APCS_32__");
-
- if (FPUModeIsVFP((FPUMode) FPU)) {
- Builder.defineMacro("__VFP_FP__");
- if (FPU & VFP2FPU)
- Builder.defineMacro("__ARM_VFPV2__");
- if (FPU & VFP3FPU)
- Builder.defineMacro("__ARM_VFPV3__");
- if (FPU & VFP4FPU)
- Builder.defineMacro("__ARM_VFPV4__");
- if (FPU & FPARMV8)
- Builder.defineMacro("__ARM_FPV5__");
- }
-
- // This only gets set when Neon instructions are actually available, unlike
- // the VFP define, hence the soft float and arch check. This is subtly
- // different from gcc, we follow the intent which was that it should be set
- // when Neon instructions are actually available.
- if ((FPU & NeonFPU) && !SoftFloat && ArchVersion >= 7) {
- Builder.defineMacro("__ARM_NEON", "1");
- Builder.defineMacro("__ARM_NEON__");
- // current AArch32 NEON implementations do not support double-precision
- // floating-point even when it is present in VFP.
- Builder.defineMacro("__ARM_NEON_FP",
- "0x" + llvm::utohexstr(HW_FP & ~HW_FP_DP));
- }
-
- Builder.defineMacro("__ARM_SIZEOF_WCHAR_T",
- Opts.ShortWChar ? "2" : "4");
-
- Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM",
- Opts.ShortEnums ? "1" : "4");
-
- if (ArchVersion >= 6 && CPUAttr != "6M" && CPUAttr != "8M_BASE") {
- Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
- Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
- Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
- Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
- }
-
- // ACLE 6.4.7 DSP instructions
- if (DSP) {
- Builder.defineMacro("__ARM_FEATURE_DSP", "1");
- }
-
- // ACLE 6.4.8 Saturation instructions
- bool SAT = false;
- if ((ArchVersion == 6 && CPUProfile != "M") || ArchVersion > 6 ) {
- Builder.defineMacro("__ARM_FEATURE_SAT", "1");
- SAT = true;
- }
-
- // ACLE 6.4.6 Q (saturation) flag
- if (DSP || SAT)
- Builder.defineMacro("__ARM_FEATURE_QBIT", "1");
-
- if (Opts.UnsafeFPMath)
- Builder.defineMacro("__ARM_FP_FAST", "1");
-
- switch(ArchKind) {
- default: break;
- case llvm::ARM::AK_ARMV8_1A:
- getTargetDefinesARMV81A(Opts, Builder);
- break;
- case llvm::ARM::AK_ARMV8_2A:
- getTargetDefinesARMV82A(Opts, Builder);
- break;
- }
- }
-
- ArrayRef<Builtin::Info> getTargetBuiltins() const override {
- return llvm::makeArrayRef(BuiltinInfo,
- clang::ARM::LastTSBuiltin-Builtin::FirstTSBuiltin);
- }
- bool isCLZForZeroUndef() const override { return false; }
- BuiltinVaListKind getBuiltinVaListKind() const override {
- return IsAAPCS
- ? AAPCSABIBuiltinVaList
- : (getTriple().isWatchABI() ? TargetInfo::CharPtrBuiltinVaList
- : TargetInfo::VoidPtrBuiltinVaList);
- }
- ArrayRef<const char *> getGCCRegNames() const override;
- ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
- bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &Info) const override {
- switch (*Name) {
- default: break;
- case 'l': // r0-r7
- case 'h': // r8-r15
- case 't': // VFP Floating point register single precision
- case 'w': // VFP Floating point register double precision
- Info.setAllowsRegister();
- return true;
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- // FIXME
- return true;
- case 'Q': // A memory address that is a single base register.
- Info.setAllowsMemory();
- return true;
- case 'U': // a memory reference...
- switch (Name[1]) {
- case 'q': // ...ARMV4 ldrsb
- case 'v': // ...VFP load/store (reg+constant offset)
- case 'y': // ...iWMMXt load/store
- case 't': // address valid for load/store opaque types wider
- // than 128-bits
- case 'n': // valid address for Neon doubleword vector load/store
- case 'm': // valid address for Neon element and structure load/store
- case 's': // valid address for non-offset loads/stores of quad-word
- // values in four ARM registers
- Info.setAllowsMemory();
- Name++;
- return true;
- }
- }
- return false;
- }
- std::string convertConstraint(const char *&Constraint) const override {
- std::string R;
- switch (*Constraint) {
- case 'U': // Two-character constraint; add "^" hint for later parsing.
- R = std::string("^") + std::string(Constraint, 2);
- Constraint++;
- break;
- case 'p': // 'p' should be translated to 'r' by default.
- R = std::string("r");
- break;
- default:
- return std::string(1, *Constraint);
- }
- return R;
- }
- bool
- validateConstraintModifier(StringRef Constraint, char Modifier, unsigned Size,
- std::string &SuggestedModifier) const override {
- bool isOutput = (Constraint[0] == '=');
- bool isInOut = (Constraint[0] == '+');
-
- // Strip off constraint modifiers.
- while (Constraint[0] == '=' ||
- Constraint[0] == '+' ||
- Constraint[0] == '&')
- Constraint = Constraint.substr(1);
-
- switch (Constraint[0]) {
- default: break;
- case 'r': {
- switch (Modifier) {
- default:
- return (isInOut || isOutput || Size <= 64);
- case 'q':
- // A register of size 32 cannot fit a vector type.
- return false;
- }
- }
- }
-
- return true;
- }
- const char *getClobbers() const override {
- // FIXME: Is this really right?
- return "";
- }
-
- CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
- switch (CC) {
- case CC_AAPCS:
- case CC_AAPCS_VFP:
- case CC_Swift:
- case CC_OpenCLKernel:
- return CCCR_OK;
- default:
- return CCCR_Warning;
- }
- }
-
- int getEHDataRegisterNumber(unsigned RegNo) const override {
- if (RegNo == 0) return 0;
- if (RegNo == 1) return 1;
- return -1;
- }
-
- bool hasSjLjLowering() const override {
- return true;
- }
-};
-
-bool ARMTargetInfo::setFPMath(StringRef Name) {
- if (Name == "neon") {
- FPMath = FP_Neon;
- return true;
- } else if (Name == "vfp" || Name == "vfp2" || Name == "vfp3" ||
- Name == "vfp4") {
- FPMath = FP_VFP;
- return true;
- }
- return false;
-}
-
-const char * const ARMTargetInfo::GCCRegNames[] = {
- // Integer registers
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc",
-
- // Float registers
- "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
- "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15",
- "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
- "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
-
- // Double registers
- "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
- "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15",
- "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
- "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
-
- // Quad registers
- "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7",
- "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15"
-};
-
-ArrayRef<const char *> ARMTargetInfo::getGCCRegNames() const {
- return llvm::makeArrayRef(GCCRegNames);
-}
-
-const TargetInfo::GCCRegAlias ARMTargetInfo::GCCRegAliases[] = {
- { { "a1" }, "r0" },
- { { "a2" }, "r1" },
- { { "a3" }, "r2" },
- { { "a4" }, "r3" },
- { { "v1" }, "r4" },
- { { "v2" }, "r5" },
- { { "v3" }, "r6" },
- { { "v4" }, "r7" },
- { { "v5" }, "r8" },
- { { "v6", "rfp" }, "r9" },
- { { "sl" }, "r10" },
- { { "fp" }, "r11" },
- { { "ip" }, "r12" },
- { { "r13" }, "sp" },
- { { "r14" }, "lr" },
- { { "r15" }, "pc" },
- // The S, D and Q registers overlap, but aren't really aliases; we
- // don't want to substitute one of these for a different-sized one.
-};
-
-ArrayRef<TargetInfo::GCCRegAlias> ARMTargetInfo::getGCCRegAliases() const {
- return llvm::makeArrayRef(GCCRegAliases);
-}
-
-const Builtin::Info ARMTargetInfo::BuiltinInfo[] = {
-#define BUILTIN(ID, TYPE, ATTRS) \
- { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
- { #ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr },
-#include "clang/Basic/BuiltinsNEON.def"
-
-#define BUILTIN(ID, TYPE, ATTRS) \
- { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
-#define LANGBUILTIN(ID, TYPE, ATTRS, LANG) \
- { #ID, TYPE, ATTRS, nullptr, LANG, nullptr },
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
- { #ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr },
-#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \
- { #ID, TYPE, ATTRS, HEADER, LANGS, FEATURE },
-#include "clang/Basic/BuiltinsARM.def"
-};
-
-class ARMleTargetInfo : public ARMTargetInfo {
-public:
- ARMleTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : ARMTargetInfo(Triple, Opts) {}
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- Builder.defineMacro("__ARMEL__");
- ARMTargetInfo::getTargetDefines(Opts, Builder);
- }
-};
-
-class ARMbeTargetInfo : public ARMTargetInfo {
-public:
- ARMbeTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : ARMTargetInfo(Triple, Opts) {}
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- Builder.defineMacro("__ARMEB__");
- Builder.defineMacro("__ARM_BIG_ENDIAN");
- ARMTargetInfo::getTargetDefines(Opts, Builder);
- }
-};
-
-class WindowsARMTargetInfo : public WindowsTargetInfo<ARMleTargetInfo> {
- const llvm::Triple Triple;
-public:
- WindowsARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : WindowsTargetInfo<ARMleTargetInfo>(Triple, Opts), Triple(Triple) {
- WCharType = UnsignedShort;
- SizeType = UnsignedInt;
- }
- void getVisualStudioDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- WindowsTargetInfo<ARMleTargetInfo>::getVisualStudioDefines(Opts, Builder);
-
- // FIXME: this is invalid for WindowsCE
- Builder.defineMacro("_M_ARM_NT", "1");
- Builder.defineMacro("_M_ARMT", "_M_ARM");
- Builder.defineMacro("_M_THUMB", "_M_ARM");
-
- assert((Triple.getArch() == llvm::Triple::arm ||
- Triple.getArch() == llvm::Triple::thumb) &&
- "invalid architecture for Windows ARM target info");
- unsigned Offset = Triple.getArch() == llvm::Triple::arm ? 4 : 6;
- Builder.defineMacro("_M_ARM", Triple.getArchName().substr(Offset));
-
- // TODO map the complete set of values
- // 31: VFPv3 40: VFPv4
- Builder.defineMacro("_M_ARM_FP", "31");
- }
- BuiltinVaListKind getBuiltinVaListKind() const override {
- return TargetInfo::CharPtrBuiltinVaList;
- }
- CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
- switch (CC) {
- case CC_X86StdCall:
- case CC_X86ThisCall:
- case CC_X86FastCall:
- case CC_X86VectorCall:
- return CCCR_Ignore;
- case CC_C:
- case CC_OpenCLKernel:
- return CCCR_OK;
- default:
- return CCCR_Warning;
- }
- }
-};
-
-// Windows ARM + Itanium C++ ABI Target
-class ItaniumWindowsARMleTargetInfo : public WindowsARMTargetInfo {
-public:
- ItaniumWindowsARMleTargetInfo(const llvm::Triple &Triple,
- const TargetOptions &Opts)
- : WindowsARMTargetInfo(Triple, Opts) {
- TheCXXABI.set(TargetCXXABI::GenericARM);
- }
-
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
-
- if (Opts.MSVCCompat)
- WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
- }
-};
-
-// Windows ARM, MS (C++) ABI
-class MicrosoftARMleTargetInfo : public WindowsARMTargetInfo {
-public:
- MicrosoftARMleTargetInfo(const llvm::Triple &Triple,
- const TargetOptions &Opts)
- : WindowsARMTargetInfo(Triple, Opts) {
- TheCXXABI.set(TargetCXXABI::Microsoft);
- }
-
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
- WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
- }
-};
-
-// ARM MinGW target
-class MinGWARMTargetInfo : public WindowsARMTargetInfo {
-public:
- MinGWARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : WindowsARMTargetInfo(Triple, Opts) {
- TheCXXABI.set(TargetCXXABI::GenericARM);
- }
-
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
- DefineStd(Builder, "WIN32", Opts);
- DefineStd(Builder, "WINNT", Opts);
- Builder.defineMacro("_ARM_");
- addMinGWDefines(Opts, Builder);
- }
-};
-
-// ARM Cygwin target
-class CygwinARMTargetInfo : public ARMleTargetInfo {
-public:
- CygwinARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : ARMleTargetInfo(Triple, Opts) {
- TLSSupported = false;
- WCharType = UnsignedShort;
- DoubleAlign = LongLongAlign = 64;
- resetDataLayout("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64");
- }
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- ARMleTargetInfo::getTargetDefines(Opts, Builder);
- Builder.defineMacro("_ARM_");
- Builder.defineMacro("__CYGWIN__");
- Builder.defineMacro("__CYGWIN32__");
- DefineStd(Builder, "unix", Opts);
- if (Opts.CPlusPlus)
- Builder.defineMacro("_GNU_SOURCE");
- }
-};
-
-class DarwinARMTargetInfo : public DarwinTargetInfo<ARMleTargetInfo> {
-protected:
- void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const override {
- getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
- }
-
-public:
- DarwinARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : DarwinTargetInfo<ARMleTargetInfo>(Triple, Opts) {
- HasAlignMac68kSupport = true;
- // iOS always has 64-bit atomic instructions.
- // FIXME: This should be based off of the target features in
- // ARMleTargetInfo.
- MaxAtomicInlineWidth = 64;
-
- if (Triple.isWatchABI()) {
- // Darwin on iOS uses a variant of the ARM C++ ABI.
- TheCXXABI.set(TargetCXXABI::WatchOS);
-
- // The 32-bit ABI is silent on what ptrdiff_t should be, but given that
- // size_t is long, it's a bit weird for it to be int.
- PtrDiffType = SignedLong;
-
- // BOOL should be a real boolean on the new ABI
- UseSignedCharForObjCBool = false;
- } else
- TheCXXABI.set(TargetCXXABI::iOS);
- }
-};
-
-class AArch64TargetInfo : public TargetInfo {
- virtual void setDataLayout() = 0;
- static const TargetInfo::GCCRegAlias GCCRegAliases[];
- static const char *const GCCRegNames[];
-
- enum FPUModeEnum {
- FPUMode,
- NeonMode = (1 << 0),
- SveMode = (1 << 1)
- };
-
- unsigned FPU;
- unsigned CRC;
- unsigned Crypto;
- unsigned Unaligned;
- unsigned HasFullFP16;
- llvm::AArch64::ArchKind ArchKind;
-
- static const Builtin::Info BuiltinInfo[];
-
- std::string ABI;
-
-public:
- AArch64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : TargetInfo(Triple), ABI("aapcs") {
- if (getTriple().getOS() == llvm::Triple::NetBSD ||
- getTriple().getOS() == llvm::Triple::OpenBSD) {
- WCharType = SignedInt;
-
- // NetBSD apparently prefers consistency across ARM targets to consistency
- // across 64-bit targets.
- Int64Type = SignedLongLong;
- IntMaxType = SignedLongLong;
- } else {
- WCharType = UnsignedInt;
- Int64Type = SignedLong;
- IntMaxType = SignedLong;
- }
-
- LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
- MaxVectorAlign = 128;
- MaxAtomicInlineWidth = 128;
- MaxAtomicPromoteWidth = 128;
-
- LongDoubleWidth = LongDoubleAlign = SuitableAlign = 128;
- LongDoubleFormat = &llvm::APFloat::IEEEquad();
-
- // Make __builtin_ms_va_list available.
- HasBuiltinMSVaList = true;
-
- // {} in inline assembly are neon specifiers, not assembly variant
- // specifiers.
- NoAsmVariants = true;
-
- // AAPCS gives rules for bitfields. 7.1.7 says: "The container type
- // contributes to the alignment of the containing aggregate in the same way
- // a plain (non bit-field) member of that type would, without exception for
- // zero-sized or anonymous bit-fields."
- assert(UseBitFieldTypeAlignment && "bitfields affect type alignment");
- UseZeroLengthBitfieldAlignment = true;
-
- // AArch64 targets default to using the ARM C++ ABI.
- TheCXXABI.set(TargetCXXABI::GenericAArch64);
-
- if (Triple.getOS() == llvm::Triple::Linux)
- this->MCountName = "\01_mcount";
- else if (Triple.getOS() == llvm::Triple::UnknownOS)
- this->MCountName = Opts.EABIVersion == llvm::EABI::GNU ? "\01_mcount" : "mcount";
- }
-
- StringRef getABI() const override { return ABI; }
- bool setABI(const std::string &Name) override {
- if (Name != "aapcs" && Name != "darwinpcs")
- return false;
-
- ABI = Name;
- return true;
- }
-
- bool setCPU(const std::string &Name) override {
- return Name == "generic" ||
- llvm::AArch64::parseCPUArch(Name) !=
- static_cast<unsigned>(llvm::AArch64::ArchKind::AK_INVALID);
- }
-
- void getTargetDefinesARMV81A(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
- }
-
- void getTargetDefinesARMV82A(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- // Also include the ARMv8.1 defines
- getTargetDefinesARMV81A(Opts, Builder);
- }
-
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- // Target identification.
- Builder.defineMacro("__aarch64__");
- // For bare-metal none-eabi.
- if (getTriple().getOS() == llvm::Triple::UnknownOS &&
- (getTriple().getEnvironment() == llvm::Triple::EABI ||
- getTriple().getEnvironment() == llvm::Triple::EABIHF))
- Builder.defineMacro("__ELF__");
-
- // Target properties.
- Builder.defineMacro("_LP64");
- Builder.defineMacro("__LP64__");
-
- // ACLE predefines. Many can only have one possible value on v8 AArch64.
- Builder.defineMacro("__ARM_ACLE", "200");
- Builder.defineMacro("__ARM_ARCH", "8");
- Builder.defineMacro("__ARM_ARCH_PROFILE", "'A'");
-
- Builder.defineMacro("__ARM_64BIT_STATE", "1");
- Builder.defineMacro("__ARM_PCS_AAPCS64", "1");
- Builder.defineMacro("__ARM_ARCH_ISA_A64", "1");
-
- Builder.defineMacro("__ARM_FEATURE_CLZ", "1");
- Builder.defineMacro("__ARM_FEATURE_FMA", "1");
- Builder.defineMacro("__ARM_FEATURE_LDREX", "0xF");
- Builder.defineMacro("__ARM_FEATURE_IDIV", "1"); // As specified in ACLE
- Builder.defineMacro("__ARM_FEATURE_DIV"); // For backwards compatibility
- Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");
- Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");
-
- Builder.defineMacro("__ARM_ALIGN_MAX_STACK_PWR", "4");
-
- // 0xe implies support for half, single and double precision operations.
- Builder.defineMacro("__ARM_FP", "0xE");
-
- // PCS specifies this for SysV variants, which is all we support. Other ABIs
- // may choose __ARM_FP16_FORMAT_ALTERNATIVE.
- Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
- Builder.defineMacro("__ARM_FP16_ARGS", "1");
-
- if (Opts.UnsafeFPMath)
- Builder.defineMacro("__ARM_FP_FAST", "1");
-
- Builder.defineMacro("__ARM_SIZEOF_WCHAR_T", Opts.ShortWChar ? "2" : "4");
-
- Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM",
- Opts.ShortEnums ? "1" : "4");
-
- if (FPU & NeonMode) {
- Builder.defineMacro("__ARM_NEON", "1");
- // 64-bit NEON supports half, single and double precision operations.
- Builder.defineMacro("__ARM_NEON_FP", "0xE");
- }
-
- if (FPU & SveMode)
- Builder.defineMacro("__ARM_FEATURE_SVE", "1");
-
- if (CRC)
- Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
-
- if (Crypto)
- Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
-
- if (Unaligned)
- Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
-
- switch(ArchKind) {
- default: break;
- case llvm::AArch64::ArchKind::AK_ARMV8_1A:
- getTargetDefinesARMV81A(Opts, Builder);
- break;
- case llvm::AArch64::ArchKind::AK_ARMV8_2A:
- getTargetDefinesARMV82A(Opts, Builder);
- break;
- }
-
- // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work.
- Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
- Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
- Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
- Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
- }
-
- ArrayRef<Builtin::Info> getTargetBuiltins() const override {
- return llvm::makeArrayRef(BuiltinInfo,
- clang::AArch64::LastTSBuiltin - Builtin::FirstTSBuiltin);
- }
-
- bool hasFeature(StringRef Feature) const override {
- return Feature == "aarch64" ||
- Feature == "arm64" ||
- Feature == "arm" ||
- (Feature == "neon" && (FPU & NeonMode)) ||
- (Feature == "sve" && (FPU & SveMode));
- }
-
- bool handleTargetFeatures(std::vector<std::string> &Features,
- DiagnosticsEngine &Diags) override {
- FPU = FPUMode;
- CRC = 0;
- Crypto = 0;
- Unaligned = 1;
- HasFullFP16 = 0;
- ArchKind = llvm::AArch64::ArchKind::AK_ARMV8A;
-
- for (const auto &Feature : Features) {
- if (Feature == "+neon")
- FPU |= NeonMode;
- if (Feature == "+sve")
- FPU |= SveMode;
- if (Feature == "+crc")
- CRC = 1;
- if (Feature == "+crypto")
- Crypto = 1;
- if (Feature == "+strict-align")
- Unaligned = 0;
- if (Feature == "+v8.1a")
- ArchKind = llvm::AArch64::ArchKind::AK_ARMV8_1A;
- if (Feature == "+v8.2a")
- ArchKind = llvm::AArch64::ArchKind::AK_ARMV8_2A;
- if (Feature == "+fullfp16")
- HasFullFP16 = 1;
- }
-
- setDataLayout();
-
- return true;
- }
-
- CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
- switch (CC) {
- case CC_C:
- case CC_Swift:
- case CC_PreserveMost:
- case CC_PreserveAll:
- case CC_OpenCLKernel:
- case CC_Win64:
- return CCCR_OK;
- default:
- return CCCR_Warning;
- }
- }
-
- bool isCLZForZeroUndef() const override { return false; }
-
- BuiltinVaListKind getBuiltinVaListKind() const override {
- return TargetInfo::AArch64ABIBuiltinVaList;
- }
-
- ArrayRef<const char *> getGCCRegNames() const override;
- ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
-
- bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &Info) const override {
- switch (*Name) {
- default:
- return false;
- case 'w': // Floating point and SIMD registers (V0-V31)
- Info.setAllowsRegister();
- return true;
- case 'I': // Constant that can be used with an ADD instruction
- case 'J': // Constant that can be used with a SUB instruction
- case 'K': // Constant that can be used with a 32-bit logical instruction
- case 'L': // Constant that can be used with a 64-bit logical instruction
- case 'M': // Constant that can be used as a 32-bit MOV immediate
- case 'N': // Constant that can be used as a 64-bit MOV immediate
- case 'Y': // Floating point constant zero
- case 'Z': // Integer constant zero
- return true;
- case 'Q': // A memory reference with base register and no offset
- Info.setAllowsMemory();
- return true;
- case 'S': // A symbolic address
- Info.setAllowsRegister();
- return true;
- case 'U':
- // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes.
- // Utf: A memory address suitable for ldp/stp in TF mode.
- // Usa: An absolute symbolic address.
- // Ush: The high part (bits 32:12) of a pc-relative symbolic address.
- llvm_unreachable("FIXME: Unimplemented support for U* constraints.");
- case 'z': // Zero register, wzr or xzr
- Info.setAllowsRegister();
- return true;
- case 'x': // Floating point and SIMD registers (V0-V15)
- Info.setAllowsRegister();
- return true;
- }
- return false;
- }
-
- bool
- validateConstraintModifier(StringRef Constraint, char Modifier, unsigned Size,
- std::string &SuggestedModifier) const override {
- // Strip off constraint modifiers.
- while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
- Constraint = Constraint.substr(1);
-
- switch (Constraint[0]) {
- default:
- return true;
- case 'z':
- case 'r': {
- switch (Modifier) {
- case 'x':
- case 'w':
- // For now assume that the person knows what they're
- // doing with the modifier.
- return true;
- default:
- // By default an 'r' constraint will be in the 'x'
- // registers.
- if (Size == 64)
- return true;
-
- SuggestedModifier = "w";
- return false;
- }
- }
- }
- }
-
- const char *getClobbers() const override { return ""; }
-
- int getEHDataRegisterNumber(unsigned RegNo) const override {
- if (RegNo == 0)
- return 0;
- if (RegNo == 1)
- return 1;
- return -1;
- }
-};
-
-const char *const AArch64TargetInfo::GCCRegNames[] = {
- // 32-bit Integer registers
- "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10",
- "w11", "w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21",
- "w22", "w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp",
-
- // 64-bit Integer registers
- "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10",
- "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21",
- "x22", "x23", "x24", "x25", "x26", "x27", "x28", "fp", "lr", "sp",
-
- // 32-bit floating point regsisters
- "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10",
- "s11", "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21",
- "s22", "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
-
- // 64-bit floating point regsisters
- "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
- "d11", "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21",
- "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
-
- // Vector registers
- "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10",
- "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21",
- "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
-};
-
-ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const {
- return llvm::makeArrayRef(GCCRegNames);
-}
-
-const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = {
- { { "w31" }, "wsp" },
- { { "x29" }, "fp" },
- { { "x30" }, "lr" },
- { { "x31" }, "sp" },
- // The S/D/Q and W/X registers overlap, but aren't really aliases; we
- // don't want to substitute one of these for a different-sized one.
-};
-
-ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const {
- return llvm::makeArrayRef(GCCRegAliases);
-}
-
-const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = {
-#define BUILTIN(ID, TYPE, ATTRS) \
- { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
-#include "clang/Basic/BuiltinsNEON.def"
-
-#define BUILTIN(ID, TYPE, ATTRS) \
- { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
-#include "clang/Basic/BuiltinsAArch64.def"
-};
-
-class AArch64leTargetInfo : public AArch64TargetInfo {
- void setDataLayout() override {
- if (getTriple().isOSBinFormatMachO())
- resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128");
- else
- resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
- }
-
-public:
- AArch64leTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : AArch64TargetInfo(Triple, Opts) {
- }
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- Builder.defineMacro("__AARCH64EL__");
- AArch64TargetInfo::getTargetDefines(Opts, Builder);
- }
-};
-
-class MicrosoftARM64TargetInfo
- : public WindowsTargetInfo<AArch64leTargetInfo> {
- const llvm::Triple Triple;
-
-public:
- MicrosoftARM64TargetInfo(const llvm::Triple &Triple,
- const TargetOptions &Opts)
- : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) {
-
- // This is an LLP64 platform.
- // int:4, long:4, long long:8, long double:8.
- WCharType = UnsignedShort;
- IntWidth = IntAlign = 32;
- LongWidth = LongAlign = 32;
- DoubleAlign = LongLongAlign = 64;
- LongDoubleWidth = LongDoubleAlign = 64;
- LongDoubleFormat = &llvm::APFloat::IEEEdouble();
- IntMaxType = SignedLongLong;
- Int64Type = SignedLongLong;
- SizeType = UnsignedLongLong;
- PtrDiffType = SignedLongLong;
- IntPtrType = SignedLongLong;
-
- TheCXXABI.set(TargetCXXABI::Microsoft);
- }
-
- void setDataLayout() override {
- resetDataLayout("e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128");
- }
-
- void getVisualStudioDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- WindowsTargetInfo<AArch64leTargetInfo>::getVisualStudioDefines(Opts,
- Builder);
- Builder.defineMacro("_WIN32", "1");
- Builder.defineMacro("_WIN64", "1");
- Builder.defineMacro("_M_ARM64", "1");
- }
-
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- WindowsTargetInfo::getTargetDefines(Opts, Builder);
- getVisualStudioDefines(Opts, Builder);
- }
-
- BuiltinVaListKind getBuiltinVaListKind() const override {
- return TargetInfo::CharPtrBuiltinVaList;
- }
-};
-
-class AArch64beTargetInfo : public AArch64TargetInfo {
- void setDataLayout() override {
- assert(!getTriple().isOSBinFormatMachO());
- resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
- }
-
-public:
- AArch64beTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : AArch64TargetInfo(Triple, Opts) {}
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- Builder.defineMacro("__AARCH64EB__");
- Builder.defineMacro("__AARCH_BIG_ENDIAN");
- Builder.defineMacro("__ARM_BIG_ENDIAN");
- AArch64TargetInfo::getTargetDefines(Opts, Builder);
- }
-};
-
-class DarwinAArch64TargetInfo : public DarwinTargetInfo<AArch64leTargetInfo> {
-protected:
- void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const override {
- Builder.defineMacro("__AARCH64_SIMD__");
- Builder.defineMacro("__ARM64_ARCH_8__");
- Builder.defineMacro("__ARM_NEON__");
- Builder.defineMacro("__LITTLE_ENDIAN__");
- Builder.defineMacro("__REGISTER_PREFIX__", "");
- Builder.defineMacro("__arm64", "1");
- Builder.defineMacro("__arm64__", "1");
-
- getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
- }
-
-public:
- DarwinAArch64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) {
- Int64Type = SignedLongLong;
- WCharType = SignedInt;
- UseSignedCharForObjCBool = false;
-
- LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64;
- LongDoubleFormat = &llvm::APFloat::IEEEdouble();
-
- TheCXXABI.set(TargetCXXABI::iOS64);
- }
-
- BuiltinVaListKind getBuiltinVaListKind() const override {
- return TargetInfo::CharPtrBuiltinVaList;
- }
-};
-
-// Hexagon abstract base class
-class HexagonTargetInfo : public TargetInfo {
- static const Builtin::Info BuiltinInfo[];
- static const char * const GCCRegNames[];
- static const TargetInfo::GCCRegAlias GCCRegAliases[];
- std::string CPU;
- bool HasHVX, HasHVXDouble;
- bool UseLongCalls;
-
-public:
- HexagonTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
- : TargetInfo(Triple) {
- // Specify the vector alignment explicitly. For v512x1, the calculated
- // alignment would be 512*alignment(i1), which is 512 bytes, instead of
- // the required minimum of 64 bytes.
- resetDataLayout("e-m:e-p:32:32:32-a:0-n16:32-"
- "i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-"
- "v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048");
- SizeType = UnsignedInt;
- PtrDiffType = SignedInt;
- IntPtrType = SignedInt;
-
- // {} in inline assembly are packet specifiers, not assembly variant
- // specifiers.
- NoAsmVariants = true;
-
- LargeArrayMinWidth = 64;
- LargeArrayAlign = 64;
- UseBitFieldTypeAlignment = true;
- ZeroLengthBitfieldBoundary = 32;
- HasHVX = HasHVXDouble = false;
- UseLongCalls = false;
- }
-
- ArrayRef<Builtin::Info> getTargetBuiltins() const override {
- return llvm::makeArrayRef(BuiltinInfo,
- clang::Hexagon::LastTSBuiltin-Builtin::FirstTSBuiltin);
- }
-
- bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &Info) const override {
- switch (*Name) {
- case 'v':
- case 'q':
- if (HasHVX) {
- Info.setAllowsRegister();
- return true;
- }
- break;
- case 's':
- // Relocatable constant.
- return true;
- }
- return false;
- }
-
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override;
-
- bool isCLZForZeroUndef() const override { return false; }
-
- bool hasFeature(StringRef Feature) const override {
- return llvm::StringSwitch<bool>(Feature)
- .Case("hexagon", true)
- .Case("hvx", HasHVX)
- .Case("hvx-double", HasHVXDouble)
- .Case("long-calls", UseLongCalls)
- .Default(false);
- }
-
- bool initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
- StringRef CPU, const std::vector<std::string> &FeaturesVec)
- const override;
-
- bool handleTargetFeatures(std::vector<std::string> &Features,
- DiagnosticsEngine &Diags) override;
-
- void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name,
- bool Enabled) const override;
-
- BuiltinVaListKind getBuiltinVaListKind() const override {
- return TargetInfo::CharPtrBuiltinVaList;
- }
- ArrayRef<const char *> getGCCRegNames() const override;
- ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
- const char *getClobbers() const override {
- return "";
- }
-
- static const char *getHexagonCPUSuffix(StringRef Name) {
- return llvm::StringSwitch<const char*>(Name)
- .Case("hexagonv4", "4")
- .Case("hexagonv5", "5")
- .Case("hexagonv55", "55")
- .Case("hexagonv60", "60")
- .Case("hexagonv62", "62")
- .Default(nullptr);
- }
-
- bool setCPU(const std::string &Name) override {
- if (!getHexagonCPUSuffix(Name))
- return false;
- CPU = Name;
- return true;
- }
-
- int getEHDataRegisterNumber(unsigned RegNo) const override {
- return RegNo < 2 ? RegNo : -1;
- }
-};
-
-void HexagonTargetInfo::getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- Builder.defineMacro("__qdsp6__", "1");
- Builder.defineMacro("__hexagon__", "1");
-
- if (CPU == "hexagonv4") {
- Builder.defineMacro("__HEXAGON_V4__");
- Builder.defineMacro("__HEXAGON_ARCH__", "4");
- if (Opts.HexagonQdsp6Compat) {
- Builder.defineMacro("__QDSP6_V4__");
- Builder.defineMacro("__QDSP6_ARCH__", "4");
- }
- } else if (CPU == "hexagonv5") {
- Builder.defineMacro("__HEXAGON_V5__");
- Builder.defineMacro("__HEXAGON_ARCH__", "5");
- if(Opts.HexagonQdsp6Compat) {
- Builder.defineMacro("__QDSP6_V5__");
- Builder.defineMacro("__QDSP6_ARCH__", "5");
- }
- } else if (CPU == "hexagonv55") {
- Builder.defineMacro("__HEXAGON_V55__");
- Builder.defineMacro("__HEXAGON_ARCH__", "55");
- Builder.defineMacro("__QDSP6_V55__");
- Builder.defineMacro("__QDSP6_ARCH__", "55");
- } else if (CPU == "hexagonv60") {
- Builder.defineMacro("__HEXAGON_V60__");
- Builder.defineMacro("__HEXAGON_ARCH__", "60");
- Builder.defineMacro("__QDSP6_V60__");
- Builder.defineMacro("__QDSP6_ARCH__", "60");
- } else if (CPU == "hexagonv62") {
- Builder.defineMacro("__HEXAGON_V62__");
- Builder.defineMacro("__HEXAGON_ARCH__", "62");
- }
-
- if (hasFeature("hvx")) {
- Builder.defineMacro("__HVX__");
- if (hasFeature("hvx-double"))
- Builder.defineMacro("__HVXDBL__");
- }
-}
-
-bool HexagonTargetInfo::initFeatureMap(llvm::StringMap<bool> &Features,
- DiagnosticsEngine &Diags, StringRef CPU,
- const std::vector<std::string> &FeaturesVec) const {
- // Default for v60: -hvx, -hvx-double.
- Features["hvx"] = false;
- Features["hvx-double"] = false;
- Features["long-calls"] = false;
-
- return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
-}
-
-bool HexagonTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
- DiagnosticsEngine &Diags) {
- for (auto &F : Features) {
- if (F == "+hvx")
- HasHVX = true;
- else if (F == "-hvx")
- HasHVX = HasHVXDouble = false;
- else if (F == "+hvx-double")
- HasHVX = HasHVXDouble = true;
- else if (F == "-hvx-double")
- HasHVXDouble = false;
-
- if (F == "+long-calls")
- UseLongCalls = true;
- else if (F == "-long-calls")
- UseLongCalls = false;
- }
- return true;
-}
-
-void HexagonTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
- StringRef Name, bool Enabled) const {
- if (Enabled) {
- if (Name == "hvx-double")
- Features["hvx"] = true;
- } else {
- if (Name == "hvx")
- Features["hvx-double"] = false;
- }
- Features[Name] = Enabled;
-}
-
-const char *const HexagonTargetInfo::GCCRegNames[] = {
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
- "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
- "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
- "p0", "p1", "p2", "p3",
- "sa0", "lc0", "sa1", "lc1", "m0", "m1", "usr", "ugp"
-};
-
-ArrayRef<const char*> HexagonTargetInfo::getGCCRegNames() const {
- return llvm::makeArrayRef(GCCRegNames);
-}
-
-const TargetInfo::GCCRegAlias HexagonTargetInfo::GCCRegAliases[] = {
- { { "sp" }, "r29" },
- { { "fp" }, "r30" },
- { { "lr" }, "r31" },
-};
-
-ArrayRef<TargetInfo::GCCRegAlias> HexagonTargetInfo::getGCCRegAliases() const {
- return llvm::makeArrayRef(GCCRegAliases);
-}
-
-
-const Builtin::Info HexagonTargetInfo::BuiltinInfo[] = {
-#define BUILTIN(ID, TYPE, ATTRS) \
- { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
- { #ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr },
-#include "clang/Basic/BuiltinsHexagon.def"
-};
-
-class LanaiTargetInfo : public TargetInfo {
- // Class for Lanai (32-bit).
- // The CPU profiles supported by the Lanai backend
- enum CPUKind {
- CK_NONE,
- CK_V11,
- } CPU;
-
- static const TargetInfo::GCCRegAlias GCCRegAliases[];
- static const char *const GCCRegNames[];
-
-public:
- LanaiTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
- : TargetInfo(Triple) {
- // Description string has to be kept in sync with backend.
- resetDataLayout("E" // Big endian
- "-m:e" // ELF name manging
- "-p:32:32" // 32 bit pointers, 32 bit aligned
- "-i64:64" // 64 bit integers, 64 bit aligned
- "-a:0:32" // 32 bit alignment of objects of aggregate type
- "-n32" // 32 bit native integer width
- "-S64" // 64 bit natural stack alignment
- );
-
- // Setting RegParmMax equal to what mregparm was set to in the old
- // toolchain
- RegParmMax = 4;
-
- // Set the default CPU to V11
- CPU = CK_V11;
-
- // Temporary approach to make everything at least word-aligned and allow for
- // safely casting between pointers with different alignment requirements.
- // TODO: Remove this when there are no more cast align warnings on the
- // firmware.
- MinGlobalAlign = 32;
- }
-
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- // Define __lanai__ when building for target lanai.
- Builder.defineMacro("__lanai__");
-
- // Set define for the CPU specified.
- switch (CPU) {
- case CK_V11:
- Builder.defineMacro("__LANAI_V11__");
- break;
- case CK_NONE:
- llvm_unreachable("Unhandled target CPU");
- }
- }
-
- bool setCPU(const std::string &Name) override {
- CPU = llvm::StringSwitch<CPUKind>(Name)
- .Case("v11", CK_V11)
- .Default(CK_NONE);
-
- return CPU != CK_NONE;
- }
-
- bool hasFeature(StringRef Feature) const override {
- return llvm::StringSwitch<bool>(Feature).Case("lanai", true).Default(false);
- }
-
- ArrayRef<const char *> getGCCRegNames() const override;
-
- ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
-
- BuiltinVaListKind getBuiltinVaListKind() const override {
- return TargetInfo::VoidPtrBuiltinVaList;
- }
-
- ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
-
- bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &info) const override {
- return false;
- }
-
- const char *getClobbers() const override { return ""; }
-};
-
-const char *const LanaiTargetInfo::GCCRegNames[] = {
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
- "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21",
- "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"};
-
-ArrayRef<const char *> LanaiTargetInfo::getGCCRegNames() const {
- return llvm::makeArrayRef(GCCRegNames);
-}
-
-const TargetInfo::GCCRegAlias LanaiTargetInfo::GCCRegAliases[] = {
- {{"pc"}, "r2"},
- {{"sp"}, "r4"},
- {{"fp"}, "r5"},
- {{"rv"}, "r8"},
- {{"rr1"}, "r10"},
- {{"rr2"}, "r11"},
- {{"rca"}, "r15"},
-};
-
-ArrayRef<TargetInfo::GCCRegAlias> LanaiTargetInfo::getGCCRegAliases() const {
- return llvm::makeArrayRef(GCCRegAliases);
-}
-
-// Shared base class for SPARC v8 (32-bit) and SPARC v9 (64-bit).
-class SparcTargetInfo : public TargetInfo {
- static const TargetInfo::GCCRegAlias GCCRegAliases[];
- static const char * const GCCRegNames[];
- bool SoftFloat;
-public:
- SparcTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
- : TargetInfo(Triple), SoftFloat(false) {}
-
- int getEHDataRegisterNumber(unsigned RegNo) const override {
- if (RegNo == 0) return 24;
- if (RegNo == 1) return 25;
- return -1;
- }
-
- bool handleTargetFeatures(std::vector<std::string> &Features,
- DiagnosticsEngine &Diags) override {
- // Check if software floating point is enabled
- auto Feature = std::find(Features.begin(), Features.end(), "+soft-float");
- if (Feature != Features.end()) {
- SoftFloat = true;
- }
- return true;
- }
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- DefineStd(Builder, "sparc", Opts);
- Builder.defineMacro("__REGISTER_PREFIX__", "");
-
- if (SoftFloat)
- Builder.defineMacro("SOFT_FLOAT", "1");
- }
-
- bool hasFeature(StringRef Feature) const override {
- return llvm::StringSwitch<bool>(Feature)
- .Case("softfloat", SoftFloat)
- .Case("sparc", true)
- .Default(false);
- }
-
- bool hasSjLjLowering() const override {
- return true;
- }
-
- ArrayRef<Builtin::Info> getTargetBuiltins() const override {
- // FIXME: Implement!
- return None;
- }
- BuiltinVaListKind getBuiltinVaListKind() const override {
- return TargetInfo::VoidPtrBuiltinVaList;
- }
- ArrayRef<const char *> getGCCRegNames() const override;
- ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
- bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &info) const override {
- // FIXME: Implement!
- switch (*Name) {
- case 'I': // Signed 13-bit constant
- case 'J': // Zero
- case 'K': // 32-bit constant with the low 12 bits clear
- case 'L': // A constant in the range supported by movcc (11-bit signed imm)
- case 'M': // A constant in the range supported by movrcc (19-bit signed imm)
- case 'N': // Same as 'K' but zext (required for SIMode)
- case 'O': // The constant 4096
- return true;
-
- case 'f':
- case 'e':
- info.setAllowsRegister();
- return true;
- }
- return false;
- }
- const char *getClobbers() const override {
- // FIXME: Implement!
- return "";
- }
-
- // No Sparc V7 for now, the backend doesn't support it anyway.
- enum CPUKind {
- CK_GENERIC,
- CK_V8,
- CK_SUPERSPARC,
- CK_SPARCLITE,
- CK_F934,
- CK_HYPERSPARC,
- CK_SPARCLITE86X,
- CK_SPARCLET,
- CK_TSC701,
- CK_V9,
- CK_ULTRASPARC,
- CK_ULTRASPARC3,
- CK_NIAGARA,
- CK_NIAGARA2,
- CK_NIAGARA3,
- CK_NIAGARA4,
- CK_MYRIAD2100,
- CK_MYRIAD2150,
- CK_MYRIAD2450,
- CK_LEON2,
- CK_LEON2_AT697E,
- CK_LEON2_AT697F,
- CK_LEON3,
- CK_LEON3_UT699,
- CK_LEON3_GR712RC,
- CK_LEON4,
- CK_LEON4_GR740
- } CPU = CK_GENERIC;
-
- enum CPUGeneration {
- CG_V8,
- CG_V9,
- };
-
- CPUGeneration getCPUGeneration(CPUKind Kind) const {
- switch (Kind) {
- case CK_GENERIC:
- case CK_V8:
- case CK_SUPERSPARC:
- case CK_SPARCLITE:
- case CK_F934:
- case CK_HYPERSPARC:
- case CK_SPARCLITE86X:
- case CK_SPARCLET:
- case CK_TSC701:
- case CK_MYRIAD2100:
- case CK_MYRIAD2150:
- case CK_MYRIAD2450:
- case CK_LEON2:
- case CK_LEON2_AT697E:
- case CK_LEON2_AT697F:
- case CK_LEON3:
- case CK_LEON3_UT699:
- case CK_LEON3_GR712RC:
- case CK_LEON4:
- case CK_LEON4_GR740:
- return CG_V8;
- case CK_V9:
- case CK_ULTRASPARC:
- case CK_ULTRASPARC3:
- case CK_NIAGARA:
- case CK_NIAGARA2:
- case CK_NIAGARA3:
- case CK_NIAGARA4:
- return CG_V9;
- }
- llvm_unreachable("Unexpected CPU kind");
- }
-
- CPUKind getCPUKind(StringRef Name) const {
- return llvm::StringSwitch<CPUKind>(Name)
- .Case("v8", CK_V8)
- .Case("supersparc", CK_SUPERSPARC)
- .Case("sparclite", CK_SPARCLITE)
- .Case("f934", CK_F934)
- .Case("hypersparc", CK_HYPERSPARC)
- .Case("sparclite86x", CK_SPARCLITE86X)
- .Case("sparclet", CK_SPARCLET)
- .Case("tsc701", CK_TSC701)
- .Case("v9", CK_V9)
- .Case("ultrasparc", CK_ULTRASPARC)
- .Case("ultrasparc3", CK_ULTRASPARC3)
- .Case("niagara", CK_NIAGARA)
- .Case("niagara2", CK_NIAGARA2)
- .Case("niagara3", CK_NIAGARA3)
- .Case("niagara4", CK_NIAGARA4)
- .Case("ma2100", CK_MYRIAD2100)
- .Case("ma2150", CK_MYRIAD2150)
- .Case("ma2450", CK_MYRIAD2450)
- // FIXME: the myriad2[.n] spellings are obsolete,
- // but a grace period is needed to allow updating dependent builds.
- .Case("myriad2", CK_MYRIAD2100)
- .Case("myriad2.1", CK_MYRIAD2100)
- .Case("myriad2.2", CK_MYRIAD2150)
- .Case("leon2", CK_LEON2)
- .Case("at697e", CK_LEON2_AT697E)
- .Case("at697f", CK_LEON2_AT697F)
- .Case("leon3", CK_LEON3)
- .Case("ut699", CK_LEON3_UT699)
- .Case("gr712rc", CK_LEON3_GR712RC)
- .Case("leon4", CK_LEON4)
- .Case("gr740", CK_LEON4_GR740)
- .Default(CK_GENERIC);
- }
-
- bool setCPU(const std::string &Name) override {
- CPU = getCPUKind(Name);
- return CPU != CK_GENERIC;
- }
-};
-
-const char * const SparcTargetInfo::GCCRegNames[] = {
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
- "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
- "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
-};
-
-ArrayRef<const char *> SparcTargetInfo::getGCCRegNames() const {
- return llvm::makeArrayRef(GCCRegNames);
-}
-
-const TargetInfo::GCCRegAlias SparcTargetInfo::GCCRegAliases[] = {
- { { "g0" }, "r0" },
- { { "g1" }, "r1" },
- { { "g2" }, "r2" },
- { { "g3" }, "r3" },
- { { "g4" }, "r4" },
- { { "g5" }, "r5" },
- { { "g6" }, "r6" },
- { { "g7" }, "r7" },
- { { "o0" }, "r8" },
- { { "o1" }, "r9" },
- { { "o2" }, "r10" },
- { { "o3" }, "r11" },
- { { "o4" }, "r12" },
- { { "o5" }, "r13" },
- { { "o6", "sp" }, "r14" },
- { { "o7" }, "r15" },
- { { "l0" }, "r16" },
- { { "l1" }, "r17" },
- { { "l2" }, "r18" },
- { { "l3" }, "r19" },
- { { "l4" }, "r20" },
- { { "l5" }, "r21" },
- { { "l6" }, "r22" },
- { { "l7" }, "r23" },
- { { "i0" }, "r24" },
- { { "i1" }, "r25" },
- { { "i2" }, "r26" },
- { { "i3" }, "r27" },
- { { "i4" }, "r28" },
- { { "i5" }, "r29" },
- { { "i6", "fp" }, "r30" },
- { { "i7" }, "r31" },
-};
-
-ArrayRef<TargetInfo::GCCRegAlias> SparcTargetInfo::getGCCRegAliases() const {
- return llvm::makeArrayRef(GCCRegAliases);
-}
-
-// SPARC v8 is the 32-bit mode selected by Triple::sparc.
-class SparcV8TargetInfo : public SparcTargetInfo {
-public:
- SparcV8TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : SparcTargetInfo(Triple, Opts) {
- resetDataLayout("E-m:e-p:32:32-i64:64-f128:64-n32-S64");
- // NetBSD / OpenBSD use long (same as llvm default); everyone else uses int.
- switch (getTriple().getOS()) {
- default:
- SizeType = UnsignedInt;
- IntPtrType = SignedInt;
- PtrDiffType = SignedInt;
- break;
- case llvm::Triple::NetBSD:
- case llvm::Triple::OpenBSD:
- SizeType = UnsignedLong;
- IntPtrType = SignedLong;
- PtrDiffType = SignedLong;
- break;
- }
- // Up to 32 bits are lock-free atomic, but we're willing to do atomic ops
- // on up to 64 bits.
- MaxAtomicPromoteWidth = 64;
- MaxAtomicInlineWidth = 32;
- }
-
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- SparcTargetInfo::getTargetDefines(Opts, Builder);
- switch (getCPUGeneration(CPU)) {
- case CG_V8:
- Builder.defineMacro("__sparcv8");
- if (getTriple().getOS() != llvm::Triple::Solaris)
- Builder.defineMacro("__sparcv8__");
- break;
- case CG_V9:
- Builder.defineMacro("__sparcv9");
- if (getTriple().getOS() != llvm::Triple::Solaris) {
- Builder.defineMacro("__sparcv9__");
- Builder.defineMacro("__sparc_v9__");
- }
- break;
- }
- if (getTriple().getVendor() == llvm::Triple::Myriad) {
- std::string MyriadArchValue, Myriad2Value;
- Builder.defineMacro("__sparc_v8__");
- Builder.defineMacro("__leon__");
- switch (CPU) {
- case CK_MYRIAD2150:
- MyriadArchValue = "__ma2150";
- Myriad2Value = "2";
- break;
- case CK_MYRIAD2450:
- MyriadArchValue = "__ma2450";
- Myriad2Value = "2";
- break;
- default:
- MyriadArchValue = "__ma2100";
- Myriad2Value = "1";
- break;
- }
- Builder.defineMacro(MyriadArchValue, "1");
- Builder.defineMacro(MyriadArchValue+"__", "1");
- Builder.defineMacro("__myriad2__", Myriad2Value);
- Builder.defineMacro("__myriad2", Myriad2Value);
- }
- }
-
- bool hasSjLjLowering() const override {
- return true;
- }
-};
-
-// SPARCV8el is the 32-bit little-endian mode selected by Triple::sparcel.
-class SparcV8elTargetInfo : public SparcV8TargetInfo {
- public:
- SparcV8elTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : SparcV8TargetInfo(Triple, Opts) {
- resetDataLayout("e-m:e-p:32:32-i64:64-f128:64-n32-S64");
- }
-};
-
-// SPARC v9 is the 64-bit mode selected by Triple::sparcv9.
-class SparcV9TargetInfo : public SparcTargetInfo {
-public:
- SparcV9TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : SparcTargetInfo(Triple, Opts) {
- // FIXME: Support Sparc quad-precision long double?
- resetDataLayout("E-m:e-i64:64-n32:64-S128");
- // This is an LP64 platform.
- LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
-
- // OpenBSD uses long long for int64_t and intmax_t.
- if (getTriple().getOS() == llvm::Triple::OpenBSD)
- IntMaxType = SignedLongLong;
- else
- IntMaxType = SignedLong;
- Int64Type = IntMaxType;
-
- // The SPARCv8 System V ABI has long double 128-bits in size, but 64-bit
- // aligned. The SPARCv9 SCD 2.4.1 says 16-byte aligned.
- LongDoubleWidth = 128;
- LongDoubleAlign = 128;
- LongDoubleFormat = &llvm::APFloat::IEEEquad();
- MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
- }
-
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- SparcTargetInfo::getTargetDefines(Opts, Builder);
- Builder.defineMacro("__sparcv9");
- Builder.defineMacro("__arch64__");
- // Solaris doesn't need these variants, but the BSDs do.
- if (getTriple().getOS() != llvm::Triple::Solaris) {
- Builder.defineMacro("__sparc64__");
- Builder.defineMacro("__sparc_v9__");
- Builder.defineMacro("__sparcv9__");
- }
- }
-
- bool setCPU(const std::string &Name) override {
- if (!SparcTargetInfo::setCPU(Name))
- return false;
- return getCPUGeneration(CPU) == CG_V9;
- }
-};
-
-class SystemZTargetInfo : public TargetInfo {
- static const Builtin::Info BuiltinInfo[];
- static const char *const GCCRegNames[];
- std::string CPU;
- int ISARevision;
- bool HasTransactionalExecution;
- bool HasVector;
-
-public:
- SystemZTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
- : TargetInfo(Triple), CPU("z10"), ISARevision(8),
- HasTransactionalExecution(false), HasVector(false) {
- IntMaxType = SignedLong;
- Int64Type = SignedLong;
- TLSSupported = true;
- IntWidth = IntAlign = 32;
- LongWidth = LongLongWidth = LongAlign = LongLongAlign = 64;
- PointerWidth = PointerAlign = 64;
- LongDoubleWidth = 128;
- LongDoubleAlign = 64;
- LongDoubleFormat = &llvm::APFloat::IEEEquad();
- DefaultAlignForAttributeAligned = 64;
- MinGlobalAlign = 16;
- resetDataLayout("E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64");
- MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
- }
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- Builder.defineMacro("__s390__");
- Builder.defineMacro("__s390x__");
- Builder.defineMacro("__zarch__");
- Builder.defineMacro("__LONG_DOUBLE_128__");
-
- Builder.defineMacro("__ARCH__", Twine(ISARevision));
-
- Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
- Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
- Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
- Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
-
- if (HasTransactionalExecution)
- Builder.defineMacro("__HTM__");
- if (HasVector)
- Builder.defineMacro("__VX__");
- if (Opts.ZVector)
- Builder.defineMacro("__VEC__", "10302");
- }
- ArrayRef<Builtin::Info> getTargetBuiltins() const override {
- return llvm::makeArrayRef(BuiltinInfo,
- clang::SystemZ::LastTSBuiltin-Builtin::FirstTSBuiltin);
- }
-
- ArrayRef<const char *> getGCCRegNames() const override;
- ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
- // No aliases.
- return None;
- }
- bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &info) const override;
- const char *getClobbers() const override {
- // FIXME: Is this really right?
- return "";
- }
- BuiltinVaListKind getBuiltinVaListKind() const override {
- return TargetInfo::SystemZBuiltinVaList;
- }
- int getISARevision(const StringRef &Name) const {
- return llvm::StringSwitch<int>(Name)
- .Cases("arch8", "z10", 8)
- .Cases("arch9", "z196", 9)
- .Cases("arch10", "zEC12", 10)
- .Cases("arch11", "z13", 11)
- .Cases("arch12", "z14", 12)
- .Default(-1);
- }
- bool setCPU(const std::string &Name) override {
- CPU = Name;
- ISARevision = getISARevision(CPU);
- return ISARevision != -1;
- }
- bool
- initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
- StringRef CPU,
- const std::vector<std::string> &FeaturesVec) const override {
- int ISARevision = getISARevision(CPU);
- if (ISARevision >= 10)
- Features["transactional-execution"] = true;
- if (ISARevision >= 11)
- Features["vector"] = true;
- if (ISARevision >= 12)
- Features["vector-enhancements-1"] = true;
- return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
- }
-
- bool handleTargetFeatures(std::vector<std::string> &Features,
- DiagnosticsEngine &Diags) override {
- HasTransactionalExecution = false;
- HasVector = false;
- for (const auto &Feature : Features) {
- if (Feature == "+transactional-execution")
- HasTransactionalExecution = true;
- else if (Feature == "+vector")
- HasVector = true;
- }
- // If we use the vector ABI, vector types are 64-bit aligned.
- if (HasVector) {
- MaxVectorAlign = 64;
- resetDataLayout("E-m:e-i1:8:16-i8:8:16-i64:64-f128:64"
- "-v128:64-a:8:16-n32:64");
- }
- return true;
- }
-
- bool hasFeature(StringRef Feature) const override {
- return llvm::StringSwitch<bool>(Feature)
- .Case("systemz", true)
- .Case("arch8", ISARevision >= 8)
- .Case("arch9", ISARevision >= 9)
- .Case("arch10", ISARevision >= 10)
- .Case("arch11", ISARevision >= 11)
- .Case("arch12", ISARevision >= 12)
- .Case("htm", HasTransactionalExecution)
- .Case("vx", HasVector)
- .Default(false);
- }
-
- CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
- switch (CC) {
- case CC_C:
- case CC_Swift:
- case CC_OpenCLKernel:
- return CCCR_OK;
- default:
- return CCCR_Warning;
- }
- }
-
- StringRef getABI() const override {
- if (HasVector)
- return "vector";
- return "";
- }
-
- bool useFloat128ManglingForLongDouble() const override {
- return true;
- }
-};
-
-const Builtin::Info SystemZTargetInfo::BuiltinInfo[] = {
-#define BUILTIN(ID, TYPE, ATTRS) \
- { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
-#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
- { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE },
-#include "clang/Basic/BuiltinsSystemZ.def"
-};
-
-const char *const SystemZTargetInfo::GCCRegNames[] = {
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
- "f0", "f2", "f4", "f6", "f1", "f3", "f5", "f7",
- "f8", "f10", "f12", "f14", "f9", "f11", "f13", "f15"
-};
-
-ArrayRef<const char *> SystemZTargetInfo::getGCCRegNames() const {
- return llvm::makeArrayRef(GCCRegNames);
-}
-
-bool SystemZTargetInfo::
-validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &Info) const {
- switch (*Name) {
- default:
- return false;
-
- case 'a': // Address register
- case 'd': // Data register (equivalent to 'r')
- case 'f': // Floating-point register
- Info.setAllowsRegister();
- return true;
-
- case 'I': // Unsigned 8-bit constant
- case 'J': // Unsigned 12-bit constant
- case 'K': // Signed 16-bit constant
- case 'L': // Signed 20-bit displacement (on all targets we support)
- case 'M': // 0x7fffffff
- return true;
-
- case 'Q': // Memory with base and unsigned 12-bit displacement
- case 'R': // Likewise, plus an index
- case 'S': // Memory with base and signed 20-bit displacement
- case 'T': // Likewise, plus an index
- Info.setAllowsMemory();
- return true;
- }
-}
-
-class MSP430TargetInfo : public TargetInfo {
- static const char *const GCCRegNames[];
-
-public:
- MSP430TargetInfo(const llvm::Triple &Triple, const TargetOptions &)
- : TargetInfo(Triple) {
- TLSSupported = false;
- IntWidth = 16;
- IntAlign = 16;
- LongWidth = 32;
- LongLongWidth = 64;
- LongAlign = LongLongAlign = 16;
- PointerWidth = 16;
- PointerAlign = 16;
- SuitableAlign = 16;
- SizeType = UnsignedInt;
- IntMaxType = SignedLongLong;
- IntPtrType = SignedInt;
- PtrDiffType = SignedInt;
- SigAtomicType = SignedLong;
- resetDataLayout("e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16");
- }
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- Builder.defineMacro("MSP430");
- Builder.defineMacro("__MSP430__");
- // FIXME: defines for different 'flavours' of MCU
- }
- ArrayRef<Builtin::Info> getTargetBuiltins() const override {
- // FIXME: Implement.
- return None;
- }
- bool hasFeature(StringRef Feature) const override {
- return Feature == "msp430";
- }
- ArrayRef<const char *> getGCCRegNames() const override;
- ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
- // No aliases.
- return None;
- }
- bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &info) const override {
- // FIXME: implement
- switch (*Name) {
- case 'K': // the constant 1
- case 'L': // constant -1^20 .. 1^19
- case 'M': // constant 1-4:
- return true;
- }
- // No target constraints for now.
- return false;
- }
- const char *getClobbers() const override {
- // FIXME: Is this really right?
- return "";
- }
- BuiltinVaListKind getBuiltinVaListKind() const override {
- // FIXME: implement
- return TargetInfo::CharPtrBuiltinVaList;
- }
-};
-
-const char *const MSP430TargetInfo::GCCRegNames[] = {
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"};
-
-ArrayRef<const char *> MSP430TargetInfo::getGCCRegNames() const {
- return llvm::makeArrayRef(GCCRegNames);
-}
-
-// LLVM and Clang cannot be used directly to output native binaries for
-// target, but is used to compile C code to llvm bitcode with correct
-// type and alignment information.
-//
-// TCE uses the llvm bitcode as input and uses it for generating customized
-// target processor and program binary. TCE co-design environment is
-// publicly available in http://tce.cs.tut.fi
-
-static const unsigned TCEOpenCLAddrSpaceMap[] = {
- 0, // Default
- 3, // opencl_global
- 4, // opencl_local
- 5, // opencl_constant
- // FIXME: generic has to be added to the target
- 0, // opencl_generic
- 0, // cuda_device
- 0, // cuda_constant
- 0 // cuda_shared
-};
-
-class TCETargetInfo : public TargetInfo {
-public:
- TCETargetInfo(const llvm::Triple &Triple, const TargetOptions &)
- : TargetInfo(Triple) {
- TLSSupported = false;
- IntWidth = 32;
- LongWidth = LongLongWidth = 32;
- PointerWidth = 32;
- IntAlign = 32;
- LongAlign = LongLongAlign = 32;
- PointerAlign = 32;
- SuitableAlign = 32;
- SizeType = UnsignedInt;
- IntMaxType = SignedLong;
- IntPtrType = SignedInt;
- PtrDiffType = SignedInt;
- FloatWidth = 32;
- FloatAlign = 32;
- DoubleWidth = 32;
- DoubleAlign = 32;
- LongDoubleWidth = 32;
- LongDoubleAlign = 32;
- FloatFormat = &llvm::APFloat::IEEEsingle();
- DoubleFormat = &llvm::APFloat::IEEEsingle();
- LongDoubleFormat = &llvm::APFloat::IEEEsingle();
- resetDataLayout("E-p:32:32:32-i1:8:8-i8:8:32-"
- "i16:16:32-i32:32:32-i64:32:32-"
- "f32:32:32-f64:32:32-v64:32:32-"
- "v128:32:32-v256:32:32-v512:32:32-"
- "v1024:32:32-a0:0:32-n32");
- AddrSpaceMap = &TCEOpenCLAddrSpaceMap;
- UseAddrSpaceMapMangling = true;
- }
-
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- DefineStd(Builder, "tce", Opts);
- Builder.defineMacro("__TCE__");
- Builder.defineMacro("__TCE_V1__");
- }
- bool hasFeature(StringRef Feature) const override { return Feature == "tce"; }
-
- ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
- const char *getClobbers() const override { return ""; }
- BuiltinVaListKind getBuiltinVaListKind() const override {
- return TargetInfo::VoidPtrBuiltinVaList;
- }
- ArrayRef<const char *> getGCCRegNames() const override { return None; }
- bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &info) const override {
- return true;
- }
- ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
- return None;
- }
-};
-
-class TCELETargetInfo : public TCETargetInfo {
-public:
- TCELETargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : TCETargetInfo(Triple, Opts) {
- BigEndian = false;
-
- resetDataLayout("e-p:32:32:32-i1:8:8-i8:8:32-"
- "i16:16:32-i32:32:32-i64:32:32-"
- "f32:32:32-f64:32:32-v64:32:32-"
- "v128:32:32-v256:32:32-v512:32:32-"
- "v1024:32:32-a0:0:32-n32");
-
- }
-
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- DefineStd(Builder, "tcele", Opts);
- Builder.defineMacro("__TCE__");
- Builder.defineMacro("__TCE_V1__");
- Builder.defineMacro("__TCELE__");
- Builder.defineMacro("__TCELE_V1__");
- }
-
-};
-
-class BPFTargetInfo : public TargetInfo {
-public:
- BPFTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
- : TargetInfo(Triple) {
- LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
- SizeType = UnsignedLong;
- PtrDiffType = SignedLong;
- IntPtrType = SignedLong;
- IntMaxType = SignedLong;
- Int64Type = SignedLong;
- RegParmMax = 5;
- if (Triple.getArch() == llvm::Triple::bpfeb) {
- resetDataLayout("E-m:e-p:64:64-i64:64-n32:64-S128");
- } else {
- resetDataLayout("e-m:e-p:64:64-i64:64-n32:64-S128");
- }
- MaxAtomicPromoteWidth = 64;
- MaxAtomicInlineWidth = 64;
- TLSSupported = false;
- }
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- DefineStd(Builder, "bpf", Opts);
- Builder.defineMacro("__BPF__");
- }
- bool hasFeature(StringRef Feature) const override {
- return Feature == "bpf";
- }
-
- ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
- const char *getClobbers() const override {
- return "";
- }
- BuiltinVaListKind getBuiltinVaListKind() const override {
- return TargetInfo::VoidPtrBuiltinVaList;
- }
- ArrayRef<const char *> getGCCRegNames() const override {
- return None;
- }
- bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &info) const override {
- return true;
- }
- ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
- return None;
- }
- CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
- switch (CC) {
- default:
- return CCCR_Warning;
- case CC_C:
- case CC_OpenCLKernel:
- return CCCR_OK;
- }
- }
-};
-
-class Nios2TargetInfo : public TargetInfo {
- void setDataLayout() {
- if (BigEndian)
- resetDataLayout("E-p:32:32:32-i8:8:32-i16:16:32-n32");
- else
- resetDataLayout("e-p:32:32:32-i8:8:32-i16:16:32-n32");
- }
-
- static const Builtin::Info BuiltinInfo[];
- std::string CPU;
- std::string ABI;
-
-public:
- Nios2TargetInfo(const llvm::Triple &triple, const TargetOptions &opts)
- : TargetInfo(triple), CPU(opts.CPU), ABI(opts.ABI) {
- SizeType = UnsignedInt;
- PtrDiffType = SignedInt;
- MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;
- setDataLayout();
- }
-
- StringRef getABI() const override { return ABI; }
- bool setABI(const std::string &Name) override {
- if (Name == "o32" || Name == "eabi") {
- ABI = Name;
- return true;
- }
- return false;
- }
-
- bool setCPU(const std::string &Name) override {
- if (Name == "nios2r1" || Name == "nios2r2") {
- CPU = Name;
- return true;
- }
- return false;
- }
-
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- DefineStd(Builder, "nios2", Opts);
- DefineStd(Builder, "NIOS2", Opts);
-
- Builder.defineMacro("__nios2");
- Builder.defineMacro("__NIOS2");
- Builder.defineMacro("__nios2__");
- Builder.defineMacro("__NIOS2__");
- }
-
- ArrayRef<Builtin::Info> getTargetBuiltins() const override {
- return llvm::makeArrayRef(BuiltinInfo, clang::Nios2::LastTSBuiltin -
- Builtin::FirstTSBuiltin);
- }
-
- bool isFeatureSupportedByCPU(StringRef Feature, StringRef CPU) const {
- const bool isR2 = CPU == "nios2r2";
- return llvm::StringSwitch<bool>(Feature)
- .Case("nios2r2mandatory", isR2)
- .Case("nios2r2bmx", isR2)
- .Case("nios2r2mpx", isR2)
- .Case("nios2r2cdx", isR2)
- .Default(false);
- }
-
- bool initFeatureMap(llvm::StringMap<bool> &Features,
- DiagnosticsEngine &Diags, StringRef CPU,
- const std::vector<std::string> &FeatureVec) const override {
- static const char *allFeatures[] = {
- "nios2r2mandatory", "nios2r2bmx", "nios2r2mpx", "nios2r2cdx"
- };
- for (const char *feature : allFeatures) {
- Features[feature] = isFeatureSupportedByCPU(feature, CPU);
- }
- return true;
- }
-
- bool hasFeature(StringRef Feature) const override {
- return isFeatureSupportedByCPU(Feature, CPU);
- }
-
- BuiltinVaListKind getBuiltinVaListKind() const override {
- return TargetInfo::VoidPtrBuiltinVaList;
- }
-
- ArrayRef<const char *> getGCCRegNames() const override {
- static const char *const GCCRegNames[] = {
- // CPU register names
- // Must match second column of GCCRegAliases
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
- "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20",
- "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30",
- "r31",
- // Floating point register names
- "ctl0", "ctl1", "ctl2", "ctl3", "ctl4", "ctl5", "ctl6", "ctl7", "ctl8",
- "ctl9", "ctl10", "ctl11", "ctl12", "ctl13", "ctl14", "ctl15"
- };
- return llvm::makeArrayRef(GCCRegNames);
- }
-
- bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &Info) const override {
- switch (*Name) {
- default:
- return false;
-
- case 'r': // CPU registers.
- case 'd': // Equivalent to "r" unless generating MIPS16 code.
- case 'y': // Equivalent to "r", backwards compatibility only.
- case 'f': // floating-point registers.
- case 'c': // $25 for indirect jumps
- case 'l': // lo register
- case 'x': // hilo register pair
- Info.setAllowsRegister();
- return true;
- }
- }
-
- const char *getClobbers() const override { return ""; }
-
- ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
- static const TargetInfo::GCCRegAlias aliases[] = {
- {{"zero"}, "r0"}, {{"at"}, "r1"}, {{"et"}, "r24"},
- {{"bt"}, "r25"}, {{"gp"}, "r26"}, {{"sp"}, "r27"},
- {{"fp"}, "r28"}, {{"ea"}, "r29"}, {{"ba"}, "r30"},
- {{"ra"}, "r31"}, {{"status"}, "ctl0"}, {{"estatus"}, "ctl1"},
- {{"bstatus"}, "ctl2"}, {{"ienable"}, "ctl3"}, {{"ipending"}, "ctl4"},
- {{"cpuid"}, "ctl5"}, {{"exception"}, "ctl7"}, {{"pteaddr"}, "ctl8"},
- {{"tlbacc"}, "ctl9"}, {{"tlbmisc"}, "ctl10"}, {{"badaddr"}, "ctl12"},
- {{"config"}, "ctl13"}, {{"mpubase"}, "ctl14"}, {{"mpuacc"}, "ctl15"},
- };
- return llvm::makeArrayRef(aliases);
- }
-};
-
-const Builtin::Info Nios2TargetInfo::BuiltinInfo[] = {
-#define BUILTIN(ID, TYPE, ATTRS) \
- {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
-#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
- {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
-#include "clang/Basic/BuiltinsNios2.def"
-};
-
-class MipsTargetInfo : public TargetInfo {
- void setDataLayout() {
- StringRef Layout;
-
- if (ABI == "o32")
- Layout = "m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64";
- else if (ABI == "n32")
- Layout = "m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32:64-S128";
- else if (ABI == "n64")
- Layout = "m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128";
- else
- llvm_unreachable("Invalid ABI");
-
- if (BigEndian)
- resetDataLayout(("E-" + Layout).str());
- else
- resetDataLayout(("e-" + Layout).str());
- }
-
-
- static const Builtin::Info BuiltinInfo[];
- std::string CPU;
- bool IsMips16;
- bool IsMicromips;
- bool IsNan2008;
- bool IsSingleFloat;
- bool IsNoABICalls;
- bool CanUseBSDABICalls;
- enum MipsFloatABI {
- HardFloat, SoftFloat
- } FloatABI;
- enum DspRevEnum {
- NoDSP, DSP1, DSP2
- } DspRev;
- bool HasMSA;
- bool DisableMadd4;
-
-protected:
- bool HasFP64;
- std::string ABI;
-
-public:
- MipsTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
- : TargetInfo(Triple), IsMips16(false), IsMicromips(false),
- IsNan2008(false), IsSingleFloat(false), IsNoABICalls(false),
- CanUseBSDABICalls(false), FloatABI(HardFloat), DspRev(NoDSP),
- HasMSA(false), DisableMadd4(false), HasFP64(false) {
- TheCXXABI.set(TargetCXXABI::GenericMIPS);
-
- setABI((getTriple().getArch() == llvm::Triple::mips ||
- getTriple().getArch() == llvm::Triple::mipsel)
- ? "o32"
- : "n64");
-
- CPU = ABI == "o32" ? "mips32r2" : "mips64r2";
-
- CanUseBSDABICalls = Triple.getOS() == llvm::Triple::FreeBSD ||
- Triple.getOS() == llvm::Triple::OpenBSD;
- }
-
- bool isNaN2008Default() const {
- return CPU == "mips32r6" || CPU == "mips64r6";
- }
-
- bool isFP64Default() const {
- return CPU == "mips32r6" || ABI == "n32" || ABI == "n64" || ABI == "64";
- }
-
- bool isNan2008() const override {
- return IsNan2008;
- }
-
- bool processorSupportsGPR64() const {
- return llvm::StringSwitch<bool>(CPU)
- .Case("mips3", true)
- .Case("mips4", true)
- .Case("mips5", true)
- .Case("mips64", true)
- .Case("mips64r2", true)
- .Case("mips64r3", true)
- .Case("mips64r5", true)
- .Case("mips64r6", true)
- .Case("octeon", true)
- .Default(false);
- return false;
- }
-
- StringRef getABI() const override { return ABI; }
- bool setABI(const std::string &Name) override {
- if (Name == "o32") {
- setO32ABITypes();
- ABI = Name;
- return true;
- }
-
- if (Name == "n32") {
- setN32ABITypes();
- ABI = Name;
- return true;
- }
- if (Name == "n64") {
- setN64ABITypes();
- ABI = Name;
- return true;
- }
- return false;
- }
-
- void setO32ABITypes() {
- Int64Type = SignedLongLong;
- IntMaxType = Int64Type;
- LongDoubleFormat = &llvm::APFloat::IEEEdouble();
- LongDoubleWidth = LongDoubleAlign = 64;
- LongWidth = LongAlign = 32;
- MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;
- PointerWidth = PointerAlign = 32;
- PtrDiffType = SignedInt;
- SizeType = UnsignedInt;
- SuitableAlign = 64;
- }
-
- void setN32N64ABITypes() {
- LongDoubleWidth = LongDoubleAlign = 128;
- LongDoubleFormat = &llvm::APFloat::IEEEquad();
- if (getTriple().getOS() == llvm::Triple::FreeBSD) {
- LongDoubleWidth = LongDoubleAlign = 64;
- LongDoubleFormat = &llvm::APFloat::IEEEdouble();
- }
- MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
- SuitableAlign = 128;
- }
-
- void setN64ABITypes() {
- setN32N64ABITypes();
- if (getTriple().getOS() == llvm::Triple::OpenBSD) {
- Int64Type = SignedLongLong;
- } else {
- Int64Type = SignedLong;
- }
- IntMaxType = Int64Type;
- LongWidth = LongAlign = 64;
- PointerWidth = PointerAlign = 64;
- PtrDiffType = SignedLong;
- SizeType = UnsignedLong;
- }
-
- void setN32ABITypes() {
- setN32N64ABITypes();
- Int64Type = SignedLongLong;
- IntMaxType = Int64Type;
- LongWidth = LongAlign = 32;
- PointerWidth = PointerAlign = 32;
- PtrDiffType = SignedInt;
- SizeType = UnsignedInt;
- }
-
- bool setCPU(const std::string &Name) override {
- CPU = Name;
- return llvm::StringSwitch<bool>(Name)
- .Case("mips1", true)
- .Case("mips2", true)
- .Case("mips3", true)
- .Case("mips4", true)
- .Case("mips5", true)
- .Case("mips32", true)
- .Case("mips32r2", true)
- .Case("mips32r3", true)
- .Case("mips32r5", true)
- .Case("mips32r6", true)
- .Case("mips64", true)
- .Case("mips64r2", true)
- .Case("mips64r3", true)
- .Case("mips64r5", true)
- .Case("mips64r6", true)
- .Case("octeon", true)
- .Case("p5600", true)
- .Default(false);
- }
- const std::string& getCPU() const { return CPU; }
- bool
- initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
- StringRef CPU,
- const std::vector<std::string> &FeaturesVec) const override {
- if (CPU.empty())
- CPU = getCPU();
- if (CPU == "octeon")
- Features["mips64r2"] = Features["cnmips"] = true;
- else
- Features[CPU] = true;
- return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
- }
-
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- if (BigEndian) {
- DefineStd(Builder, "MIPSEB", Opts);
- Builder.defineMacro("_MIPSEB");
- } else {
- DefineStd(Builder, "MIPSEL", Opts);
- Builder.defineMacro("_MIPSEL");
- }
-
- Builder.defineMacro("__mips__");
- Builder.defineMacro("_mips");
- if (Opts.GNUMode)
- Builder.defineMacro("mips");
-
- if (ABI == "o32") {
- Builder.defineMacro("__mips", "32");
- Builder.defineMacro("_MIPS_ISA", "_MIPS_ISA_MIPS32");
- } else {
- Builder.defineMacro("__mips", "64");
- Builder.defineMacro("__mips64");
- Builder.defineMacro("__mips64__");
- Builder.defineMacro("_MIPS_ISA", "_MIPS_ISA_MIPS64");
- }
-
- const std::string ISARev = llvm::StringSwitch<std::string>(getCPU())
- .Cases("mips32", "mips64", "1")
- .Cases("mips32r2", "mips64r2", "2")
- .Cases("mips32r3", "mips64r3", "3")
- .Cases("mips32r5", "mips64r5", "5")
- .Cases("mips32r6", "mips64r6", "6")
- .Default("");
- if (!ISARev.empty())
- Builder.defineMacro("__mips_isa_rev", ISARev);
-
- if (ABI == "o32") {
- Builder.defineMacro("__mips_o32");
- Builder.defineMacro("_ABIO32", "1");
- Builder.defineMacro("_MIPS_SIM", "_ABIO32");
- } else if (ABI == "n32") {
- Builder.defineMacro("__mips_n32");
- Builder.defineMacro("_ABIN32", "2");
- Builder.defineMacro("_MIPS_SIM", "_ABIN32");
- } else if (ABI == "n64") {
- Builder.defineMacro("__mips_n64");
- Builder.defineMacro("_ABI64", "3");
- Builder.defineMacro("_MIPS_SIM", "_ABI64");
- } else
- llvm_unreachable("Invalid ABI.");
-
- if (!IsNoABICalls) {
- Builder.defineMacro("__mips_abicalls");
- if (CanUseBSDABICalls)
- Builder.defineMacro("__ABICALLS__");
- }
-
- Builder.defineMacro("__REGISTER_PREFIX__", "");
-
- switch (FloatABI) {
- case HardFloat:
- Builder.defineMacro("__mips_hard_float", Twine(1));
- break;
- case SoftFloat:
- Builder.defineMacro("__mips_soft_float", Twine(1));
- break;
- }
-
- if (IsSingleFloat)
- Builder.defineMacro("__mips_single_float", Twine(1));
-
- Builder.defineMacro("__mips_fpr", HasFP64 ? Twine(64) : Twine(32));
- Builder.defineMacro("_MIPS_FPSET",
- Twine(32 / (HasFP64 || IsSingleFloat ? 1 : 2)));
-
- if (IsMips16)
- Builder.defineMacro("__mips16", Twine(1));
-
- if (IsMicromips)
- Builder.defineMacro("__mips_micromips", Twine(1));
-
- if (IsNan2008)
- Builder.defineMacro("__mips_nan2008", Twine(1));
-
- switch (DspRev) {
- default:
- break;
- case DSP1:
- Builder.defineMacro("__mips_dsp_rev", Twine(1));
- Builder.defineMacro("__mips_dsp", Twine(1));
- break;
- case DSP2:
- Builder.defineMacro("__mips_dsp_rev", Twine(2));
- Builder.defineMacro("__mips_dspr2", Twine(1));
- Builder.defineMacro("__mips_dsp", Twine(1));
- break;
- }
-
- if (HasMSA)
- Builder.defineMacro("__mips_msa", Twine(1));
-
- if (DisableMadd4)
- Builder.defineMacro("__mips_no_madd4", Twine(1));
-
- Builder.defineMacro("_MIPS_SZPTR", Twine(getPointerWidth(0)));
- Builder.defineMacro("_MIPS_SZINT", Twine(getIntWidth()));
- Builder.defineMacro("_MIPS_SZLONG", Twine(getLongWidth()));
-
- Builder.defineMacro("_MIPS_ARCH", "\"" + CPU + "\"");
- Builder.defineMacro("_MIPS_ARCH_" + StringRef(CPU).upper());
-
- // These shouldn't be defined for MIPS-I but there's no need to check
- // for that since MIPS-I isn't supported.
- Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
- Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
- Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
-
- // 32-bit MIPS processors don't have the necessary lld/scd instructions
- // found in 64-bit processors. In the case of O32 on a 64-bit processor,
- // the instructions exist but using them violates the ABI since they
- // require 64-bit GPRs and O32 only supports 32-bit GPRs.
- if (ABI == "n32" || ABI == "n64")
- Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
- }
-
- ArrayRef<Builtin::Info> getTargetBuiltins() const override {
- return llvm::makeArrayRef(BuiltinInfo,
- clang::Mips::LastTSBuiltin - Builtin::FirstTSBuiltin);
- }
- bool hasFeature(StringRef Feature) const override {
- return llvm::StringSwitch<bool>(Feature)
- .Case("mips", true)
- .Case("fp64", HasFP64)
- .Default(false);
- }
- BuiltinVaListKind getBuiltinVaListKind() const override {
- return TargetInfo::VoidPtrBuiltinVaList;
- }
- ArrayRef<const char *> getGCCRegNames() const override {
- static const char *const GCCRegNames[] = {
- // CPU register names
- // Must match second column of GCCRegAliases
- "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
- "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
- "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
- "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31",
- // Floating point register names
- "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",
- "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
- "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
- "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31",
- // Hi/lo and condition register names
- "hi", "lo", "", "$fcc0","$fcc1","$fcc2","$fcc3","$fcc4",
- "$fcc5","$fcc6","$fcc7","$ac1hi","$ac1lo","$ac2hi","$ac2lo",
- "$ac3hi","$ac3lo",
- // MSA register names
- "$w0", "$w1", "$w2", "$w3", "$w4", "$w5", "$w6", "$w7",
- "$w8", "$w9", "$w10", "$w11", "$w12", "$w13", "$w14", "$w15",
- "$w16", "$w17", "$w18", "$w19", "$w20", "$w21", "$w22", "$w23",
- "$w24", "$w25", "$w26", "$w27", "$w28", "$w29", "$w30", "$w31",
- // MSA control register names
- "$msair", "$msacsr", "$msaaccess", "$msasave", "$msamodify",
- "$msarequest", "$msamap", "$msaunmap"
- };
- return llvm::makeArrayRef(GCCRegNames);
- }
- bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &Info) const override {
- switch (*Name) {
- default:
- return false;
- case 'r': // CPU registers.
- case 'd': // Equivalent to "r" unless generating MIPS16 code.
- case 'y': // Equivalent to "r", backward compatibility only.
- case 'f': // floating-point registers.
- case 'c': // $25 for indirect jumps
- case 'l': // lo register
- case 'x': // hilo register pair
- Info.setAllowsRegister();
- return true;
- case 'I': // Signed 16-bit constant
- case 'J': // Integer 0
- case 'K': // Unsigned 16-bit constant
- case 'L': // Signed 32-bit constant, lower 16-bit zeros (for lui)
- case 'M': // Constants not loadable via lui, addiu, or ori
- case 'N': // Constant -1 to -65535
- case 'O': // A signed 15-bit constant
- case 'P': // A constant between 1 go 65535
- return true;
- case 'R': // An address that can be used in a non-macro load or store
- Info.setAllowsMemory();
- return true;
- case 'Z':
- if (Name[1] == 'C') { // An address usable by ll, and sc.
- Info.setAllowsMemory();
- Name++; // Skip over 'Z'.
- return true;
- }
- return false;
- }
- }
-
- std::string convertConstraint(const char *&Constraint) const override {
- std::string R;
- switch (*Constraint) {
- case 'Z': // Two-character constraint; add "^" hint for later parsing.
- if (Constraint[1] == 'C') {
- R = std::string("^") + std::string(Constraint, 2);
- Constraint++;
- return R;
- }
- break;
- }
- return TargetInfo::convertConstraint(Constraint);
- }
-
- const char *getClobbers() const override {
- // In GCC, $1 is not widely used in generated code (it's used only in a few
- // specific situations), so there is no real need for users to add it to
- // the clobbers list if they want to use it in their inline assembly code.
- //
- // In LLVM, $1 is treated as a normal GPR and is always allocatable during
- // code generation, so using it in inline assembly without adding it to the
- // clobbers list can cause conflicts between the inline assembly code and
- // the surrounding generated code.
- //
- // Another problem is that LLVM is allowed to choose $1 for inline assembly
- // operands, which will conflict with the ".set at" assembler option (which
- // we use only for inline assembly, in order to maintain compatibility with
- // GCC) and will also conflict with the user's usage of $1.
- //
- // The easiest way to avoid these conflicts and keep $1 as an allocatable
- // register for generated code is to automatically clobber $1 for all inline
- // assembly code.
- //
- // FIXME: We should automatically clobber $1 only for inline assembly code
- // which actually uses it. This would allow LLVM to use $1 for inline
- // assembly operands if the user's assembly code doesn't use it.
- return "~{$1}";
- }
-
- bool handleTargetFeatures(std::vector<std::string> &Features,
- DiagnosticsEngine &Diags) override {
- IsMips16 = false;
- IsMicromips = false;
- IsNan2008 = isNaN2008Default();
- IsSingleFloat = false;
- FloatABI = HardFloat;
- DspRev = NoDSP;
- HasFP64 = isFP64Default();
-
- for (const auto &Feature : Features) {
- if (Feature == "+single-float")
- IsSingleFloat = true;
- else if (Feature == "+soft-float")
- FloatABI = SoftFloat;
- else if (Feature == "+mips16")
- IsMips16 = true;
- else if (Feature == "+micromips")
- IsMicromips = true;
- else if (Feature == "+dsp")
- DspRev = std::max(DspRev, DSP1);
- else if (Feature == "+dspr2")
- DspRev = std::max(DspRev, DSP2);
- else if (Feature == "+msa")
- HasMSA = true;
- else if (Feature == "+nomadd4")
- DisableMadd4 = true;
- else if (Feature == "+fp64")
- HasFP64 = true;
- else if (Feature == "-fp64")
- HasFP64 = false;
- else if (Feature == "+nan2008")
- IsNan2008 = true;
- else if (Feature == "-nan2008")
- IsNan2008 = false;
- else if (Feature == "+noabicalls")
- IsNoABICalls = true;
- }
-
- setDataLayout();
-
- return true;
- }
-
- int getEHDataRegisterNumber(unsigned RegNo) const override {
- if (RegNo == 0) return 4;
- if (RegNo == 1) return 5;
- return -1;
- }
-
- bool isCLZForZeroUndef() const override { return false; }
-
- ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
- static const TargetInfo::GCCRegAlias O32RegAliases[] = {
- {{"at"}, "$1"}, {{"v0"}, "$2"}, {{"v1"}, "$3"},
- {{"a0"}, "$4"}, {{"a1"}, "$5"}, {{"a2"}, "$6"},
- {{"a3"}, "$7"}, {{"t0"}, "$8"}, {{"t1"}, "$9"},
- {{"t2"}, "$10"}, {{"t3"}, "$11"}, {{"t4"}, "$12"},
- {{"t5"}, "$13"}, {{"t6"}, "$14"}, {{"t7"}, "$15"},
- {{"s0"}, "$16"}, {{"s1"}, "$17"}, {{"s2"}, "$18"},
- {{"s3"}, "$19"}, {{"s4"}, "$20"}, {{"s5"}, "$21"},
- {{"s6"}, "$22"}, {{"s7"}, "$23"}, {{"t8"}, "$24"},
- {{"t9"}, "$25"}, {{"k0"}, "$26"}, {{"k1"}, "$27"},
- {{"gp"}, "$28"}, {{"sp", "$sp"}, "$29"}, {{"fp", "$fp"}, "$30"},
- {{"ra"}, "$31"}};
- static const TargetInfo::GCCRegAlias NewABIRegAliases[] = {
- {{"at"}, "$1"}, {{"v0"}, "$2"}, {{"v1"}, "$3"},
- {{"a0"}, "$4"}, {{"a1"}, "$5"}, {{"a2"}, "$6"},
- {{"a3"}, "$7"}, {{"a4"}, "$8"}, {{"a5"}, "$9"},
- {{"a6"}, "$10"}, {{"a7"}, "$11"}, {{"t0"}, "$12"},
- {{"t1"}, "$13"}, {{"t2"}, "$14"}, {{"t3"}, "$15"},
- {{"s0"}, "$16"}, {{"s1"}, "$17"}, {{"s2"}, "$18"},
- {{"s3"}, "$19"}, {{"s4"}, "$20"}, {{"s5"}, "$21"},
- {{"s6"}, "$22"}, {{"s7"}, "$23"}, {{"t8"}, "$24"},
- {{"t9"}, "$25"}, {{"k0"}, "$26"}, {{"k1"}, "$27"},
- {{"gp"}, "$28"}, {{"sp", "$sp"}, "$29"}, {{"fp", "$fp"}, "$30"},
- {{"ra"}, "$31"}};
- if (ABI == "o32")
- return llvm::makeArrayRef(O32RegAliases);
- return llvm::makeArrayRef(NewABIRegAliases);
- }
-
- bool hasInt128Type() const override {
- return ABI == "n32" || ABI == "n64";
- }
-
- bool validateTarget(DiagnosticsEngine &Diags) const override {
- // FIXME: It's valid to use O32 on a 64-bit CPU but the backend can't handle
- // this yet. It's better to fail here than on the backend assertion.
- if (processorSupportsGPR64() && ABI == "o32") {
- Diags.Report(diag::err_target_unsupported_abi) << ABI << CPU;
- return false;
- }
-
- // 64-bit ABI's require 64-bit CPU's.
- if (!processorSupportsGPR64() && (ABI == "n32" || ABI == "n64")) {
- Diags.Report(diag::err_target_unsupported_abi) << ABI << CPU;
- return false;
- }
-
- // FIXME: It's valid to use O32 on a mips64/mips64el triple but the backend
- // can't handle this yet. It's better to fail here than on the
- // backend assertion.
- if ((getTriple().getArch() == llvm::Triple::mips64 ||
- getTriple().getArch() == llvm::Triple::mips64el) &&
- ABI == "o32") {
- Diags.Report(diag::err_target_unsupported_abi_for_triple)
- << ABI << getTriple().str();
- return false;
- }
-
- // FIXME: It's valid to use N32/N64 on a mips/mipsel triple but the backend
- // can't handle this yet. It's better to fail here than on the
- // backend assertion.
- if ((getTriple().getArch() == llvm::Triple::mips ||
- getTriple().getArch() == llvm::Triple::mipsel) &&
- (ABI == "n32" || ABI == "n64")) {
- Diags.Report(diag::err_target_unsupported_abi_for_triple)
- << ABI << getTriple().str();
- return false;
- }
-
- return true;
- }
-};
-
-const Builtin::Info MipsTargetInfo::BuiltinInfo[] = {
-#define BUILTIN(ID, TYPE, ATTRS) \
- { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
- { #ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr },
-#include "clang/Basic/BuiltinsMips.def"
-};
-
-class PNaClTargetInfo : public TargetInfo {
-public:
- PNaClTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : TargetInfo(Triple) {
- this->LongAlign = 32;
- this->LongWidth = 32;
- this->PointerAlign = 32;
- this->PointerWidth = 32;
- this->IntMaxType = TargetInfo::SignedLongLong;
- this->Int64Type = TargetInfo::SignedLongLong;
- this->DoubleAlign = 64;
- this->LongDoubleWidth = 64;
- this->LongDoubleAlign = 64;
- this->SizeType = TargetInfo::UnsignedInt;
- this->PtrDiffType = TargetInfo::SignedInt;
- this->IntPtrType = TargetInfo::SignedInt;
- this->RegParmMax = 0; // Disallow regparm
- }
-
- void getArchDefines(const LangOptions &Opts, MacroBuilder &Builder) const {
- Builder.defineMacro("__le32__");
- Builder.defineMacro("__pnacl__");
- }
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- getArchDefines(Opts, Builder);
- }
- bool hasFeature(StringRef Feature) const override {
- return Feature == "pnacl";
- }
- ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
- BuiltinVaListKind getBuiltinVaListKind() const override {
- return TargetInfo::PNaClABIBuiltinVaList;
- }
- ArrayRef<const char *> getGCCRegNames() const override;
- ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
- bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &Info) const override {
- return false;
- }
-
- const char *getClobbers() const override {
- return "";
- }
-};
-
-ArrayRef<const char *> PNaClTargetInfo::getGCCRegNames() const {
- return None;
-}
-
-ArrayRef<TargetInfo::GCCRegAlias> PNaClTargetInfo::getGCCRegAliases() const {
- return None;
+ Builder.defineMacro("__MSVCRT__");
+ Builder.defineMacro("__MINGW32__");
+ addCygMingDefines(Opts, Builder);
}
-// We attempt to use PNaCl (le32) frontend and Mips32EL backend.
-class NaClMips32TargetInfo : public MipsTargetInfo {
-public:
- NaClMips32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : MipsTargetInfo(Triple, Opts) {}
-
- BuiltinVaListKind getBuiltinVaListKind() const override {
- return TargetInfo::PNaClABIBuiltinVaList;
- }
-};
-
-class Le64TargetInfo : public TargetInfo {
- static const Builtin::Info BuiltinInfo[];
-
-public:
- Le64TargetInfo(const llvm::Triple &Triple, const TargetOptions &)
- : TargetInfo(Triple) {
- NoAsmVariants = true;
- LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
- MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
- resetDataLayout("e-m:e-v128:32-v16:16-v32:32-v96:32-n8:16:32:64-S128");
- }
-
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- DefineStd(Builder, "unix", Opts);
- defineCPUMacros(Builder, "le64", /*Tuning=*/false);
- Builder.defineMacro("__ELF__");
- }
- ArrayRef<Builtin::Info> getTargetBuiltins() const override {
- return llvm::makeArrayRef(BuiltinInfo,
- clang::Le64::LastTSBuiltin - Builtin::FirstTSBuiltin);
- }
- BuiltinVaListKind getBuiltinVaListKind() const override {
- return TargetInfo::PNaClABIBuiltinVaList;
- }
- const char *getClobbers() const override { return ""; }
- ArrayRef<const char *> getGCCRegNames() const override {
- return None;
- }
- ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
- return None;
- }
- bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &Info) const override {
- return false;
- }
-
- bool hasProtectedVisibility() const override { return false; }
-};
-
-class WebAssemblyTargetInfo : public TargetInfo {
- static const Builtin::Info BuiltinInfo[];
-
- enum SIMDEnum {
- NoSIMD,
- SIMD128,
- } SIMDLevel;
-
-public:
- explicit WebAssemblyTargetInfo(const llvm::Triple &T, const TargetOptions &)
- : TargetInfo(T), SIMDLevel(NoSIMD) {
- NoAsmVariants = true;
- SuitableAlign = 128;
- LargeArrayMinWidth = 128;
- LargeArrayAlign = 128;
- SimdDefaultAlign = 128;
- SigAtomicType = SignedLong;
- LongDoubleWidth = LongDoubleAlign = 128;
- LongDoubleFormat = &llvm::APFloat::IEEEquad();
- SizeType = UnsignedInt;
- PtrDiffType = SignedInt;
- IntPtrType = SignedInt;
- }
-
-protected:
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- defineCPUMacros(Builder, "wasm", /*Tuning=*/false);
- if (SIMDLevel >= SIMD128)
- Builder.defineMacro("__wasm_simd128__");
- }
-
-private:
- bool
- initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
- StringRef CPU,
- const std::vector<std::string> &FeaturesVec) const override {
- if (CPU == "bleeding-edge")
- Features["simd128"] = true;
- return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
- }
- bool hasFeature(StringRef Feature) const final {
- return llvm::StringSwitch<bool>(Feature)
- .Case("simd128", SIMDLevel >= SIMD128)
- .Default(false);
- }
- bool handleTargetFeatures(std::vector<std::string> &Features,
- DiagnosticsEngine &Diags) final {
- for (const auto &Feature : Features) {
- if (Feature == "+simd128") {
- SIMDLevel = std::max(SIMDLevel, SIMD128);
- continue;
- }
- if (Feature == "-simd128") {
- SIMDLevel = std::min(SIMDLevel, SIMDEnum(SIMD128 - 1));
- continue;
- }
-
- Diags.Report(diag::err_opt_not_valid_with_opt) << Feature
- << "-target-feature";
- return false;
- }
- return true;
- }
- bool setCPU(const std::string &Name) final {
- return llvm::StringSwitch<bool>(Name)
- .Case("mvp", true)
- .Case("bleeding-edge", true)
- .Case("generic", true)
- .Default(false);
- }
- ArrayRef<Builtin::Info> getTargetBuiltins() const final {
- return llvm::makeArrayRef(BuiltinInfo,
- clang::WebAssembly::LastTSBuiltin - Builtin::FirstTSBuiltin);
- }
- BuiltinVaListKind getBuiltinVaListKind() const final {
- return VoidPtrBuiltinVaList;
- }
- ArrayRef<const char *> getGCCRegNames() const final {
- return None;
- }
- ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const final {
- return None;
- }
- bool
- validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &Info) const final {
- return false;
- }
- const char *getClobbers() const final { return ""; }
- bool isCLZForZeroUndef() const final { return false; }
- bool hasInt128Type() const final { return true; }
- IntType getIntTypeByWidth(unsigned BitWidth,
- bool IsSigned) const final {
- // WebAssembly prefers long long for explicitly 64-bit integers.
- return BitWidth == 64 ? (IsSigned ? SignedLongLong : UnsignedLongLong)
- : TargetInfo::getIntTypeByWidth(BitWidth, IsSigned);
- }
- IntType getLeastIntTypeByWidth(unsigned BitWidth,
- bool IsSigned) const final {
- // WebAssembly uses long long for int_least64_t and int_fast64_t.
- return BitWidth == 64
- ? (IsSigned ? SignedLongLong : UnsignedLongLong)
- : TargetInfo::getLeastIntTypeByWidth(BitWidth, IsSigned);
- }
-};
-
-const Builtin::Info WebAssemblyTargetInfo::BuiltinInfo[] = {
-#define BUILTIN(ID, TYPE, ATTRS) \
- { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
- { #ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr },
-#include "clang/Basic/BuiltinsWebAssembly.def"
-};
-
-class WebAssembly32TargetInfo : public WebAssemblyTargetInfo {
-public:
- explicit WebAssembly32TargetInfo(const llvm::Triple &T,
- const TargetOptions &Opts)
- : WebAssemblyTargetInfo(T, Opts) {
- MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
- resetDataLayout("e-m:e-p:32:32-i64:64-n32:64-S128");
- }
-
-protected:
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);
- defineCPUMacros(Builder, "wasm32", /*Tuning=*/false);
- }
-};
-
-class WebAssembly64TargetInfo : public WebAssemblyTargetInfo {
-public:
- explicit WebAssembly64TargetInfo(const llvm::Triple &T,
- const TargetOptions &Opts)
- : WebAssemblyTargetInfo(T, Opts) {
- LongAlign = LongWidth = 64;
- PointerAlign = PointerWidth = 64;
- MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
- SizeType = UnsignedLong;
- PtrDiffType = SignedLong;
- IntPtrType = SignedLong;
- resetDataLayout("e-m:e-p:64:64-i64:64-n32:64-S128");
- }
-
-protected:
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);
- defineCPUMacros(Builder, "wasm64", /*Tuning=*/false);
- }
-};
-
-const Builtin::Info Le64TargetInfo::BuiltinInfo[] = {
-#define BUILTIN(ID, TYPE, ATTRS) \
- { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
-#include "clang/Basic/BuiltinsLe64.def"
-};
-
-static const unsigned SPIRAddrSpaceMap[] = {
- 0, // Default
- 1, // opencl_global
- 3, // opencl_local
- 2, // opencl_constant
- 4, // opencl_generic
- 0, // cuda_device
- 0, // cuda_constant
- 0 // cuda_shared
-};
-class SPIRTargetInfo : public TargetInfo {
-public:
- SPIRTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
- : TargetInfo(Triple) {
- assert(getTriple().getOS() == llvm::Triple::UnknownOS &&
- "SPIR target must use unknown OS");
- assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment &&
- "SPIR target must use unknown environment type");
- TLSSupported = false;
- LongWidth = LongAlign = 64;
- AddrSpaceMap = &SPIRAddrSpaceMap;
- UseAddrSpaceMapMangling = true;
- // Define available target features
- // These must be defined in sorted order!
- NoAsmVariants = true;
- }
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- DefineStd(Builder, "SPIR", Opts);
- }
- bool hasFeature(StringRef Feature) const override {
- return Feature == "spir";
- }
-
- ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
- const char *getClobbers() const override { return ""; }
- ArrayRef<const char *> getGCCRegNames() const override { return None; }
- bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &info) const override {
- return true;
- }
- ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
- return None;
- }
- BuiltinVaListKind getBuiltinVaListKind() const override {
- return TargetInfo::VoidPtrBuiltinVaList;
- }
-
- CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
- return (CC == CC_SpirFunction || CC == CC_OpenCLKernel) ? CCCR_OK
- : CCCR_Warning;
- }
-
- CallingConv getDefaultCallingConv(CallingConvMethodType MT) const override {
- return CC_SpirFunction;
- }
-
- void setSupportedOpenCLOpts() override {
- // Assume all OpenCL extensions and optional core features are supported
- // for SPIR since it is a generic target.
- getSupportedOpenCLOpts().supportAll();
- }
-};
-
-class SPIR32TargetInfo : public SPIRTargetInfo {
-public:
- SPIR32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : SPIRTargetInfo(Triple, Opts) {
- PointerWidth = PointerAlign = 32;
- SizeType = TargetInfo::UnsignedInt;
- PtrDiffType = IntPtrType = TargetInfo::SignedInt;
- resetDataLayout("e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-"
- "v96:128-v192:256-v256:256-v512:512-v1024:1024");
- }
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- DefineStd(Builder, "SPIR32", Opts);
- }
-};
-
-class SPIR64TargetInfo : public SPIRTargetInfo {
-public:
- SPIR64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : SPIRTargetInfo(Triple, Opts) {
- PointerWidth = PointerAlign = 64;
- SizeType = TargetInfo::UnsignedLong;
- PtrDiffType = IntPtrType = TargetInfo::SignedLong;
- resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-"
- "v96:128-v192:256-v256:256-v512:512-v1024:1024");
- }
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- DefineStd(Builder, "SPIR64", Opts);
- }
-};
-
-class XCoreTargetInfo : public TargetInfo {
- static const Builtin::Info BuiltinInfo[];
-public:
- XCoreTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
- : TargetInfo(Triple) {
- NoAsmVariants = true;
- LongLongAlign = 32;
- SuitableAlign = 32;
- DoubleAlign = LongDoubleAlign = 32;
- SizeType = UnsignedInt;
- PtrDiffType = SignedInt;
- IntPtrType = SignedInt;
- WCharType = UnsignedChar;
- WIntType = UnsignedInt;
- UseZeroLengthBitfieldAlignment = true;
- resetDataLayout("e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:32"
- "-f64:32-a:0:32-n32");
- }
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- Builder.defineMacro("__XS1B__");
- }
- ArrayRef<Builtin::Info> getTargetBuiltins() const override {
- return llvm::makeArrayRef(BuiltinInfo,
- clang::XCore::LastTSBuiltin-Builtin::FirstTSBuiltin);
- }
- BuiltinVaListKind getBuiltinVaListKind() const override {
- return TargetInfo::VoidPtrBuiltinVaList;
- }
- const char *getClobbers() const override {
- return "";
- }
- ArrayRef<const char *> getGCCRegNames() const override {
- static const char * const GCCRegNames[] = {
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "cp", "dp", "sp", "lr"
- };
- return llvm::makeArrayRef(GCCRegNames);
- }
- ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
- return None;
- }
- bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &Info) const override {
- return false;
- }
- int getEHDataRegisterNumber(unsigned RegNo) const override {
- // R0=ExceptionPointerRegister R1=ExceptionSelectorRegister
- return (RegNo < 2)? RegNo : -1;
- }
- bool allowsLargerPreferedTypeAlignment() const override {
- return false;
- }
-};
-
-const Builtin::Info XCoreTargetInfo::BuiltinInfo[] = {
-#define BUILTIN(ID, TYPE, ATTRS) \
- { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
- { #ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr },
-#include "clang/Basic/BuiltinsXCore.def"
-};
-
-// x86_32 Android target
-class AndroidX86_32TargetInfo : public LinuxTargetInfo<X86_32TargetInfo> {
-public:
- AndroidX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : LinuxTargetInfo<X86_32TargetInfo>(Triple, Opts) {
- SuitableAlign = 32;
- LongDoubleWidth = 64;
- LongDoubleFormat = &llvm::APFloat::IEEEdouble();
- }
-};
-
-// x86_64 Android target
-class AndroidX86_64TargetInfo : public LinuxTargetInfo<X86_64TargetInfo> {
-public:
- AndroidX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : LinuxTargetInfo<X86_64TargetInfo>(Triple, Opts) {
- LongDoubleFormat = &llvm::APFloat::IEEEquad();
- }
-
- bool useFloat128ManglingForLongDouble() const override {
- return true;
- }
-};
-
-// 32-bit RenderScript is armv7 with width and align of 'long' set to 8-bytes
-class RenderScript32TargetInfo : public ARMleTargetInfo {
-public:
- RenderScript32TargetInfo(const llvm::Triple &Triple,
- const TargetOptions &Opts)
- : ARMleTargetInfo(llvm::Triple("armv7", Triple.getVendorName(),
- Triple.getOSName(),
- Triple.getEnvironmentName()),
- Opts) {
- IsRenderScriptTarget = true;
- LongWidth = LongAlign = 64;
- }
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- Builder.defineMacro("__RENDERSCRIPT__");
- ARMleTargetInfo::getTargetDefines(Opts, Builder);
- }
-};
-
-// 64-bit RenderScript is aarch64
-class RenderScript64TargetInfo : public AArch64leTargetInfo {
-public:
- RenderScript64TargetInfo(const llvm::Triple &Triple,
- const TargetOptions &Opts)
- : AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(),
- Triple.getOSName(),
- Triple.getEnvironmentName()),
- Opts) {
- IsRenderScriptTarget = true;
- }
-
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- Builder.defineMacro("__RENDERSCRIPT__");
- AArch64leTargetInfo::getTargetDefines(Opts, Builder);
- }
-};
-
-/// Information about a specific microcontroller.
-struct MCUInfo {
- const char *Name;
- const char *DefineName;
-};
-
-// This list should be kept up-to-date with AVRDevices.td in LLVM.
-static ArrayRef<MCUInfo> AVRMcus = {
- { "at90s1200", "__AVR_AT90S1200__" },
- { "attiny11", "__AVR_ATtiny11__" },
- { "attiny12", "__AVR_ATtiny12__" },
- { "attiny15", "__AVR_ATtiny15__" },
- { "attiny28", "__AVR_ATtiny28__" },
- { "at90s2313", "__AVR_AT90S2313__" },
- { "at90s2323", "__AVR_AT90S2323__" },
- { "at90s2333", "__AVR_AT90S2333__" },
- { "at90s2343", "__AVR_AT90S2343__" },
- { "attiny22", "__AVR_ATtiny22__" },
- { "attiny26", "__AVR_ATtiny26__" },
- { "at86rf401", "__AVR_AT86RF401__" },
- { "at90s4414", "__AVR_AT90S4414__" },
- { "at90s4433", "__AVR_AT90S4433__" },
- { "at90s4434", "__AVR_AT90S4434__" },
- { "at90s8515", "__AVR_AT90S8515__" },
- { "at90c8534", "__AVR_AT90c8534__" },
- { "at90s8535", "__AVR_AT90S8535__" },
- { "ata5272", "__AVR_ATA5272__" },
- { "attiny13", "__AVR_ATtiny13__" },
- { "attiny13a", "__AVR_ATtiny13A__" },
- { "attiny2313", "__AVR_ATtiny2313__" },
- { "attiny2313a", "__AVR_ATtiny2313A__" },
- { "attiny24", "__AVR_ATtiny24__" },
- { "attiny24a", "__AVR_ATtiny24A__" },
- { "attiny4313", "__AVR_ATtiny4313__" },
- { "attiny44", "__AVR_ATtiny44__" },
- { "attiny44a", "__AVR_ATtiny44A__" },
- { "attiny84", "__AVR_ATtiny84__" },
- { "attiny84a", "__AVR_ATtiny84A__" },
- { "attiny25", "__AVR_ATtiny25__" },
- { "attiny45", "__AVR_ATtiny45__" },
- { "attiny85", "__AVR_ATtiny85__" },
- { "attiny261", "__AVR_ATtiny261__" },
- { "attiny261a", "__AVR_ATtiny261A__" },
- { "attiny461", "__AVR_ATtiny461__" },
- { "attiny461a", "__AVR_ATtiny461A__" },
- { "attiny861", "__AVR_ATtiny861__" },
- { "attiny861a", "__AVR_ATtiny861A__" },
- { "attiny87", "__AVR_ATtiny87__" },
- { "attiny43u", "__AVR_ATtiny43U__" },
- { "attiny48", "__AVR_ATtiny48__" },
- { "attiny88", "__AVR_ATtiny88__" },
- { "attiny828", "__AVR_ATtiny828__" },
- { "at43usb355", "__AVR_AT43USB355__" },
- { "at76c711", "__AVR_AT76C711__" },
- { "atmega103", "__AVR_ATmega103__" },
- { "at43usb320", "__AVR_AT43USB320__" },
- { "attiny167", "__AVR_ATtiny167__" },
- { "at90usb82", "__AVR_AT90USB82__" },
- { "at90usb162", "__AVR_AT90USB162__" },
- { "ata5505", "__AVR_ATA5505__" },
- { "atmega8u2", "__AVR_ATmega8U2__" },
- { "atmega16u2", "__AVR_ATmega16U2__" },
- { "atmega32u2", "__AVR_ATmega32U2__" },
- { "attiny1634", "__AVR_ATtiny1634__" },
- { "atmega8", "__AVR_ATmega8__" },
- { "ata6289", "__AVR_ATA6289__" },
- { "atmega8a", "__AVR_ATmega8A__" },
- { "ata6285", "__AVR_ATA6285__" },
- { "ata6286", "__AVR_ATA6286__" },
- { "atmega48", "__AVR_ATmega48__" },
- { "atmega48a", "__AVR_ATmega48A__" },
- { "atmega48pa", "__AVR_ATmega48PA__" },
- { "atmega48p", "__AVR_ATmega48P__" },
- { "atmega88", "__AVR_ATmega88__" },
- { "atmega88a", "__AVR_ATmega88A__" },
- { "atmega88p", "__AVR_ATmega88P__" },
- { "atmega88pa", "__AVR_ATmega88PA__" },
- { "atmega8515", "__AVR_ATmega8515__" },
- { "atmega8535", "__AVR_ATmega8535__" },
- { "atmega8hva", "__AVR_ATmega8HVA__" },
- { "at90pwm1", "__AVR_AT90PWM1__" },
- { "at90pwm2", "__AVR_AT90PWM2__" },
- { "at90pwm2b", "__AVR_AT90PWM2B__" },
- { "at90pwm3", "__AVR_AT90PWM3__" },
- { "at90pwm3b", "__AVR_AT90PWM3B__" },
- { "at90pwm81", "__AVR_AT90PWM81__" },
- { "ata5790", "__AVR_ATA5790__" },
- { "ata5795", "__AVR_ATA5795__" },
- { "atmega16", "__AVR_ATmega16__" },
- { "atmega16a", "__AVR_ATmega16A__" },
- { "atmega161", "__AVR_ATmega161__" },
- { "atmega162", "__AVR_ATmega162__" },
- { "atmega163", "__AVR_ATmega163__" },
- { "atmega164a", "__AVR_ATmega164A__" },
- { "atmega164p", "__AVR_ATmega164P__" },
- { "atmega164pa", "__AVR_ATmega164PA__" },
- { "atmega165", "__AVR_ATmega165__" },
- { "atmega165a", "__AVR_ATmega165A__" },
- { "atmega165p", "__AVR_ATmega165P__" },
- { "atmega165pa", "__AVR_ATmega165PA__" },
- { "atmega168", "__AVR_ATmega168__" },
- { "atmega168a", "__AVR_ATmega168A__" },
- { "atmega168p", "__AVR_ATmega168P__" },
- { "atmega168pa", "__AVR_ATmega168PA__" },
- { "atmega169", "__AVR_ATmega169__" },
- { "atmega169a", "__AVR_ATmega169A__" },
- { "atmega169p", "__AVR_ATmega169P__" },
- { "atmega169pa", "__AVR_ATmega169PA__" },
- { "atmega32", "__AVR_ATmega32__" },
- { "atmega32a", "__AVR_ATmega32A__" },
- { "atmega323", "__AVR_ATmega323__" },
- { "atmega324a", "__AVR_ATmega324A__" },
- { "atmega324p", "__AVR_ATmega324P__" },
- { "atmega324pa", "__AVR_ATmega324PA__" },
- { "atmega325", "__AVR_ATmega325__" },
- { "atmega325a", "__AVR_ATmega325A__" },
- { "atmega325p", "__AVR_ATmega325P__" },
- { "atmega325pa", "__AVR_ATmega325PA__" },
- { "atmega3250", "__AVR_ATmega3250__" },
- { "atmega3250a", "__AVR_ATmega3250A__" },
- { "atmega3250p", "__AVR_ATmega3250P__" },
- { "atmega3250pa", "__AVR_ATmega3250PA__" },
- { "atmega328", "__AVR_ATmega328__" },
- { "atmega328p", "__AVR_ATmega328P__" },
- { "atmega329", "__AVR_ATmega329__" },
- { "atmega329a", "__AVR_ATmega329A__" },
- { "atmega329p", "__AVR_ATmega329P__" },
- { "atmega329pa", "__AVR_ATmega329PA__" },
- { "atmega3290", "__AVR_ATmega3290__" },
- { "atmega3290a", "__AVR_ATmega3290A__" },
- { "atmega3290p", "__AVR_ATmega3290P__" },
- { "atmega3290pa", "__AVR_ATmega3290PA__" },
- { "atmega406", "__AVR_ATmega406__" },
- { "atmega64", "__AVR_ATmega64__" },
- { "atmega64a", "__AVR_ATmega64A__" },
- { "atmega640", "__AVR_ATmega640__" },
- { "atmega644", "__AVR_ATmega644__" },
- { "atmega644a", "__AVR_ATmega644A__" },
- { "atmega644p", "__AVR_ATmega644P__" },
- { "atmega644pa", "__AVR_ATmega644PA__" },
- { "atmega645", "__AVR_ATmega645__" },
- { "atmega645a", "__AVR_ATmega645A__" },
- { "atmega645p", "__AVR_ATmega645P__" },
- { "atmega649", "__AVR_ATmega649__" },
- { "atmega649a", "__AVR_ATmega649A__" },
- { "atmega649p", "__AVR_ATmega649P__" },
- { "atmega6450", "__AVR_ATmega6450__" },
- { "atmega6450a", "__AVR_ATmega6450A__" },
- { "atmega6450p", "__AVR_ATmega6450P__" },
- { "atmega6490", "__AVR_ATmega6490__" },
- { "atmega6490a", "__AVR_ATmega6490A__" },
- { "atmega6490p", "__AVR_ATmega6490P__" },
- { "atmega64rfr2", "__AVR_ATmega64RFR2__" },
- { "atmega644rfr2", "__AVR_ATmega644RFR2__" },
- { "atmega16hva", "__AVR_ATmega16HVA__" },
- { "atmega16hva2", "__AVR_ATmega16HVA2__" },
- { "atmega16hvb", "__AVR_ATmega16HVB__" },
- { "atmega16hvbrevb", "__AVR_ATmega16HVBREVB__" },
- { "atmega32hvb", "__AVR_ATmega32HVB__" },
- { "atmega32hvbrevb", "__AVR_ATmega32HVBREVB__" },
- { "atmega64hve", "__AVR_ATmega64HVE__" },
- { "at90can32", "__AVR_AT90CAN32__" },
- { "at90can64", "__AVR_AT90CAN64__" },
- { "at90pwm161", "__AVR_AT90PWM161__" },
- { "at90pwm216", "__AVR_AT90PWM216__" },
- { "at90pwm316", "__AVR_AT90PWM316__" },
- { "atmega32c1", "__AVR_ATmega32C1__" },
- { "atmega64c1", "__AVR_ATmega64C1__" },
- { "atmega16m1", "__AVR_ATmega16M1__" },
- { "atmega32m1", "__AVR_ATmega32M1__" },
- { "atmega64m1", "__AVR_ATmega64M1__" },
- { "atmega16u4", "__AVR_ATmega16U4__" },
- { "atmega32u4", "__AVR_ATmega32U4__" },
- { "atmega32u6", "__AVR_ATmega32U6__" },
- { "at90usb646", "__AVR_AT90USB646__" },
- { "at90usb647", "__AVR_AT90USB647__" },
- { "at90scr100", "__AVR_AT90SCR100__" },
- { "at94k", "__AVR_AT94K__" },
- { "m3000", "__AVR_AT000__" },
- { "atmega128", "__AVR_ATmega128__" },
- { "atmega128a", "__AVR_ATmega128A__" },
- { "atmega1280", "__AVR_ATmega1280__" },
- { "atmega1281", "__AVR_ATmega1281__" },
- { "atmega1284", "__AVR_ATmega1284__" },
- { "atmega1284p", "__AVR_ATmega1284P__" },
- { "atmega128rfa1", "__AVR_ATmega128RFA1__" },
- { "atmega128rfr2", "__AVR_ATmega128RFR2__" },
- { "atmega1284rfr2", "__AVR_ATmega1284RFR2__" },
- { "at90can128", "__AVR_AT90CAN128__" },
- { "at90usb1286", "__AVR_AT90USB1286__" },
- { "at90usb1287", "__AVR_AT90USB1287__" },
- { "atmega2560", "__AVR_ATmega2560__" },
- { "atmega2561", "__AVR_ATmega2561__" },
- { "atmega256rfr2", "__AVR_ATmega256RFR2__" },
- { "atmega2564rfr2", "__AVR_ATmega2564RFR2__" },
- { "atxmega16a4", "__AVR_ATxmega16A4__" },
- { "atxmega16a4u", "__AVR_ATxmega16a4U__" },
- { "atxmega16c4", "__AVR_ATxmega16C4__" },
- { "atxmega16d4", "__AVR_ATxmega16D4__" },
- { "atxmega32a4", "__AVR_ATxmega32A4__" },
- { "atxmega32a4u", "__AVR_ATxmega32A4U__" },
- { "atxmega32c4", "__AVR_ATxmega32C4__" },
- { "atxmega32d4", "__AVR_ATxmega32D4__" },
- { "atxmega32e5", "__AVR_ATxmega32E5__" },
- { "atxmega16e5", "__AVR_ATxmega16E5__" },
- { "atxmega8e5", "__AVR_ATxmega8E5__" },
- { "atxmega32x1", "__AVR_ATxmega32X1__" },
- { "atxmega64a3", "__AVR_ATxmega64A3__" },
- { "atxmega64a3u", "__AVR_ATxmega64A3U__" },
- { "atxmega64a4u", "__AVR_ATxmega64A4U__" },
- { "atxmega64b1", "__AVR_ATxmega64B1__" },
- { "atxmega64b3", "__AVR_ATxmega64B3__" },
- { "atxmega64c3", "__AVR_ATxmega64C3__" },
- { "atxmega64d3", "__AVR_ATxmega64D3__" },
- { "atxmega64d4", "__AVR_ATxmega64D4__" },
- { "atxmega64a1", "__AVR_ATxmega64A1__" },
- { "atxmega64a1u", "__AVR_ATxmega64A1U__" },
- { "atxmega128a3", "__AVR_ATxmega128A3__" },
- { "atxmega128a3u", "__AVR_ATxmega128A3U__" },
- { "atxmega128b1", "__AVR_ATxmega128B1__" },
- { "atxmega128b3", "__AVR_ATxmega128B3__" },
- { "atxmega128c3", "__AVR_ATxmega128C3__" },
- { "atxmega128d3", "__AVR_ATxmega128D3__" },
- { "atxmega128d4", "__AVR_ATxmega128D4__" },
- { "atxmega192a3", "__AVR_ATxmega192A3__" },
- { "atxmega192a3u", "__AVR_ATxmega192A3U__" },
- { "atxmega192c3", "__AVR_ATxmega192C3__" },
- { "atxmega192d3", "__AVR_ATxmega192D3__" },
- { "atxmega256a3", "__AVR_ATxmega256A3__" },
- { "atxmega256a3u", "__AVR_ATxmega256A3U__" },
- { "atxmega256a3b", "__AVR_ATxmega256A3B__" },
- { "atxmega256a3bu", "__AVR_ATxmega256A3BU__" },
- { "atxmega256c3", "__AVR_ATxmega256C3__" },
- { "atxmega256d3", "__AVR_ATxmega256D3__" },
- { "atxmega384c3", "__AVR_ATxmega384C3__" },
- { "atxmega384d3", "__AVR_ATxmega384D3__" },
- { "atxmega128a1", "__AVR_ATxmega128A1__" },
- { "atxmega128a1u", "__AVR_ATxmega128A1U__" },
- { "atxmega128a4u", "__AVR_ATxmega128a4U__" },
- { "attiny4", "__AVR_ATtiny4__" },
- { "attiny5", "__AVR_ATtiny5__" },
- { "attiny9", "__AVR_ATtiny9__" },
- { "attiny10", "__AVR_ATtiny10__" },
- { "attiny20", "__AVR_ATtiny20__" },
- { "attiny40", "__AVR_ATtiny40__" },
- { "attiny102", "__AVR_ATtiny102__" },
- { "attiny104", "__AVR_ATtiny104__" },
-};
-
-// AVR Target
-class AVRTargetInfo : public TargetInfo {
-public:
- AVRTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
- : TargetInfo(Triple) {
- TLSSupported = false;
- PointerWidth = 16;
- PointerAlign = 8;
- IntWidth = 16;
- IntAlign = 8;
- LongWidth = 32;
- LongAlign = 8;
- LongLongWidth = 64;
- LongLongAlign = 8;
- SuitableAlign = 8;
- DefaultAlignForAttributeAligned = 8;
- HalfWidth = 16;
- HalfAlign = 8;
- FloatWidth = 32;
- FloatAlign = 8;
- DoubleWidth = 32;
- DoubleAlign = 8;
- DoubleFormat = &llvm::APFloat::IEEEsingle();
- LongDoubleWidth = 32;
- LongDoubleAlign = 8;
- LongDoubleFormat = &llvm::APFloat::IEEEsingle();
- SizeType = UnsignedInt;
- PtrDiffType = SignedInt;
- IntPtrType = SignedInt;
- Char16Type = UnsignedInt;
- WCharType = SignedInt;
- WIntType = SignedInt;
- Char32Type = UnsignedLong;
- SigAtomicType = SignedChar;
- resetDataLayout("e-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8");
- }
-
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- Builder.defineMacro("AVR");
- Builder.defineMacro("__AVR");
- Builder.defineMacro("__AVR__");
-
- if (!this->CPU.empty()) {
- auto It = std::find_if(AVRMcus.begin(), AVRMcus.end(),
- [&](const MCUInfo &Info) { return Info.Name == this->CPU; });
-
- if (It != AVRMcus.end())
- Builder.defineMacro(It->DefineName);
- }
- }
-
- ArrayRef<Builtin::Info> getTargetBuiltins() const override {
- return None;
- }
-
- BuiltinVaListKind getBuiltinVaListKind() const override {
- return TargetInfo::VoidPtrBuiltinVaList;
- }
-
- const char *getClobbers() const override {
- return "";
- }
-
- ArrayRef<const char *> getGCCRegNames() const override {
- static const char * const GCCRegNames[] = {
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
- "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
- "r24", "r25", "X", "Y", "Z", "SP"
- };
- return llvm::makeArrayRef(GCCRegNames);
- }
-
- ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
- return None;
- }
-
- ArrayRef<TargetInfo::AddlRegName> getGCCAddlRegNames() const override {
- static const TargetInfo::AddlRegName AddlRegNames[] = {
- { { "r26", "r27"}, 26 },
- { { "r28", "r29"}, 27 },
- { { "r30", "r31"}, 28 },
- { { "SPL", "SPH"}, 29 },
- };
- return llvm::makeArrayRef(AddlRegNames);
- }
-
- bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &Info) const override {
- // There aren't any multi-character AVR specific constraints.
- if (StringRef(Name).size() > 1) return false;
-
- switch (*Name) {
- default: return false;
- case 'a': // Simple upper registers
- case 'b': // Base pointer registers pairs
- case 'd': // Upper register
- case 'l': // Lower registers
- case 'e': // Pointer register pairs
- case 'q': // Stack pointer register
- case 'r': // Any register
- case 'w': // Special upper register pairs
- case 't': // Temporary register
- case 'x': case 'X': // Pointer register pair X
- case 'y': case 'Y': // Pointer register pair Y
- case 'z': case 'Z': // Pointer register pair Z
- Info.setAllowsRegister();
- return true;
- case 'I': // 6-bit positive integer constant
- Info.setRequiresImmediate(0, 63);
- return true;
- case 'J': // 6-bit negative integer constant
- Info.setRequiresImmediate(-63, 0);
- return true;
- case 'K': // Integer constant (Range: 2)
- Info.setRequiresImmediate(2);
- return true;
- case 'L': // Integer constant (Range: 0)
- Info.setRequiresImmediate(0);
- return true;
- case 'M': // 8-bit integer constant
- Info.setRequiresImmediate(0, 0xff);
- return true;
- case 'N': // Integer constant (Range: -1)
- Info.setRequiresImmediate(-1);
- return true;
- case 'O': // Integer constant (Range: 8, 16, 24)
- Info.setRequiresImmediate({8, 16, 24});
- return true;
- case 'P': // Integer constant (Range: 1)
- Info.setRequiresImmediate(1);
- return true;
- case 'R': // Integer constant (Range: -6 to 5)
- Info.setRequiresImmediate(-6, 5);
- return true;
- case 'G': // Floating point constant
- case 'Q': // A memory address based on Y or Z pointer with displacement.
- return true;
- }
-
- return false;
- }
-
- IntType getIntTypeByWidth(unsigned BitWidth,
- bool IsSigned) const final {
- // AVR prefers int for 16-bit integers.
- return BitWidth == 16 ? (IsSigned ? SignedInt : UnsignedInt)
- : TargetInfo::getIntTypeByWidth(BitWidth, IsSigned);
- }
-
- IntType getLeastIntTypeByWidth(unsigned BitWidth,
- bool IsSigned) const final {
- // AVR uses int for int_least16_t and int_fast16_t.
- return BitWidth == 16
- ? (IsSigned ? SignedInt : UnsignedInt)
- : TargetInfo::getLeastIntTypeByWidth(BitWidth, IsSigned);
- }
-
- bool setCPU(const std::string &Name) override {
- bool IsFamily = llvm::StringSwitch<bool>(Name)
- .Case("avr1", true)
- .Case("avr2", true)
- .Case("avr25", true)
- .Case("avr3", true)
- .Case("avr31", true)
- .Case("avr35", true)
- .Case("avr4", true)
- .Case("avr5", true)
- .Case("avr51", true)
- .Case("avr6", true)
- .Case("avrxmega1", true)
- .Case("avrxmega2", true)
- .Case("avrxmega3", true)
- .Case("avrxmega4", true)
- .Case("avrxmega5", true)
- .Case("avrxmega6", true)
- .Case("avrxmega7", true)
- .Case("avrtiny", true)
- .Default(false);
-
- if (IsFamily) this->CPU = Name;
-
- bool IsMCU = std::find_if(AVRMcus.begin(), AVRMcus.end(),
- [&](const MCUInfo &Info) { return Info.Name == Name; }) != AVRMcus.end();
-
- if (IsMCU) this->CPU = Name;
-
- return IsFamily || IsMCU;
- }
-
-protected:
- std::string CPU;
-};
-
-} // end anonymous namespace
-
//===----------------------------------------------------------------------===//
// Driver code
//===----------------------------------------------------------------------===//
-static TargetInfo *AllocateTarget(const llvm::Triple &Triple,
- const TargetOptions &Opts) {
+TargetInfo *AllocateTarget(const llvm::Triple &Triple,
+ const TargetOptions &Opts) {
llvm::Triple::OSType os = Triple.getOS();
switch (Triple.getArch()) {
@@ -9558,7 +149,13 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple,
case llvm::Triple::OpenBSD:
return new OpenBSDTargetInfo<AArch64leTargetInfo>(Triple, Opts);
case llvm::Triple::Win32:
- return new MicrosoftARM64TargetInfo(Triple, Opts);
+ switch (Triple.getEnvironment()) {
+ case llvm::Triple::GNU:
+ return new MinGWARM64TargetInfo(Triple, Opts);
+ case llvm::Triple::MSVC:
+ default: // Assume MSVC for unknown environments
+ return new MicrosoftARM64TargetInfo(Triple, Opts);
+ }
default:
return new AArch64leTargetInfo(Triple, Opts);
}
@@ -9593,8 +190,6 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple,
return new NetBSDTargetInfo<ARMleTargetInfo>(Triple, Opts);
case llvm::Triple::OpenBSD:
return new OpenBSDTargetInfo<ARMleTargetInfo>(Triple, Opts);
- case llvm::Triple::Bitrig:
- return new BitrigTargetInfo<ARMleTargetInfo>(Triple, Opts);
case llvm::Triple::RTEMS:
return new RTEMSTargetInfo<ARMleTargetInfo>(Triple, Opts);
case llvm::Triple::NaCl:
@@ -9629,8 +224,6 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple,
return new NetBSDTargetInfo<ARMbeTargetInfo>(Triple, Opts);
case llvm::Triple::OpenBSD:
return new OpenBSDTargetInfo<ARMbeTargetInfo>(Triple, Opts);
- case llvm::Triple::Bitrig:
- return new BitrigTargetInfo<ARMbeTargetInfo>(Triple, Opts);
case llvm::Triple::RTEMS:
return new RTEMSTargetInfo<ARMbeTargetInfo>(Triple, Opts);
case llvm::Triple::NaCl:
@@ -9861,8 +454,6 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple,
return new NetBSDI386TargetInfo(Triple, Opts);
case llvm::Triple::OpenBSD:
return new OpenBSDI386TargetInfo(Triple, Opts);
- case llvm::Triple::Bitrig:
- return new BitrigI386TargetInfo(Triple, Opts);
case llvm::Triple::FreeBSD:
return new FreeBSDTargetInfo<X86_32TargetInfo>(Triple, Opts);
case llvm::Triple::KFreeBSD:
@@ -9918,8 +509,6 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple,
return new NetBSDTargetInfo<X86_64TargetInfo>(Triple, Opts);
case llvm::Triple::OpenBSD:
return new OpenBSDX86_64TargetInfo(Triple, Opts);
- case llvm::Triple::Bitrig:
- return new BitrigX86_64TargetInfo(Triple, Opts);
case llvm::Triple::FreeBSD:
return new FreeBSDTargetInfo<X86_64TargetInfo>(Triple, Opts);
case llvm::Triple::Fuchsia:
@@ -9984,7 +573,10 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple,
return new LinuxTargetInfo<RenderScript64TargetInfo>(Triple, Opts);
}
}
+} // namespace targets
+} // namespace clang
+using namespace clang::targets;
/// CreateTargetInfo - Return the target info object for the specified target
/// options.
TargetInfo *
@@ -10023,7 +615,7 @@ TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags,
llvm::StringMap<bool> Features;
if (!Target->initFeatureMap(Features, Diags, Opts->CPU,
Opts->FeaturesAsWritten))
- return nullptr;
+ return nullptr;
// Add the features to the compile options.
Opts->Features.clear();
@@ -10035,6 +627,7 @@ TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags,
Target->setSupportedOpenCLOpts();
Target->setOpenCLExtensionOpts();
+ Target->setMaxAtomicWidth();
if (!Target->validateTarget(Diags))
return nullptr;
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets.h b/contrib/llvm/tools/clang/lib/Basic/Targets.h
new file mode 100644
index 0000000000000..6fc967ddabee0
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets.h
@@ -0,0 +1,51 @@
+//===------- Targets.h - Declare target feature support -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares things required for construction of a TargetInfo object
+// from a target triple. Typically individual targets will need to include from
+// here in order to get these functions if required.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_H
+
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+namespace targets {
+
+LLVM_LIBRARY_VISIBILITY
+clang::TargetInfo *AllocateTarget(const llvm::Triple &Triple,
+ const clang::TargetOptions &Opts);
+
+/// DefineStd - Define a macro name and standard variants. For example if
+/// MacroName is "unix", then this will define "__unix", "__unix__", and "unix"
+/// when in GNU mode.
+LLVM_LIBRARY_VISIBILITY
+void DefineStd(clang::MacroBuilder &Builder, llvm::StringRef MacroName,
+ const clang::LangOptions &Opts);
+
+LLVM_LIBRARY_VISIBILITY
+void defineCPUMacros(clang::MacroBuilder &Builder, llvm::StringRef CPUName,
+ bool Tuning = true);
+
+LLVM_LIBRARY_VISIBILITY
+void addMinGWDefines(const llvm::Triple &Triple, const clang::LangOptions &Opts,
+ clang::MacroBuilder &Builder);
+
+LLVM_LIBRARY_VISIBILITY
+void addCygMingDefines(const clang::LangOptions &Opts,
+ clang::MacroBuilder &Builder);
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/AArch64.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/AArch64.cpp
new file mode 100644
index 0000000000000..62990dc23821e
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/AArch64.cpp
@@ -0,0 +1,537 @@
+//===--- AArch64.cpp - Implement AArch64 target feature support -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements AArch64 TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AArch64.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringExtras.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#include "clang/Basic/BuiltinsNEON.def"
+
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define LANGBUILTIN(ID, TYPE, ATTRS, LANG) \
+ {#ID, TYPE, ATTRS, nullptr, LANG, nullptr},
+#include "clang/Basic/BuiltinsAArch64.def"
+};
+
+AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : TargetInfo(Triple), ABI("aapcs") {
+ if (getTriple().getOS() == llvm::Triple::NetBSD ||
+ getTriple().getOS() == llvm::Triple::OpenBSD) {
+ // NetBSD apparently prefers consistency across ARM targets to
+ // consistency across 64-bit targets.
+ Int64Type = SignedLongLong;
+ IntMaxType = SignedLongLong;
+ } else {
+ if (!getTriple().isOSDarwin())
+ WCharType = UnsignedInt;
+
+ Int64Type = SignedLong;
+ IntMaxType = SignedLong;
+ }
+
+
+ LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
+ MaxVectorAlign = 128;
+ MaxAtomicInlineWidth = 128;
+ MaxAtomicPromoteWidth = 128;
+
+ LongDoubleWidth = LongDoubleAlign = SuitableAlign = 128;
+ LongDoubleFormat = &llvm::APFloat::IEEEquad();
+
+ // Make __builtin_ms_va_list available.
+ HasBuiltinMSVaList = true;
+
+ // {} in inline assembly are neon specifiers, not assembly variant
+ // specifiers.
+ NoAsmVariants = true;
+
+ // AAPCS gives rules for bitfields. 7.1.7 says: "The container type
+ // contributes to the alignment of the containing aggregate in the same way
+ // a plain (non bit-field) member of that type would, without exception for
+ // zero-sized or anonymous bit-fields."
+ assert(UseBitFieldTypeAlignment && "bitfields affect type alignment");
+ UseZeroLengthBitfieldAlignment = true;
+
+ // AArch64 targets default to using the ARM C++ ABI.
+ TheCXXABI.set(TargetCXXABI::GenericAArch64);
+
+ if (Triple.getOS() == llvm::Triple::Linux)
+ this->MCountName = "\01_mcount";
+ else if (Triple.getOS() == llvm::Triple::UnknownOS)
+ this->MCountName =
+ Opts.EABIVersion == llvm::EABI::GNU ? "\01_mcount" : "mcount";
+}
+
+StringRef AArch64TargetInfo::getABI() const { return ABI; }
+
+bool AArch64TargetInfo::setABI(const std::string &Name) {
+ if (Name != "aapcs" && Name != "darwinpcs")
+ return false;
+
+ ABI = Name;
+ return true;
+}
+
+bool AArch64TargetInfo::isValidCPUName(StringRef Name) const {
+ return Name == "generic" ||
+ llvm::AArch64::parseCPUArch(Name) != llvm::AArch64::ArchKind::INVALID;
+}
+
+bool AArch64TargetInfo::setCPU(const std::string &Name) {
+ return isValidCPUName(Name);
+}
+
+void AArch64TargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
+}
+
+void AArch64TargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ // Also include the ARMv8.1 defines
+ getTargetDefinesARMV81A(Opts, Builder);
+}
+
+void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ // Target identification.
+ Builder.defineMacro("__aarch64__");
+ // For bare-metal none-eabi.
+ if (getTriple().getOS() == llvm::Triple::UnknownOS &&
+ (getTriple().getEnvironment() == llvm::Triple::EABI ||
+ getTriple().getEnvironment() == llvm::Triple::EABIHF))
+ Builder.defineMacro("__ELF__");
+
+ // Target properties.
+ if (!getTriple().isOSWindows()) {
+ Builder.defineMacro("_LP64");
+ Builder.defineMacro("__LP64__");
+ }
+
+ // ACLE predefines. Many can only have one possible value on v8 AArch64.
+ Builder.defineMacro("__ARM_ACLE", "200");
+ Builder.defineMacro("__ARM_ARCH", "8");
+ Builder.defineMacro("__ARM_ARCH_PROFILE", "'A'");
+
+ Builder.defineMacro("__ARM_64BIT_STATE", "1");
+ Builder.defineMacro("__ARM_PCS_AAPCS64", "1");
+ Builder.defineMacro("__ARM_ARCH_ISA_A64", "1");
+
+ Builder.defineMacro("__ARM_FEATURE_CLZ", "1");
+ Builder.defineMacro("__ARM_FEATURE_FMA", "1");
+ Builder.defineMacro("__ARM_FEATURE_LDREX", "0xF");
+ Builder.defineMacro("__ARM_FEATURE_IDIV", "1"); // As specified in ACLE
+ Builder.defineMacro("__ARM_FEATURE_DIV"); // For backwards compatibility
+ Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");
+ Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");
+
+ Builder.defineMacro("__ARM_ALIGN_MAX_STACK_PWR", "4");
+
+ // 0xe implies support for half, single and double precision operations.
+ Builder.defineMacro("__ARM_FP", "0xE");
+
+ // PCS specifies this for SysV variants, which is all we support. Other ABIs
+ // may choose __ARM_FP16_FORMAT_ALTERNATIVE.
+ Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
+ Builder.defineMacro("__ARM_FP16_ARGS", "1");
+
+ if (Opts.UnsafeFPMath)
+ Builder.defineMacro("__ARM_FP_FAST", "1");
+
+ Builder.defineMacro("__ARM_SIZEOF_WCHAR_T",
+ llvm::utostr(Opts.WCharSize ? Opts.WCharSize : 4));
+
+ Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4");
+
+ if (FPU & NeonMode) {
+ Builder.defineMacro("__ARM_NEON", "1");
+ // 64-bit NEON supports half, single and double precision operations.
+ Builder.defineMacro("__ARM_NEON_FP", "0xE");
+ }
+
+ if (FPU & SveMode)
+ Builder.defineMacro("__ARM_FEATURE_SVE", "1");
+
+ if (CRC)
+ Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
+
+ if (Crypto)
+ Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
+
+ if (Unaligned)
+ Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
+
+ switch (ArchKind) {
+ default:
+ break;
+ case llvm::AArch64::ArchKind::ARMV8_1A:
+ getTargetDefinesARMV81A(Opts, Builder);
+ break;
+ case llvm::AArch64::ArchKind::ARMV8_2A:
+ getTargetDefinesARMV82A(Opts, Builder);
+ break;
+ }
+
+ // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work.
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
+}
+
+ArrayRef<Builtin::Info> AArch64TargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin -
+ Builtin::FirstTSBuiltin);
+}
+
+bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
+ return Feature == "aarch64" || Feature == "arm64" || Feature == "arm" ||
+ (Feature == "neon" && (FPU & NeonMode)) ||
+ (Feature == "sve" && (FPU & SveMode));
+}
+
+bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) {
+ FPU = FPUMode;
+ CRC = 0;
+ Crypto = 0;
+ Unaligned = 1;
+ HasFullFP16 = 0;
+ ArchKind = llvm::AArch64::ArchKind::ARMV8A;
+
+ for (const auto &Feature : Features) {
+ if (Feature == "+neon")
+ FPU |= NeonMode;
+ if (Feature == "+sve")
+ FPU |= SveMode;
+ if (Feature == "+crc")
+ CRC = 1;
+ if (Feature == "+crypto")
+ Crypto = 1;
+ if (Feature == "+strict-align")
+ Unaligned = 0;
+ if (Feature == "+v8.1a")
+ ArchKind = llvm::AArch64::ArchKind::ARMV8_1A;
+ if (Feature == "+v8.2a")
+ ArchKind = llvm::AArch64::ArchKind::ARMV8_2A;
+ if (Feature == "+fullfp16")
+ HasFullFP16 = 1;
+ }
+
+ setDataLayout();
+
+ return true;
+}
+
+TargetInfo::CallingConvCheckResult
+AArch64TargetInfo::checkCallingConvention(CallingConv CC) const {
+ switch (CC) {
+ case CC_C:
+ case CC_Swift:
+ case CC_PreserveMost:
+ case CC_PreserveAll:
+ case CC_OpenCLKernel:
+ case CC_Win64:
+ return CCCR_OK;
+ default:
+ return CCCR_Warning;
+ }
+}
+
+bool AArch64TargetInfo::isCLZForZeroUndef() const { return false; }
+
+TargetInfo::BuiltinVaListKind AArch64TargetInfo::getBuiltinVaListKind() const {
+ return TargetInfo::AArch64ABIBuiltinVaList;
+}
+
+const char *const AArch64TargetInfo::GCCRegNames[] = {
+ // 32-bit Integer registers
+ "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", "w11",
+ "w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21", "w22",
+ "w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp",
+
+ // 64-bit Integer registers
+ "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11",
+ "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22",
+ "x23", "x24", "x25", "x26", "x27", "x28", "fp", "lr", "sp",
+
+ // 32-bit floating point regsisters
+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
+ "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
+ "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
+
+ // 64-bit floating point regsisters
+ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",
+ "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",
+ "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
+
+ // Vector registers
+ "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11",
+ "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22",
+ "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
+};
+
+ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
+}
+
+const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = {
+ {{"w31"}, "wsp"}, {{"x29"}, "fp"}, {{"x30"}, "lr"}, {{"x31"}, "sp"},
+ // The S/D/Q and W/X registers overlap, but aren't really aliases; we
+ // don't want to substitute one of these for a different-sized one.
+};
+
+ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const {
+ return llvm::makeArrayRef(GCCRegAliases);
+}
+
+bool AArch64TargetInfo::validateAsmConstraint(
+ const char *&Name, TargetInfo::ConstraintInfo &Info) const {
+ switch (*Name) {
+ default:
+ return false;
+ case 'w': // Floating point and SIMD registers (V0-V31)
+ Info.setAllowsRegister();
+ return true;
+ case 'I': // Constant that can be used with an ADD instruction
+ case 'J': // Constant that can be used with a SUB instruction
+ case 'K': // Constant that can be used with a 32-bit logical instruction
+ case 'L': // Constant that can be used with a 64-bit logical instruction
+ case 'M': // Constant that can be used as a 32-bit MOV immediate
+ case 'N': // Constant that can be used as a 64-bit MOV immediate
+ case 'Y': // Floating point constant zero
+ case 'Z': // Integer constant zero
+ return true;
+ case 'Q': // A memory reference with base register and no offset
+ Info.setAllowsMemory();
+ return true;
+ case 'S': // A symbolic address
+ Info.setAllowsRegister();
+ return true;
+ case 'U':
+ // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes.
+ // Utf: A memory address suitable for ldp/stp in TF mode.
+ // Usa: An absolute symbolic address.
+ // Ush: The high part (bits 32:12) of a pc-relative symbolic address.
+ llvm_unreachable("FIXME: Unimplemented support for U* constraints.");
+ case 'z': // Zero register, wzr or xzr
+ Info.setAllowsRegister();
+ return true;
+ case 'x': // Floating point and SIMD registers (V0-V15)
+ Info.setAllowsRegister();
+ return true;
+ }
+ return false;
+}
+
+bool AArch64TargetInfo::validateConstraintModifier(
+ StringRef Constraint, char Modifier, unsigned Size,
+ std::string &SuggestedModifier) const {
+ // Strip off constraint modifiers.
+ while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
+ Constraint = Constraint.substr(1);
+
+ switch (Constraint[0]) {
+ default:
+ return true;
+ case 'z':
+ case 'r': {
+ switch (Modifier) {
+ case 'x':
+ case 'w':
+ // For now assume that the person knows what they're
+ // doing with the modifier.
+ return true;
+ default:
+ // By default an 'r' constraint will be in the 'x'
+ // registers.
+ if (Size == 64)
+ return true;
+
+ SuggestedModifier = "w";
+ return false;
+ }
+ }
+ }
+}
+
+const char *AArch64TargetInfo::getClobbers() const { return ""; }
+
+int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
+ if (RegNo == 0)
+ return 0;
+ if (RegNo == 1)
+ return 1;
+ return -1;
+}
+
+AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : AArch64TargetInfo(Triple, Opts) {}
+
+void AArch64leTargetInfo::setDataLayout() {
+ if (getTriple().isOSBinFormatMachO())
+ resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128");
+ else
+ resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
+}
+
+void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__AARCH64EL__");
+ AArch64TargetInfo::getTargetDefines(Opts, Builder);
+}
+
+AArch64beTargetInfo::AArch64beTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : AArch64TargetInfo(Triple, Opts) {}
+
+void AArch64beTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__AARCH64EB__");
+ Builder.defineMacro("__AARCH_BIG_ENDIAN");
+ Builder.defineMacro("__ARM_BIG_ENDIAN");
+ AArch64TargetInfo::getTargetDefines(Opts, Builder);
+}
+
+void AArch64beTargetInfo::setDataLayout() {
+ assert(!getTriple().isOSBinFormatMachO());
+ resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
+}
+
+WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) {
+
+ // This is an LLP64 platform.
+ // int:4, long:4, long long:8, long double:8.
+ IntWidth = IntAlign = 32;
+ LongWidth = LongAlign = 32;
+ DoubleAlign = LongLongAlign = 64;
+ LongDoubleWidth = LongDoubleAlign = 64;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
+ IntMaxType = SignedLongLong;
+ Int64Type = SignedLongLong;
+ SizeType = UnsignedLongLong;
+ PtrDiffType = SignedLongLong;
+ IntPtrType = SignedLongLong;
+}
+
+void WindowsARM64TargetInfo::setDataLayout() {
+ resetDataLayout("e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128");
+}
+
+TargetInfo::BuiltinVaListKind
+WindowsARM64TargetInfo::getBuiltinVaListKind() const {
+ return TargetInfo::CharPtrBuiltinVaList;
+}
+
+TargetInfo::CallingConvCheckResult
+WindowsARM64TargetInfo::checkCallingConvention(CallingConv CC) const {
+ switch (CC) {
+ case CC_X86StdCall:
+ case CC_X86ThisCall:
+ case CC_X86FastCall:
+ case CC_X86VectorCall:
+ return CCCR_Ignore;
+ case CC_C:
+ case CC_OpenCLKernel:
+ case CC_PreserveMost:
+ case CC_PreserveAll:
+ case CC_Win64:
+ return CCCR_OK;
+ default:
+ return CCCR_Warning;
+ }
+}
+
+MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : WindowsARM64TargetInfo(Triple, Opts) {
+ TheCXXABI.set(TargetCXXABI::Microsoft);
+}
+
+void MicrosoftARM64TargetInfo::getVisualStudioDefines(
+ const LangOptions &Opts, MacroBuilder &Builder) const {
+ WindowsTargetInfo<AArch64leTargetInfo>::getVisualStudioDefines(Opts, Builder);
+ Builder.defineMacro("_M_ARM64", "1");
+}
+
+void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ WindowsTargetInfo::getTargetDefines(Opts, Builder);
+ getVisualStudioDefines(Opts, Builder);
+}
+
+MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : WindowsARM64TargetInfo(Triple, Opts) {
+ TheCXXABI.set(TargetCXXABI::GenericAArch64);
+}
+
+DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) {
+ Int64Type = SignedLongLong;
+ UseSignedCharForObjCBool = false;
+
+ LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
+
+ TheCXXABI.set(TargetCXXABI::iOS64);
+}
+
+void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts,
+ const llvm::Triple &Triple,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__AARCH64_SIMD__");
+ Builder.defineMacro("__ARM64_ARCH_8__");
+ Builder.defineMacro("__ARM_NEON__");
+ Builder.defineMacro("__LITTLE_ENDIAN__");
+ Builder.defineMacro("__REGISTER_PREFIX__", "");
+ Builder.defineMacro("__arm64", "1");
+ Builder.defineMacro("__arm64__", "1");
+
+ getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
+}
+
+TargetInfo::BuiltinVaListKind
+DarwinAArch64TargetInfo::getBuiltinVaListKind() const {
+ return TargetInfo::CharPtrBuiltinVaList;
+}
+
+// 64-bit RenderScript is aarch64
+RenderScript64TargetInfo::RenderScript64TargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(),
+ Triple.getOSName(),
+ Triple.getEnvironmentName()),
+ Opts) {
+ IsRenderScriptTarget = true;
+}
+
+void RenderScript64TargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__RENDERSCRIPT__");
+ AArch64leTargetInfo::getTargetDefines(Opts, Builder);
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/AArch64.h b/contrib/llvm/tools/clang/lib/Basic/Targets/AArch64.h
new file mode 100644
index 0000000000000..33268f0f8d990
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/AArch64.h
@@ -0,0 +1,167 @@
+//===--- AArch64.h - Declare AArch64 target feature support -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares AArch64 TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_AARCH64_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_AARCH64_H
+
+#include "OSTargets.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "llvm/Support/TargetParser.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo {
+ virtual void setDataLayout() = 0;
+ static const TargetInfo::GCCRegAlias GCCRegAliases[];
+ static const char *const GCCRegNames[];
+
+ enum FPUModeEnum { FPUMode, NeonMode = (1 << 0), SveMode = (1 << 1) };
+
+ unsigned FPU;
+ unsigned CRC;
+ unsigned Crypto;
+ unsigned Unaligned;
+ unsigned HasFullFP16;
+ llvm::AArch64::ArchKind ArchKind;
+
+ static const Builtin::Info BuiltinInfo[];
+
+ std::string ABI;
+
+public:
+ AArch64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+
+ StringRef getABI() const override;
+ bool setABI(const std::string &Name) override;
+
+ bool isValidCPUName(StringRef Name) const override;
+ bool setCPU(const std::string &Name) override;
+
+ bool useFP16ConversionIntrinsics() const override {
+ return false;
+ }
+
+ void getTargetDefinesARMV81A(const LangOptions &Opts,
+ MacroBuilder &Builder) const;
+ void getTargetDefinesARMV82A(const LangOptions &Opts,
+ MacroBuilder &Builder) const;
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+
+ bool hasFeature(StringRef Feature) const override;
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) override;
+
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override;
+
+ bool isCLZForZeroUndef() const override;
+
+ BuiltinVaListKind getBuiltinVaListKind() const override;
+
+ ArrayRef<const char *> getGCCRegNames() const override;
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override;
+ bool
+ validateConstraintModifier(StringRef Constraint, char Modifier, unsigned Size,
+ std::string &SuggestedModifier) const override;
+ const char *getClobbers() const override;
+
+ int getEHDataRegisterNumber(unsigned RegNo) const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY AArch64leTargetInfo : public AArch64TargetInfo {
+public:
+ AArch64leTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+private:
+ void setDataLayout() override;
+};
+
+class LLVM_LIBRARY_VISIBILITY WindowsARM64TargetInfo
+ : public WindowsTargetInfo<AArch64leTargetInfo> {
+ const llvm::Triple Triple;
+
+public:
+ WindowsARM64TargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts);
+
+ void setDataLayout() override;
+
+ BuiltinVaListKind getBuiltinVaListKind() const override;
+
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override;
+};
+
+// Windows ARM, MS (C++) ABI
+class LLVM_LIBRARY_VISIBILITY MicrosoftARM64TargetInfo
+ : public WindowsARM64TargetInfo {
+public:
+ MicrosoftARM64TargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts);
+
+ void getVisualStudioDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const;
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+};
+
+// ARM64 MinGW target
+class LLVM_LIBRARY_VISIBILITY MinGWARM64TargetInfo
+ : public WindowsARM64TargetInfo {
+public:
+ MinGWARM64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+};
+
+class LLVM_LIBRARY_VISIBILITY AArch64beTargetInfo : public AArch64TargetInfo {
+public:
+ AArch64beTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+private:
+ void setDataLayout() override;
+};
+
+class LLVM_LIBRARY_VISIBILITY DarwinAArch64TargetInfo
+ : public DarwinTargetInfo<AArch64leTargetInfo> {
+public:
+ DarwinAArch64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+
+ BuiltinVaListKind getBuiltinVaListKind() const override;
+
+ protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override;
+};
+
+// 64-bit RenderScript is aarch64
+class LLVM_LIBRARY_VISIBILITY RenderScript64TargetInfo
+ : public AArch64leTargetInfo {
+public:
+ RenderScript64TargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts);
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+};
+
+} // namespace targets
+} // namespace clang
+
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_AARCH64_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/AMDGPU.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/AMDGPU.cpp
new file mode 100644
index 0000000000000..4c510e47379f5
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/AMDGPU.cpp
@@ -0,0 +1,373 @@
+//===--- AMDGPU.cpp - Implement AMDGPU target feature support -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements AMDGPU TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AMDGPU.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "clang/Frontend/CodeGenOptions.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+namespace clang {
+namespace targets {
+
+// If you edit the description strings, make sure you update
+// getPointerWidthV().
+
+static const char *const DataLayoutStringR600 =
+ "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128"
+ "-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64";
+
+static const char *const DataLayoutStringSIPrivateIsZero =
+ "e-p:32:32-p1:64:64-p2:64:64-p3:32:32-p4:64:64-p5:32:32"
+ "-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128"
+ "-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64";
+
+static const char *const DataLayoutStringSIGenericIsZero =
+ "e-p:64:64-p1:64:64-p2:64:64-p3:32:32-p4:32:32-p5:32:32"
+ "-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128"
+ "-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-A5";
+
+static const LangASMap AMDGPUPrivIsZeroDefIsGenMap = {
+ 4, // Default
+ 1, // opencl_global
+ 3, // opencl_local
+ 2, // opencl_constant
+ 0, // opencl_private
+ 4, // opencl_generic
+ 1, // cuda_device
+ 2, // cuda_constant
+ 3 // cuda_shared
+};
+
+static const LangASMap AMDGPUGenIsZeroDefIsGenMap = {
+ 0, // Default
+ 1, // opencl_global
+ 3, // opencl_local
+ 2, // opencl_constant
+ 5, // opencl_private
+ 0, // opencl_generic
+ 1, // cuda_device
+ 2, // cuda_constant
+ 3 // cuda_shared
+};
+
+static const LangASMap AMDGPUPrivIsZeroDefIsPrivMap = {
+ 0, // Default
+ 1, // opencl_global
+ 3, // opencl_local
+ 2, // opencl_constant
+ 0, // opencl_private
+ 4, // opencl_generic
+ 1, // cuda_device
+ 2, // cuda_constant
+ 3 // cuda_shared
+};
+
+static const LangASMap AMDGPUGenIsZeroDefIsPrivMap = {
+ 5, // Default
+ 1, // opencl_global
+ 3, // opencl_local
+ 2, // opencl_constant
+ 5, // opencl_private
+ 0, // opencl_generic
+ 1, // cuda_device
+ 2, // cuda_constant
+ 3 // cuda_shared
+};
+} // namespace targets
+} // namespace clang
+
+const Builtin::Info AMDGPUTargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
+#include "clang/Basic/BuiltinsAMDGPU.def"
+};
+
+const char *const AMDGPUTargetInfo::GCCRegNames[] = {
+ "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8",
+ "v9", "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17",
+ "v18", "v19", "v20", "v21", "v22", "v23", "v24", "v25", "v26",
+ "v27", "v28", "v29", "v30", "v31", "v32", "v33", "v34", "v35",
+ "v36", "v37", "v38", "v39", "v40", "v41", "v42", "v43", "v44",
+ "v45", "v46", "v47", "v48", "v49", "v50", "v51", "v52", "v53",
+ "v54", "v55", "v56", "v57", "v58", "v59", "v60", "v61", "v62",
+ "v63", "v64", "v65", "v66", "v67", "v68", "v69", "v70", "v71",
+ "v72", "v73", "v74", "v75", "v76", "v77", "v78", "v79", "v80",
+ "v81", "v82", "v83", "v84", "v85", "v86", "v87", "v88", "v89",
+ "v90", "v91", "v92", "v93", "v94", "v95", "v96", "v97", "v98",
+ "v99", "v100", "v101", "v102", "v103", "v104", "v105", "v106", "v107",
+ "v108", "v109", "v110", "v111", "v112", "v113", "v114", "v115", "v116",
+ "v117", "v118", "v119", "v120", "v121", "v122", "v123", "v124", "v125",
+ "v126", "v127", "v128", "v129", "v130", "v131", "v132", "v133", "v134",
+ "v135", "v136", "v137", "v138", "v139", "v140", "v141", "v142", "v143",
+ "v144", "v145", "v146", "v147", "v148", "v149", "v150", "v151", "v152",
+ "v153", "v154", "v155", "v156", "v157", "v158", "v159", "v160", "v161",
+ "v162", "v163", "v164", "v165", "v166", "v167", "v168", "v169", "v170",
+ "v171", "v172", "v173", "v174", "v175", "v176", "v177", "v178", "v179",
+ "v180", "v181", "v182", "v183", "v184", "v185", "v186", "v187", "v188",
+ "v189", "v190", "v191", "v192", "v193", "v194", "v195", "v196", "v197",
+ "v198", "v199", "v200", "v201", "v202", "v203", "v204", "v205", "v206",
+ "v207", "v208", "v209", "v210", "v211", "v212", "v213", "v214", "v215",
+ "v216", "v217", "v218", "v219", "v220", "v221", "v222", "v223", "v224",
+ "v225", "v226", "v227", "v228", "v229", "v230", "v231", "v232", "v233",
+ "v234", "v235", "v236", "v237", "v238", "v239", "v240", "v241", "v242",
+ "v243", "v244", "v245", "v246", "v247", "v248", "v249", "v250", "v251",
+ "v252", "v253", "v254", "v255", "s0", "s1", "s2", "s3", "s4",
+ "s5", "s6", "s7", "s8", "s9", "s10", "s11", "s12", "s13",
+ "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
+ "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
+ "s32", "s33", "s34", "s35", "s36", "s37", "s38", "s39", "s40",
+ "s41", "s42", "s43", "s44", "s45", "s46", "s47", "s48", "s49",
+ "s50", "s51", "s52", "s53", "s54", "s55", "s56", "s57", "s58",
+ "s59", "s60", "s61", "s62", "s63", "s64", "s65", "s66", "s67",
+ "s68", "s69", "s70", "s71", "s72", "s73", "s74", "s75", "s76",
+ "s77", "s78", "s79", "s80", "s81", "s82", "s83", "s84", "s85",
+ "s86", "s87", "s88", "s89", "s90", "s91", "s92", "s93", "s94",
+ "s95", "s96", "s97", "s98", "s99", "s100", "s101", "s102", "s103",
+ "s104", "s105", "s106", "s107", "s108", "s109", "s110", "s111", "s112",
+ "s113", "s114", "s115", "s116", "s117", "s118", "s119", "s120", "s121",
+ "s122", "s123", "s124", "s125", "s126", "s127", "exec", "vcc", "scc",
+ "m0", "flat_scratch", "exec_lo", "exec_hi", "vcc_lo", "vcc_hi",
+ "flat_scratch_lo", "flat_scratch_hi"
+};
+
+ArrayRef<const char *> AMDGPUTargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
+}
+
+bool AMDGPUTargetInfo::initFeatureMap(
+ llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
+ const std::vector<std::string> &FeatureVec) const {
+
+ // XXX - What does the member GPU mean if device name string passed here?
+ if (getTriple().getArch() == llvm::Triple::amdgcn) {
+ if (CPU.empty())
+ CPU = "tahiti";
+
+ switch (parseAMDGCNName(CPU)) {
+ case GK_GFX6:
+ case GK_GFX7:
+ break;
+
+ case GK_GFX9:
+ Features["gfx9-insts"] = true;
+ LLVM_FALLTHROUGH;
+ case GK_GFX8:
+ Features["s-memrealtime"] = true;
+ Features["16-bit-insts"] = true;
+ Features["dpp"] = true;
+ break;
+
+ case GK_NONE:
+ return false;
+ default:
+ llvm_unreachable("unhandled subtarget");
+ }
+ } else {
+ if (CPU.empty())
+ CPU = "r600";
+
+ switch (parseR600Name(CPU)) {
+ case GK_R600:
+ case GK_R700:
+ case GK_EVERGREEN:
+ case GK_NORTHERN_ISLANDS:
+ break;
+ case GK_R600_DOUBLE_OPS:
+ case GK_R700_DOUBLE_OPS:
+ case GK_EVERGREEN_DOUBLE_OPS:
+ case GK_CAYMAN:
+ // TODO: Add fp64 when implemented.
+ break;
+ case GK_NONE:
+ return false;
+ default:
+ llvm_unreachable("unhandled subtarget");
+ }
+ }
+
+ return TargetInfo::initFeatureMap(Features, Diags, CPU, FeatureVec);
+}
+
+void AMDGPUTargetInfo::adjustTargetOptions(const CodeGenOptions &CGOpts,
+ TargetOptions &TargetOpts) const {
+ bool hasFP32Denormals = false;
+ bool hasFP64Denormals = false;
+ for (auto &I : TargetOpts.FeaturesAsWritten) {
+ if (I == "+fp32-denormals" || I == "-fp32-denormals")
+ hasFP32Denormals = true;
+ if (I == "+fp64-fp16-denormals" || I == "-fp64-fp16-denormals")
+ hasFP64Denormals = true;
+ }
+ if (!hasFP32Denormals)
+ TargetOpts.Features.push_back(
+ (Twine(hasFullSpeedFMAF32(TargetOpts.CPU) && !CGOpts.FlushDenorm
+ ? '+'
+ : '-') +
+ Twine("fp32-denormals"))
+ .str());
+ // Always do not flush fp64 or fp16 denorms.
+ if (!hasFP64Denormals && hasFP64)
+ TargetOpts.Features.push_back("+fp64-fp16-denormals");
+}
+
+AMDGPUTargetInfo::GPUKind AMDGPUTargetInfo::parseR600Name(StringRef Name) {
+ return llvm::StringSwitch<GPUKind>(Name)
+ .Case("r600", GK_R600)
+ .Case("rv610", GK_R600)
+ .Case("rv620", GK_R600)
+ .Case("rv630", GK_R600)
+ .Case("rv635", GK_R600)
+ .Case("rs780", GK_R600)
+ .Case("rs880", GK_R600)
+ .Case("rv670", GK_R600_DOUBLE_OPS)
+ .Case("rv710", GK_R700)
+ .Case("rv730", GK_R700)
+ .Case("rv740", GK_R700_DOUBLE_OPS)
+ .Case("rv770", GK_R700_DOUBLE_OPS)
+ .Case("palm", GK_EVERGREEN)
+ .Case("cedar", GK_EVERGREEN)
+ .Case("sumo", GK_EVERGREEN)
+ .Case("sumo2", GK_EVERGREEN)
+ .Case("redwood", GK_EVERGREEN)
+ .Case("juniper", GK_EVERGREEN)
+ .Case("hemlock", GK_EVERGREEN_DOUBLE_OPS)
+ .Case("cypress", GK_EVERGREEN_DOUBLE_OPS)
+ .Case("barts", GK_NORTHERN_ISLANDS)
+ .Case("turks", GK_NORTHERN_ISLANDS)
+ .Case("caicos", GK_NORTHERN_ISLANDS)
+ .Case("cayman", GK_CAYMAN)
+ .Case("aruba", GK_CAYMAN)
+ .Default(GK_NONE);
+}
+
+AMDGPUTargetInfo::GPUKind AMDGPUTargetInfo::parseAMDGCNName(StringRef Name) {
+ return llvm::StringSwitch<GPUKind>(Name)
+ .Case("gfx600", GK_GFX6)
+ .Case("tahiti", GK_GFX6)
+ .Case("gfx601", GK_GFX6)
+ .Case("pitcairn", GK_GFX6)
+ .Case("verde", GK_GFX6)
+ .Case("oland", GK_GFX6)
+ .Case("hainan", GK_GFX6)
+ .Case("gfx700", GK_GFX7)
+ .Case("bonaire", GK_GFX7)
+ .Case("kaveri", GK_GFX7)
+ .Case("gfx701", GK_GFX7)
+ .Case("hawaii", GK_GFX7)
+ .Case("gfx702", GK_GFX7)
+ .Case("gfx703", GK_GFX7)
+ .Case("kabini", GK_GFX7)
+ .Case("mullins", GK_GFX7)
+ .Case("gfx800", GK_GFX8)
+ .Case("iceland", GK_GFX8)
+ .Case("gfx801", GK_GFX8)
+ .Case("carrizo", GK_GFX8)
+ .Case("gfx802", GK_GFX8)
+ .Case("tonga", GK_GFX8)
+ .Case("gfx803", GK_GFX8)
+ .Case("fiji", GK_GFX8)
+ .Case("polaris10", GK_GFX8)
+ .Case("polaris11", GK_GFX8)
+ .Case("gfx804", GK_GFX8)
+ .Case("gfx810", GK_GFX8)
+ .Case("stoney", GK_GFX8)
+ .Case("gfx900", GK_GFX9)
+ .Case("gfx901", GK_GFX9)
+ .Case("gfx902", GK_GFX9)
+ .Case("gfx903", GK_GFX9)
+ .Default(GK_NONE);
+}
+
+void AMDGPUTargetInfo::setAddressSpaceMap(bool DefaultIsPrivate) {
+ if (isGenericZero(getTriple())) {
+ AddrSpaceMap = DefaultIsPrivate ? &AMDGPUGenIsZeroDefIsPrivMap
+ : &AMDGPUGenIsZeroDefIsGenMap;
+ } else {
+ AddrSpaceMap = DefaultIsPrivate ? &AMDGPUPrivIsZeroDefIsPrivMap
+ : &AMDGPUPrivIsZeroDefIsGenMap;
+ }
+}
+
+AMDGPUTargetInfo::AMDGPUTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : TargetInfo(Triple),
+ GPU(isAMDGCN(Triple) ? GK_GFX6 : parseR600Name(Opts.CPU)),
+ hasFP64(false), hasFMAF(false), hasLDEXPF(false),
+ AS(isGenericZero(Triple)) {
+ if (getTriple().getArch() == llvm::Triple::amdgcn) {
+ hasFP64 = true;
+ hasFMAF = true;
+ hasLDEXPF = true;
+ }
+ if (getTriple().getArch() == llvm::Triple::r600) {
+ if (GPU == GK_EVERGREEN_DOUBLE_OPS || GPU == GK_CAYMAN) {
+ hasFMAF = true;
+ }
+ }
+ auto IsGenericZero = isGenericZero(Triple);
+ resetDataLayout(getTriple().getArch() == llvm::Triple::amdgcn
+ ? (IsGenericZero ? DataLayoutStringSIGenericIsZero
+ : DataLayoutStringSIPrivateIsZero)
+ : DataLayoutStringR600);
+ assert(DataLayout->getAllocaAddrSpace() == AS.Private);
+
+ setAddressSpaceMap(Triple.getOS() == llvm::Triple::Mesa3D ||
+ Triple.getEnvironment() == llvm::Triple::OpenCL ||
+ Triple.getEnvironmentName() == "amdgizcl" ||
+ !isAMDGCN(Triple));
+ UseAddrSpaceMapMangling = true;
+
+ // Set pointer width and alignment for target address space 0.
+ PointerWidth = PointerAlign = DataLayout->getPointerSizeInBits();
+ if (getMaxPointerWidth() == 64) {
+ LongWidth = LongAlign = 64;
+ SizeType = UnsignedLong;
+ PtrDiffType = SignedLong;
+ IntPtrType = SignedLong;
+ }
+
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
+}
+
+void AMDGPUTargetInfo::adjust(LangOptions &Opts) {
+ TargetInfo::adjust(Opts);
+ setAddressSpaceMap(Opts.OpenCL || !isAMDGCN(getTriple()));
+}
+
+ArrayRef<Builtin::Info> AMDGPUTargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfo, clang::AMDGPU::LastTSBuiltin -
+ Builtin::FirstTSBuiltin);
+}
+
+void AMDGPUTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ if (getTriple().getArch() == llvm::Triple::amdgcn)
+ Builder.defineMacro("__AMDGCN__");
+ else
+ Builder.defineMacro("__R600__");
+
+ if (hasFMAF)
+ Builder.defineMacro("__HAS_FMAF__");
+ if (hasLDEXPF)
+ Builder.defineMacro("__HAS_LDEXPF__");
+ if (hasFP64)
+ Builder.defineMacro("__HAS_FP64__");
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/AMDGPU.h b/contrib/llvm/tools/clang/lib/Basic/Targets/AMDGPU.h
new file mode 100644
index 0000000000000..a4e070f1cb12e
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/AMDGPU.h
@@ -0,0 +1,322 @@
+//===--- AMDGPU.h - Declare AMDGPU target feature support -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares AMDGPU TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY AMDGPUTargetInfo final : public TargetInfo {
+
+ static const Builtin::Info BuiltinInfo[];
+ static const char *const GCCRegNames[];
+
+ struct LLVM_LIBRARY_VISIBILITY AddrSpace {
+ unsigned Generic, Global, Local, Constant, Private;
+ AddrSpace(bool IsGenericZero_ = false) {
+ if (IsGenericZero_) {
+ Generic = 0;
+ Global = 1;
+ Local = 3;
+ Constant = 2;
+ Private = 5;
+ } else {
+ Generic = 4;
+ Global = 1;
+ Local = 3;
+ Constant = 2;
+ Private = 0;
+ }
+ }
+ };
+
+ /// \brief The GPU profiles supported by the AMDGPU target.
+ enum GPUKind {
+ GK_NONE,
+ GK_R600,
+ GK_R600_DOUBLE_OPS,
+ GK_R700,
+ GK_R700_DOUBLE_OPS,
+ GK_EVERGREEN,
+ GK_EVERGREEN_DOUBLE_OPS,
+ GK_NORTHERN_ISLANDS,
+ GK_CAYMAN,
+ GK_GFX6,
+ GK_GFX7,
+ GK_GFX8,
+ GK_GFX9
+ } GPU;
+
+ bool hasFP64 : 1;
+ bool hasFMAF : 1;
+ bool hasLDEXPF : 1;
+ const AddrSpace AS;
+
+ static bool hasFullSpeedFMAF32(StringRef GPUName) {
+ return parseAMDGCNName(GPUName) >= GK_GFX9;
+ }
+
+ static bool isAMDGCN(const llvm::Triple &TT) {
+ return TT.getArch() == llvm::Triple::amdgcn;
+ }
+
+ static bool isGenericZero(const llvm::Triple &TT) {
+ return TT.getEnvironmentName() == "amdgiz" ||
+ TT.getEnvironmentName() == "amdgizcl";
+ }
+
+public:
+ AMDGPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+
+ void setAddressSpaceMap(bool DefaultIsPrivate);
+
+ void adjust(LangOptions &Opts) override;
+
+ uint64_t getPointerWidthV(unsigned AddrSpace) const override {
+ if (GPU <= GK_CAYMAN)
+ return 32;
+
+ if (AddrSpace == AS.Private || AddrSpace == AS.Local) {
+ return 32;
+ }
+ return 64;
+ }
+
+ uint64_t getPointerAlignV(unsigned AddrSpace) const override {
+ return getPointerWidthV(AddrSpace);
+ }
+
+ uint64_t getMaxPointerWidth() const override {
+ return getTriple().getArch() == llvm::Triple::amdgcn ? 64 : 32;
+ }
+
+ const char *getClobbers() const override { return ""; }
+
+ ArrayRef<const char *> getGCCRegNames() const override;
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ return None;
+ }
+
+ /// Accepted register names: (n, m is unsigned integer, n < m)
+ /// v
+ /// s
+ /// {vn}, {v[n]}
+ /// {sn}, {s[n]}
+ /// {S} , where S is a special register name
+ ////{v[n:m]}
+ /// {s[n:m]}
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override {
+ static const ::llvm::StringSet<> SpecialRegs({
+ "exec", "vcc", "flat_scratch", "m0", "scc", "tba", "tma",
+ "flat_scratch_lo", "flat_scratch_hi", "vcc_lo", "vcc_hi", "exec_lo",
+ "exec_hi", "tma_lo", "tma_hi", "tba_lo", "tba_hi",
+ });
+
+ StringRef S(Name);
+ bool HasLeftParen = false;
+ if (S.front() == '{') {
+ HasLeftParen = true;
+ S = S.drop_front();
+ }
+ if (S.empty())
+ return false;
+ if (S.front() != 'v' && S.front() != 's') {
+ if (!HasLeftParen)
+ return false;
+ auto E = S.find('}');
+ if (!SpecialRegs.count(S.substr(0, E)))
+ return false;
+ S = S.drop_front(E + 1);
+ if (!S.empty())
+ return false;
+ // Found {S} where S is a special register.
+ Info.setAllowsRegister();
+ Name = S.data() - 1;
+ return true;
+ }
+ S = S.drop_front();
+ if (!HasLeftParen) {
+ if (!S.empty())
+ return false;
+ // Found s or v.
+ Info.setAllowsRegister();
+ Name = S.data() - 1;
+ return true;
+ }
+ bool HasLeftBracket = false;
+ if (!S.empty() && S.front() == '[') {
+ HasLeftBracket = true;
+ S = S.drop_front();
+ }
+ unsigned long long N;
+ if (S.empty() || consumeUnsignedInteger(S, 10, N))
+ return false;
+ if (!S.empty() && S.front() == ':') {
+ if (!HasLeftBracket)
+ return false;
+ S = S.drop_front();
+ unsigned long long M;
+ if (consumeUnsignedInteger(S, 10, M) || N >= M)
+ return false;
+ }
+ if (HasLeftBracket) {
+ if (S.empty() || S.front() != ']')
+ return false;
+ S = S.drop_front();
+ }
+ if (S.empty() || S.front() != '}')
+ return false;
+ S = S.drop_front();
+ if (!S.empty())
+ return false;
+ // Found {vn}, {sn}, {v[n]}, {s[n]}, {v[n:m]}, or {s[n:m]}.
+ Info.setAllowsRegister();
+ Name = S.data() - 1;
+ return true;
+ }
+
+ bool
+ initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
+ StringRef CPU,
+ const std::vector<std::string> &FeatureVec) const override;
+
+ void adjustTargetOptions(const CodeGenOptions &CGOpts,
+ TargetOptions &TargetOpts) const override;
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::CharPtrBuiltinVaList;
+ }
+
+ static GPUKind parseR600Name(StringRef Name);
+
+ static GPUKind parseAMDGCNName(StringRef Name);
+
+ bool isValidCPUName(StringRef Name) const override {
+ if (getTriple().getArch() == llvm::Triple::amdgcn)
+ return GK_NONE != parseAMDGCNName(Name);
+ else
+ return GK_NONE != parseR600Name(Name);
+ }
+
+ bool setCPU(const std::string &Name) override {
+ if (getTriple().getArch() == llvm::Triple::amdgcn)
+ GPU = parseAMDGCNName(Name);
+ else
+ GPU = parseR600Name(Name);
+
+ return GPU != GK_NONE;
+ }
+
+ void setSupportedOpenCLOpts() override {
+ auto &Opts = getSupportedOpenCLOpts();
+ Opts.support("cl_clang_storage_class_specifiers");
+ Opts.support("cl_khr_icd");
+
+ if (hasFP64)
+ Opts.support("cl_khr_fp64");
+ if (GPU >= GK_EVERGREEN) {
+ Opts.support("cl_khr_byte_addressable_store");
+ Opts.support("cl_khr_global_int32_base_atomics");
+ Opts.support("cl_khr_global_int32_extended_atomics");
+ Opts.support("cl_khr_local_int32_base_atomics");
+ Opts.support("cl_khr_local_int32_extended_atomics");
+ }
+ if (GPU >= GK_GFX6) {
+ Opts.support("cl_khr_fp16");
+ Opts.support("cl_khr_int64_base_atomics");
+ Opts.support("cl_khr_int64_extended_atomics");
+ Opts.support("cl_khr_mipmap_image");
+ Opts.support("cl_khr_subgroups");
+ Opts.support("cl_khr_3d_image_writes");
+ Opts.support("cl_amd_media_ops");
+ Opts.support("cl_amd_media_ops2");
+ }
+ }
+
+ LangAS getOpenCLTypeAddrSpace(OpenCLTypeKind TK) const override {
+ switch (TK) {
+ case OCLTK_Image:
+ return LangAS::opencl_constant;
+
+ case OCLTK_ClkEvent:
+ case OCLTK_Queue:
+ case OCLTK_ReserveID:
+ return LangAS::opencl_global;
+
+ default:
+ return TargetInfo::getOpenCLTypeAddrSpace(TK);
+ }
+ }
+
+ llvm::Optional<LangAS> getConstantAddressSpace() const override {
+ return getLangASFromTargetAS(AS.Constant);
+ }
+
+ /// \returns Target specific vtbl ptr address space.
+ unsigned getVtblPtrAddressSpace() const override { return AS.Constant; }
+
+ /// \returns If a target requires an address within a target specific address
+ /// space \p AddressSpace to be converted in order to be used, then return the
+ /// corresponding target specific DWARF address space.
+ ///
+ /// \returns Otherwise return None and no conversion will be emitted in the
+ /// DWARF.
+ Optional<unsigned>
+ getDWARFAddressSpace(unsigned AddressSpace) const override {
+ const unsigned DWARF_Private = 1;
+ const unsigned DWARF_Local = 2;
+ if (AddressSpace == AS.Private) {
+ return DWARF_Private;
+ } else if (AddressSpace == AS.Local) {
+ return DWARF_Local;
+ } else {
+ return None;
+ }
+ }
+
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
+ switch (CC) {
+ default:
+ return CCCR_Warning;
+ case CC_C:
+ case CC_OpenCLKernel:
+ return CCCR_OK;
+ }
+ }
+
+ // In amdgcn target the null pointer in global, constant, and generic
+ // address space has value 0 but in private and local address space has
+ // value ~0.
+ uint64_t getNullPointerValue(LangAS AS) const override {
+ return AS == LangAS::opencl_local ? ~0 : 0;
+ }
+};
+
+} // namespace targets
+} // namespace clang
+
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/ARM.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/ARM.cpp
new file mode 100644
index 0000000000000..fe261b7748550
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/ARM.cpp
@@ -0,0 +1,1064 @@
+//===--- ARM.cpp - Implement ARM target feature support -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements ARM TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ARM.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+void ARMTargetInfo::setABIAAPCS() {
+ IsAAPCS = true;
+
+ DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;
+ const llvm::Triple &T = getTriple();
+
+ bool IsNetBSD = T.getOS() == llvm::Triple::NetBSD;
+ bool IsOpenBSD = T.getOS() == llvm::Triple::OpenBSD;
+ if (!T.isOSWindows() && !IsNetBSD && !IsOpenBSD)
+ WCharType = UnsignedInt;
+
+ UseBitFieldTypeAlignment = true;
+
+ ZeroLengthBitfieldBoundary = 0;
+
+ // Thumb1 add sp, #imm requires the immediate value be multiple of 4,
+ // so set preferred for small types to 32.
+ if (T.isOSBinFormatMachO()) {
+ resetDataLayout(BigEndian
+ ? "E-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
+ : "e-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64");
+ } else if (T.isOSWindows()) {
+ assert(!BigEndian && "Windows on ARM does not support big endian");
+ resetDataLayout("e"
+ "-m:w"
+ "-p:32:32"
+ "-i64:64"
+ "-v128:64:128"
+ "-a:0:32"
+ "-n32"
+ "-S64");
+ } else if (T.isOSNaCl()) {
+ assert(!BigEndian && "NaCl on ARM does not support big endian");
+ resetDataLayout("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S128");
+ } else {
+ resetDataLayout(BigEndian
+ ? "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
+ : "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64");
+ }
+
+ // FIXME: Enumerated types are variable width in straight AAPCS.
+}
+
+void ARMTargetInfo::setABIAPCS(bool IsAAPCS16) {
+ const llvm::Triple &T = getTriple();
+
+ IsAAPCS = false;
+
+ if (IsAAPCS16)
+ DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;
+ else
+ DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 32;
+
+ WCharType = SignedInt;
+
+ // Do not respect the alignment of bit-field types when laying out
+ // structures. This corresponds to PCC_BITFIELD_TYPE_MATTERS in gcc.
+ UseBitFieldTypeAlignment = false;
+
+ /// gcc forces the alignment to 4 bytes, regardless of the type of the
+ /// zero length bitfield. This corresponds to EMPTY_FIELD_BOUNDARY in
+ /// gcc.
+ ZeroLengthBitfieldBoundary = 32;
+
+ if (T.isOSBinFormatMachO() && IsAAPCS16) {
+ assert(!BigEndian && "AAPCS16 does not support big-endian");
+ resetDataLayout("e-m:o-p:32:32-i64:64-a:0:32-n32-S128");
+ } else if (T.isOSBinFormatMachO())
+ resetDataLayout(
+ BigEndian
+ ? "E-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
+ : "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32");
+ else
+ resetDataLayout(
+ BigEndian
+ ? "E-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
+ : "e-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32");
+
+ // FIXME: Override "preferred align" for double and long long.
+}
+
+void ARMTargetInfo::setArchInfo() {
+ StringRef ArchName = getTriple().getArchName();
+
+ ArchISA = llvm::ARM::parseArchISA(ArchName);
+ CPU = llvm::ARM::getDefaultCPU(ArchName);
+ llvm::ARM::ArchKind AK = llvm::ARM::parseArch(ArchName);
+ if (AK != llvm::ARM::ArchKind::INVALID)
+ ArchKind = AK;
+ setArchInfo(ArchKind);
+}
+
+void ARMTargetInfo::setArchInfo(llvm::ARM::ArchKind Kind) {
+ StringRef SubArch;
+
+ // cache TargetParser info
+ ArchKind = Kind;
+ SubArch = llvm::ARM::getSubArch(ArchKind);
+ ArchProfile = llvm::ARM::parseArchProfile(SubArch);
+ ArchVersion = llvm::ARM::parseArchVersion(SubArch);
+
+ // cache CPU related strings
+ CPUAttr = getCPUAttr();
+ CPUProfile = getCPUProfile();
+}
+
+void ARMTargetInfo::setAtomic() {
+ // when triple does not specify a sub arch,
+ // then we are not using inline atomics
+ bool ShouldUseInlineAtomic =
+ (ArchISA == llvm::ARM::ISAKind::ARM && ArchVersion >= 6) ||
+ (ArchISA == llvm::ARM::ISAKind::THUMB && ArchVersion >= 7);
+ // Cortex M does not support 8 byte atomics, while general Thumb2 does.
+ if (ArchProfile == llvm::ARM::ProfileKind::M) {
+ MaxAtomicPromoteWidth = 32;
+ if (ShouldUseInlineAtomic)
+ MaxAtomicInlineWidth = 32;
+ } else {
+ MaxAtomicPromoteWidth = 64;
+ if (ShouldUseInlineAtomic)
+ MaxAtomicInlineWidth = 64;
+ }
+}
+
+bool ARMTargetInfo::isThumb() const {
+ return ArchISA == llvm::ARM::ISAKind::THUMB;
+}
+
+bool ARMTargetInfo::supportsThumb() const {
+ return CPUAttr.count('T') || ArchVersion >= 6;
+}
+
+bool ARMTargetInfo::supportsThumb2() const {
+ return CPUAttr.equals("6T2") ||
+ (ArchVersion >= 7 && !CPUAttr.equals("8M_BASE"));
+}
+
+StringRef ARMTargetInfo::getCPUAttr() const {
+ // For most sub-arches, the build attribute CPU name is enough.
+ // For Cortex variants, it's slightly different.
+ switch (ArchKind) {
+ default:
+ return llvm::ARM::getCPUAttr(ArchKind);
+ case llvm::ARM::ArchKind::ARMV6M:
+ return "6M";
+ case llvm::ARM::ArchKind::ARMV7S:
+ return "7S";
+ case llvm::ARM::ArchKind::ARMV7A:
+ return "7A";
+ case llvm::ARM::ArchKind::ARMV7R:
+ return "7R";
+ case llvm::ARM::ArchKind::ARMV7M:
+ return "7M";
+ case llvm::ARM::ArchKind::ARMV7EM:
+ return "7EM";
+ case llvm::ARM::ArchKind::ARMV7VE:
+ return "7VE";
+ case llvm::ARM::ArchKind::ARMV8A:
+ return "8A";
+ case llvm::ARM::ArchKind::ARMV8_1A:
+ return "8_1A";
+ case llvm::ARM::ArchKind::ARMV8_2A:
+ return "8_2A";
+ case llvm::ARM::ArchKind::ARMV8MBaseline:
+ return "8M_BASE";
+ case llvm::ARM::ArchKind::ARMV8MMainline:
+ return "8M_MAIN";
+ case llvm::ARM::ArchKind::ARMV8R:
+ return "8R";
+ }
+}
+
+StringRef ARMTargetInfo::getCPUProfile() const {
+ switch (ArchProfile) {
+ case llvm::ARM::ProfileKind::A:
+ return "A";
+ case llvm::ARM::ProfileKind::R:
+ return "R";
+ case llvm::ARM::ProfileKind::M:
+ return "M";
+ default:
+ return "";
+ }
+}
+
+ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : TargetInfo(Triple), FPMath(FP_Default), IsAAPCS(true), LDREX(0),
+ HW_FP(0) {
+ bool IsOpenBSD = Triple.getOS() == llvm::Triple::OpenBSD;
+ bool IsNetBSD = Triple.getOS() == llvm::Triple::NetBSD;
+
+ // FIXME: the isOSBinFormatMachO is a workaround for identifying a Darwin-like
+ // environment where size_t is `unsigned long` rather than `unsigned int`
+
+ PtrDiffType = IntPtrType =
+ (Triple.isOSDarwin() || Triple.isOSBinFormatMachO() || IsOpenBSD ||
+ IsNetBSD)
+ ? SignedLong
+ : SignedInt;
+
+ SizeType = (Triple.isOSDarwin() || Triple.isOSBinFormatMachO() || IsOpenBSD ||
+ IsNetBSD)
+ ? UnsignedLong
+ : UnsignedInt;
+
+ // ptrdiff_t is inconsistent on Darwin
+ if ((Triple.isOSDarwin() || Triple.isOSBinFormatMachO()) &&
+ !Triple.isWatchABI())
+ PtrDiffType = SignedInt;
+
+ // Cache arch related info.
+ setArchInfo();
+
+ // {} in inline assembly are neon specifiers, not assembly variant
+ // specifiers.
+ NoAsmVariants = true;
+
+ // FIXME: This duplicates code from the driver that sets the -target-abi
+ // option - this code is used if -target-abi isn't passed and should
+ // be unified in some way.
+ if (Triple.isOSBinFormatMachO()) {
+ // The backend is hardwired to assume AAPCS for M-class processors, ensure
+ // the frontend matches that.
+ if (Triple.getEnvironment() == llvm::Triple::EABI ||
+ Triple.getOS() == llvm::Triple::UnknownOS ||
+ ArchProfile == llvm::ARM::ProfileKind::M) {
+ setABI("aapcs");
+ } else if (Triple.isWatchABI()) {
+ setABI("aapcs16");
+ } else {
+ setABI("apcs-gnu");
+ }
+ } else if (Triple.isOSWindows()) {
+ // FIXME: this is invalid for WindowsCE
+ setABI("aapcs");
+ } else {
+ // Select the default based on the platform.
+ switch (Triple.getEnvironment()) {
+ case llvm::Triple::Android:
+ case llvm::Triple::GNUEABI:
+ case llvm::Triple::GNUEABIHF:
+ case llvm::Triple::MuslEABI:
+ case llvm::Triple::MuslEABIHF:
+ setABI("aapcs-linux");
+ break;
+ case llvm::Triple::EABIHF:
+ case llvm::Triple::EABI:
+ setABI("aapcs");
+ break;
+ case llvm::Triple::GNU:
+ setABI("apcs-gnu");
+ break;
+ default:
+ if (Triple.getOS() == llvm::Triple::NetBSD)
+ setABI("apcs-gnu");
+ else if (Triple.getOS() == llvm::Triple::OpenBSD)
+ setABI("aapcs-linux");
+ else
+ setABI("aapcs");
+ break;
+ }
+ }
+
+ // ARM targets default to using the ARM C++ ABI.
+ TheCXXABI.set(TargetCXXABI::GenericARM);
+
+ // ARM has atomics up to 8 bytes
+ setAtomic();
+
+ // Maximum alignment for ARM NEON data types should be 64-bits (AAPCS)
+ if (IsAAPCS && (Triple.getEnvironment() != llvm::Triple::Android))
+ MaxVectorAlign = 64;
+
+ // Do force alignment of members that follow zero length bitfields. If
+ // the alignment of the zero-length bitfield is greater than the member
+ // that follows it, `bar', `bar' will be aligned as the type of the
+ // zero length bitfield.
+ UseZeroLengthBitfieldAlignment = true;
+
+ if (Triple.getOS() == llvm::Triple::Linux ||
+ Triple.getOS() == llvm::Triple::UnknownOS)
+ this->MCountName = Opts.EABIVersion == llvm::EABI::GNU
+ ? "\01__gnu_mcount_nc"
+ : "\01mcount";
+}
+
+StringRef ARMTargetInfo::getABI() const { return ABI; }
+
+bool ARMTargetInfo::setABI(const std::string &Name) {
+ ABI = Name;
+
+ // The defaults (above) are for AAPCS, check if we need to change them.
+ //
+ // FIXME: We need support for -meabi... we could just mangle it into the
+ // name.
+ if (Name == "apcs-gnu" || Name == "aapcs16") {
+ setABIAPCS(Name == "aapcs16");
+ return true;
+ }
+ if (Name == "aapcs" || Name == "aapcs-vfp" || Name == "aapcs-linux") {
+ setABIAAPCS();
+ return true;
+ }
+ return false;
+}
+
+// FIXME: This should be based on Arch attributes, not CPU names.
+bool ARMTargetInfo::initFeatureMap(
+ llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const {
+
+ std::vector<StringRef> TargetFeatures;
+ llvm::ARM::ArchKind Arch = llvm::ARM::parseArch(getTriple().getArchName());
+
+ // get default FPU features
+ unsigned FPUKind = llvm::ARM::getDefaultFPU(CPU, Arch);
+ llvm::ARM::getFPUFeatures(FPUKind, TargetFeatures);
+
+ // get default Extension features
+ unsigned Extensions = llvm::ARM::getDefaultExtensions(CPU, Arch);
+ llvm::ARM::getExtensionFeatures(Extensions, TargetFeatures);
+
+ for (auto Feature : TargetFeatures)
+ if (Feature[0] == '+')
+ Features[Feature.drop_front(1)] = true;
+
+ // Enable or disable thumb-mode explicitly per function to enable mixed
+ // ARM and Thumb code generation.
+ if (isThumb())
+ Features["thumb-mode"] = true;
+ else
+ Features["thumb-mode"] = false;
+
+ // Convert user-provided arm and thumb GNU target attributes to
+ // [-|+]thumb-mode target features respectively.
+ std::vector<std::string> UpdatedFeaturesVec(FeaturesVec);
+ for (auto &Feature : UpdatedFeaturesVec) {
+ if (Feature.compare("+arm") == 0)
+ Feature = "-thumb-mode";
+ else if (Feature.compare("+thumb") == 0)
+ Feature = "+thumb-mode";
+ }
+
+ return TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeaturesVec);
+}
+
+
+bool ARMTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) {
+ FPU = 0;
+ CRC = 0;
+ Crypto = 0;
+ DSP = 0;
+ Unaligned = 1;
+ SoftFloat = SoftFloatABI = false;
+ HWDiv = 0;
+
+ // This does not diagnose illegal cases like having both
+ // "+vfpv2" and "+vfpv3" or having "+neon" and "+fp-only-sp".
+ uint32_t HW_FP_remove = 0;
+ for (const auto &Feature : Features) {
+ if (Feature == "+soft-float") {
+ SoftFloat = true;
+ } else if (Feature == "+soft-float-abi") {
+ SoftFloatABI = true;
+ } else if (Feature == "+vfp2") {
+ FPU |= VFP2FPU;
+ HW_FP |= HW_FP_SP | HW_FP_DP;
+ } else if (Feature == "+vfp3") {
+ FPU |= VFP3FPU;
+ HW_FP |= HW_FP_SP | HW_FP_DP;
+ } else if (Feature == "+vfp4") {
+ FPU |= VFP4FPU;
+ HW_FP |= HW_FP_SP | HW_FP_DP | HW_FP_HP;
+ } else if (Feature == "+fp-armv8") {
+ FPU |= FPARMV8;
+ HW_FP |= HW_FP_SP | HW_FP_DP | HW_FP_HP;
+ } else if (Feature == "+neon") {
+ FPU |= NeonFPU;
+ HW_FP |= HW_FP_SP | HW_FP_DP;
+ } else if (Feature == "+hwdiv") {
+ HWDiv |= HWDivThumb;
+ } else if (Feature == "+hwdiv-arm") {
+ HWDiv |= HWDivARM;
+ } else if (Feature == "+crc") {
+ CRC = 1;
+ } else if (Feature == "+crypto") {
+ Crypto = 1;
+ } else if (Feature == "+dsp") {
+ DSP = 1;
+ } else if (Feature == "+fp-only-sp") {
+ HW_FP_remove |= HW_FP_DP;
+ } else if (Feature == "+strict-align") {
+ Unaligned = 0;
+ } else if (Feature == "+fp16") {
+ HW_FP |= HW_FP_HP;
+ }
+ }
+ HW_FP &= ~HW_FP_remove;
+
+ switch (ArchVersion) {
+ case 6:
+ if (ArchProfile == llvm::ARM::ProfileKind::M)
+ LDREX = 0;
+ else if (ArchKind == llvm::ARM::ArchKind::ARMV6K)
+ LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
+ else
+ LDREX = LDREX_W;
+ break;
+ case 7:
+ if (ArchProfile == llvm::ARM::ProfileKind::M)
+ LDREX = LDREX_W | LDREX_H | LDREX_B;
+ else
+ LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
+ break;
+ case 8:
+ LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
+ }
+
+ if (!(FPU & NeonFPU) && FPMath == FP_Neon) {
+ Diags.Report(diag::err_target_unsupported_fpmath) << "neon";
+ return false;
+ }
+
+ if (FPMath == FP_Neon)
+ Features.push_back("+neonfp");
+ else if (FPMath == FP_VFP)
+ Features.push_back("-neonfp");
+
+ // Remove front-end specific options which the backend handles differently.
+ auto Feature = std::find(Features.begin(), Features.end(), "+soft-float-abi");
+ if (Feature != Features.end())
+ Features.erase(Feature);
+
+ return true;
+}
+
+bool ARMTargetInfo::hasFeature(StringRef Feature) const {
+ return llvm::StringSwitch<bool>(Feature)
+ .Case("arm", true)
+ .Case("aarch32", true)
+ .Case("softfloat", SoftFloat)
+ .Case("thumb", isThumb())
+ .Case("neon", (FPU & NeonFPU) && !SoftFloat)
+ .Case("vfp", FPU && !SoftFloat)
+ .Case("hwdiv", HWDiv & HWDivThumb)
+ .Case("hwdiv-arm", HWDiv & HWDivARM)
+ .Default(false);
+}
+
+bool ARMTargetInfo::isValidCPUName(StringRef Name) const {
+ return Name == "generic" ||
+ llvm::ARM::parseCPUArch(Name) != llvm::ARM::ArchKind::INVALID;
+}
+
+bool ARMTargetInfo::setCPU(const std::string &Name) {
+ if (Name != "generic")
+ setArchInfo(llvm::ARM::parseCPUArch(Name));
+
+ if (ArchKind == llvm::ARM::ArchKind::INVALID)
+ return false;
+ setAtomic();
+ CPU = Name;
+ return true;
+}
+
+bool ARMTargetInfo::setFPMath(StringRef Name) {
+ if (Name == "neon") {
+ FPMath = FP_Neon;
+ return true;
+ } else if (Name == "vfp" || Name == "vfp2" || Name == "vfp3" ||
+ Name == "vfp4") {
+ FPMath = FP_VFP;
+ return true;
+ }
+ return false;
+}
+
+void ARMTargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
+}
+
+void ARMTargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ // Also include the ARMv8.1-A defines
+ getTargetDefinesARMV81A(Opts, Builder);
+}
+
+void ARMTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ // Target identification.
+ Builder.defineMacro("__arm");
+ Builder.defineMacro("__arm__");
+ // For bare-metal none-eabi.
+ if (getTriple().getOS() == llvm::Triple::UnknownOS &&
+ (getTriple().getEnvironment() == llvm::Triple::EABI ||
+ getTriple().getEnvironment() == llvm::Triple::EABIHF))
+ Builder.defineMacro("__ELF__");
+
+ // Target properties.
+ Builder.defineMacro("__REGISTER_PREFIX__", "");
+
+ // Unfortunately, __ARM_ARCH_7K__ is now more of an ABI descriptor. The CPU
+ // happens to be Cortex-A7 though, so it should still get __ARM_ARCH_7A__.
+ if (getTriple().isWatchABI())
+ Builder.defineMacro("__ARM_ARCH_7K__", "2");
+
+ if (!CPUAttr.empty())
+ Builder.defineMacro("__ARM_ARCH_" + CPUAttr + "__");
+
+ // ACLE 6.4.1 ARM/Thumb instruction set architecture
+ // __ARM_ARCH is defined as an integer value indicating the current ARM ISA
+ Builder.defineMacro("__ARM_ARCH", Twine(ArchVersion));
+
+ if (ArchVersion >= 8) {
+ // ACLE 6.5.7 Crypto Extension
+ if (Crypto)
+ Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
+ // ACLE 6.5.8 CRC32 Extension
+ if (CRC)
+ Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
+ // ACLE 6.5.10 Numeric Maximum and Minimum
+ Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");
+ // ACLE 6.5.9 Directed Rounding
+ Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");
+ }
+
+ // __ARM_ARCH_ISA_ARM is defined to 1 if the core supports the ARM ISA. It
+ // is not defined for the M-profile.
+ // NOTE that the default profile is assumed to be 'A'
+ if (CPUProfile.empty() || ArchProfile != llvm::ARM::ProfileKind::M)
+ Builder.defineMacro("__ARM_ARCH_ISA_ARM", "1");
+
+ // __ARM_ARCH_ISA_THUMB is defined to 1 if the core supports the original
+ // Thumb ISA (including v6-M and v8-M Baseline). It is set to 2 if the
+ // core supports the Thumb-2 ISA as found in the v6T2 architecture and all
+ // v7 and v8 architectures excluding v8-M Baseline.
+ if (supportsThumb2())
+ Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "2");
+ else if (supportsThumb())
+ Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "1");
+
+ // __ARM_32BIT_STATE is defined to 1 if code is being generated for a 32-bit
+ // instruction set such as ARM or Thumb.
+ Builder.defineMacro("__ARM_32BIT_STATE", "1");
+
+ // ACLE 6.4.2 Architectural Profile (A, R, M or pre-Cortex)
+
+ // __ARM_ARCH_PROFILE is defined as 'A', 'R', 'M' or 'S', or unset.
+ if (!CPUProfile.empty())
+ Builder.defineMacro("__ARM_ARCH_PROFILE", "'" + CPUProfile + "'");
+
+ // ACLE 6.4.3 Unaligned access supported in hardware
+ if (Unaligned)
+ Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
+
+ // ACLE 6.4.4 LDREX/STREX
+ if (LDREX)
+ Builder.defineMacro("__ARM_FEATURE_LDREX", "0x" + llvm::utohexstr(LDREX));
+
+ // ACLE 6.4.5 CLZ
+ if (ArchVersion == 5 || (ArchVersion == 6 && CPUProfile != "M") ||
+ ArchVersion > 6)
+ Builder.defineMacro("__ARM_FEATURE_CLZ", "1");
+
+ // ACLE 6.5.1 Hardware Floating Point
+ if (HW_FP)
+ Builder.defineMacro("__ARM_FP", "0x" + llvm::utohexstr(HW_FP));
+
+ // ACLE predefines.
+ Builder.defineMacro("__ARM_ACLE", "200");
+
+ // FP16 support (we currently only support IEEE format).
+ Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
+ Builder.defineMacro("__ARM_FP16_ARGS", "1");
+
+ // ACLE 6.5.3 Fused multiply-accumulate (FMA)
+ if (ArchVersion >= 7 && (FPU & VFP4FPU))
+ Builder.defineMacro("__ARM_FEATURE_FMA", "1");
+
+ // Subtarget options.
+
+ // FIXME: It's more complicated than this and we don't really support
+ // interworking.
+ // Windows on ARM does not "support" interworking
+ if (5 <= ArchVersion && ArchVersion <= 8 && !getTriple().isOSWindows())
+ Builder.defineMacro("__THUMB_INTERWORK__");
+
+ if (ABI == "aapcs" || ABI == "aapcs-linux" || ABI == "aapcs-vfp") {
+ // Embedded targets on Darwin follow AAPCS, but not EABI.
+ // Windows on ARM follows AAPCS VFP, but does not conform to EABI.
+ if (!getTriple().isOSBinFormatMachO() && !getTriple().isOSWindows())
+ Builder.defineMacro("__ARM_EABI__");
+ Builder.defineMacro("__ARM_PCS", "1");
+ }
+
+ if ((!SoftFloat && !SoftFloatABI) || ABI == "aapcs-vfp" || ABI == "aapcs16")
+ Builder.defineMacro("__ARM_PCS_VFP", "1");
+
+ if (SoftFloat)
+ Builder.defineMacro("__SOFTFP__");
+
+ if (ArchKind == llvm::ARM::ArchKind::XSCALE)
+ Builder.defineMacro("__XSCALE__");
+
+ if (isThumb()) {
+ Builder.defineMacro("__THUMBEL__");
+ Builder.defineMacro("__thumb__");
+ if (supportsThumb2())
+ Builder.defineMacro("__thumb2__");
+ }
+
+ // ACLE 6.4.9 32-bit SIMD instructions
+ if (ArchVersion >= 6 && (CPUProfile != "M" || CPUAttr == "7EM"))
+ Builder.defineMacro("__ARM_FEATURE_SIMD32", "1");
+
+ // ACLE 6.4.10 Hardware Integer Divide
+ if (((HWDiv & HWDivThumb) && isThumb()) ||
+ ((HWDiv & HWDivARM) && !isThumb())) {
+ Builder.defineMacro("__ARM_FEATURE_IDIV", "1");
+ Builder.defineMacro("__ARM_ARCH_EXT_IDIV__", "1");
+ }
+
+ // Note, this is always on in gcc, even though it doesn't make sense.
+ Builder.defineMacro("__APCS_32__");
+
+ if (FPUModeIsVFP((FPUMode)FPU)) {
+ Builder.defineMacro("__VFP_FP__");
+ if (FPU & VFP2FPU)
+ Builder.defineMacro("__ARM_VFPV2__");
+ if (FPU & VFP3FPU)
+ Builder.defineMacro("__ARM_VFPV3__");
+ if (FPU & VFP4FPU)
+ Builder.defineMacro("__ARM_VFPV4__");
+ if (FPU & FPARMV8)
+ Builder.defineMacro("__ARM_FPV5__");
+ }
+
+ // This only gets set when Neon instructions are actually available, unlike
+ // the VFP define, hence the soft float and arch check. This is subtly
+ // different from gcc, we follow the intent which was that it should be set
+ // when Neon instructions are actually available.
+ if ((FPU & NeonFPU) && !SoftFloat && ArchVersion >= 7) {
+ Builder.defineMacro("__ARM_NEON", "1");
+ Builder.defineMacro("__ARM_NEON__");
+ // current AArch32 NEON implementations do not support double-precision
+ // floating-point even when it is present in VFP.
+ Builder.defineMacro("__ARM_NEON_FP",
+ "0x" + llvm::utohexstr(HW_FP & ~HW_FP_DP));
+ }
+
+ Builder.defineMacro("__ARM_SIZEOF_WCHAR_T",
+ llvm::utostr(Opts.WCharSize ? Opts.WCharSize : 4));
+
+ Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4");
+
+ if (ArchVersion >= 6 && CPUAttr != "6M" && CPUAttr != "8M_BASE") {
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
+ }
+
+ // ACLE 6.4.7 DSP instructions
+ if (DSP) {
+ Builder.defineMacro("__ARM_FEATURE_DSP", "1");
+ }
+
+ // ACLE 6.4.8 Saturation instructions
+ bool SAT = false;
+ if ((ArchVersion == 6 && CPUProfile != "M") || ArchVersion > 6) {
+ Builder.defineMacro("__ARM_FEATURE_SAT", "1");
+ SAT = true;
+ }
+
+ // ACLE 6.4.6 Q (saturation) flag
+ if (DSP || SAT)
+ Builder.defineMacro("__ARM_FEATURE_QBIT", "1");
+
+ if (Opts.UnsafeFPMath)
+ Builder.defineMacro("__ARM_FP_FAST", "1");
+
+ switch (ArchKind) {
+ default:
+ break;
+ case llvm::ARM::ArchKind::ARMV8_1A:
+ getTargetDefinesARMV81A(Opts, Builder);
+ break;
+ case llvm::ARM::ArchKind::ARMV8_2A:
+ getTargetDefinesARMV82A(Opts, Builder);
+ break;
+ }
+}
+
+const Builtin::Info ARMTargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
+ {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
+#include "clang/Basic/BuiltinsNEON.def"
+
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define LANGBUILTIN(ID, TYPE, ATTRS, LANG) \
+ {#ID, TYPE, ATTRS, nullptr, LANG, nullptr},
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
+ {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
+#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \
+ {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE},
+#include "clang/Basic/BuiltinsARM.def"
+};
+
+ArrayRef<Builtin::Info> ARMTargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfo, clang::ARM::LastTSBuiltin -
+ Builtin::FirstTSBuiltin);
+}
+
+bool ARMTargetInfo::isCLZForZeroUndef() const { return false; }
+TargetInfo::BuiltinVaListKind ARMTargetInfo::getBuiltinVaListKind() const {
+ return IsAAPCS
+ ? AAPCSABIBuiltinVaList
+ : (getTriple().isWatchABI() ? TargetInfo::CharPtrBuiltinVaList
+ : TargetInfo::VoidPtrBuiltinVaList);
+}
+
+const char *const ARMTargetInfo::GCCRegNames[] = {
+ // Integer registers
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",
+ "r12", "sp", "lr", "pc",
+
+ // Float registers
+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
+ "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
+ "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
+
+ // Double registers
+ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",
+ "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",
+ "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
+
+ // Quad registers
+ "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11",
+ "q12", "q13", "q14", "q15"};
+
+ArrayRef<const char *> ARMTargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
+}
+
+const TargetInfo::GCCRegAlias ARMTargetInfo::GCCRegAliases[] = {
+ {{"a1"}, "r0"}, {{"a2"}, "r1"}, {{"a3"}, "r2"}, {{"a4"}, "r3"},
+ {{"v1"}, "r4"}, {{"v2"}, "r5"}, {{"v3"}, "r6"}, {{"v4"}, "r7"},
+ {{"v5"}, "r8"}, {{"v6", "rfp"}, "r9"}, {{"sl"}, "r10"}, {{"fp"}, "r11"},
+ {{"ip"}, "r12"}, {{"r13"}, "sp"}, {{"r14"}, "lr"}, {{"r15"}, "pc"},
+ // The S, D and Q registers overlap, but aren't really aliases; we
+ // don't want to substitute one of these for a different-sized one.
+};
+
+ArrayRef<TargetInfo::GCCRegAlias> ARMTargetInfo::getGCCRegAliases() const {
+ return llvm::makeArrayRef(GCCRegAliases);
+}
+
+bool ARMTargetInfo::validateAsmConstraint(
+ const char *&Name, TargetInfo::ConstraintInfo &Info) const {
+ switch (*Name) {
+ default:
+ break;
+ case 'l': // r0-r7
+ case 'h': // r8-r15
+ case 't': // VFP Floating point register single precision
+ case 'w': // VFP Floating point register double precision
+ Info.setAllowsRegister();
+ return true;
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ // FIXME
+ return true;
+ case 'Q': // A memory address that is a single base register.
+ Info.setAllowsMemory();
+ return true;
+ case 'U': // a memory reference...
+ switch (Name[1]) {
+ case 'q': // ...ARMV4 ldrsb
+ case 'v': // ...VFP load/store (reg+constant offset)
+ case 'y': // ...iWMMXt load/store
+ case 't': // address valid for load/store opaque types wider
+ // than 128-bits
+ case 'n': // valid address for Neon doubleword vector load/store
+ case 'm': // valid address for Neon element and structure load/store
+ case 's': // valid address for non-offset loads/stores of quad-word
+ // values in four ARM registers
+ Info.setAllowsMemory();
+ Name++;
+ return true;
+ }
+ }
+ return false;
+}
+
+std::string ARMTargetInfo::convertConstraint(const char *&Constraint) const {
+ std::string R;
+ switch (*Constraint) {
+ case 'U': // Two-character constraint; add "^" hint for later parsing.
+ R = std::string("^") + std::string(Constraint, 2);
+ Constraint++;
+ break;
+ case 'p': // 'p' should be translated to 'r' by default.
+ R = std::string("r");
+ break;
+ default:
+ return std::string(1, *Constraint);
+ }
+ return R;
+}
+
+bool ARMTargetInfo::validateConstraintModifier(
+ StringRef Constraint, char Modifier, unsigned Size,
+ std::string &SuggestedModifier) const {
+ bool isOutput = (Constraint[0] == '=');
+ bool isInOut = (Constraint[0] == '+');
+
+ // Strip off constraint modifiers.
+ while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
+ Constraint = Constraint.substr(1);
+
+ switch (Constraint[0]) {
+ default:
+ break;
+ case 'r': {
+ switch (Modifier) {
+ default:
+ return (isInOut || isOutput || Size <= 64);
+ case 'q':
+ // A register of size 32 cannot fit a vector type.
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+const char *ARMTargetInfo::getClobbers() const {
+ // FIXME: Is this really right?
+ return "";
+}
+
+TargetInfo::CallingConvCheckResult
+ARMTargetInfo::checkCallingConvention(CallingConv CC) const {
+ switch (CC) {
+ case CC_AAPCS:
+ case CC_AAPCS_VFP:
+ case CC_Swift:
+ case CC_OpenCLKernel:
+ return CCCR_OK;
+ default:
+ return CCCR_Warning;
+ }
+}
+
+int ARMTargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
+ if (RegNo == 0)
+ return 0;
+ if (RegNo == 1)
+ return 1;
+ return -1;
+}
+
+bool ARMTargetInfo::hasSjLjLowering() const { return true; }
+
+ARMleTargetInfo::ARMleTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : ARMTargetInfo(Triple, Opts) {}
+
+void ARMleTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__ARMEL__");
+ ARMTargetInfo::getTargetDefines(Opts, Builder);
+}
+
+ARMbeTargetInfo::ARMbeTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : ARMTargetInfo(Triple, Opts) {}
+
+void ARMbeTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__ARMEB__");
+ Builder.defineMacro("__ARM_BIG_ENDIAN");
+ ARMTargetInfo::getTargetDefines(Opts, Builder);
+}
+
+WindowsARMTargetInfo::WindowsARMTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : WindowsTargetInfo<ARMleTargetInfo>(Triple, Opts), Triple(Triple) {
+}
+
+void WindowsARMTargetInfo::getVisualStudioDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ WindowsTargetInfo<ARMleTargetInfo>::getVisualStudioDefines(Opts, Builder);
+
+ // FIXME: this is invalid for WindowsCE
+ Builder.defineMacro("_M_ARM_NT", "1");
+ Builder.defineMacro("_M_ARMT", "_M_ARM");
+ Builder.defineMacro("_M_THUMB", "_M_ARM");
+
+ assert((Triple.getArch() == llvm::Triple::arm ||
+ Triple.getArch() == llvm::Triple::thumb) &&
+ "invalid architecture for Windows ARM target info");
+ unsigned Offset = Triple.getArch() == llvm::Triple::arm ? 4 : 6;
+ Builder.defineMacro("_M_ARM", Triple.getArchName().substr(Offset));
+
+ // TODO map the complete set of values
+ // 31: VFPv3 40: VFPv4
+ Builder.defineMacro("_M_ARM_FP", "31");
+}
+
+TargetInfo::BuiltinVaListKind
+WindowsARMTargetInfo::getBuiltinVaListKind() const {
+ return TargetInfo::CharPtrBuiltinVaList;
+}
+
+TargetInfo::CallingConvCheckResult
+WindowsARMTargetInfo::checkCallingConvention(CallingConv CC) const {
+ switch (CC) {
+ case CC_X86StdCall:
+ case CC_X86ThisCall:
+ case CC_X86FastCall:
+ case CC_X86VectorCall:
+ return CCCR_Ignore;
+ case CC_C:
+ case CC_OpenCLKernel:
+ return CCCR_OK;
+ default:
+ return CCCR_Warning;
+ }
+}
+
+// Windows ARM + Itanium C++ ABI Target
+ItaniumWindowsARMleTargetInfo::ItaniumWindowsARMleTargetInfo(
+ const llvm::Triple &Triple, const TargetOptions &Opts)
+ : WindowsARMTargetInfo(Triple, Opts) {
+ TheCXXABI.set(TargetCXXABI::GenericARM);
+}
+
+void ItaniumWindowsARMleTargetInfo::getTargetDefines(
+ const LangOptions &Opts, MacroBuilder &Builder) const {
+ WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
+
+ if (Opts.MSVCCompat)
+ WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
+}
+
+// Windows ARM, MS (C++) ABI
+MicrosoftARMleTargetInfo::MicrosoftARMleTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : WindowsARMTargetInfo(Triple, Opts) {
+ TheCXXABI.set(TargetCXXABI::Microsoft);
+}
+
+void MicrosoftARMleTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
+ WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
+}
+
+MinGWARMTargetInfo::MinGWARMTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : WindowsARMTargetInfo(Triple, Opts) {
+ TheCXXABI.set(TargetCXXABI::GenericARM);
+}
+
+void MinGWARMTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("_ARM_");
+}
+
+CygwinARMTargetInfo::CygwinARMTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : ARMleTargetInfo(Triple, Opts) {
+ this->WCharType = TargetInfo::UnsignedShort;
+ TLSSupported = false;
+ DoubleAlign = LongLongAlign = 64;
+ resetDataLayout("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64");
+}
+
+void CygwinARMTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ ARMleTargetInfo::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("_ARM_");
+ Builder.defineMacro("__CYGWIN__");
+ Builder.defineMacro("__CYGWIN32__");
+ DefineStd(Builder, "unix", Opts);
+ if (Opts.CPlusPlus)
+ Builder.defineMacro("_GNU_SOURCE");
+}
+
+DarwinARMTargetInfo::DarwinARMTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : DarwinTargetInfo<ARMleTargetInfo>(Triple, Opts) {
+ HasAlignMac68kSupport = true;
+ // iOS always has 64-bit atomic instructions.
+ // FIXME: This should be based off of the target features in
+ // ARMleTargetInfo.
+ MaxAtomicInlineWidth = 64;
+
+ if (Triple.isWatchABI()) {
+ // Darwin on iOS uses a variant of the ARM C++ ABI.
+ TheCXXABI.set(TargetCXXABI::WatchOS);
+
+ // BOOL should be a real boolean on the new ABI
+ UseSignedCharForObjCBool = false;
+ } else
+ TheCXXABI.set(TargetCXXABI::iOS);
+}
+
+void DarwinARMTargetInfo::getOSDefines(const LangOptions &Opts,
+ const llvm::Triple &Triple,
+ MacroBuilder &Builder) const {
+ getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
+}
+
+RenderScript32TargetInfo::RenderScript32TargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : ARMleTargetInfo(llvm::Triple("armv7", Triple.getVendorName(),
+ Triple.getOSName(),
+ Triple.getEnvironmentName()),
+ Opts) {
+ IsRenderScriptTarget = true;
+ LongWidth = LongAlign = 64;
+}
+
+void RenderScript32TargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__RENDERSCRIPT__");
+ ARMleTargetInfo::getTargetDefines(Opts, Builder);
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/ARM.h b/contrib/llvm/tools/clang/lib/Basic/Targets/ARM.h
new file mode 100644
index 0000000000000..fb0e7e66bea38
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/ARM.h
@@ -0,0 +1,256 @@
+//===--- ARM.h - Declare ARM target feature support -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares ARM TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_ARM_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_ARM_H
+
+#include "OSTargets.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/TargetParser.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY ARMTargetInfo : public TargetInfo {
+ // Possible FPU choices.
+ enum FPUMode {
+ VFP2FPU = (1 << 0),
+ VFP3FPU = (1 << 1),
+ VFP4FPU = (1 << 2),
+ NeonFPU = (1 << 3),
+ FPARMV8 = (1 << 4)
+ };
+
+ // Possible HWDiv features.
+ enum HWDivMode { HWDivThumb = (1 << 0), HWDivARM = (1 << 1) };
+
+ static bool FPUModeIsVFP(FPUMode Mode) {
+ return Mode & (VFP2FPU | VFP3FPU | VFP4FPU | NeonFPU | FPARMV8);
+ }
+
+ static const TargetInfo::GCCRegAlias GCCRegAliases[];
+ static const char *const GCCRegNames[];
+
+ std::string ABI, CPU;
+
+ StringRef CPUProfile;
+ StringRef CPUAttr;
+
+ enum { FP_Default, FP_VFP, FP_Neon } FPMath;
+
+ llvm::ARM::ISAKind ArchISA;
+ llvm::ARM::ArchKind ArchKind = llvm::ARM::ArchKind::ARMV4T;
+ llvm::ARM::ProfileKind ArchProfile;
+ unsigned ArchVersion;
+
+ unsigned FPU : 5;
+
+ unsigned IsAAPCS : 1;
+ unsigned HWDiv : 2;
+
+ // Initialized via features.
+ unsigned SoftFloat : 1;
+ unsigned SoftFloatABI : 1;
+
+ unsigned CRC : 1;
+ unsigned Crypto : 1;
+ unsigned DSP : 1;
+ unsigned Unaligned : 1;
+
+ enum {
+ LDREX_B = (1 << 0), /// byte (8-bit)
+ LDREX_H = (1 << 1), /// half (16-bit)
+ LDREX_W = (1 << 2), /// word (32-bit)
+ LDREX_D = (1 << 3), /// double (64-bit)
+ };
+
+ uint32_t LDREX;
+
+ // ACLE 6.5.1 Hardware floating point
+ enum {
+ HW_FP_HP = (1 << 1), /// half (16-bit)
+ HW_FP_SP = (1 << 2), /// single (32-bit)
+ HW_FP_DP = (1 << 3), /// double (64-bit)
+ };
+ uint32_t HW_FP;
+
+ static const Builtin::Info BuiltinInfo[];
+
+ void setABIAAPCS();
+ void setABIAPCS(bool IsAAPCS16);
+
+ void setArchInfo();
+ void setArchInfo(llvm::ARM::ArchKind Kind);
+
+ void setAtomic();
+
+ bool isThumb() const;
+ bool supportsThumb() const;
+ bool supportsThumb2() const;
+
+ StringRef getCPUAttr() const;
+ StringRef getCPUProfile() const;
+
+public:
+ ARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+
+ StringRef getABI() const override;
+ bool setABI(const std::string &Name) override;
+
+ // FIXME: This should be based on Arch attributes, not CPU names.
+ bool
+ initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
+ StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const override;
+
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) override;
+
+ bool hasFeature(StringRef Feature) const override;
+
+ bool isValidCPUName(StringRef Name) const override;
+ bool setCPU(const std::string &Name) override;
+
+ bool setFPMath(StringRef Name) override;
+
+ bool useFP16ConversionIntrinsics() const override {
+ return false;
+ }
+
+ void getTargetDefinesARMV81A(const LangOptions &Opts,
+ MacroBuilder &Builder) const;
+
+ void getTargetDefinesARMV82A(const LangOptions &Opts,
+ MacroBuilder &Builder) const;
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+
+ bool isCLZForZeroUndef() const override;
+ BuiltinVaListKind getBuiltinVaListKind() const override;
+
+ ArrayRef<const char *> getGCCRegNames() const override;
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override;
+ std::string convertConstraint(const char *&Constraint) const override;
+ bool
+ validateConstraintModifier(StringRef Constraint, char Modifier, unsigned Size,
+ std::string &SuggestedModifier) const override;
+ const char *getClobbers() const override;
+
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override;
+
+ int getEHDataRegisterNumber(unsigned RegNo) const override;
+
+ bool hasSjLjLowering() const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY ARMleTargetInfo : public ARMTargetInfo {
+public:
+ ARMleTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY ARMbeTargetInfo : public ARMTargetInfo {
+public:
+ ARMbeTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY WindowsARMTargetInfo
+ : public WindowsTargetInfo<ARMleTargetInfo> {
+ const llvm::Triple Triple;
+
+public:
+ WindowsARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+
+ void getVisualStudioDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const;
+
+ BuiltinVaListKind getBuiltinVaListKind() const override;
+
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override;
+};
+
+// Windows ARM + Itanium C++ ABI Target
+class LLVM_LIBRARY_VISIBILITY ItaniumWindowsARMleTargetInfo
+ : public WindowsARMTargetInfo {
+public:
+ ItaniumWindowsARMleTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts);
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+};
+
+// Windows ARM, MS (C++) ABI
+class LLVM_LIBRARY_VISIBILITY MicrosoftARMleTargetInfo
+ : public WindowsARMTargetInfo {
+public:
+ MicrosoftARMleTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts);
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+};
+
+// ARM MinGW target
+class LLVM_LIBRARY_VISIBILITY MinGWARMTargetInfo : public WindowsARMTargetInfo {
+public:
+ MinGWARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+};
+
+// ARM Cygwin target
+class LLVM_LIBRARY_VISIBILITY CygwinARMTargetInfo : public ARMleTargetInfo {
+public:
+ CygwinARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY DarwinARMTargetInfo
+ : public DarwinTargetInfo<ARMleTargetInfo> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override;
+
+public:
+ DarwinARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+};
+
+// 32-bit RenderScript is armv7 with width and align of 'long' set to 8-bytes
+class LLVM_LIBRARY_VISIBILITY RenderScript32TargetInfo
+ : public ARMleTargetInfo {
+public:
+ RenderScript32TargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts);
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+};
+
+} // namespace targets
+} // namespace clang
+
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_ARM_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/AVR.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/AVR.cpp
new file mode 100644
index 0000000000000..3022fe33d76cc
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/AVR.cpp
@@ -0,0 +1,320 @@
+//===--- AVR.cpp - Implement AVR target feature support -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements AVR TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AVR.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+namespace clang {
+namespace targets {
+
+/// Information about a specific microcontroller.
+struct LLVM_LIBRARY_VISIBILITY MCUInfo {
+ const char *Name;
+ const char *DefineName;
+};
+
+// This list should be kept up-to-date with AVRDevices.td in LLVM.
+static ArrayRef<MCUInfo> AVRMcus = {
+ {"at90s1200", "__AVR_AT90S1200__"},
+ {"attiny11", "__AVR_ATtiny11__"},
+ {"attiny12", "__AVR_ATtiny12__"},
+ {"attiny15", "__AVR_ATtiny15__"},
+ {"attiny28", "__AVR_ATtiny28__"},
+ {"at90s2313", "__AVR_AT90S2313__"},
+ {"at90s2323", "__AVR_AT90S2323__"},
+ {"at90s2333", "__AVR_AT90S2333__"},
+ {"at90s2343", "__AVR_AT90S2343__"},
+ {"attiny22", "__AVR_ATtiny22__"},
+ {"attiny26", "__AVR_ATtiny26__"},
+ {"at86rf401", "__AVR_AT86RF401__"},
+ {"at90s4414", "__AVR_AT90S4414__"},
+ {"at90s4433", "__AVR_AT90S4433__"},
+ {"at90s4434", "__AVR_AT90S4434__"},
+ {"at90s8515", "__AVR_AT90S8515__"},
+ {"at90c8534", "__AVR_AT90c8534__"},
+ {"at90s8535", "__AVR_AT90S8535__"},
+ {"ata5272", "__AVR_ATA5272__"},
+ {"attiny13", "__AVR_ATtiny13__"},
+ {"attiny13a", "__AVR_ATtiny13A__"},
+ {"attiny2313", "__AVR_ATtiny2313__"},
+ {"attiny2313a", "__AVR_ATtiny2313A__"},
+ {"attiny24", "__AVR_ATtiny24__"},
+ {"attiny24a", "__AVR_ATtiny24A__"},
+ {"attiny4313", "__AVR_ATtiny4313__"},
+ {"attiny44", "__AVR_ATtiny44__"},
+ {"attiny44a", "__AVR_ATtiny44A__"},
+ {"attiny84", "__AVR_ATtiny84__"},
+ {"attiny84a", "__AVR_ATtiny84A__"},
+ {"attiny25", "__AVR_ATtiny25__"},
+ {"attiny45", "__AVR_ATtiny45__"},
+ {"attiny85", "__AVR_ATtiny85__"},
+ {"attiny261", "__AVR_ATtiny261__"},
+ {"attiny261a", "__AVR_ATtiny261A__"},
+ {"attiny461", "__AVR_ATtiny461__"},
+ {"attiny461a", "__AVR_ATtiny461A__"},
+ {"attiny861", "__AVR_ATtiny861__"},
+ {"attiny861a", "__AVR_ATtiny861A__"},
+ {"attiny87", "__AVR_ATtiny87__"},
+ {"attiny43u", "__AVR_ATtiny43U__"},
+ {"attiny48", "__AVR_ATtiny48__"},
+ {"attiny88", "__AVR_ATtiny88__"},
+ {"attiny828", "__AVR_ATtiny828__"},
+ {"at43usb355", "__AVR_AT43USB355__"},
+ {"at76c711", "__AVR_AT76C711__"},
+ {"atmega103", "__AVR_ATmega103__"},
+ {"at43usb320", "__AVR_AT43USB320__"},
+ {"attiny167", "__AVR_ATtiny167__"},
+ {"at90usb82", "__AVR_AT90USB82__"},
+ {"at90usb162", "__AVR_AT90USB162__"},
+ {"ata5505", "__AVR_ATA5505__"},
+ {"atmega8u2", "__AVR_ATmega8U2__"},
+ {"atmega16u2", "__AVR_ATmega16U2__"},
+ {"atmega32u2", "__AVR_ATmega32U2__"},
+ {"attiny1634", "__AVR_ATtiny1634__"},
+ {"atmega8", "__AVR_ATmega8__"},
+ {"ata6289", "__AVR_ATA6289__"},
+ {"atmega8a", "__AVR_ATmega8A__"},
+ {"ata6285", "__AVR_ATA6285__"},
+ {"ata6286", "__AVR_ATA6286__"},
+ {"atmega48", "__AVR_ATmega48__"},
+ {"atmega48a", "__AVR_ATmega48A__"},
+ {"atmega48pa", "__AVR_ATmega48PA__"},
+ {"atmega48p", "__AVR_ATmega48P__"},
+ {"atmega88", "__AVR_ATmega88__"},
+ {"atmega88a", "__AVR_ATmega88A__"},
+ {"atmega88p", "__AVR_ATmega88P__"},
+ {"atmega88pa", "__AVR_ATmega88PA__"},
+ {"atmega8515", "__AVR_ATmega8515__"},
+ {"atmega8535", "__AVR_ATmega8535__"},
+ {"atmega8hva", "__AVR_ATmega8HVA__"},
+ {"at90pwm1", "__AVR_AT90PWM1__"},
+ {"at90pwm2", "__AVR_AT90PWM2__"},
+ {"at90pwm2b", "__AVR_AT90PWM2B__"},
+ {"at90pwm3", "__AVR_AT90PWM3__"},
+ {"at90pwm3b", "__AVR_AT90PWM3B__"},
+ {"at90pwm81", "__AVR_AT90PWM81__"},
+ {"ata5790", "__AVR_ATA5790__"},
+ {"ata5795", "__AVR_ATA5795__"},
+ {"atmega16", "__AVR_ATmega16__"},
+ {"atmega16a", "__AVR_ATmega16A__"},
+ {"atmega161", "__AVR_ATmega161__"},
+ {"atmega162", "__AVR_ATmega162__"},
+ {"atmega163", "__AVR_ATmega163__"},
+ {"atmega164a", "__AVR_ATmega164A__"},
+ {"atmega164p", "__AVR_ATmega164P__"},
+ {"atmega164pa", "__AVR_ATmega164PA__"},
+ {"atmega165", "__AVR_ATmega165__"},
+ {"atmega165a", "__AVR_ATmega165A__"},
+ {"atmega165p", "__AVR_ATmega165P__"},
+ {"atmega165pa", "__AVR_ATmega165PA__"},
+ {"atmega168", "__AVR_ATmega168__"},
+ {"atmega168a", "__AVR_ATmega168A__"},
+ {"atmega168p", "__AVR_ATmega168P__"},
+ {"atmega168pa", "__AVR_ATmega168PA__"},
+ {"atmega169", "__AVR_ATmega169__"},
+ {"atmega169a", "__AVR_ATmega169A__"},
+ {"atmega169p", "__AVR_ATmega169P__"},
+ {"atmega169pa", "__AVR_ATmega169PA__"},
+ {"atmega32", "__AVR_ATmega32__"},
+ {"atmega32a", "__AVR_ATmega32A__"},
+ {"atmega323", "__AVR_ATmega323__"},
+ {"atmega324a", "__AVR_ATmega324A__"},
+ {"atmega324p", "__AVR_ATmega324P__"},
+ {"atmega324pa", "__AVR_ATmega324PA__"},
+ {"atmega325", "__AVR_ATmega325__"},
+ {"atmega325a", "__AVR_ATmega325A__"},
+ {"atmega325p", "__AVR_ATmega325P__"},
+ {"atmega325pa", "__AVR_ATmega325PA__"},
+ {"atmega3250", "__AVR_ATmega3250__"},
+ {"atmega3250a", "__AVR_ATmega3250A__"},
+ {"atmega3250p", "__AVR_ATmega3250P__"},
+ {"atmega3250pa", "__AVR_ATmega3250PA__"},
+ {"atmega328", "__AVR_ATmega328__"},
+ {"atmega328p", "__AVR_ATmega328P__"},
+ {"atmega329", "__AVR_ATmega329__"},
+ {"atmega329a", "__AVR_ATmega329A__"},
+ {"atmega329p", "__AVR_ATmega329P__"},
+ {"atmega329pa", "__AVR_ATmega329PA__"},
+ {"atmega3290", "__AVR_ATmega3290__"},
+ {"atmega3290a", "__AVR_ATmega3290A__"},
+ {"atmega3290p", "__AVR_ATmega3290P__"},
+ {"atmega3290pa", "__AVR_ATmega3290PA__"},
+ {"atmega406", "__AVR_ATmega406__"},
+ {"atmega64", "__AVR_ATmega64__"},
+ {"atmega64a", "__AVR_ATmega64A__"},
+ {"atmega640", "__AVR_ATmega640__"},
+ {"atmega644", "__AVR_ATmega644__"},
+ {"atmega644a", "__AVR_ATmega644A__"},
+ {"atmega644p", "__AVR_ATmega644P__"},
+ {"atmega644pa", "__AVR_ATmega644PA__"},
+ {"atmega645", "__AVR_ATmega645__"},
+ {"atmega645a", "__AVR_ATmega645A__"},
+ {"atmega645p", "__AVR_ATmega645P__"},
+ {"atmega649", "__AVR_ATmega649__"},
+ {"atmega649a", "__AVR_ATmega649A__"},
+ {"atmega649p", "__AVR_ATmega649P__"},
+ {"atmega6450", "__AVR_ATmega6450__"},
+ {"atmega6450a", "__AVR_ATmega6450A__"},
+ {"atmega6450p", "__AVR_ATmega6450P__"},
+ {"atmega6490", "__AVR_ATmega6490__"},
+ {"atmega6490a", "__AVR_ATmega6490A__"},
+ {"atmega6490p", "__AVR_ATmega6490P__"},
+ {"atmega64rfr2", "__AVR_ATmega64RFR2__"},
+ {"atmega644rfr2", "__AVR_ATmega644RFR2__"},
+ {"atmega16hva", "__AVR_ATmega16HVA__"},
+ {"atmega16hva2", "__AVR_ATmega16HVA2__"},
+ {"atmega16hvb", "__AVR_ATmega16HVB__"},
+ {"atmega16hvbrevb", "__AVR_ATmega16HVBREVB__"},
+ {"atmega32hvb", "__AVR_ATmega32HVB__"},
+ {"atmega32hvbrevb", "__AVR_ATmega32HVBREVB__"},
+ {"atmega64hve", "__AVR_ATmega64HVE__"},
+ {"at90can32", "__AVR_AT90CAN32__"},
+ {"at90can64", "__AVR_AT90CAN64__"},
+ {"at90pwm161", "__AVR_AT90PWM161__"},
+ {"at90pwm216", "__AVR_AT90PWM216__"},
+ {"at90pwm316", "__AVR_AT90PWM316__"},
+ {"atmega32c1", "__AVR_ATmega32C1__"},
+ {"atmega64c1", "__AVR_ATmega64C1__"},
+ {"atmega16m1", "__AVR_ATmega16M1__"},
+ {"atmega32m1", "__AVR_ATmega32M1__"},
+ {"atmega64m1", "__AVR_ATmega64M1__"},
+ {"atmega16u4", "__AVR_ATmega16U4__"},
+ {"atmega32u4", "__AVR_ATmega32U4__"},
+ {"atmega32u6", "__AVR_ATmega32U6__"},
+ {"at90usb646", "__AVR_AT90USB646__"},
+ {"at90usb647", "__AVR_AT90USB647__"},
+ {"at90scr100", "__AVR_AT90SCR100__"},
+ {"at94k", "__AVR_AT94K__"},
+ {"m3000", "__AVR_AT000__"},
+ {"atmega128", "__AVR_ATmega128__"},
+ {"atmega128a", "__AVR_ATmega128A__"},
+ {"atmega1280", "__AVR_ATmega1280__"},
+ {"atmega1281", "__AVR_ATmega1281__"},
+ {"atmega1284", "__AVR_ATmega1284__"},
+ {"atmega1284p", "__AVR_ATmega1284P__"},
+ {"atmega128rfa1", "__AVR_ATmega128RFA1__"},
+ {"atmega128rfr2", "__AVR_ATmega128RFR2__"},
+ {"atmega1284rfr2", "__AVR_ATmega1284RFR2__"},
+ {"at90can128", "__AVR_AT90CAN128__"},
+ {"at90usb1286", "__AVR_AT90USB1286__"},
+ {"at90usb1287", "__AVR_AT90USB1287__"},
+ {"atmega2560", "__AVR_ATmega2560__"},
+ {"atmega2561", "__AVR_ATmega2561__"},
+ {"atmega256rfr2", "__AVR_ATmega256RFR2__"},
+ {"atmega2564rfr2", "__AVR_ATmega2564RFR2__"},
+ {"atxmega16a4", "__AVR_ATxmega16A4__"},
+ {"atxmega16a4u", "__AVR_ATxmega16a4U__"},
+ {"atxmega16c4", "__AVR_ATxmega16C4__"},
+ {"atxmega16d4", "__AVR_ATxmega16D4__"},
+ {"atxmega32a4", "__AVR_ATxmega32A4__"},
+ {"atxmega32a4u", "__AVR_ATxmega32A4U__"},
+ {"atxmega32c4", "__AVR_ATxmega32C4__"},
+ {"atxmega32d4", "__AVR_ATxmega32D4__"},
+ {"atxmega32e5", "__AVR_ATxmega32E5__"},
+ {"atxmega16e5", "__AVR_ATxmega16E5__"},
+ {"atxmega8e5", "__AVR_ATxmega8E5__"},
+ {"atxmega32x1", "__AVR_ATxmega32X1__"},
+ {"atxmega64a3", "__AVR_ATxmega64A3__"},
+ {"atxmega64a3u", "__AVR_ATxmega64A3U__"},
+ {"atxmega64a4u", "__AVR_ATxmega64A4U__"},
+ {"atxmega64b1", "__AVR_ATxmega64B1__"},
+ {"atxmega64b3", "__AVR_ATxmega64B3__"},
+ {"atxmega64c3", "__AVR_ATxmega64C3__"},
+ {"atxmega64d3", "__AVR_ATxmega64D3__"},
+ {"atxmega64d4", "__AVR_ATxmega64D4__"},
+ {"atxmega64a1", "__AVR_ATxmega64A1__"},
+ {"atxmega64a1u", "__AVR_ATxmega64A1U__"},
+ {"atxmega128a3", "__AVR_ATxmega128A3__"},
+ {"atxmega128a3u", "__AVR_ATxmega128A3U__"},
+ {"atxmega128b1", "__AVR_ATxmega128B1__"},
+ {"atxmega128b3", "__AVR_ATxmega128B3__"},
+ {"atxmega128c3", "__AVR_ATxmega128C3__"},
+ {"atxmega128d3", "__AVR_ATxmega128D3__"},
+ {"atxmega128d4", "__AVR_ATxmega128D4__"},
+ {"atxmega192a3", "__AVR_ATxmega192A3__"},
+ {"atxmega192a3u", "__AVR_ATxmega192A3U__"},
+ {"atxmega192c3", "__AVR_ATxmega192C3__"},
+ {"atxmega192d3", "__AVR_ATxmega192D3__"},
+ {"atxmega256a3", "__AVR_ATxmega256A3__"},
+ {"atxmega256a3u", "__AVR_ATxmega256A3U__"},
+ {"atxmega256a3b", "__AVR_ATxmega256A3B__"},
+ {"atxmega256a3bu", "__AVR_ATxmega256A3BU__"},
+ {"atxmega256c3", "__AVR_ATxmega256C3__"},
+ {"atxmega256d3", "__AVR_ATxmega256D3__"},
+ {"atxmega384c3", "__AVR_ATxmega384C3__"},
+ {"atxmega384d3", "__AVR_ATxmega384D3__"},
+ {"atxmega128a1", "__AVR_ATxmega128A1__"},
+ {"atxmega128a1u", "__AVR_ATxmega128A1U__"},
+ {"atxmega128a4u", "__AVR_ATxmega128a4U__"},
+ {"attiny4", "__AVR_ATtiny4__"},
+ {"attiny5", "__AVR_ATtiny5__"},
+ {"attiny9", "__AVR_ATtiny9__"},
+ {"attiny10", "__AVR_ATtiny10__"},
+ {"attiny20", "__AVR_ATtiny20__"},
+ {"attiny40", "__AVR_ATtiny40__"},
+ {"attiny102", "__AVR_ATtiny102__"},
+ {"attiny104", "__AVR_ATtiny104__"},
+};
+
+} // namespace targets
+} // namespace clang
+
+bool AVRTargetInfo::isValidCPUName(StringRef Name) const {
+ bool IsFamily = llvm::StringSwitch<bool>(Name)
+ .Case("avr1", true)
+ .Case("avr2", true)
+ .Case("avr25", true)
+ .Case("avr3", true)
+ .Case("avr31", true)
+ .Case("avr35", true)
+ .Case("avr4", true)
+ .Case("avr5", true)
+ .Case("avr51", true)
+ .Case("avr6", true)
+ .Case("avrxmega1", true)
+ .Case("avrxmega2", true)
+ .Case("avrxmega3", true)
+ .Case("avrxmega4", true)
+ .Case("avrxmega5", true)
+ .Case("avrxmega6", true)
+ .Case("avrxmega7", true)
+ .Case("avrtiny", true)
+ .Default(false);
+
+ bool IsMCU =
+ std::find_if(AVRMcus.begin(), AVRMcus.end(), [&](const MCUInfo &Info) {
+ return Info.Name == Name;
+ }) != AVRMcus.end();
+ return IsFamily || IsMCU;
+}
+
+void AVRTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("AVR");
+ Builder.defineMacro("__AVR");
+ Builder.defineMacro("__AVR__");
+
+ if (!this->CPU.empty()) {
+ auto It =
+ std::find_if(AVRMcus.begin(), AVRMcus.end(), [&](const MCUInfo &Info) {
+ return Info.Name == this->CPU;
+ });
+
+ if (It != AVRMcus.end())
+ Builder.defineMacro(It->DefineName);
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/AVR.h b/contrib/llvm/tools/clang/lib/Basic/Targets/AVR.h
new file mode 100644
index 0000000000000..3dfb84f756684
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/AVR.h
@@ -0,0 +1,184 @@
+//===--- AVR.h - Declare AVR target feature support -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares AVR TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_AVR_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_AVR_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+// AVR Target
+class LLVM_LIBRARY_VISIBILITY AVRTargetInfo : public TargetInfo {
+public:
+ AVRTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple) {
+ TLSSupported = false;
+ PointerWidth = 16;
+ PointerAlign = 8;
+ IntWidth = 16;
+ IntAlign = 8;
+ LongWidth = 32;
+ LongAlign = 8;
+ LongLongWidth = 64;
+ LongLongAlign = 8;
+ SuitableAlign = 8;
+ DefaultAlignForAttributeAligned = 8;
+ HalfWidth = 16;
+ HalfAlign = 8;
+ FloatWidth = 32;
+ FloatAlign = 8;
+ DoubleWidth = 32;
+ DoubleAlign = 8;
+ DoubleFormat = &llvm::APFloat::IEEEsingle();
+ LongDoubleWidth = 32;
+ LongDoubleAlign = 8;
+ LongDoubleFormat = &llvm::APFloat::IEEEsingle();
+ SizeType = UnsignedInt;
+ PtrDiffType = SignedInt;
+ IntPtrType = SignedInt;
+ Char16Type = UnsignedInt;
+ WIntType = SignedInt;
+ Char32Type = UnsignedLong;
+ SigAtomicType = SignedChar;
+ resetDataLayout("e-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8");
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::VoidPtrBuiltinVaList;
+ }
+
+ const char *getClobbers() const override { return ""; }
+
+ ArrayRef<const char *> getGCCRegNames() const override {
+ static const char *const GCCRegNames[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9",
+ "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19",
+ "r20", "r21", "r22", "r23", "r24", "r25", "X", "Y", "Z", "SP"
+ };
+ return llvm::makeArrayRef(GCCRegNames);
+ }
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ return None;
+ }
+
+ ArrayRef<TargetInfo::AddlRegName> getGCCAddlRegNames() const override {
+ static const TargetInfo::AddlRegName AddlRegNames[] = {
+ {{"r26", "r27"}, 26},
+ {{"r28", "r29"}, 27},
+ {{"r30", "r31"}, 28},
+ {{"SPL", "SPH"}, 29},
+ };
+ return llvm::makeArrayRef(AddlRegNames);
+ }
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override {
+ // There aren't any multi-character AVR specific constraints.
+ if (StringRef(Name).size() > 1)
+ return false;
+
+ switch (*Name) {
+ default:
+ return false;
+ case 'a': // Simple upper registers
+ case 'b': // Base pointer registers pairs
+ case 'd': // Upper register
+ case 'l': // Lower registers
+ case 'e': // Pointer register pairs
+ case 'q': // Stack pointer register
+ case 'r': // Any register
+ case 'w': // Special upper register pairs
+ case 't': // Temporary register
+ case 'x':
+ case 'X': // Pointer register pair X
+ case 'y':
+ case 'Y': // Pointer register pair Y
+ case 'z':
+ case 'Z': // Pointer register pair Z
+ Info.setAllowsRegister();
+ return true;
+ case 'I': // 6-bit positive integer constant
+ Info.setRequiresImmediate(0, 63);
+ return true;
+ case 'J': // 6-bit negative integer constant
+ Info.setRequiresImmediate(-63, 0);
+ return true;
+ case 'K': // Integer constant (Range: 2)
+ Info.setRequiresImmediate(2);
+ return true;
+ case 'L': // Integer constant (Range: 0)
+ Info.setRequiresImmediate(0);
+ return true;
+ case 'M': // 8-bit integer constant
+ Info.setRequiresImmediate(0, 0xff);
+ return true;
+ case 'N': // Integer constant (Range: -1)
+ Info.setRequiresImmediate(-1);
+ return true;
+ case 'O': // Integer constant (Range: 8, 16, 24)
+ Info.setRequiresImmediate({8, 16, 24});
+ return true;
+ case 'P': // Integer constant (Range: 1)
+ Info.setRequiresImmediate(1);
+ return true;
+ case 'R': // Integer constant (Range: -6 to 5)
+ Info.setRequiresImmediate(-6, 5);
+ return true;
+ case 'G': // Floating point constant
+ case 'Q': // A memory address based on Y or Z pointer with displacement.
+ return true;
+ }
+
+ return false;
+ }
+
+ IntType getIntTypeByWidth(unsigned BitWidth, bool IsSigned) const final {
+ // AVR prefers int for 16-bit integers.
+ return BitWidth == 16 ? (IsSigned ? SignedInt : UnsignedInt)
+ : TargetInfo::getIntTypeByWidth(BitWidth, IsSigned);
+ }
+
+ IntType getLeastIntTypeByWidth(unsigned BitWidth, bool IsSigned) const final {
+ // AVR uses int for int_least16_t and int_fast16_t.
+ return BitWidth == 16
+ ? (IsSigned ? SignedInt : UnsignedInt)
+ : TargetInfo::getLeastIntTypeByWidth(BitWidth, IsSigned);
+ }
+
+ bool isValidCPUName(StringRef Name) const override;
+ bool setCPU(const std::string &Name) override {
+ bool isValid = isValidCPUName(Name);
+ if (isValid)
+ CPU = Name;
+ return isValid;
+ }
+
+protected:
+ std::string CPU;
+};
+
+} // namespace targets
+} // namespace clang
+
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_AVR_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/BPF.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/BPF.cpp
new file mode 100644
index 0000000000000..54e34f15532da
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/BPF.cpp
@@ -0,0 +1,25 @@
+//===--- BPF.cpp - Implement BPF target feature support -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements BPF TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "BPF.h"
+#include "Targets.h"
+#include "clang/Basic/MacroBuilder.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+void BPFTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "bpf", Opts);
+ Builder.defineMacro("__BPF__");
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/BPF.h b/contrib/llvm/tools/clang/lib/Basic/Targets/BPF.h
new file mode 100644
index 0000000000000..4dd9cbd9d2219
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/BPF.h
@@ -0,0 +1,94 @@
+//===--- BPF.h - Declare BPF target feature support -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares BPF TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_BPF_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_BPF_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY BPFTargetInfo : public TargetInfo {
+public:
+ BPFTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple) {
+ LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
+ SizeType = UnsignedLong;
+ PtrDiffType = SignedLong;
+ IntPtrType = SignedLong;
+ IntMaxType = SignedLong;
+ Int64Type = SignedLong;
+ RegParmMax = 5;
+ if (Triple.getArch() == llvm::Triple::bpfeb) {
+ resetDataLayout("E-m:e-p:64:64-i64:64-n32:64-S128");
+ } else {
+ resetDataLayout("e-m:e-p:64:64-i64:64-n32:64-S128");
+ }
+ MaxAtomicPromoteWidth = 64;
+ MaxAtomicInlineWidth = 64;
+ TLSSupported = false;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ bool hasFeature(StringRef Feature) const override { return Feature == "bpf"; }
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
+
+ const char *getClobbers() const override { return ""; }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::VoidPtrBuiltinVaList;
+ }
+
+ ArrayRef<const char *> getGCCRegNames() const override { return None; }
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const override {
+ return true;
+ }
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ return None;
+ }
+
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
+ switch (CC) {
+ default:
+ return CCCR_Warning;
+ case CC_C:
+ case CC_OpenCLKernel:
+ return CCCR_OK;
+ }
+ }
+
+ bool isValidCPUName(StringRef Name) const override {
+ if (Name == "generic" || Name == "v1" ||
+ Name == "v2" || Name == "probe")
+ return true;
+ return false;
+ }
+
+ bool setCPU(const std::string &Name) override {
+ StringRef CPUName(Name);
+ return isValidCPUName(CPUName);
+ }
+};
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_BPF_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Hexagon.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/Hexagon.cpp
new file mode 100644
index 0000000000000..71d4c1e0f1611
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Hexagon.cpp
@@ -0,0 +1,158 @@
+//===--- Hexagon.cpp - Implement Hexagon target feature support -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements Hexagon TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Hexagon.h"
+#include "Targets.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+void HexagonTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__qdsp6__", "1");
+ Builder.defineMacro("__hexagon__", "1");
+
+ if (CPU == "hexagonv4") {
+ Builder.defineMacro("__HEXAGON_V4__");
+ Builder.defineMacro("__HEXAGON_ARCH__", "4");
+ if (Opts.HexagonQdsp6Compat) {
+ Builder.defineMacro("__QDSP6_V4__");
+ Builder.defineMacro("__QDSP6_ARCH__", "4");
+ }
+ } else if (CPU == "hexagonv5") {
+ Builder.defineMacro("__HEXAGON_V5__");
+ Builder.defineMacro("__HEXAGON_ARCH__", "5");
+ if (Opts.HexagonQdsp6Compat) {
+ Builder.defineMacro("__QDSP6_V5__");
+ Builder.defineMacro("__QDSP6_ARCH__", "5");
+ }
+ } else if (CPU == "hexagonv55") {
+ Builder.defineMacro("__HEXAGON_V55__");
+ Builder.defineMacro("__HEXAGON_ARCH__", "55");
+ Builder.defineMacro("__QDSP6_V55__");
+ Builder.defineMacro("__QDSP6_ARCH__", "55");
+ } else if (CPU == "hexagonv60") {
+ Builder.defineMacro("__HEXAGON_V60__");
+ Builder.defineMacro("__HEXAGON_ARCH__", "60");
+ Builder.defineMacro("__QDSP6_V60__");
+ Builder.defineMacro("__QDSP6_ARCH__", "60");
+ } else if (CPU == "hexagonv62") {
+ Builder.defineMacro("__HEXAGON_V62__");
+ Builder.defineMacro("__HEXAGON_ARCH__", "62");
+ } else if (CPU == "hexagonv65") {
+ Builder.defineMacro("__HEXAGON_V65__");
+ Builder.defineMacro("__HEXAGON_ARCH__", "65");
+ }
+
+ if (hasFeature("hvx-length64b")) {
+ Builder.defineMacro("__HVX__");
+ Builder.defineMacro("__HVX_ARCH__", HVXVersion);
+ Builder.defineMacro("__HVX_LENGTH__", "64");
+ }
+
+ if (hasFeature("hvx-length128b")) {
+ Builder.defineMacro("__HVX__");
+ Builder.defineMacro("__HVX_ARCH__", HVXVersion);
+ Builder.defineMacro("__HVX_LENGTH__", "128");
+ // FIXME: This macro is deprecated.
+ Builder.defineMacro("__HVXDBL__");
+ }
+}
+
+bool HexagonTargetInfo::initFeatureMap(
+ llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const {
+ Features["hvx-double"] = false;
+ Features["long-calls"] = false;
+
+ return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
+}
+
+bool HexagonTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) {
+ for (auto &F : Features) {
+ if (F == "+hvx-length64b")
+ HasHVX = HasHVX64B = true;
+ else if (F == "+hvx-length128b")
+ HasHVX = HasHVX128B = true;
+ else if (F.find("+hvxv") != std::string::npos) {
+ HasHVX = true;
+ HVXVersion = F.substr(std::string("+hvxv").length());
+ } else if (F == "-hvx")
+ HasHVX = HasHVX64B = HasHVX128B = false;
+ else if (F == "+long-calls")
+ UseLongCalls = true;
+ else if (F == "-long-calls")
+ UseLongCalls = false;
+ }
+ return true;
+}
+
+const char *const HexagonTargetInfo::GCCRegNames[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8",
+ "r9", "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17",
+ "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26",
+ "r27", "r28", "r29", "r30", "r31", "p0", "p1", "p2", "p3",
+ "sa0", "lc0", "sa1", "lc1", "m0", "m1", "usr", "ugp"
+};
+
+ArrayRef<const char *> HexagonTargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
+}
+
+const TargetInfo::GCCRegAlias HexagonTargetInfo::GCCRegAliases[] = {
+ {{"sp"}, "r29"},
+ {{"fp"}, "r30"},
+ {{"lr"}, "r31"},
+};
+
+ArrayRef<TargetInfo::GCCRegAlias> HexagonTargetInfo::getGCCRegAliases() const {
+ return llvm::makeArrayRef(GCCRegAliases);
+}
+
+const Builtin::Info HexagonTargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
+ {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
+#include "clang/Basic/BuiltinsHexagon.def"
+};
+
+bool HexagonTargetInfo::hasFeature(StringRef Feature) const {
+ return llvm::StringSwitch<bool>(Feature)
+ .Case("hexagon", true)
+ .Case("hvx", HasHVX)
+ .Case("hvx-length64b", HasHVX64B)
+ .Case("hvx-length128b", HasHVX128B)
+ .Case("long-calls", UseLongCalls)
+ .Default(false);
+}
+
+const char *HexagonTargetInfo::getHexagonCPUSuffix(StringRef Name) {
+ return llvm::StringSwitch<const char *>(Name)
+ .Case("hexagonv4", "4")
+ .Case("hexagonv5", "5")
+ .Case("hexagonv55", "55")
+ .Case("hexagonv60", "60")
+ .Case("hexagonv62", "62")
+ .Case("hexagonv65", "65")
+ .Default(nullptr);
+}
+
+ArrayRef<Builtin::Info> HexagonTargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfo, clang::Hexagon::LastTSBuiltin -
+ Builtin::FirstTSBuiltin);
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Hexagon.h b/contrib/llvm/tools/clang/lib/Basic/Targets/Hexagon.h
new file mode 100644
index 0000000000000..7b0966457c4bf
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Hexagon.h
@@ -0,0 +1,128 @@
+//===--- Hexagon.h - Declare Hexagon target feature support -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares Hexagon TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_HEXAGON_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_HEXAGON_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+// Hexagon abstract base class
+class LLVM_LIBRARY_VISIBILITY HexagonTargetInfo : public TargetInfo {
+
+ static const Builtin::Info BuiltinInfo[];
+ static const char *const GCCRegNames[];
+ static const TargetInfo::GCCRegAlias GCCRegAliases[];
+ std::string CPU;
+ std::string HVXVersion;
+ bool HasHVX = false;
+ bool HasHVX64B = false;
+ bool HasHVX128B = false;
+ bool UseLongCalls = false;
+
+public:
+ HexagonTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple) {
+ // Specify the vector alignment explicitly. For v512x1, the calculated
+ // alignment would be 512*alignment(i1), which is 512 bytes, instead of
+ // the required minimum of 64 bytes.
+ resetDataLayout(
+ "e-m:e-p:32:32:32-a:0-n16:32-"
+ "i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-"
+ "v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048");
+ SizeType = UnsignedInt;
+ PtrDiffType = SignedInt;
+ IntPtrType = SignedInt;
+
+ // {} in inline assembly are packet specifiers, not assembly variant
+ // specifiers.
+ NoAsmVariants = true;
+
+ LargeArrayMinWidth = 64;
+ LargeArrayAlign = 64;
+ UseBitFieldTypeAlignment = true;
+ ZeroLengthBitfieldBoundary = 32;
+ }
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override {
+ switch (*Name) {
+ case 'v':
+ case 'q':
+ if (HasHVX) {
+ Info.setAllowsRegister();
+ return true;
+ }
+ break;
+ case 'a': // Modifier register m0-m1.
+ Info.setAllowsRegister();
+ return true;
+ case 's':
+ // Relocatable constant.
+ return true;
+ }
+ return false;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ bool isCLZForZeroUndef() const override { return false; }
+
+ bool hasFeature(StringRef Feature) const override;
+
+ bool
+ initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
+ StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const override;
+
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) override;
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::CharPtrBuiltinVaList;
+ }
+
+ ArrayRef<const char *> getGCCRegNames() const override;
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
+
+ const char *getClobbers() const override { return ""; }
+
+ static const char *getHexagonCPUSuffix(StringRef Name);
+
+ bool isValidCPUName(StringRef Name) const override {
+ return getHexagonCPUSuffix(Name);
+ }
+
+ bool setCPU(const std::string &Name) override {
+ if (!isValidCPUName(Name))
+ return false;
+ CPU = Name;
+ return true;
+ }
+
+ int getEHDataRegisterNumber(unsigned RegNo) const override {
+ return RegNo < 2 ? RegNo : -1;
+ }
+};
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_HEXAGON_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Lanai.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/Lanai.cpp
new file mode 100644
index 0000000000000..1d8314af99fbe
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Lanai.cpp
@@ -0,0 +1,67 @@
+//===--- Lanai.cpp - Implement Lanai target feature support ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements Lanai TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Lanai.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+const char *const LanaiTargetInfo::GCCRegNames[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
+ "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21",
+ "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
+};
+
+ArrayRef<const char *> LanaiTargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
+}
+
+const TargetInfo::GCCRegAlias LanaiTargetInfo::GCCRegAliases[] = {
+ {{"pc"}, "r2"}, {{"sp"}, "r4"}, {{"fp"}, "r5"}, {{"rv"}, "r8"},
+ {{"rr1"}, "r10"}, {{"rr2"}, "r11"}, {{"rca"}, "r15"},
+};
+
+ArrayRef<TargetInfo::GCCRegAlias> LanaiTargetInfo::getGCCRegAliases() const {
+ return llvm::makeArrayRef(GCCRegAliases);
+}
+
+bool LanaiTargetInfo::isValidCPUName(StringRef Name) const {
+ return llvm::StringSwitch<bool>(Name).Case("v11", true).Default(false);
+}
+
+bool LanaiTargetInfo::setCPU(const std::string &Name) {
+ CPU = llvm::StringSwitch<CPUKind>(Name).Case("v11", CK_V11).Default(CK_NONE);
+
+ return CPU != CK_NONE;
+}
+
+bool LanaiTargetInfo::hasFeature(StringRef Feature) const {
+ return llvm::StringSwitch<bool>(Feature).Case("lanai", true).Default(false);
+}
+
+void LanaiTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ // Define __lanai__ when building for target lanai.
+ Builder.defineMacro("__lanai__");
+
+ // Set define for the CPU specified.
+ switch (CPU) {
+ case CK_V11:
+ Builder.defineMacro("__LANAI_V11__");
+ break;
+ case CK_NONE:
+ llvm_unreachable("Unhandled target CPU");
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Lanai.h b/contrib/llvm/tools/clang/lib/Basic/Targets/Lanai.h
new file mode 100644
index 0000000000000..5f99c17a53447
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Lanai.h
@@ -0,0 +1,92 @@
+//===--- Lanai.h - Declare Lanai target feature support ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares Lanai TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_LANAI_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_LANAI_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY LanaiTargetInfo : public TargetInfo {
+ // Class for Lanai (32-bit).
+ // The CPU profiles supported by the Lanai backend
+ enum CPUKind {
+ CK_NONE,
+ CK_V11,
+ } CPU;
+
+ static const TargetInfo::GCCRegAlias GCCRegAliases[];
+ static const char *const GCCRegNames[];
+
+public:
+ LanaiTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple) {
+ // Description string has to be kept in sync with backend.
+ resetDataLayout("E" // Big endian
+ "-m:e" // ELF name manging
+ "-p:32:32" // 32 bit pointers, 32 bit aligned
+ "-i64:64" // 64 bit integers, 64 bit aligned
+ "-a:0:32" // 32 bit alignment of objects of aggregate type
+ "-n32" // 32 bit native integer width
+ "-S64" // 64 bit natural stack alignment
+ );
+
+ // Setting RegParmMax equal to what mregparm was set to in the old
+ // toolchain
+ RegParmMax = 4;
+
+ // Set the default CPU to V11
+ CPU = CK_V11;
+
+ // Temporary approach to make everything at least word-aligned and allow for
+ // safely casting between pointers with different alignment requirements.
+ // TODO: Remove this when there are no more cast align warnings on the
+ // firmware.
+ MinGlobalAlign = 32;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ bool isValidCPUName(StringRef Name) const override;
+
+ bool setCPU(const std::string &Name) override;
+
+ bool hasFeature(StringRef Feature) const override;
+
+ ArrayRef<const char *> getGCCRegNames() const override;
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::VoidPtrBuiltinVaList;
+ }
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const override {
+ return false;
+ }
+
+ const char *getClobbers() const override { return ""; }
+};
+} // namespace targets
+} // namespace clang
+
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_LANAI_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Le64.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/Le64.cpp
new file mode 100644
index 0000000000000..5a1c1c88e7e3d
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Le64.cpp
@@ -0,0 +1,39 @@
+//===--- Le64.cpp - Implement Le64 target feature support -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements Le64 TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Le64.h"
+#include "Targets.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "clang/Basic/TargetBuiltins.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+const Builtin::Info Le64TargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#include "clang/Basic/BuiltinsLe64.def"
+};
+
+ArrayRef<Builtin::Info> Le64TargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfo, clang::Le64::LastTSBuiltin -
+ Builtin::FirstTSBuiltin);
+}
+
+void Le64TargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "unix", Opts);
+ defineCPUMacros(Builder, "le64", /*Tuning=*/false);
+ Builder.defineMacro("__ELF__");
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Le64.h b/contrib/llvm/tools/clang/lib/Basic/Targets/Le64.h
new file mode 100644
index 0000000000000..5e18d04986415
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Le64.h
@@ -0,0 +1,64 @@
+//===--- Le64.h - Declare Le64 target feature support -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares Le64 TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_LE64_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_LE64_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY Le64TargetInfo : public TargetInfo {
+ static const Builtin::Info BuiltinInfo[];
+
+public:
+ Le64TargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple) {
+ NoAsmVariants = true;
+ LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
+ resetDataLayout("e-m:e-v128:32-v16:16-v32:32-v96:32-n8:16:32:64-S128");
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::PNaClABIBuiltinVaList;
+ }
+
+ const char *getClobbers() const override { return ""; }
+
+ ArrayRef<const char *> getGCCRegNames() const override { return None; }
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ return None;
+ }
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override {
+ return false;
+ }
+
+ bool hasProtectedVisibility() const override { return false; }
+};
+
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_LE64_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/MSP430.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/MSP430.cpp
new file mode 100644
index 0000000000000..86f85a398f142
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/MSP430.cpp
@@ -0,0 +1,34 @@
+//===--- MSP430.cpp - Implement MSP430 target feature support -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements MSP430 TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MSP430.h"
+#include "clang/Basic/MacroBuilder.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+const char *const MSP430TargetInfo::GCCRegNames[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
+};
+
+ArrayRef<const char *> MSP430TargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
+}
+
+void MSP430TargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("MSP430");
+ Builder.defineMacro("__MSP430__");
+ // FIXME: defines for different 'flavours' of MCU
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/MSP430.h b/contrib/llvm/tools/clang/lib/Basic/Targets/MSP430.h
new file mode 100644
index 0000000000000..72aafb9459bdb
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/MSP430.h
@@ -0,0 +1,92 @@
+//===--- MSP430.h - Declare MSP430 target feature support -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares MSP430 TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_MSP430_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_MSP430_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY MSP430TargetInfo : public TargetInfo {
+ static const char *const GCCRegNames[];
+
+public:
+ MSP430TargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple) {
+ TLSSupported = false;
+ IntWidth = 16;
+ IntAlign = 16;
+ LongWidth = 32;
+ LongLongWidth = 64;
+ LongAlign = LongLongAlign = 16;
+ PointerWidth = 16;
+ PointerAlign = 16;
+ SuitableAlign = 16;
+ SizeType = UnsignedInt;
+ IntMaxType = SignedLongLong;
+ IntPtrType = SignedInt;
+ PtrDiffType = SignedInt;
+ SigAtomicType = SignedLong;
+ resetDataLayout("e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16");
+ }
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override {
+ // FIXME: Implement.
+ return None;
+ }
+
+ bool hasFeature(StringRef Feature) const override {
+ return Feature == "msp430";
+ }
+
+ ArrayRef<const char *> getGCCRegNames() const override;
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ // No aliases.
+ return None;
+ }
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const override {
+ // FIXME: implement
+ switch (*Name) {
+ case 'K': // the constant 1
+ case 'L': // constant -1^20 .. 1^19
+ case 'M': // constant 1-4:
+ return true;
+ }
+ // No target constraints for now.
+ return false;
+ }
+
+ const char *getClobbers() const override {
+ // FIXME: Is this really right?
+ return "";
+ }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ // FIXME: implement
+ return TargetInfo::CharPtrBuiltinVaList;
+ }
+};
+
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_MSP430_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Mips.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/Mips.cpp
new file mode 100644
index 0000000000000..a8a1bcc363618
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Mips.cpp
@@ -0,0 +1,252 @@
+//===--- Mips.cpp - Implement Mips target feature support -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements Mips TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Mips.h"
+#include "Targets.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+const Builtin::Info MipsTargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
+ {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
+#include "clang/Basic/BuiltinsMips.def"
+};
+
+bool MipsTargetInfo::processorSupportsGPR64() const {
+ return llvm::StringSwitch<bool>(CPU)
+ .Case("mips3", true)
+ .Case("mips4", true)
+ .Case("mips5", true)
+ .Case("mips64", true)
+ .Case("mips64r2", true)
+ .Case("mips64r3", true)
+ .Case("mips64r5", true)
+ .Case("mips64r6", true)
+ .Case("octeon", true)
+ .Default(false);
+ return false;
+}
+
+bool MipsTargetInfo::isValidCPUName(StringRef Name) const {
+ return llvm::StringSwitch<bool>(Name)
+ .Case("mips1", true)
+ .Case("mips2", true)
+ .Case("mips3", true)
+ .Case("mips4", true)
+ .Case("mips5", true)
+ .Case("mips32", true)
+ .Case("mips32r2", true)
+ .Case("mips32r3", true)
+ .Case("mips32r5", true)
+ .Case("mips32r6", true)
+ .Case("mips64", true)
+ .Case("mips64r2", true)
+ .Case("mips64r3", true)
+ .Case("mips64r5", true)
+ .Case("mips64r6", true)
+ .Case("octeon", true)
+ .Case("p5600", true)
+ .Default(false);
+}
+
+void MipsTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ if (BigEndian) {
+ DefineStd(Builder, "MIPSEB", Opts);
+ Builder.defineMacro("_MIPSEB");
+ } else {
+ DefineStd(Builder, "MIPSEL", Opts);
+ Builder.defineMacro("_MIPSEL");
+ }
+
+ Builder.defineMacro("__mips__");
+ Builder.defineMacro("_mips");
+ if (Opts.GNUMode)
+ Builder.defineMacro("mips");
+
+ if (ABI == "o32") {
+ Builder.defineMacro("__mips", "32");
+ Builder.defineMacro("_MIPS_ISA", "_MIPS_ISA_MIPS32");
+ } else {
+ Builder.defineMacro("__mips", "64");
+ Builder.defineMacro("__mips64");
+ Builder.defineMacro("__mips64__");
+ Builder.defineMacro("_MIPS_ISA", "_MIPS_ISA_MIPS64");
+ }
+
+ const std::string ISARev = llvm::StringSwitch<std::string>(getCPU())
+ .Cases("mips32", "mips64", "1")
+ .Cases("mips32r2", "mips64r2", "2")
+ .Cases("mips32r3", "mips64r3", "3")
+ .Cases("mips32r5", "mips64r5", "5")
+ .Cases("mips32r6", "mips64r6", "6")
+ .Default("");
+ if (!ISARev.empty())
+ Builder.defineMacro("__mips_isa_rev", ISARev);
+
+ if (ABI == "o32") {
+ Builder.defineMacro("__mips_o32");
+ Builder.defineMacro("_ABIO32", "1");
+ Builder.defineMacro("_MIPS_SIM", "_ABIO32");
+ } else if (ABI == "n32") {
+ Builder.defineMacro("__mips_n32");
+ Builder.defineMacro("_ABIN32", "2");
+ Builder.defineMacro("_MIPS_SIM", "_ABIN32");
+ } else if (ABI == "n64") {
+ Builder.defineMacro("__mips_n64");
+ Builder.defineMacro("_ABI64", "3");
+ Builder.defineMacro("_MIPS_SIM", "_ABI64");
+ } else
+ llvm_unreachable("Invalid ABI.");
+
+ if (!IsNoABICalls) {
+ Builder.defineMacro("__mips_abicalls");
+ if (CanUseBSDABICalls)
+ Builder.defineMacro("__ABICALLS__");
+ }
+
+ Builder.defineMacro("__REGISTER_PREFIX__", "");
+
+ switch (FloatABI) {
+ case HardFloat:
+ Builder.defineMacro("__mips_hard_float", Twine(1));
+ break;
+ case SoftFloat:
+ Builder.defineMacro("__mips_soft_float", Twine(1));
+ break;
+ }
+
+ if (IsSingleFloat)
+ Builder.defineMacro("__mips_single_float", Twine(1));
+
+ Builder.defineMacro("__mips_fpr", HasFP64 ? Twine(64) : Twine(32));
+ Builder.defineMacro("_MIPS_FPSET",
+ Twine(32 / (HasFP64 || IsSingleFloat ? 1 : 2)));
+
+ if (IsMips16)
+ Builder.defineMacro("__mips16", Twine(1));
+
+ if (IsMicromips)
+ Builder.defineMacro("__mips_micromips", Twine(1));
+
+ if (IsNan2008)
+ Builder.defineMacro("__mips_nan2008", Twine(1));
+
+ if (IsAbs2008)
+ Builder.defineMacro("__mips_abs2008", Twine(1));
+
+ switch (DspRev) {
+ default:
+ break;
+ case DSP1:
+ Builder.defineMacro("__mips_dsp_rev", Twine(1));
+ Builder.defineMacro("__mips_dsp", Twine(1));
+ break;
+ case DSP2:
+ Builder.defineMacro("__mips_dsp_rev", Twine(2));
+ Builder.defineMacro("__mips_dspr2", Twine(1));
+ Builder.defineMacro("__mips_dsp", Twine(1));
+ break;
+ }
+
+ if (HasMSA)
+ Builder.defineMacro("__mips_msa", Twine(1));
+
+ if (DisableMadd4)
+ Builder.defineMacro("__mips_no_madd4", Twine(1));
+
+ Builder.defineMacro("_MIPS_SZPTR", Twine(getPointerWidth(0)));
+ Builder.defineMacro("_MIPS_SZINT", Twine(getIntWidth()));
+ Builder.defineMacro("_MIPS_SZLONG", Twine(getLongWidth()));
+
+ Builder.defineMacro("_MIPS_ARCH", "\"" + CPU + "\"");
+ Builder.defineMacro("_MIPS_ARCH_" + StringRef(CPU).upper());
+
+ // These shouldn't be defined for MIPS-I but there's no need to check
+ // for that since MIPS-I isn't supported.
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
+
+ // 32-bit MIPS processors don't have the necessary lld/scd instructions
+ // found in 64-bit processors. In the case of O32 on a 64-bit processor,
+ // the instructions exist but using them violates the ABI since they
+ // require 64-bit GPRs and O32 only supports 32-bit GPRs.
+ if (ABI == "n32" || ABI == "n64")
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
+}
+
+bool MipsTargetInfo::hasFeature(StringRef Feature) const {
+ return llvm::StringSwitch<bool>(Feature)
+ .Case("mips", true)
+ .Case("fp64", HasFP64)
+ .Default(false);
+}
+
+ArrayRef<Builtin::Info> MipsTargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfo, clang::Mips::LastTSBuiltin -
+ Builtin::FirstTSBuiltin);
+}
+
+bool MipsTargetInfo::validateTarget(DiagnosticsEngine &Diags) const {
+ // microMIPS64R6 backend was removed.
+ if ((getTriple().getArch() == llvm::Triple::mips64 ||
+ getTriple().getArch() == llvm::Triple::mips64el) &&
+ IsMicromips && (ABI == "n32" || ABI == "n64")) {
+ Diags.Report(diag::err_target_unsupported_cpu_for_micromips) << CPU;
+ return false;
+ }
+ // FIXME: It's valid to use O32 on a 64-bit CPU but the backend can't handle
+ // this yet. It's better to fail here than on the backend assertion.
+ if (processorSupportsGPR64() && ABI == "o32") {
+ Diags.Report(diag::err_target_unsupported_abi) << ABI << CPU;
+ return false;
+ }
+
+ // 64-bit ABI's require 64-bit CPU's.
+ if (!processorSupportsGPR64() && (ABI == "n32" || ABI == "n64")) {
+ Diags.Report(diag::err_target_unsupported_abi) << ABI << CPU;
+ return false;
+ }
+
+ // FIXME: It's valid to use O32 on a mips64/mips64el triple but the backend
+ // can't handle this yet. It's better to fail here than on the
+ // backend assertion.
+ if ((getTriple().getArch() == llvm::Triple::mips64 ||
+ getTriple().getArch() == llvm::Triple::mips64el) &&
+ ABI == "o32") {
+ Diags.Report(diag::err_target_unsupported_abi_for_triple)
+ << ABI << getTriple().str();
+ return false;
+ }
+
+ // FIXME: It's valid to use N32/N64 on a mips/mipsel triple but the backend
+ // can't handle this yet. It's better to fail here than on the
+ // backend assertion.
+ if ((getTriple().getArch() == llvm::Triple::mips ||
+ getTriple().getArch() == llvm::Triple::mipsel) &&
+ (ABI == "n32" || ABI == "n64")) {
+ Diags.Report(diag::err_target_unsupported_abi_for_triple)
+ << ABI << getTriple().str();
+ return false;
+ }
+
+ return true;
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Mips.h b/contrib/llvm/tools/clang/lib/Basic/Targets/Mips.h
new file mode 100644
index 0000000000000..28900f21f86ba
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Mips.h
@@ -0,0 +1,397 @@
+//===--- Mips.h - Declare Mips target feature support -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares Mips TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo {
+ void setDataLayout() {
+ StringRef Layout;
+
+ if (ABI == "o32")
+ Layout = "m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64";
+ else if (ABI == "n32")
+ Layout = "m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32:64-S128";
+ else if (ABI == "n64")
+ Layout = "m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128";
+ else
+ llvm_unreachable("Invalid ABI");
+
+ if (BigEndian)
+ resetDataLayout(("E-" + Layout).str());
+ else
+ resetDataLayout(("e-" + Layout).str());
+ }
+
+ static const Builtin::Info BuiltinInfo[];
+ std::string CPU;
+ bool IsMips16;
+ bool IsMicromips;
+ bool IsNan2008;
+ bool IsAbs2008;
+ bool IsSingleFloat;
+ bool IsNoABICalls;
+ bool CanUseBSDABICalls;
+ enum MipsFloatABI { HardFloat, SoftFloat } FloatABI;
+ enum DspRevEnum { NoDSP, DSP1, DSP2 } DspRev;
+ bool HasMSA;
+ bool DisableMadd4;
+
+protected:
+ bool HasFP64;
+ std::string ABI;
+
+public:
+ MipsTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple), IsMips16(false), IsMicromips(false),
+ IsNan2008(false), IsAbs2008(false), IsSingleFloat(false),
+ IsNoABICalls(false), CanUseBSDABICalls(false), FloatABI(HardFloat),
+ DspRev(NoDSP), HasMSA(false), DisableMadd4(false), HasFP64(false) {
+ TheCXXABI.set(TargetCXXABI::GenericMIPS);
+
+ setABI((getTriple().getArch() == llvm::Triple::mips ||
+ getTriple().getArch() == llvm::Triple::mipsel)
+ ? "o32"
+ : "n64");
+
+ CPU = ABI == "o32" ? "mips32r2" : "mips64r2";
+
+ CanUseBSDABICalls = Triple.getOS() == llvm::Triple::FreeBSD ||
+ Triple.getOS() == llvm::Triple::OpenBSD;
+ }
+
+ bool isIEEE754_2008Default() const {
+ return CPU == "mips32r6" || CPU == "mips64r6";
+ }
+
+ bool isFP64Default() const {
+ return CPU == "mips32r6" || ABI == "n32" || ABI == "n64" || ABI == "64";
+ }
+
+ bool isNan2008() const override { return IsNan2008; }
+
+ bool processorSupportsGPR64() const;
+
+ StringRef getABI() const override { return ABI; }
+
+ bool setABI(const std::string &Name) override {
+ if (Name == "o32") {
+ setO32ABITypes();
+ ABI = Name;
+ return true;
+ }
+
+ if (Name == "n32") {
+ setN32ABITypes();
+ ABI = Name;
+ return true;
+ }
+ if (Name == "n64") {
+ setN64ABITypes();
+ ABI = Name;
+ return true;
+ }
+ return false;
+ }
+
+ void setO32ABITypes() {
+ Int64Type = SignedLongLong;
+ IntMaxType = Int64Type;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
+ LongDoubleWidth = LongDoubleAlign = 64;
+ LongWidth = LongAlign = 32;
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;
+ PointerWidth = PointerAlign = 32;
+ PtrDiffType = SignedInt;
+ SizeType = UnsignedInt;
+ SuitableAlign = 64;
+ }
+
+ void setN32N64ABITypes() {
+ LongDoubleWidth = LongDoubleAlign = 128;
+ LongDoubleFormat = &llvm::APFloat::IEEEquad();
+ if (getTriple().getOS() == llvm::Triple::FreeBSD) {
+ LongDoubleWidth = LongDoubleAlign = 64;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
+ }
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
+ SuitableAlign = 128;
+ }
+
+ void setN64ABITypes() {
+ setN32N64ABITypes();
+ if (getTriple().getOS() == llvm::Triple::OpenBSD) {
+ Int64Type = SignedLongLong;
+ } else {
+ Int64Type = SignedLong;
+ }
+ IntMaxType = Int64Type;
+ LongWidth = LongAlign = 64;
+ PointerWidth = PointerAlign = 64;
+ PtrDiffType = SignedLong;
+ SizeType = UnsignedLong;
+ }
+
+ void setN32ABITypes() {
+ setN32N64ABITypes();
+ Int64Type = SignedLongLong;
+ IntMaxType = Int64Type;
+ LongWidth = LongAlign = 32;
+ PointerWidth = PointerAlign = 32;
+ PtrDiffType = SignedInt;
+ SizeType = UnsignedInt;
+ }
+
+ bool isValidCPUName(StringRef Name) const override;
+
+ bool setCPU(const std::string &Name) override {
+ CPU = Name;
+ return isValidCPUName(Name);
+ }
+
+ const std::string &getCPU() const { return CPU; }
+ bool
+ initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
+ StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const override {
+ if (CPU.empty())
+ CPU = getCPU();
+ if (CPU == "octeon")
+ Features["mips64r2"] = Features["cnmips"] = true;
+ else
+ Features[CPU] = true;
+ return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+
+ bool hasFeature(StringRef Feature) const override;
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::VoidPtrBuiltinVaList;
+ }
+
+ ArrayRef<const char *> getGCCRegNames() const override {
+ static const char *const GCCRegNames[] = {
+ // CPU register names
+ // Must match second column of GCCRegAliases
+ "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10",
+ "$11", "$12", "$13", "$14", "$15", "$16", "$17", "$18", "$19", "$20",
+ "$21", "$22", "$23", "$24", "$25", "$26", "$27", "$28", "$29", "$30",
+ "$31",
+ // Floating point register names
+ "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", "$f9",
+ "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", "$f16", "$f17", "$f18",
+ "$f19", "$f20", "$f21", "$f22", "$f23", "$f24", "$f25", "$f26", "$f27",
+ "$f28", "$f29", "$f30", "$f31",
+ // Hi/lo and condition register names
+ "hi", "lo", "", "$fcc0", "$fcc1", "$fcc2", "$fcc3", "$fcc4", "$fcc5",
+ "$fcc6", "$fcc7", "$ac1hi", "$ac1lo", "$ac2hi", "$ac2lo", "$ac3hi",
+ "$ac3lo",
+ // MSA register names
+ "$w0", "$w1", "$w2", "$w3", "$w4", "$w5", "$w6", "$w7", "$w8", "$w9",
+ "$w10", "$w11", "$w12", "$w13", "$w14", "$w15", "$w16", "$w17", "$w18",
+ "$w19", "$w20", "$w21", "$w22", "$w23", "$w24", "$w25", "$w26", "$w27",
+ "$w28", "$w29", "$w30", "$w31",
+ // MSA control register names
+ "$msair", "$msacsr", "$msaaccess", "$msasave", "$msamodify",
+ "$msarequest", "$msamap", "$msaunmap"
+ };
+ return llvm::makeArrayRef(GCCRegNames);
+ }
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override {
+ switch (*Name) {
+ default:
+ return false;
+ case 'r': // CPU registers.
+ case 'd': // Equivalent to "r" unless generating MIPS16 code.
+ case 'y': // Equivalent to "r", backward compatibility only.
+ case 'f': // floating-point registers.
+ case 'c': // $25 for indirect jumps
+ case 'l': // lo register
+ case 'x': // hilo register pair
+ Info.setAllowsRegister();
+ return true;
+ case 'I': // Signed 16-bit constant
+ case 'J': // Integer 0
+ case 'K': // Unsigned 16-bit constant
+ case 'L': // Signed 32-bit constant, lower 16-bit zeros (for lui)
+ case 'M': // Constants not loadable via lui, addiu, or ori
+ case 'N': // Constant -1 to -65535
+ case 'O': // A signed 15-bit constant
+ case 'P': // A constant between 1 go 65535
+ return true;
+ case 'R': // An address that can be used in a non-macro load or store
+ Info.setAllowsMemory();
+ return true;
+ case 'Z':
+ if (Name[1] == 'C') { // An address usable by ll, and sc.
+ Info.setAllowsMemory();
+ Name++; // Skip over 'Z'.
+ return true;
+ }
+ return false;
+ }
+ }
+
+ std::string convertConstraint(const char *&Constraint) const override {
+ std::string R;
+ switch (*Constraint) {
+ case 'Z': // Two-character constraint; add "^" hint for later parsing.
+ if (Constraint[1] == 'C') {
+ R = std::string("^") + std::string(Constraint, 2);
+ Constraint++;
+ return R;
+ }
+ break;
+ }
+ return TargetInfo::convertConstraint(Constraint);
+ }
+
+ const char *getClobbers() const override {
+ // In GCC, $1 is not widely used in generated code (it's used only in a few
+ // specific situations), so there is no real need for users to add it to
+ // the clobbers list if they want to use it in their inline assembly code.
+ //
+ // In LLVM, $1 is treated as a normal GPR and is always allocatable during
+ // code generation, so using it in inline assembly without adding it to the
+ // clobbers list can cause conflicts between the inline assembly code and
+ // the surrounding generated code.
+ //
+ // Another problem is that LLVM is allowed to choose $1 for inline assembly
+ // operands, which will conflict with the ".set at" assembler option (which
+ // we use only for inline assembly, in order to maintain compatibility with
+ // GCC) and will also conflict with the user's usage of $1.
+ //
+ // The easiest way to avoid these conflicts and keep $1 as an allocatable
+ // register for generated code is to automatically clobber $1 for all inline
+ // assembly code.
+ //
+ // FIXME: We should automatically clobber $1 only for inline assembly code
+ // which actually uses it. This would allow LLVM to use $1 for inline
+ // assembly operands if the user's assembly code doesn't use it.
+ return "~{$1}";
+ }
+
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) override {
+ IsMips16 = false;
+ IsMicromips = false;
+ IsNan2008 = isIEEE754_2008Default();
+ IsAbs2008 = isIEEE754_2008Default();
+ IsSingleFloat = false;
+ FloatABI = HardFloat;
+ DspRev = NoDSP;
+ HasFP64 = isFP64Default();
+
+ for (const auto &Feature : Features) {
+ if (Feature == "+single-float")
+ IsSingleFloat = true;
+ else if (Feature == "+soft-float")
+ FloatABI = SoftFloat;
+ else if (Feature == "+mips16")
+ IsMips16 = true;
+ else if (Feature == "+micromips")
+ IsMicromips = true;
+ else if (Feature == "+dsp")
+ DspRev = std::max(DspRev, DSP1);
+ else if (Feature == "+dspr2")
+ DspRev = std::max(DspRev, DSP2);
+ else if (Feature == "+msa")
+ HasMSA = true;
+ else if (Feature == "+nomadd4")
+ DisableMadd4 = true;
+ else if (Feature == "+fp64")
+ HasFP64 = true;
+ else if (Feature == "-fp64")
+ HasFP64 = false;
+ else if (Feature == "+nan2008")
+ IsNan2008 = true;
+ else if (Feature == "-nan2008")
+ IsNan2008 = false;
+ else if (Feature == "+abs2008")
+ IsAbs2008 = true;
+ else if (Feature == "-abs2008")
+ IsAbs2008 = false;
+ else if (Feature == "+noabicalls")
+ IsNoABICalls = true;
+ }
+
+ setDataLayout();
+
+ return true;
+ }
+
+ int getEHDataRegisterNumber(unsigned RegNo) const override {
+ if (RegNo == 0)
+ return 4;
+ if (RegNo == 1)
+ return 5;
+ return -1;
+ }
+
+ bool isCLZForZeroUndef() const override { return false; }
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ static const TargetInfo::GCCRegAlias O32RegAliases[] = {
+ {{"at"}, "$1"}, {{"v0"}, "$2"}, {{"v1"}, "$3"},
+ {{"a0"}, "$4"}, {{"a1"}, "$5"}, {{"a2"}, "$6"},
+ {{"a3"}, "$7"}, {{"t0"}, "$8"}, {{"t1"}, "$9"},
+ {{"t2"}, "$10"}, {{"t3"}, "$11"}, {{"t4"}, "$12"},
+ {{"t5"}, "$13"}, {{"t6"}, "$14"}, {{"t7"}, "$15"},
+ {{"s0"}, "$16"}, {{"s1"}, "$17"}, {{"s2"}, "$18"},
+ {{"s3"}, "$19"}, {{"s4"}, "$20"}, {{"s5"}, "$21"},
+ {{"s6"}, "$22"}, {{"s7"}, "$23"}, {{"t8"}, "$24"},
+ {{"t9"}, "$25"}, {{"k0"}, "$26"}, {{"k1"}, "$27"},
+ {{"gp"}, "$28"}, {{"sp", "$sp"}, "$29"}, {{"fp", "$fp"}, "$30"},
+ {{"ra"}, "$31"}
+ };
+ static const TargetInfo::GCCRegAlias NewABIRegAliases[] = {
+ {{"at"}, "$1"}, {{"v0"}, "$2"}, {{"v1"}, "$3"},
+ {{"a0"}, "$4"}, {{"a1"}, "$5"}, {{"a2"}, "$6"},
+ {{"a3"}, "$7"}, {{"a4"}, "$8"}, {{"a5"}, "$9"},
+ {{"a6"}, "$10"}, {{"a7"}, "$11"}, {{"t0"}, "$12"},
+ {{"t1"}, "$13"}, {{"t2"}, "$14"}, {{"t3"}, "$15"},
+ {{"s0"}, "$16"}, {{"s1"}, "$17"}, {{"s2"}, "$18"},
+ {{"s3"}, "$19"}, {{"s4"}, "$20"}, {{"s5"}, "$21"},
+ {{"s6"}, "$22"}, {{"s7"}, "$23"}, {{"t8"}, "$24"},
+ {{"t9"}, "$25"}, {{"k0"}, "$26"}, {{"k1"}, "$27"},
+ {{"gp"}, "$28"}, {{"sp", "$sp"}, "$29"}, {{"fp", "$fp"}, "$30"},
+ {{"ra"}, "$31"}
+ };
+ if (ABI == "o32")
+ return llvm::makeArrayRef(O32RegAliases);
+ return llvm::makeArrayRef(NewABIRegAliases);
+ }
+
+ bool hasInt128Type() const override { return ABI == "n32" || ABI == "n64"; }
+
+ bool validateTarget(DiagnosticsEngine &Diags) const override;
+};
+} // namespace targets
+} // namespace clang
+
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/NVPTX.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/NVPTX.cpp
new file mode 100644
index 0000000000000..add3b318aeb6d
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/NVPTX.cpp
@@ -0,0 +1,199 @@
+//===--- NVPTX.cpp - Implement NVPTX target feature support ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements NVPTX TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "NVPTX.h"
+#include "Targets.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+const Builtin::Info NVPTXTargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
+ {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
+#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
+#include "clang/Basic/BuiltinsNVPTX.def"
+};
+
+const char *const NVPTXTargetInfo::GCCRegNames[] = {"r0"};
+
+NVPTXTargetInfo::NVPTXTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts,
+ unsigned TargetPointerWidth)
+ : TargetInfo(Triple) {
+ assert((TargetPointerWidth == 32 || TargetPointerWidth == 64) &&
+ "NVPTX only supports 32- and 64-bit modes.");
+
+ TLSSupported = false;
+ VLASupported = false;
+ AddrSpaceMap = &NVPTXAddrSpaceMap;
+ UseAddrSpaceMapMangling = true;
+
+ // Define available target features
+ // These must be defined in sorted order!
+ NoAsmVariants = true;
+ GPU = CudaArch::SM_20;
+
+ if (TargetPointerWidth == 32)
+ resetDataLayout("e-p:32:32-i64:64-i128:128-v16:16-v32:32-n16:32:64");
+ else
+ resetDataLayout("e-i64:64-i128:128-v16:16-v32:32-n16:32:64");
+
+ // If possible, get a TargetInfo for our host triple, so we can match its
+ // types.
+ llvm::Triple HostTriple(Opts.HostTriple);
+ if (!HostTriple.isNVPTX())
+ HostTarget.reset(AllocateTarget(llvm::Triple(Opts.HostTriple), Opts));
+
+ // If no host target, make some guesses about the data layout and return.
+ if (!HostTarget) {
+ LongWidth = LongAlign = TargetPointerWidth;
+ PointerWidth = PointerAlign = TargetPointerWidth;
+ switch (TargetPointerWidth) {
+ case 32:
+ SizeType = TargetInfo::UnsignedInt;
+ PtrDiffType = TargetInfo::SignedInt;
+ IntPtrType = TargetInfo::SignedInt;
+ break;
+ case 64:
+ SizeType = TargetInfo::UnsignedLong;
+ PtrDiffType = TargetInfo::SignedLong;
+ IntPtrType = TargetInfo::SignedLong;
+ break;
+ default:
+ llvm_unreachable("TargetPointerWidth must be 32 or 64");
+ }
+ return;
+ }
+
+ // Copy properties from host target.
+ PointerWidth = HostTarget->getPointerWidth(/* AddrSpace = */ 0);
+ PointerAlign = HostTarget->getPointerAlign(/* AddrSpace = */ 0);
+ BoolWidth = HostTarget->getBoolWidth();
+ BoolAlign = HostTarget->getBoolAlign();
+ IntWidth = HostTarget->getIntWidth();
+ IntAlign = HostTarget->getIntAlign();
+ HalfWidth = HostTarget->getHalfWidth();
+ HalfAlign = HostTarget->getHalfAlign();
+ FloatWidth = HostTarget->getFloatWidth();
+ FloatAlign = HostTarget->getFloatAlign();
+ DoubleWidth = HostTarget->getDoubleWidth();
+ DoubleAlign = HostTarget->getDoubleAlign();
+ LongWidth = HostTarget->getLongWidth();
+ LongAlign = HostTarget->getLongAlign();
+ LongLongWidth = HostTarget->getLongLongWidth();
+ LongLongAlign = HostTarget->getLongLongAlign();
+ MinGlobalAlign = HostTarget->getMinGlobalAlign();
+ NewAlign = HostTarget->getNewAlign();
+ DefaultAlignForAttributeAligned =
+ HostTarget->getDefaultAlignForAttributeAligned();
+ SizeType = HostTarget->getSizeType();
+ IntMaxType = HostTarget->getIntMaxType();
+ PtrDiffType = HostTarget->getPtrDiffType(/* AddrSpace = */ 0);
+ IntPtrType = HostTarget->getIntPtrType();
+ WCharType = HostTarget->getWCharType();
+ WIntType = HostTarget->getWIntType();
+ Char16Type = HostTarget->getChar16Type();
+ Char32Type = HostTarget->getChar32Type();
+ Int64Type = HostTarget->getInt64Type();
+ SigAtomicType = HostTarget->getSigAtomicType();
+ ProcessIDType = HostTarget->getProcessIDType();
+
+ UseBitFieldTypeAlignment = HostTarget->useBitFieldTypeAlignment();
+ UseZeroLengthBitfieldAlignment = HostTarget->useZeroLengthBitfieldAlignment();
+ UseExplicitBitFieldAlignment = HostTarget->useExplicitBitFieldAlignment();
+ ZeroLengthBitfieldBoundary = HostTarget->getZeroLengthBitfieldBoundary();
+
+ // This is a bit of a lie, but it controls __GCC_ATOMIC_XXX_LOCK_FREE, and
+ // we need those macros to be identical on host and device, because (among
+ // other things) they affect which standard library classes are defined, and
+ // we need all classes to be defined on both the host and device.
+ MaxAtomicInlineWidth = HostTarget->getMaxAtomicInlineWidth();
+
+ // Properties intentionally not copied from host:
+ // - LargeArrayMinWidth, LargeArrayAlign: Not visible across the
+ // host/device boundary.
+ // - SuitableAlign: Not visible across the host/device boundary, and may
+ // correctly be different on host/device, e.g. if host has wider vector
+ // types than device.
+ // - LongDoubleWidth, LongDoubleAlign: nvptx's long double type is the same
+ // as its double type, but that's not necessarily true on the host.
+ // TODO: nvcc emits a warning when using long double on device; we should
+ // do the same.
+}
+
+ArrayRef<const char *> NVPTXTargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
+}
+
+bool NVPTXTargetInfo::hasFeature(StringRef Feature) const {
+ return llvm::StringSwitch<bool>(Feature)
+ .Cases("ptx", "nvptx", true)
+ .Case("satom", GPU >= CudaArch::SM_60) // Atomics w/ scope.
+ .Default(false);
+}
+
+void NVPTXTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__PTX__");
+ Builder.defineMacro("__NVPTX__");
+ if (Opts.CUDAIsDevice) {
+ // Set __CUDA_ARCH__ for the GPU specified.
+ std::string CUDAArchCode = [this] {
+ switch (GPU) {
+ case CudaArch::UNKNOWN:
+ assert(false && "No GPU arch when compiling CUDA device code.");
+ return "";
+ case CudaArch::SM_20:
+ return "200";
+ case CudaArch::SM_21:
+ return "210";
+ case CudaArch::SM_30:
+ return "300";
+ case CudaArch::SM_32:
+ return "320";
+ case CudaArch::SM_35:
+ return "350";
+ case CudaArch::SM_37:
+ return "370";
+ case CudaArch::SM_50:
+ return "500";
+ case CudaArch::SM_52:
+ return "520";
+ case CudaArch::SM_53:
+ return "530";
+ case CudaArch::SM_60:
+ return "600";
+ case CudaArch::SM_61:
+ return "610";
+ case CudaArch::SM_62:
+ return "620";
+ case CudaArch::SM_70:
+ return "700";
+ }
+ llvm_unreachable("unhandled CudaArch");
+ }();
+ Builder.defineMacro("__CUDA_ARCH__", CUDAArchCode);
+ }
+}
+
+ArrayRef<Builtin::Info> NVPTXTargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfo, clang::NVPTX::LastTSBuiltin -
+ Builtin::FirstTSBuiltin);
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/NVPTX.h b/contrib/llvm/tools/clang/lib/Basic/Targets/NVPTX.h
new file mode 100644
index 0000000000000..a84870763f545
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/NVPTX.h
@@ -0,0 +1,132 @@
+//===--- NVPTX.h - Declare NVPTX target feature support ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares NVPTX TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_NVPTX_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_NVPTX_H
+
+#include "clang/Basic/Cuda.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+static const unsigned NVPTXAddrSpaceMap[] = {
+ 0, // Default
+ 1, // opencl_global
+ 3, // opencl_local
+ 4, // opencl_constant
+ 0, // opencl_private
+ // FIXME: generic has to be added to the target
+ 0, // opencl_generic
+ 1, // cuda_device
+ 4, // cuda_constant
+ 3, // cuda_shared
+};
+
+class LLVM_LIBRARY_VISIBILITY NVPTXTargetInfo : public TargetInfo {
+ static const char *const GCCRegNames[];
+ static const Builtin::Info BuiltinInfo[];
+ CudaArch GPU;
+ std::unique_ptr<TargetInfo> HostTarget;
+
+public:
+ NVPTXTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts,
+ unsigned TargetPointerWidth);
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+
+ bool
+ initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
+ StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const override {
+ Features["satom"] = GPU >= CudaArch::SM_60;
+ return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
+ }
+
+ bool hasFeature(StringRef Feature) const override;
+
+ ArrayRef<const char *> getGCCRegNames() const override;
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ // No aliases.
+ return None;
+ }
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override {
+ switch (*Name) {
+ default:
+ return false;
+ case 'c':
+ case 'h':
+ case 'r':
+ case 'l':
+ case 'f':
+ case 'd':
+ Info.setAllowsRegister();
+ return true;
+ }
+ }
+
+ const char *getClobbers() const override {
+ // FIXME: Is this really right?
+ return "";
+ }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ // FIXME: implement
+ return TargetInfo::CharPtrBuiltinVaList;
+ }
+
+ bool isValidCPUName(StringRef Name) const override {
+ return StringToCudaArch(Name) != CudaArch::UNKNOWN;
+ }
+
+ bool setCPU(const std::string &Name) override {
+ GPU = StringToCudaArch(Name);
+ return GPU != CudaArch::UNKNOWN;
+ }
+
+ void setSupportedOpenCLOpts() override {
+ auto &Opts = getSupportedOpenCLOpts();
+ Opts.support("cl_clang_storage_class_specifiers");
+ Opts.support("cl_khr_gl_sharing");
+ Opts.support("cl_khr_icd");
+
+ Opts.support("cl_khr_fp64");
+ Opts.support("cl_khr_byte_addressable_store");
+ Opts.support("cl_khr_global_int32_base_atomics");
+ Opts.support("cl_khr_global_int32_extended_atomics");
+ Opts.support("cl_khr_local_int32_base_atomics");
+ Opts.support("cl_khr_local_int32_extended_atomics");
+ }
+
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
+ // CUDA compilations support all of the host's calling conventions.
+ //
+ // TODO: We should warn if you apply a non-default CC to anything other than
+ // a host function.
+ if (HostTarget)
+ return HostTarget->checkCallingConvention(CC);
+ return CCCR_Warning;
+ }
+};
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_NVPTX_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Nios2.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/Nios2.cpp
new file mode 100644
index 0000000000000..48f662dd98c1d
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Nios2.cpp
@@ -0,0 +1,56 @@
+//===--- Nios2.cpp - Implement Nios2 target feature support ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements Nios2 TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Nios2.h"
+#include "Targets.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+const Builtin::Info Nios2TargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
+#include "clang/Basic/BuiltinsNios2.def"
+};
+
+bool Nios2TargetInfo::isFeatureSupportedByCPU(StringRef Feature,
+ StringRef CPU) const {
+ const bool isR2 = CPU == "nios2r2";
+ return llvm::StringSwitch<bool>(Feature)
+ .Case("nios2r2mandatory", isR2)
+ .Case("nios2r2bmx", isR2)
+ .Case("nios2r2mpx", isR2)
+ .Case("nios2r2cdx", isR2)
+ .Default(false);
+}
+
+void Nios2TargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "nios2", Opts);
+ DefineStd(Builder, "NIOS2", Opts);
+
+ Builder.defineMacro("__nios2");
+ Builder.defineMacro("__NIOS2");
+ Builder.defineMacro("__nios2__");
+ Builder.defineMacro("__NIOS2__");
+}
+
+ArrayRef<Builtin::Info> Nios2TargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfo, clang::Nios2::LastTSBuiltin -
+ Builtin::FirstTSBuiltin);
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Nios2.h b/contrib/llvm/tools/clang/lib/Basic/Targets/Nios2.h
new file mode 100644
index 0000000000000..aa02f8f6262fe
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Nios2.h
@@ -0,0 +1,147 @@
+//===--- Nios2.h - Declare Nios2 target feature support ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares Nios2 TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_NIOS2_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_NIOS2_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY Nios2TargetInfo : public TargetInfo {
+ void setDataLayout() {
+ if (BigEndian)
+ resetDataLayout("E-p:32:32:32-i8:8:32-i16:16:32-n32");
+ else
+ resetDataLayout("e-p:32:32:32-i8:8:32-i16:16:32-n32");
+ }
+
+ static const Builtin::Info BuiltinInfo[];
+ std::string CPU;
+ std::string ABI;
+
+public:
+ Nios2TargetInfo(const llvm::Triple &triple, const TargetOptions &opts)
+ : TargetInfo(triple), CPU(opts.CPU), ABI(opts.ABI) {
+ SizeType = UnsignedInt;
+ PtrDiffType = SignedInt;
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;
+ setDataLayout();
+ }
+
+ StringRef getABI() const override { return ABI; }
+ bool setABI(const std::string &Name) override {
+ if (Name == "o32" || Name == "eabi") {
+ ABI = Name;
+ return true;
+ }
+ return false;
+ }
+
+ bool isValidCPUName(StringRef Name) const override {
+ return Name == "nios2r1" || Name == "nios2r2";
+ }
+
+ bool setCPU(const std::string &Name) override {
+ if (isValidCPUName(Name)) {
+ CPU = Name;
+ return true;
+ }
+ return false;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+
+ bool isFeatureSupportedByCPU(StringRef Feature, StringRef CPU) const;
+
+ bool
+ initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
+ StringRef CPU,
+ const std::vector<std::string> &FeatureVec) const override {
+ static const char *allFeatures[] = {"nios2r2mandatory", "nios2r2bmx",
+ "nios2r2mpx", "nios2r2cdx"
+ };
+ for (const char *feature : allFeatures) {
+ Features[feature] = isFeatureSupportedByCPU(feature, CPU);
+ }
+ return true;
+ }
+
+ bool hasFeature(StringRef Feature) const override {
+ return isFeatureSupportedByCPU(Feature, CPU);
+ }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::VoidPtrBuiltinVaList;
+ }
+
+ ArrayRef<const char *> getGCCRegNames() const override {
+ static const char *const GCCRegNames[] = {
+ // CPU register names
+ // Must match second column of GCCRegAliases
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
+ "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20",
+ "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30",
+ "r31",
+ // Floating point register names
+ "ctl0", "ctl1", "ctl2", "ctl3", "ctl4", "ctl5", "ctl6", "ctl7", "ctl8",
+ "ctl9", "ctl10", "ctl11", "ctl12", "ctl13", "ctl14", "ctl15"
+ };
+ return llvm::makeArrayRef(GCCRegNames);
+ }
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override {
+ switch (*Name) {
+ default:
+ return false;
+
+ case 'r': // CPU registers.
+ case 'd': // Equivalent to "r" unless generating MIPS16 code.
+ case 'y': // Equivalent to "r", backwards compatibility only.
+ case 'f': // floating-point registers.
+ case 'c': // $25 for indirect jumps
+ case 'l': // lo register
+ case 'x': // hilo register pair
+ Info.setAllowsRegister();
+ return true;
+ }
+ }
+
+ const char *getClobbers() const override { return ""; }
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ static const TargetInfo::GCCRegAlias aliases[] = {
+ {{"zero"}, "r0"}, {{"at"}, "r1"}, {{"et"}, "r24"},
+ {{"bt"}, "r25"}, {{"gp"}, "r26"}, {{"sp"}, "r27"},
+ {{"fp"}, "r28"}, {{"ea"}, "r29"}, {{"ba"}, "r30"},
+ {{"ra"}, "r31"}, {{"status"}, "ctl0"}, {{"estatus"}, "ctl1"},
+ {{"bstatus"}, "ctl2"}, {{"ienable"}, "ctl3"}, {{"ipending"}, "ctl4"},
+ {{"cpuid"}, "ctl5"}, {{"exception"}, "ctl7"}, {{"pteaddr"}, "ctl8"},
+ {{"tlbacc"}, "ctl9"}, {{"tlbmisc"}, "ctl10"}, {{"badaddr"}, "ctl12"},
+ {{"config"}, "ctl13"}, {{"mpubase"}, "ctl14"}, {{"mpuacc"}, "ctl15"},
+ };
+ return llvm::makeArrayRef(aliases);
+ }
+};
+
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_NIOS2_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/OSTargets.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/OSTargets.cpp
new file mode 100644
index 0000000000000..50abd4ce0c8c3
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/OSTargets.cpp
@@ -0,0 +1,139 @@
+//===--- OSTargets.cpp - Implement OS target feature support --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements OS specific TargetInfo types.
+//===----------------------------------------------------------------------===//
+
+#include "OSTargets.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "llvm/ADT/StringRef.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+namespace clang {
+namespace targets {
+
+void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts,
+ const llvm::Triple &Triple, StringRef &PlatformName,
+ VersionTuple &PlatformMinVersion) {
+ Builder.defineMacro("__APPLE_CC__", "6000");
+ Builder.defineMacro("__APPLE__");
+ Builder.defineMacro("__STDC_NO_THREADS__");
+ Builder.defineMacro("OBJC_NEW_PROPERTIES");
+ // AddressSanitizer doesn't play well with source fortification, which is on
+ // by default on Darwin.
+ if (Opts.Sanitize.has(SanitizerKind::Address))
+ Builder.defineMacro("_FORTIFY_SOURCE", "0");
+
+ // Darwin defines __weak, __strong, and __unsafe_unretained even in C mode.
+ if (!Opts.ObjC1) {
+ // __weak is always defined, for use in blocks and with objc pointers.
+ Builder.defineMacro("__weak", "__attribute__((objc_gc(weak)))");
+ Builder.defineMacro("__strong", "");
+ Builder.defineMacro("__unsafe_unretained", "");
+ }
+
+ if (Opts.Static)
+ Builder.defineMacro("__STATIC__");
+ else
+ Builder.defineMacro("__DYNAMIC__");
+
+ if (Opts.POSIXThreads)
+ Builder.defineMacro("_REENTRANT");
+
+ // Get the platform type and version number from the triple.
+ unsigned Maj, Min, Rev;
+ if (Triple.isMacOSX()) {
+ Triple.getMacOSXVersion(Maj, Min, Rev);
+ PlatformName = "macos";
+ } else {
+ Triple.getOSVersion(Maj, Min, Rev);
+ PlatformName = llvm::Triple::getOSTypeName(Triple.getOS());
+ }
+
+ // If -target arch-pc-win32-macho option specified, we're
+ // generating code for Win32 ABI. No need to emit
+ // __ENVIRONMENT_XX_OS_VERSION_MIN_REQUIRED__.
+ if (PlatformName == "win32") {
+ PlatformMinVersion = VersionTuple(Maj, Min, Rev);
+ return;
+ }
+
+ // Set the appropriate OS version define.
+ if (Triple.isiOS()) {
+ assert(Maj < 100 && Min < 100 && Rev < 100 && "Invalid version!");
+ char Str[7];
+ if (Maj < 10) {
+ Str[0] = '0' + Maj;
+ Str[1] = '0' + (Min / 10);
+ Str[2] = '0' + (Min % 10);
+ Str[3] = '0' + (Rev / 10);
+ Str[4] = '0' + (Rev % 10);
+ Str[5] = '\0';
+ } else {
+ // Handle versions >= 10.
+ Str[0] = '0' + (Maj / 10);
+ Str[1] = '0' + (Maj % 10);
+ Str[2] = '0' + (Min / 10);
+ Str[3] = '0' + (Min % 10);
+ Str[4] = '0' + (Rev / 10);
+ Str[5] = '0' + (Rev % 10);
+ Str[6] = '\0';
+ }
+ if (Triple.isTvOS())
+ Builder.defineMacro("__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__", Str);
+ else
+ Builder.defineMacro("__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__",
+ Str);
+
+ } else if (Triple.isWatchOS()) {
+ assert(Maj < 10 && Min < 100 && Rev < 100 && "Invalid version!");
+ char Str[6];
+ Str[0] = '0' + Maj;
+ Str[1] = '0' + (Min / 10);
+ Str[2] = '0' + (Min % 10);
+ Str[3] = '0' + (Rev / 10);
+ Str[4] = '0' + (Rev % 10);
+ Str[5] = '\0';
+ Builder.defineMacro("__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__", Str);
+ } else if (Triple.isMacOSX()) {
+ // Note that the Driver allows versions which aren't representable in the
+ // define (because we only get a single digit for the minor and micro
+ // revision numbers). So, we limit them to the maximum representable
+ // version.
+ assert(Maj < 100 && Min < 100 && Rev < 100 && "Invalid version!");
+ char Str[7];
+ if (Maj < 10 || (Maj == 10 && Min < 10)) {
+ Str[0] = '0' + (Maj / 10);
+ Str[1] = '0' + (Maj % 10);
+ Str[2] = '0' + std::min(Min, 9U);
+ Str[3] = '0' + std::min(Rev, 9U);
+ Str[4] = '\0';
+ } else {
+ // Handle versions > 10.9.
+ Str[0] = '0' + (Maj / 10);
+ Str[1] = '0' + (Maj % 10);
+ Str[2] = '0' + (Min / 10);
+ Str[3] = '0' + (Min % 10);
+ Str[4] = '0' + (Rev / 10);
+ Str[5] = '0' + (Rev % 10);
+ Str[6] = '\0';
+ }
+ Builder.defineMacro("__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", Str);
+ }
+
+ // Tell users about the kernel if there is one.
+ if (Triple.isOSDarwin())
+ Builder.defineMacro("__MACH__");
+
+ PlatformMinVersion = VersionTuple(Maj, Min, Rev);
+}
+} // namespace targets
+} // namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/OSTargets.h b/contrib/llvm/tools/clang/lib/Basic/Targets/OSTargets.h
new file mode 100644
index 0000000000000..5af63615dc5ec
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/OSTargets.h
@@ -0,0 +1,725 @@
+//===--- OSTargets.h - Declare OS target feature support --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares OS specific TargetInfo types.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_OSTARGETS_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_OSTARGETS_H
+
+#include "Targets.h"
+#include "llvm/MC/MCSectionMachO.h"
+
+namespace clang {
+namespace targets {
+
+template <typename TgtInfo>
+class LLVM_LIBRARY_VISIBILITY OSTargetInfo : public TgtInfo {
+protected:
+ virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const = 0;
+
+public:
+ OSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : TgtInfo(Triple, Opts) {}
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ TgtInfo::getTargetDefines(Opts, Builder);
+ getOSDefines(Opts, TgtInfo::getTriple(), Builder);
+ }
+};
+
+// CloudABI Target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY CloudABITargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ Builder.defineMacro("__CloudABI__");
+ Builder.defineMacro("__ELF__");
+
+ // CloudABI uses ISO/IEC 10646:2012 for wchar_t, char16_t and char32_t.
+ Builder.defineMacro("__STDC_ISO_10646__", "201206L");
+ Builder.defineMacro("__STDC_UTF_16__");
+ Builder.defineMacro("__STDC_UTF_32__");
+ }
+
+public:
+ CloudABITargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {}
+};
+
+// Ananas target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY AnanasTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ // Ananas defines
+ Builder.defineMacro("__Ananas__");
+ Builder.defineMacro("__ELF__");
+ }
+
+public:
+ AnanasTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {}
+};
+
+void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts,
+ const llvm::Triple &Triple, StringRef &PlatformName,
+ VersionTuple &PlatformMinVersion);
+
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY DarwinTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ getDarwinDefines(Builder, Opts, Triple, this->PlatformName,
+ this->PlatformMinVersion);
+ }
+
+public:
+ DarwinTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ // By default, no TLS, and we whitelist permitted architecture/OS
+ // combinations.
+ this->TLSSupported = false;
+
+ if (Triple.isMacOSX())
+ this->TLSSupported = !Triple.isMacOSXVersionLT(10, 7);
+ else if (Triple.isiOS()) {
+ // 64-bit iOS supported it from 8 onwards, 32-bit from 9 onwards.
+ if (Triple.getArch() == llvm::Triple::x86_64 ||
+ Triple.getArch() == llvm::Triple::aarch64)
+ this->TLSSupported = !Triple.isOSVersionLT(8);
+ else if (Triple.getArch() == llvm::Triple::x86 ||
+ Triple.getArch() == llvm::Triple::arm ||
+ Triple.getArch() == llvm::Triple::thumb)
+ this->TLSSupported = !Triple.isOSVersionLT(9);
+ } else if (Triple.isWatchOS())
+ this->TLSSupported = !Triple.isOSVersionLT(2);
+
+ this->MCountName = "\01mcount";
+ }
+
+ std::string isValidSectionSpecifier(StringRef SR) const override {
+ // Let MCSectionMachO validate this.
+ StringRef Segment, Section;
+ unsigned TAA, StubSize;
+ bool HasTAA;
+ return llvm::MCSectionMachO::ParseSectionSpecifier(SR, Segment, Section,
+ TAA, HasTAA, StubSize);
+ }
+
+ const char *getStaticInitSectionSpecifier() const override {
+ // FIXME: We should return 0 when building kexts.
+ return "__TEXT,__StaticInit,regular,pure_instructions";
+ }
+
+ /// Darwin does not support protected visibility. Darwin's "default"
+ /// is very similar to ELF's "protected"; Darwin requires a "weak"
+ /// attribute on declarations that can be dynamically replaced.
+ bool hasProtectedVisibility() const override { return false; }
+};
+
+// DragonFlyBSD Target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY DragonFlyBSDTargetInfo
+ : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ // DragonFly defines; list based off of gcc output
+ Builder.defineMacro("__DragonFly__");
+ Builder.defineMacro("__DragonFly_cc_version", "100001");
+ Builder.defineMacro("__ELF__");
+ Builder.defineMacro("__KPRINTF_ATTRIBUTE__");
+ Builder.defineMacro("__tune_i386__");
+ DefineStd(Builder, "unix", Opts);
+ }
+
+public:
+ DragonFlyBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ switch (Triple.getArch()) {
+ default:
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ this->MCountName = ".mcount";
+ break;
+ }
+ }
+};
+
+#ifndef FREEBSD_CC_VERSION
+#define FREEBSD_CC_VERSION 0U
+#endif
+
+// FreeBSD Target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY FreeBSDTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ // FreeBSD defines; list based off of gcc output
+
+ unsigned Release = Triple.getOSMajorVersion();
+ if (Release == 0U)
+ Release = 8U;
+ unsigned CCVersion = FREEBSD_CC_VERSION;
+ if (CCVersion == 0U)
+ CCVersion = Release * 100000U + 1U;
+
+ Builder.defineMacro("__FreeBSD__", Twine(Release));
+ Builder.defineMacro("__FreeBSD_cc_version", Twine(CCVersion));
+ Builder.defineMacro("__KPRINTF_ATTRIBUTE__");
+ DefineStd(Builder, "unix", Opts);
+ Builder.defineMacro("__ELF__");
+
+ // On FreeBSD, wchar_t contains the number of the code point as
+ // used by the character set of the locale. These character sets are
+ // not necessarily a superset of ASCII.
+ //
+ // FIXME: This is wrong; the macro refers to the numerical values
+ // of wchar_t *literals*, which are not locale-dependent. However,
+ // FreeBSD systems apparently depend on us getting this wrong, and
+ // setting this to 1 is conforming even if all the basic source
+ // character literals have the same encoding as char and wchar_t.
+ Builder.defineMacro("__STDC_MB_MIGHT_NEQ_WC__", "1");
+ }
+
+public:
+ FreeBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ switch (Triple.getArch()) {
+ default:
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ this->MCountName = ".mcount";
+ break;
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ case llvm::Triple::ppc64le:
+ this->MCountName = "_mcount";
+ break;
+ case llvm::Triple::arm:
+ this->MCountName = "__mcount";
+ break;
+ }
+ }
+};
+
+// GNU/kFreeBSD Target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY KFreeBSDTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ // GNU/kFreeBSD defines; list based off of gcc output
+
+ DefineStd(Builder, "unix", Opts);
+ Builder.defineMacro("__FreeBSD_kernel__");
+ Builder.defineMacro("__GLIBC__");
+ Builder.defineMacro("__ELF__");
+ if (Opts.POSIXThreads)
+ Builder.defineMacro("_REENTRANT");
+ if (Opts.CPlusPlus)
+ Builder.defineMacro("_GNU_SOURCE");
+ }
+
+public:
+ KFreeBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {}
+};
+
+// Haiku Target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY HaikuTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ // Haiku defines; list based off of gcc output
+ Builder.defineMacro("__HAIKU__");
+ Builder.defineMacro("__ELF__");
+ DefineStd(Builder, "unix", Opts);
+ }
+
+public:
+ HaikuTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ this->SizeType = TargetInfo::UnsignedLong;
+ this->IntPtrType = TargetInfo::SignedLong;
+ this->PtrDiffType = TargetInfo::SignedLong;
+ this->ProcessIDType = TargetInfo::SignedLong;
+ this->TLSSupported = false;
+ }
+};
+
+// Minix Target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY MinixTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ // Minix defines
+
+ Builder.defineMacro("__minix", "3");
+ Builder.defineMacro("_EM_WSIZE", "4");
+ Builder.defineMacro("_EM_PSIZE", "4");
+ Builder.defineMacro("_EM_SSIZE", "2");
+ Builder.defineMacro("_EM_LSIZE", "4");
+ Builder.defineMacro("_EM_FSIZE", "4");
+ Builder.defineMacro("_EM_DSIZE", "8");
+ Builder.defineMacro("__ELF__");
+ DefineStd(Builder, "unix", Opts);
+ }
+
+public:
+ MinixTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {}
+};
+
+// Linux target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY LinuxTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ // Linux defines; list based off of gcc output
+ DefineStd(Builder, "unix", Opts);
+ DefineStd(Builder, "linux", Opts);
+ Builder.defineMacro("__gnu_linux__");
+ Builder.defineMacro("__ELF__");
+ if (Triple.isAndroid()) {
+ Builder.defineMacro("__ANDROID__", "1");
+ unsigned Maj, Min, Rev;
+ Triple.getEnvironmentVersion(Maj, Min, Rev);
+ this->PlatformName = "android";
+ this->PlatformMinVersion = VersionTuple(Maj, Min, Rev);
+ if (Maj)
+ Builder.defineMacro("__ANDROID_API__", Twine(Maj));
+ }
+ if (Opts.POSIXThreads)
+ Builder.defineMacro("_REENTRANT");
+ if (Opts.CPlusPlus)
+ Builder.defineMacro("_GNU_SOURCE");
+ if (this->HasFloat128)
+ Builder.defineMacro("__FLOAT128__");
+ }
+
+public:
+ LinuxTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ this->WIntType = TargetInfo::UnsignedInt;
+
+ switch (Triple.getArch()) {
+ default:
+ break;
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ case llvm::Triple::ppc64le:
+ this->MCountName = "_mcount";
+ break;
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ case llvm::Triple::systemz:
+ this->HasFloat128 = true;
+ break;
+ }
+ }
+
+ const char *getStaticInitSectionSpecifier() const override {
+ return ".text.startup";
+ }
+};
+
+// NetBSD Target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY NetBSDTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ // NetBSD defines; list based off of gcc output
+ Builder.defineMacro("__NetBSD__");
+ Builder.defineMacro("__unix__");
+ Builder.defineMacro("__ELF__");
+ if (Opts.POSIXThreads)
+ Builder.defineMacro("_REENTRANT");
+ }
+
+public:
+ NetBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ this->MCountName = "_mcount";
+ }
+};
+
+// OpenBSD Target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY OpenBSDTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ // OpenBSD defines; list based off of gcc output
+
+ Builder.defineMacro("__OpenBSD__");
+ DefineStd(Builder, "unix", Opts);
+ Builder.defineMacro("__ELF__");
+ if (Opts.POSIXThreads)
+ Builder.defineMacro("_REENTRANT");
+ if (this->HasFloat128)
+ Builder.defineMacro("__FLOAT128__");
+ }
+
+public:
+ OpenBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ switch (Triple.getArch()) {
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ this->HasFloat128 = true;
+ // FALLTHROUGH
+ default:
+ this->MCountName = "__mcount";
+ break;
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ case llvm::Triple::ppc:
+ case llvm::Triple::sparcv9:
+ this->MCountName = "_mcount";
+ break;
+ }
+ }
+};
+
+// PSP Target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY PSPTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ // PSP defines; list based on the output of the pspdev gcc toolchain.
+ Builder.defineMacro("PSP");
+ Builder.defineMacro("_PSP");
+ Builder.defineMacro("__psp__");
+ Builder.defineMacro("__ELF__");
+ }
+
+public:
+ PSPTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) {}
+};
+
+// PS3 PPU Target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY PS3PPUTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ // PS3 PPU defines.
+ Builder.defineMacro("__PPC__");
+ Builder.defineMacro("__PPU__");
+ Builder.defineMacro("__CELLOS_LV2__");
+ Builder.defineMacro("__ELF__");
+ Builder.defineMacro("__LP32__");
+ Builder.defineMacro("_ARCH_PPC64");
+ Builder.defineMacro("__powerpc64__");
+ }
+
+public:
+ PS3PPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ this->LongWidth = this->LongAlign = 32;
+ this->PointerWidth = this->PointerAlign = 32;
+ this->IntMaxType = TargetInfo::SignedLongLong;
+ this->Int64Type = TargetInfo::SignedLongLong;
+ this->SizeType = TargetInfo::UnsignedInt;
+ this->resetDataLayout("E-m:e-p:32:32-i64:64-n32:64");
+ }
+};
+
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY PS4OSTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ Builder.defineMacro("__FreeBSD__", "9");
+ Builder.defineMacro("__FreeBSD_cc_version", "900001");
+ Builder.defineMacro("__KPRINTF_ATTRIBUTE__");
+ DefineStd(Builder, "unix", Opts);
+ Builder.defineMacro("__ELF__");
+ Builder.defineMacro("__ORBIS__");
+ }
+
+public:
+ PS4OSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ this->WCharType = TargetInfo::UnsignedShort;
+
+ // On PS4, TLS variable cannot be aligned to more than 32 bytes (256 bits).
+ this->MaxTLSAlign = 256;
+
+ // On PS4, do not honor explicit bit field alignment,
+ // as in "__attribute__((aligned(2))) int b : 1;".
+ this->UseExplicitBitFieldAlignment = false;
+
+ switch (Triple.getArch()) {
+ default:
+ case llvm::Triple::x86_64:
+ this->MCountName = ".mcount";
+ break;
+ }
+ }
+};
+
+// RTEMS Target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY RTEMSTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ // RTEMS defines; list based off of gcc output
+
+ Builder.defineMacro("__rtems__");
+ Builder.defineMacro("__ELF__");
+ if (Opts.CPlusPlus)
+ Builder.defineMacro("_GNU_SOURCE");
+ }
+
+public:
+ RTEMSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ switch (Triple.getArch()) {
+ default:
+ case llvm::Triple::x86:
+ // this->MCountName = ".mcount";
+ break;
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ case llvm::Triple::ppc64le:
+ // this->MCountName = "_mcount";
+ break;
+ case llvm::Triple::arm:
+ // this->MCountName = "__mcount";
+ break;
+ }
+ }
+};
+
+// Solaris target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY SolarisTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ DefineStd(Builder, "sun", Opts);
+ DefineStd(Builder, "unix", Opts);
+ Builder.defineMacro("__ELF__");
+ Builder.defineMacro("__svr4__");
+ Builder.defineMacro("__SVR4");
+ // Solaris headers require _XOPEN_SOURCE to be set to 600 for C99 and
+ // newer, but to 500 for everything else. feature_test.h has a check to
+ // ensure that you are not using C99 with an old version of X/Open or C89
+ // with a new version.
+ if (Opts.C99)
+ Builder.defineMacro("_XOPEN_SOURCE", "600");
+ else
+ Builder.defineMacro("_XOPEN_SOURCE", "500");
+ if (Opts.CPlusPlus)
+ Builder.defineMacro("__C99FEATURES__");
+ Builder.defineMacro("_LARGEFILE_SOURCE");
+ Builder.defineMacro("_LARGEFILE64_SOURCE");
+ Builder.defineMacro("__EXTENSIONS__");
+ Builder.defineMacro("_REENTRANT");
+ }
+
+public:
+ SolarisTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ // FIXME: WIntType should be SignedLong
+ }
+};
+
+// Windows target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY WindowsTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ Builder.defineMacro("_WIN32");
+ if (Triple.isArch64Bit())
+ Builder.defineMacro("_WIN64");
+ if (Triple.isWindowsGNUEnvironment())
+ addMinGWDefines(Triple, Opts, Builder);
+
+ }
+ void getVisualStudioDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ if (Opts.CPlusPlus) {
+ if (Opts.RTTIData)
+ Builder.defineMacro("_CPPRTTI");
+
+ if (Opts.CXXExceptions)
+ Builder.defineMacro("_CPPUNWIND");
+ }
+
+ if (Opts.Bool)
+ Builder.defineMacro("__BOOL_DEFINED");
+
+ if (!Opts.CharIsSigned)
+ Builder.defineMacro("_CHAR_UNSIGNED");
+
+ // FIXME: POSIXThreads isn't exactly the option this should be defined for,
+ // but it works for now.
+ if (Opts.POSIXThreads)
+ Builder.defineMacro("_MT");
+
+ if (Opts.MSCompatibilityVersion) {
+ Builder.defineMacro("_MSC_VER",
+ Twine(Opts.MSCompatibilityVersion / 100000));
+ Builder.defineMacro("_MSC_FULL_VER", Twine(Opts.MSCompatibilityVersion));
+ // FIXME We cannot encode the revision information into 32-bits
+ Builder.defineMacro("_MSC_BUILD", Twine(1));
+
+ if (Opts.CPlusPlus11 && Opts.isCompatibleWithMSVC(LangOptions::MSVC2015))
+ Builder.defineMacro("_HAS_CHAR16_T_LANGUAGE_SUPPORT", Twine(1));
+
+ if (Opts.isCompatibleWithMSVC(LangOptions::MSVC2015)) {
+ if (Opts.CPlusPlus17)
+ Builder.defineMacro("_MSVC_LANG", "201403L");
+ else if (Opts.CPlusPlus14)
+ Builder.defineMacro("_MSVC_LANG", "201402L");
+ }
+ }
+
+ if (Opts.MicrosoftExt) {
+ Builder.defineMacro("_MSC_EXTENSIONS");
+
+ if (Opts.CPlusPlus11) {
+ Builder.defineMacro("_RVALUE_REFERENCES_V2_SUPPORTED");
+ Builder.defineMacro("_RVALUE_REFERENCES_SUPPORTED");
+ Builder.defineMacro("_NATIVE_NULLPTR_SUPPORTED");
+ }
+ }
+
+ Builder.defineMacro("_INTEGRAL_MAX_BITS", "64");
+ }
+
+public:
+ WindowsTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ this->WCharType = TargetInfo::UnsignedShort;
+ }
+};
+
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY NaClTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ if (Opts.POSIXThreads)
+ Builder.defineMacro("_REENTRANT");
+ if (Opts.CPlusPlus)
+ Builder.defineMacro("_GNU_SOURCE");
+
+ DefineStd(Builder, "unix", Opts);
+ Builder.defineMacro("__ELF__");
+ Builder.defineMacro("__native_client__");
+ }
+
+public:
+ NaClTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ this->LongAlign = 32;
+ this->LongWidth = 32;
+ this->PointerAlign = 32;
+ this->PointerWidth = 32;
+ this->IntMaxType = TargetInfo::SignedLongLong;
+ this->Int64Type = TargetInfo::SignedLongLong;
+ this->DoubleAlign = 64;
+ this->LongDoubleWidth = 64;
+ this->LongDoubleAlign = 64;
+ this->LongLongWidth = 64;
+ this->LongLongAlign = 64;
+ this->SizeType = TargetInfo::UnsignedInt;
+ this->PtrDiffType = TargetInfo::SignedInt;
+ this->IntPtrType = TargetInfo::SignedInt;
+ // RegParmMax is inherited from the underlying architecture.
+ this->LongDoubleFormat = &llvm::APFloat::IEEEdouble();
+ if (Triple.getArch() == llvm::Triple::arm) {
+ // Handled in ARM's setABI().
+ } else if (Triple.getArch() == llvm::Triple::x86) {
+ this->resetDataLayout("e-m:e-p:32:32-i64:64-n8:16:32-S128");
+ } else if (Triple.getArch() == llvm::Triple::x86_64) {
+ this->resetDataLayout("e-m:e-p:32:32-i64:64-n8:16:32:64-S128");
+ } else if (Triple.getArch() == llvm::Triple::mipsel) {
+ // Handled on mips' setDataLayout.
+ } else {
+ assert(Triple.getArch() == llvm::Triple::le32);
+ this->resetDataLayout("e-p:32:32-i64:64");
+ }
+ }
+};
+
+// Fuchsia Target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY FuchsiaTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ Builder.defineMacro("__Fuchsia__");
+ Builder.defineMacro("__ELF__");
+ if (Opts.POSIXThreads)
+ Builder.defineMacro("_REENTRANT");
+ // Required by the libc++ locale support.
+ if (Opts.CPlusPlus)
+ Builder.defineMacro("_GNU_SOURCE");
+ }
+
+public:
+ FuchsiaTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ this->MCountName = "__mcount";
+ }
+};
+
+// WebAssembly target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY WebAssemblyOSTargetInfo
+ : public OSTargetInfo<Target> {
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const final {
+ // A common platform macro.
+ if (Opts.POSIXThreads)
+ Builder.defineMacro("_REENTRANT");
+ // Follow g++ convention and predefine _GNU_SOURCE for C++.
+ if (Opts.CPlusPlus)
+ Builder.defineMacro("_GNU_SOURCE");
+ }
+
+public:
+ explicit WebAssemblyOSTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ this->MCountName = "__mcount";
+ this->TheCXXABI.set(TargetCXXABI::WebAssembly);
+ }
+};
+
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_OSTARGETS_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/PNaCl.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/PNaCl.cpp
new file mode 100644
index 0000000000000..b9128c2716e87
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/PNaCl.cpp
@@ -0,0 +1,30 @@
+//===--- PNaCl.cpp - Implement PNaCl target feature support ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements PNaCl TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PNaCl.h"
+#include "clang/Basic/MacroBuilder.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+ArrayRef<const char *> PNaClTargetInfo::getGCCRegNames() const { return None; }
+
+ArrayRef<TargetInfo::GCCRegAlias> PNaClTargetInfo::getGCCRegAliases() const {
+ return None;
+}
+
+void PNaClTargetInfo::getArchDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__le32__");
+ Builder.defineMacro("__pnacl__");
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/PNaCl.h b/contrib/llvm/tools/clang/lib/Basic/Targets/PNaCl.h
new file mode 100644
index 0000000000000..922944e85ca29
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/PNaCl.h
@@ -0,0 +1,87 @@
+//===--- PNaCl.h - Declare PNaCl target feature support ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares PNaCl TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_PNACL_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_PNACL_H
+
+#include "Mips.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY PNaClTargetInfo : public TargetInfo {
+public:
+ PNaClTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : TargetInfo(Triple) {
+ this->LongAlign = 32;
+ this->LongWidth = 32;
+ this->PointerAlign = 32;
+ this->PointerWidth = 32;
+ this->IntMaxType = TargetInfo::SignedLongLong;
+ this->Int64Type = TargetInfo::SignedLongLong;
+ this->DoubleAlign = 64;
+ this->LongDoubleWidth = 64;
+ this->LongDoubleAlign = 64;
+ this->SizeType = TargetInfo::UnsignedInt;
+ this->PtrDiffType = TargetInfo::SignedInt;
+ this->IntPtrType = TargetInfo::SignedInt;
+ this->RegParmMax = 0; // Disallow regparm
+ }
+
+ void getArchDefines(const LangOptions &Opts, MacroBuilder &Builder) const;
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ getArchDefines(Opts, Builder);
+ }
+
+ bool hasFeature(StringRef Feature) const override {
+ return Feature == "pnacl";
+ }
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::PNaClABIBuiltinVaList;
+ }
+
+ ArrayRef<const char *> getGCCRegNames() const override;
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override {
+ return false;
+ }
+
+ const char *getClobbers() const override { return ""; }
+};
+
+// We attempt to use PNaCl (le32) frontend and Mips32EL backend.
+class LLVM_LIBRARY_VISIBILITY NaClMips32TargetInfo : public MipsTargetInfo {
+public:
+ NaClMips32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : MipsTargetInfo(Triple, Opts) {}
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::PNaClABIBuiltinVaList;
+ }
+};
+} // namespace targets
+} // namespace clang
+
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_PNACL_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/PPC.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/PPC.cpp
new file mode 100644
index 0000000000000..a44aa0cd96f06
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/PPC.cpp
@@ -0,0 +1,544 @@
+//===--- PPC.cpp - Implement PPC target feature support -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements PPC TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PPC.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+const Builtin::Info PPCTargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
+ {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
+#include "clang/Basic/BuiltinsPPC.def"
+};
+
+/// handleTargetFeatures - Perform initialization based on the user
+/// configured set of features.
+bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) {
+ for (const auto &Feature : Features) {
+ if (Feature == "+altivec") {
+ HasAltivec = true;
+ } else if (Feature == "+vsx") {
+ HasVSX = true;
+ } else if (Feature == "+bpermd") {
+ HasBPERMD = true;
+ } else if (Feature == "+extdiv") {
+ HasExtDiv = true;
+ } else if (Feature == "+power8-vector") {
+ HasP8Vector = true;
+ } else if (Feature == "+crypto") {
+ HasP8Crypto = true;
+ } else if (Feature == "+direct-move") {
+ HasDirectMove = true;
+ } else if (Feature == "+qpx") {
+ HasQPX = true;
+ } else if (Feature == "+htm") {
+ HasHTM = true;
+ } else if (Feature == "+float128") {
+ HasFloat128 = true;
+ } else if (Feature == "+power9-vector") {
+ HasP9Vector = true;
+ }
+ // TODO: Finish this list and add an assert that we've handled them
+ // all.
+ }
+
+ return true;
+}
+
+/// PPCTargetInfo::getTargetDefines - Return a set of the PowerPC-specific
+/// #defines that are not tied to a specific subtarget.
+void PPCTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ // Target identification.
+ Builder.defineMacro("__ppc__");
+ Builder.defineMacro("__PPC__");
+ Builder.defineMacro("_ARCH_PPC");
+ Builder.defineMacro("__powerpc__");
+ Builder.defineMacro("__POWERPC__");
+ if (PointerWidth == 64) {
+ Builder.defineMacro("_ARCH_PPC64");
+ Builder.defineMacro("__powerpc64__");
+ Builder.defineMacro("__ppc64__");
+ Builder.defineMacro("__PPC64__");
+ }
+
+ // Target properties.
+ if (getTriple().getArch() == llvm::Triple::ppc64le) {
+ Builder.defineMacro("_LITTLE_ENDIAN");
+ } else {
+ if (getTriple().getOS() != llvm::Triple::NetBSD &&
+ getTriple().getOS() != llvm::Triple::OpenBSD)
+ Builder.defineMacro("_BIG_ENDIAN");
+ }
+
+ // ABI options.
+ if (ABI == "elfv1" || ABI == "elfv1-qpx")
+ Builder.defineMacro("_CALL_ELF", "1");
+ if (ABI == "elfv2")
+ Builder.defineMacro("_CALL_ELF", "2");
+
+ // This typically is only for a new enough linker (bfd >= 2.16.2 or gold), but
+ // our suppport post-dates this and it should work on all 64-bit ppc linux
+ // platforms. It is guaranteed to work on all elfv2 platforms.
+ if (getTriple().getOS() == llvm::Triple::Linux && PointerWidth == 64)
+ Builder.defineMacro("_CALL_LINUX", "1");
+
+ // Subtarget options.
+ Builder.defineMacro("__NATURAL_ALIGNMENT__");
+ Builder.defineMacro("__REGISTER_PREFIX__", "");
+
+ // FIXME: Should be controlled by command line option.
+ if (LongDoubleWidth == 128) {
+ Builder.defineMacro("__LONG_DOUBLE_128__");
+ Builder.defineMacro("__LONGDOUBLE128");
+ }
+
+ // Define this for elfv2 (64-bit only) or 64-bit darwin.
+ if (ABI == "elfv2" ||
+ (getTriple().getOS() == llvm::Triple::Darwin && PointerWidth == 64))
+ Builder.defineMacro("__STRUCT_PARM_ALIGN__", "16");
+
+ // CPU identification.
+ ArchDefineTypes defs =
+ (ArchDefineTypes)llvm::StringSwitch<int>(CPU)
+ .Case("440", ArchDefineName)
+ .Case("450", ArchDefineName | ArchDefine440)
+ .Case("601", ArchDefineName)
+ .Case("602", ArchDefineName | ArchDefinePpcgr)
+ .Case("603", ArchDefineName | ArchDefinePpcgr)
+ .Case("603e", ArchDefineName | ArchDefine603 | ArchDefinePpcgr)
+ .Case("603ev", ArchDefineName | ArchDefine603 | ArchDefinePpcgr)
+ .Case("604", ArchDefineName | ArchDefinePpcgr)
+ .Case("604e", ArchDefineName | ArchDefine604 | ArchDefinePpcgr)
+ .Case("620", ArchDefineName | ArchDefinePpcgr)
+ .Case("630", ArchDefineName | ArchDefinePpcgr)
+ .Case("7400", ArchDefineName | ArchDefinePpcgr)
+ .Case("7450", ArchDefineName | ArchDefinePpcgr)
+ .Case("750", ArchDefineName | ArchDefinePpcgr)
+ .Case("970", ArchDefineName | ArchDefinePwr4 | ArchDefinePpcgr |
+ ArchDefinePpcsq)
+ .Case("a2", ArchDefineA2)
+ .Case("a2q", ArchDefineName | ArchDefineA2 | ArchDefineA2q)
+ .Case("pwr3", ArchDefinePpcgr)
+ .Case("pwr4", ArchDefineName | ArchDefinePpcgr | ArchDefinePpcsq)
+ .Case("pwr5", ArchDefineName | ArchDefinePwr4 | ArchDefinePpcgr |
+ ArchDefinePpcsq)
+ .Case("pwr5x", ArchDefineName | ArchDefinePwr5 | ArchDefinePwr4 |
+ ArchDefinePpcgr | ArchDefinePpcsq)
+ .Case("pwr6", ArchDefineName | ArchDefinePwr5x | ArchDefinePwr5 |
+ ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq)
+ .Case("pwr6x", ArchDefineName | ArchDefinePwr6 | ArchDefinePwr5x |
+ ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr |
+ ArchDefinePpcsq)
+ .Case("pwr7", ArchDefineName | ArchDefinePwr6x | ArchDefinePwr6 |
+ ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 |
+ ArchDefinePpcgr | ArchDefinePpcsq)
+ .Case("pwr8", ArchDefineName | ArchDefinePwr7 | ArchDefinePwr6x |
+ ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 |
+ ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq)
+ .Case("pwr9", ArchDefineName | ArchDefinePwr8 | ArchDefinePwr7 |
+ ArchDefinePwr6x | ArchDefinePwr6 | ArchDefinePwr5x |
+ ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr |
+ ArchDefinePpcsq)
+ .Case("power3", ArchDefinePpcgr)
+ .Case("power4", ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq)
+ .Case("power5", ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr |
+ ArchDefinePpcsq)
+ .Case("power5x", ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 |
+ ArchDefinePpcgr | ArchDefinePpcsq)
+ .Case("power6", ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 |
+ ArchDefinePwr4 | ArchDefinePpcgr |
+ ArchDefinePpcsq)
+ .Case("power6x", ArchDefinePwr6x | ArchDefinePwr6 | ArchDefinePwr5x |
+ ArchDefinePwr5 | ArchDefinePwr4 |
+ ArchDefinePpcgr | ArchDefinePpcsq)
+ .Case("power7", ArchDefinePwr7 | ArchDefinePwr6x | ArchDefinePwr6 |
+ ArchDefinePwr5x | ArchDefinePwr5 |
+ ArchDefinePwr4 | ArchDefinePpcgr |
+ ArchDefinePpcsq)
+ .Case("power8", ArchDefinePwr8 | ArchDefinePwr7 | ArchDefinePwr6x |
+ ArchDefinePwr6 | ArchDefinePwr5x |
+ ArchDefinePwr5 | ArchDefinePwr4 |
+ ArchDefinePpcgr | ArchDefinePpcsq)
+ .Case("power9", ArchDefinePwr9 | ArchDefinePwr8 | ArchDefinePwr7 |
+ ArchDefinePwr6x | ArchDefinePwr6 |
+ ArchDefinePwr5x | ArchDefinePwr5 |
+ ArchDefinePwr4 | ArchDefinePpcgr |
+ ArchDefinePpcsq)
+ // powerpc64le automatically defaults to at least power8.
+ .Case("ppc64le", ArchDefinePwr8 | ArchDefinePwr7 | ArchDefinePwr6x |
+ ArchDefinePwr6 | ArchDefinePwr5x |
+ ArchDefinePwr5 | ArchDefinePwr4 |
+ ArchDefinePpcgr | ArchDefinePpcsq)
+ .Default(ArchDefineNone);
+
+ if (defs & ArchDefineName)
+ Builder.defineMacro(Twine("_ARCH_", StringRef(CPU).upper()));
+ if (defs & ArchDefinePpcgr)
+ Builder.defineMacro("_ARCH_PPCGR");
+ if (defs & ArchDefinePpcsq)
+ Builder.defineMacro("_ARCH_PPCSQ");
+ if (defs & ArchDefine440)
+ Builder.defineMacro("_ARCH_440");
+ if (defs & ArchDefine603)
+ Builder.defineMacro("_ARCH_603");
+ if (defs & ArchDefine604)
+ Builder.defineMacro("_ARCH_604");
+ if (defs & ArchDefinePwr4)
+ Builder.defineMacro("_ARCH_PWR4");
+ if (defs & ArchDefinePwr5)
+ Builder.defineMacro("_ARCH_PWR5");
+ if (defs & ArchDefinePwr5x)
+ Builder.defineMacro("_ARCH_PWR5X");
+ if (defs & ArchDefinePwr6)
+ Builder.defineMacro("_ARCH_PWR6");
+ if (defs & ArchDefinePwr6x)
+ Builder.defineMacro("_ARCH_PWR6X");
+ if (defs & ArchDefinePwr7)
+ Builder.defineMacro("_ARCH_PWR7");
+ if (defs & ArchDefinePwr8)
+ Builder.defineMacro("_ARCH_PWR8");
+ if (defs & ArchDefinePwr9)
+ Builder.defineMacro("_ARCH_PWR9");
+ if (defs & ArchDefineA2)
+ Builder.defineMacro("_ARCH_A2");
+ if (defs & ArchDefineA2q) {
+ Builder.defineMacro("_ARCH_A2Q");
+ Builder.defineMacro("_ARCH_QP");
+ }
+
+ if (getTriple().getVendor() == llvm::Triple::BGQ) {
+ Builder.defineMacro("__bg__");
+ Builder.defineMacro("__THW_BLUEGENE__");
+ Builder.defineMacro("__bgq__");
+ Builder.defineMacro("__TOS_BGQ__");
+ }
+
+ if (HasAltivec) {
+ Builder.defineMacro("__VEC__", "10206");
+ Builder.defineMacro("__ALTIVEC__");
+ }
+ if (HasVSX)
+ Builder.defineMacro("__VSX__");
+ if (HasP8Vector)
+ Builder.defineMacro("__POWER8_VECTOR__");
+ if (HasP8Crypto)
+ Builder.defineMacro("__CRYPTO__");
+ if (HasHTM)
+ Builder.defineMacro("__HTM__");
+ if (HasFloat128)
+ Builder.defineMacro("__FLOAT128__");
+ if (HasP9Vector)
+ Builder.defineMacro("__POWER9_VECTOR__");
+
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
+ if (PointerWidth == 64)
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
+
+ // We have support for the bswap intrinsics so we can define this.
+ Builder.defineMacro("__HAVE_BSWAP__", "1");
+
+ // FIXME: The following are not yet generated here by Clang, but are
+ // generated by GCC:
+ //
+ // _SOFT_FLOAT_
+ // __RECIP_PRECISION__
+ // __APPLE_ALTIVEC__
+ // __RECIP__
+ // __RECIPF__
+ // __RSQRTE__
+ // __RSQRTEF__
+ // _SOFT_DOUBLE_
+ // __NO_LWSYNC__
+ // __CMODEL_MEDIUM__
+ // __CMODEL_LARGE__
+ // _CALL_SYSV
+ // _CALL_DARWIN
+ // __NO_FPRS__
+}
+
+// Handle explicit options being passed to the compiler here: if we've
+// explicitly turned off vsx and turned on any of:
+// - power8-vector
+// - direct-move
+// - float128
+// - power9-vector
+// then go ahead and error since the customer has expressed an incompatible
+// set of options.
+static bool ppcUserFeaturesCheck(DiagnosticsEngine &Diags,
+ const std::vector<std::string> &FeaturesVec) {
+
+ if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "-vsx") !=
+ FeaturesVec.end()) {
+ if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "+power8-vector") !=
+ FeaturesVec.end()) {
+ Diags.Report(diag::err_opt_not_valid_with_opt) << "-mpower8-vector"
+ << "-mno-vsx";
+ return false;
+ }
+
+ if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "+direct-move") !=
+ FeaturesVec.end()) {
+ Diags.Report(diag::err_opt_not_valid_with_opt) << "-mdirect-move"
+ << "-mno-vsx";
+ return false;
+ }
+
+ if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "+float128") !=
+ FeaturesVec.end()) {
+ Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfloat128"
+ << "-mno-vsx";
+ return false;
+ }
+
+ if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "+power9-vector") !=
+ FeaturesVec.end()) {
+ Diags.Report(diag::err_opt_not_valid_with_opt) << "-mpower9-vector"
+ << "-mno-vsx";
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool PPCTargetInfo::initFeatureMap(
+ llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const {
+ Features["altivec"] = llvm::StringSwitch<bool>(CPU)
+ .Case("7400", true)
+ .Case("g4", true)
+ .Case("7450", true)
+ .Case("g4+", true)
+ .Case("970", true)
+ .Case("g5", true)
+ .Case("pwr6", true)
+ .Case("pwr7", true)
+ .Case("pwr8", true)
+ .Case("pwr9", true)
+ .Case("ppc64", true)
+ .Case("ppc64le", true)
+ .Default(false);
+
+ Features["qpx"] = (CPU == "a2q");
+ Features["power9-vector"] = (CPU == "pwr9");
+ Features["crypto"] = llvm::StringSwitch<bool>(CPU)
+ .Case("ppc64le", true)
+ .Case("pwr9", true)
+ .Case("pwr8", true)
+ .Default(false);
+ Features["power8-vector"] = llvm::StringSwitch<bool>(CPU)
+ .Case("ppc64le", true)
+ .Case("pwr9", true)
+ .Case("pwr8", true)
+ .Default(false);
+ Features["bpermd"] = llvm::StringSwitch<bool>(CPU)
+ .Case("ppc64le", true)
+ .Case("pwr9", true)
+ .Case("pwr8", true)
+ .Case("pwr7", true)
+ .Default(false);
+ Features["extdiv"] = llvm::StringSwitch<bool>(CPU)
+ .Case("ppc64le", true)
+ .Case("pwr9", true)
+ .Case("pwr8", true)
+ .Case("pwr7", true)
+ .Default(false);
+ Features["direct-move"] = llvm::StringSwitch<bool>(CPU)
+ .Case("ppc64le", true)
+ .Case("pwr9", true)
+ .Case("pwr8", true)
+ .Default(false);
+ Features["vsx"] = llvm::StringSwitch<bool>(CPU)
+ .Case("ppc64le", true)
+ .Case("pwr9", true)
+ .Case("pwr8", true)
+ .Case("pwr7", true)
+ .Default(false);
+ Features["htm"] = llvm::StringSwitch<bool>(CPU)
+ .Case("ppc64le", true)
+ .Case("pwr9", true)
+ .Case("pwr8", true)
+ .Default(false);
+
+ if (!ppcUserFeaturesCheck(Diags, FeaturesVec))
+ return false;
+
+ return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
+}
+
+bool PPCTargetInfo::hasFeature(StringRef Feature) const {
+ return llvm::StringSwitch<bool>(Feature)
+ .Case("powerpc", true)
+ .Case("altivec", HasAltivec)
+ .Case("vsx", HasVSX)
+ .Case("power8-vector", HasP8Vector)
+ .Case("crypto", HasP8Crypto)
+ .Case("direct-move", HasDirectMove)
+ .Case("qpx", HasQPX)
+ .Case("htm", HasHTM)
+ .Case("bpermd", HasBPERMD)
+ .Case("extdiv", HasExtDiv)
+ .Case("float128", HasFloat128)
+ .Case("power9-vector", HasP9Vector)
+ .Default(false);
+}
+
+void PPCTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
+ StringRef Name, bool Enabled) const {
+ if (Enabled) {
+ // If we're enabling any of the vsx based features then enable vsx and
+ // altivec. We'll diagnose any problems later.
+ bool FeatureHasVSX = llvm::StringSwitch<bool>(Name)
+ .Case("vsx", true)
+ .Case("direct-move", true)
+ .Case("power8-vector", true)
+ .Case("power9-vector", true)
+ .Case("float128", true)
+ .Default(false);
+ if (FeatureHasVSX)
+ Features["vsx"] = Features["altivec"] = true;
+ if (Name == "power9-vector")
+ Features["power8-vector"] = true;
+ Features[Name] = true;
+ } else {
+ // If we're disabling altivec or vsx go ahead and disable all of the vsx
+ // features.
+ if ((Name == "altivec") || (Name == "vsx"))
+ Features["vsx"] = Features["direct-move"] = Features["power8-vector"] =
+ Features["float128"] = Features["power9-vector"] = false;
+ if (Name == "power8-vector")
+ Features["power9-vector"] = false;
+ Features[Name] = false;
+ }
+}
+
+const char *const PPCTargetInfo::GCCRegNames[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8",
+ "r9", "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17",
+ "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26",
+ "r27", "r28", "r29", "r30", "r31", "f0", "f1", "f2", "f3",
+ "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12",
+ "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21",
+ "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30",
+ "f31", "mq", "lr", "ctr", "ap", "cr0", "cr1", "cr2", "cr3",
+ "cr4", "cr5", "cr6", "cr7", "xer", "v0", "v1", "v2", "v3",
+ "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11", "v12",
+ "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21",
+ "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30",
+ "v31", "vrsave", "vscr", "spe_acc", "spefscr", "sfp"
+};
+
+ArrayRef<const char *> PPCTargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
+}
+
+const TargetInfo::GCCRegAlias PPCTargetInfo::GCCRegAliases[] = {
+ // While some of these aliases do map to different registers
+ // they still share the same register name.
+ {{"0"}, "r0"}, {{"1"}, "r1"}, {{"2"}, "r2"}, {{"3"}, "r3"},
+ {{"4"}, "r4"}, {{"5"}, "r5"}, {{"6"}, "r6"}, {{"7"}, "r7"},
+ {{"8"}, "r8"}, {{"9"}, "r9"}, {{"10"}, "r10"}, {{"11"}, "r11"},
+ {{"12"}, "r12"}, {{"13"}, "r13"}, {{"14"}, "r14"}, {{"15"}, "r15"},
+ {{"16"}, "r16"}, {{"17"}, "r17"}, {{"18"}, "r18"}, {{"19"}, "r19"},
+ {{"20"}, "r20"}, {{"21"}, "r21"}, {{"22"}, "r22"}, {{"23"}, "r23"},
+ {{"24"}, "r24"}, {{"25"}, "r25"}, {{"26"}, "r26"}, {{"27"}, "r27"},
+ {{"28"}, "r28"}, {{"29"}, "r29"}, {{"30"}, "r30"}, {{"31"}, "r31"},
+ {{"fr0"}, "f0"}, {{"fr1"}, "f1"}, {{"fr2"}, "f2"}, {{"fr3"}, "f3"},
+ {{"fr4"}, "f4"}, {{"fr5"}, "f5"}, {{"fr6"}, "f6"}, {{"fr7"}, "f7"},
+ {{"fr8"}, "f8"}, {{"fr9"}, "f9"}, {{"fr10"}, "f10"}, {{"fr11"}, "f11"},
+ {{"fr12"}, "f12"}, {{"fr13"}, "f13"}, {{"fr14"}, "f14"}, {{"fr15"}, "f15"},
+ {{"fr16"}, "f16"}, {{"fr17"}, "f17"}, {{"fr18"}, "f18"}, {{"fr19"}, "f19"},
+ {{"fr20"}, "f20"}, {{"fr21"}, "f21"}, {{"fr22"}, "f22"}, {{"fr23"}, "f23"},
+ {{"fr24"}, "f24"}, {{"fr25"}, "f25"}, {{"fr26"}, "f26"}, {{"fr27"}, "f27"},
+ {{"fr28"}, "f28"}, {{"fr29"}, "f29"}, {{"fr30"}, "f30"}, {{"fr31"}, "f31"},
+ {{"cc"}, "cr0"},
+};
+
+ArrayRef<TargetInfo::GCCRegAlias> PPCTargetInfo::getGCCRegAliases() const {
+ return llvm::makeArrayRef(GCCRegAliases);
+}
+
+bool PPCTargetInfo::isValidCPUName(StringRef Name) const {
+ return llvm::StringSwitch<bool>(Name)
+ .Case("generic", true)
+ .Case("440", true)
+ .Case("450", true)
+ .Case("601", true)
+ .Case("602", true)
+ .Case("603", true)
+ .Case("603e", true)
+ .Case("603ev", true)
+ .Case("604", true)
+ .Case("604e", true)
+ .Case("620", true)
+ .Case("630", true)
+ .Case("g3", true)
+ .Case("7400", true)
+ .Case("g4", true)
+ .Case("7450", true)
+ .Case("g4+", true)
+ .Case("750", true)
+ .Case("970", true)
+ .Case("g5", true)
+ .Case("a2", true)
+ .Case("a2q", true)
+ .Case("e500mc", true)
+ .Case("e5500", true)
+ .Case("power3", true)
+ .Case("pwr3", true)
+ .Case("power4", true)
+ .Case("pwr4", true)
+ .Case("power5", true)
+ .Case("pwr5", true)
+ .Case("power5x", true)
+ .Case("pwr5x", true)
+ .Case("power6", true)
+ .Case("pwr6", true)
+ .Case("power6x", true)
+ .Case("pwr6x", true)
+ .Case("power7", true)
+ .Case("pwr7", true)
+ .Case("power8", true)
+ .Case("pwr8", true)
+ .Case("power9", true)
+ .Case("pwr9", true)
+ .Case("powerpc", true)
+ .Case("ppc", true)
+ .Case("powerpc64", true)
+ .Case("ppc64", true)
+ .Case("powerpc64le", true)
+ .Case("ppc64le", true)
+ .Default(false);
+}
+
+void PPCTargetInfo::adjust(LangOptions &Opts) {
+ if (HasAltivec)
+ Opts.AltiVec = 1;
+ TargetInfo::adjust(Opts);
+}
+
+ArrayRef<Builtin::Info> PPCTargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfo, clang::PPC::LastTSBuiltin -
+ Builtin::FirstTSBuiltin);
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/PPC.h b/contrib/llvm/tools/clang/lib/Basic/Targets/PPC.h
new file mode 100644
index 0000000000000..04bef258e3865
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/PPC.h
@@ -0,0 +1,368 @@
+//===--- PPC.h - Declare PPC target feature support -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares PPC TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_PPC_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_PPC_H
+
+#include "OSTargets.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+// PPC abstract base class
+class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo {
+ static const Builtin::Info BuiltinInfo[];
+ static const char *const GCCRegNames[];
+ static const TargetInfo::GCCRegAlias GCCRegAliases[];
+ std::string CPU;
+
+ // Target cpu features.
+ bool HasAltivec;
+ bool HasVSX;
+ bool HasP8Vector;
+ bool HasP8Crypto;
+ bool HasDirectMove;
+ bool HasQPX;
+ bool HasHTM;
+ bool HasBPERMD;
+ bool HasExtDiv;
+ bool HasP9Vector;
+
+protected:
+ std::string ABI;
+
+public:
+ PPCTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple), HasAltivec(false), HasVSX(false),
+ HasP8Vector(false), HasP8Crypto(false), HasDirectMove(false),
+ HasQPX(false), HasHTM(false), HasBPERMD(false), HasExtDiv(false),
+ HasP9Vector(false) {
+ SuitableAlign = 128;
+ SimdDefaultAlign = 128;
+ LongDoubleWidth = LongDoubleAlign = 128;
+ LongDoubleFormat = &llvm::APFloat::PPCDoubleDouble();
+ }
+
+ /// \brief Flags for architecture specific defines.
+ typedef enum {
+ ArchDefineNone = 0,
+ ArchDefineName = 1 << 0, // <name> is substituted for arch name.
+ ArchDefinePpcgr = 1 << 1,
+ ArchDefinePpcsq = 1 << 2,
+ ArchDefine440 = 1 << 3,
+ ArchDefine603 = 1 << 4,
+ ArchDefine604 = 1 << 5,
+ ArchDefinePwr4 = 1 << 6,
+ ArchDefinePwr5 = 1 << 7,
+ ArchDefinePwr5x = 1 << 8,
+ ArchDefinePwr6 = 1 << 9,
+ ArchDefinePwr6x = 1 << 10,
+ ArchDefinePwr7 = 1 << 11,
+ ArchDefinePwr8 = 1 << 12,
+ ArchDefinePwr9 = 1 << 13,
+ ArchDefineA2 = 1 << 14,
+ ArchDefineA2q = 1 << 15
+ } ArchDefineTypes;
+
+ // Set the language option for altivec based on our value.
+ void adjust(LangOptions &Opts) override;
+
+ // Note: GCC recognizes the following additional cpus:
+ // 401, 403, 405, 405fp, 440fp, 464, 464fp, 476, 476fp, 505, 740, 801,
+ // 821, 823, 8540, 8548, e300c2, e300c3, e500mc64, e6500, 860, cell,
+ // titan, rs64.
+ bool isValidCPUName(StringRef Name) const override;
+
+ bool setCPU(const std::string &Name) override {
+ bool CPUKnown = isValidCPUName(Name);
+ if (CPUKnown)
+ CPU = Name;
+ return CPUKnown;
+ }
+
+ StringRef getABI() const override { return ABI; }
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+
+ bool isCLZForZeroUndef() const override { return false; }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ bool
+ initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
+ StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const override;
+
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) override;
+
+ bool hasFeature(StringRef Feature) const override;
+
+ void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name,
+ bool Enabled) const override;
+
+ ArrayRef<const char *> getGCCRegNames() const override;
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override {
+ switch (*Name) {
+ default:
+ return false;
+ case 'O': // Zero
+ break;
+ case 'b': // Base register
+ case 'f': // Floating point register
+ Info.setAllowsRegister();
+ break;
+ // FIXME: The following are added to allow parsing.
+ // I just took a guess at what the actions should be.
+ // Also, is more specific checking needed? I.e. specific registers?
+ case 'd': // Floating point register (containing 64-bit value)
+ case 'v': // Altivec vector register
+ Info.setAllowsRegister();
+ break;
+ case 'w':
+ switch (Name[1]) {
+ case 'd': // VSX vector register to hold vector double data
+ case 'f': // VSX vector register to hold vector float data
+ case 's': // VSX vector register to hold scalar float data
+ case 'a': // Any VSX register
+ case 'c': // An individual CR bit
+ break;
+ default:
+ return false;
+ }
+ Info.setAllowsRegister();
+ Name++; // Skip over 'w'.
+ break;
+ case 'h': // `MQ', `CTR', or `LINK' register
+ case 'q': // `MQ' register
+ case 'c': // `CTR' register
+ case 'l': // `LINK' register
+ case 'x': // `CR' register (condition register) number 0
+ case 'y': // `CR' register (condition register)
+ case 'z': // `XER[CA]' carry bit (part of the XER register)
+ Info.setAllowsRegister();
+ break;
+ case 'I': // Signed 16-bit constant
+ case 'J': // Unsigned 16-bit constant shifted left 16 bits
+ // (use `L' instead for SImode constants)
+ case 'K': // Unsigned 16-bit constant
+ case 'L': // Signed 16-bit constant shifted left 16 bits
+ case 'M': // Constant larger than 31
+ case 'N': // Exact power of 2
+ case 'P': // Constant whose negation is a signed 16-bit constant
+ case 'G': // Floating point constant that can be loaded into a
+ // register with one instruction per word
+ case 'H': // Integer/Floating point constant that can be loaded
+ // into a register using three instructions
+ break;
+ case 'm': // Memory operand. Note that on PowerPC targets, m can
+ // include addresses that update the base register. It
+ // is therefore only safe to use `m' in an asm statement
+ // if that asm statement accesses the operand exactly once.
+ // The asm statement must also use `%U<opno>' as a
+ // placeholder for the "update" flag in the corresponding
+ // load or store instruction. For example:
+ // asm ("st%U0 %1,%0" : "=m" (mem) : "r" (val));
+ // is correct but:
+ // asm ("st %1,%0" : "=m" (mem) : "r" (val));
+ // is not. Use es rather than m if you don't want the base
+ // register to be updated.
+ case 'e':
+ if (Name[1] != 's')
+ return false;
+ // es: A "stable" memory operand; that is, one which does not
+ // include any automodification of the base register. Unlike
+ // `m', this constraint can be used in asm statements that
+ // might access the operand several times, or that might not
+ // access it at all.
+ Info.setAllowsMemory();
+ Name++; // Skip over 'e'.
+ break;
+ case 'Q': // Memory operand that is an offset from a register (it is
+ // usually better to use `m' or `es' in asm statements)
+ case 'Z': // Memory operand that is an indexed or indirect from a
+ // register (it is usually better to use `m' or `es' in
+ // asm statements)
+ Info.setAllowsMemory();
+ Info.setAllowsRegister();
+ break;
+ case 'R': // AIX TOC entry
+ case 'a': // Address operand that is an indexed or indirect from a
+ // register (`p' is preferable for asm statements)
+ case 'S': // Constant suitable as a 64-bit mask operand
+ case 'T': // Constant suitable as a 32-bit mask operand
+ case 'U': // System V Release 4 small data area reference
+ case 't': // AND masks that can be performed by two rldic{l, r}
+ // instructions
+ case 'W': // Vector constant that does not require memory
+ case 'j': // Vector constant that is all zeros.
+ break;
+ // End FIXME.
+ }
+ return true;
+ }
+
+ std::string convertConstraint(const char *&Constraint) const override {
+ std::string R;
+ switch (*Constraint) {
+ case 'e':
+ case 'w':
+ // Two-character constraint; add "^" hint for later parsing.
+ R = std::string("^") + std::string(Constraint, 2);
+ Constraint++;
+ break;
+ default:
+ return TargetInfo::convertConstraint(Constraint);
+ }
+ return R;
+ }
+
+ const char *getClobbers() const override { return ""; }
+ int getEHDataRegisterNumber(unsigned RegNo) const override {
+ if (RegNo == 0)
+ return 3;
+ if (RegNo == 1)
+ return 4;
+ return -1;
+ }
+
+ bool hasSjLjLowering() const override { return true; }
+
+ bool useFloat128ManglingForLongDouble() const override {
+ return LongDoubleWidth == 128 &&
+ LongDoubleFormat == &llvm::APFloat::PPCDoubleDouble() &&
+ getTriple().isOSBinFormatELF();
+ }
+};
+
+class LLVM_LIBRARY_VISIBILITY PPC32TargetInfo : public PPCTargetInfo {
+public:
+ PPC32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : PPCTargetInfo(Triple, Opts) {
+ resetDataLayout("E-m:e-p:32:32-i64:64-n32");
+
+ switch (getTriple().getOS()) {
+ case llvm::Triple::Linux:
+ case llvm::Triple::FreeBSD:
+ case llvm::Triple::NetBSD:
+ SizeType = UnsignedInt;
+ PtrDiffType = SignedInt;
+ IntPtrType = SignedInt;
+ break;
+ default:
+ break;
+ }
+
+ if (getTriple().getOS() == llvm::Triple::FreeBSD) {
+ LongDoubleWidth = LongDoubleAlign = 64;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
+ }
+
+ // PPC32 supports atomics up to 4 bytes.
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;
+ }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ // This is the ELF definition, and is overridden by the Darwin sub-target
+ return TargetInfo::PowerABIBuiltinVaList;
+ }
+};
+
+// Note: ABI differences may eventually require us to have a separate
+// TargetInfo for little endian.
+class LLVM_LIBRARY_VISIBILITY PPC64TargetInfo : public PPCTargetInfo {
+public:
+ PPC64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : PPCTargetInfo(Triple, Opts) {
+ LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
+ IntMaxType = SignedLong;
+ Int64Type = SignedLong;
+
+ if ((Triple.getArch() == llvm::Triple::ppc64le)) {
+ resetDataLayout("e-m:e-i64:64-n32:64");
+ ABI = "elfv2";
+ } else {
+ resetDataLayout("E-m:e-i64:64-n32:64");
+ ABI = "elfv1";
+ }
+
+ switch (getTriple().getOS()) {
+ case llvm::Triple::FreeBSD:
+ LongDoubleWidth = LongDoubleAlign = 64;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
+ break;
+ case llvm::Triple::NetBSD:
+ IntMaxType = SignedLongLong;
+ Int64Type = SignedLongLong;
+ break;
+ default:
+ break;
+ }
+
+ // PPC64 supports atomics up to 8 bytes.
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
+ }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::CharPtrBuiltinVaList;
+ }
+
+ // PPC64 Linux-specific ABI options.
+ bool setABI(const std::string &Name) override {
+ if (Name == "elfv1" || Name == "elfv1-qpx" || Name == "elfv2") {
+ ABI = Name;
+ return true;
+ }
+ return false;
+ }
+};
+
+class LLVM_LIBRARY_VISIBILITY DarwinPPC32TargetInfo
+ : public DarwinTargetInfo<PPC32TargetInfo> {
+public:
+ DarwinPPC32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : DarwinTargetInfo<PPC32TargetInfo>(Triple, Opts) {
+ HasAlignMac68kSupport = true;
+ BoolWidth = BoolAlign = 32; // XXX support -mone-byte-bool?
+ PtrDiffType = SignedInt; // for http://llvm.org/bugs/show_bug.cgi?id=15726
+ LongLongAlign = 32;
+ resetDataLayout("E-m:o-p:32:32-f64:32:64-n32");
+ }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::CharPtrBuiltinVaList;
+ }
+};
+
+class LLVM_LIBRARY_VISIBILITY DarwinPPC64TargetInfo
+ : public DarwinTargetInfo<PPC64TargetInfo> {
+public:
+ DarwinPPC64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : DarwinTargetInfo<PPC64TargetInfo>(Triple, Opts) {
+ HasAlignMac68kSupport = true;
+ resetDataLayout("E-m:o-i64:64-n32:64");
+ }
+};
+
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_PPC_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/SPIR.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/SPIR.cpp
new file mode 100644
index 0000000000000..304d904368ca6
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/SPIR.cpp
@@ -0,0 +1,33 @@
+//===--- SPIR.cpp - Implement SPIR target feature support -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements SPIR TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SPIR.h"
+#include "Targets.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+void SPIRTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "SPIR", Opts);
+}
+
+void SPIR32TargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "SPIR32", Opts);
+}
+
+void SPIR64TargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "SPIR64", Opts);
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/SPIR.h b/contrib/llvm/tools/clang/lib/Basic/Targets/SPIR.h
new file mode 100644
index 0000000000000..c384d4260ca9e
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/SPIR.h
@@ -0,0 +1,127 @@
+//===--- SPIR.h - Declare SPIR target feature support -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares SPIR TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_SPIR_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_SPIR_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+static const unsigned SPIRAddrSpaceMap[] = {
+ 0, // Default
+ 1, // opencl_global
+ 3, // opencl_local
+ 2, // opencl_constant
+ 0, // opencl_private
+ 4, // opencl_generic
+ 0, // cuda_device
+ 0, // cuda_constant
+ 0 // cuda_shared
+};
+
+class LLVM_LIBRARY_VISIBILITY SPIRTargetInfo : public TargetInfo {
+public:
+ SPIRTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple) {
+ assert(getTriple().getOS() == llvm::Triple::UnknownOS &&
+ "SPIR target must use unknown OS");
+ assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment &&
+ "SPIR target must use unknown environment type");
+ TLSSupported = false;
+ VLASupported = false;
+ LongWidth = LongAlign = 64;
+ AddrSpaceMap = &SPIRAddrSpaceMap;
+ UseAddrSpaceMapMangling = true;
+ // Define available target features
+ // These must be defined in sorted order!
+ NoAsmVariants = true;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ bool hasFeature(StringRef Feature) const override {
+ return Feature == "spir";
+ }
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
+
+ const char *getClobbers() const override { return ""; }
+
+ ArrayRef<const char *> getGCCRegNames() const override { return None; }
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const override {
+ return true;
+ }
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ return None;
+ }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::VoidPtrBuiltinVaList;
+ }
+
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
+ return (CC == CC_SpirFunction || CC == CC_OpenCLKernel) ? CCCR_OK
+ : CCCR_Warning;
+ }
+
+ CallingConv getDefaultCallingConv(CallingConvMethodType MT) const override {
+ return CC_SpirFunction;
+ }
+
+ void setSupportedOpenCLOpts() override {
+ // Assume all OpenCL extensions and optional core features are supported
+ // for SPIR since it is a generic target.
+ getSupportedOpenCLOpts().supportAll();
+ }
+};
+class LLVM_LIBRARY_VISIBILITY SPIR32TargetInfo : public SPIRTargetInfo {
+public:
+ SPIR32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : SPIRTargetInfo(Triple, Opts) {
+ PointerWidth = PointerAlign = 32;
+ SizeType = TargetInfo::UnsignedInt;
+ PtrDiffType = IntPtrType = TargetInfo::SignedInt;
+ resetDataLayout("e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-"
+ "v96:128-v192:256-v256:256-v512:512-v1024:1024");
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY SPIR64TargetInfo : public SPIRTargetInfo {
+public:
+ SPIR64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : SPIRTargetInfo(Triple, Opts) {
+ PointerWidth = PointerAlign = 64;
+ SizeType = TargetInfo::UnsignedLong;
+ PtrDiffType = IntPtrType = TargetInfo::SignedLong;
+ resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-"
+ "v96:128-v192:256-v256:256-v512:512-v1024:1024");
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+};
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_SPIR_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Sparc.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/Sparc.cpp
new file mode 100644
index 0000000000000..429c1ee3a23c5
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Sparc.cpp
@@ -0,0 +1,197 @@
+//===--- Sparc.cpp - Implement Sparc target feature support ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements Sparc TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sparc.h"
+#include "Targets.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+const char *const SparcTargetInfo::GCCRegNames[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
+ "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21",
+ "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
+};
+
+ArrayRef<const char *> SparcTargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
+}
+
+const TargetInfo::GCCRegAlias SparcTargetInfo::GCCRegAliases[] = {
+ {{"g0"}, "r0"}, {{"g1"}, "r1"}, {{"g2"}, "r2"}, {{"g3"}, "r3"},
+ {{"g4"}, "r4"}, {{"g5"}, "r5"}, {{"g6"}, "r6"}, {{"g7"}, "r7"},
+ {{"o0"}, "r8"}, {{"o1"}, "r9"}, {{"o2"}, "r10"}, {{"o3"}, "r11"},
+ {{"o4"}, "r12"}, {{"o5"}, "r13"}, {{"o6", "sp"}, "r14"}, {{"o7"}, "r15"},
+ {{"l0"}, "r16"}, {{"l1"}, "r17"}, {{"l2"}, "r18"}, {{"l3"}, "r19"},
+ {{"l4"}, "r20"}, {{"l5"}, "r21"}, {{"l6"}, "r22"}, {{"l7"}, "r23"},
+ {{"i0"}, "r24"}, {{"i1"}, "r25"}, {{"i2"}, "r26"}, {{"i3"}, "r27"},
+ {{"i4"}, "r28"}, {{"i5"}, "r29"}, {{"i6", "fp"}, "r30"}, {{"i7"}, "r31"},
+};
+
+ArrayRef<TargetInfo::GCCRegAlias> SparcTargetInfo::getGCCRegAliases() const {
+ return llvm::makeArrayRef(GCCRegAliases);
+}
+
+bool SparcTargetInfo::hasFeature(StringRef Feature) const {
+ return llvm::StringSwitch<bool>(Feature)
+ .Case("softfloat", SoftFloat)
+ .Case("sparc", true)
+ .Default(false);
+}
+
+SparcTargetInfo::CPUKind SparcTargetInfo::getCPUKind(StringRef Name) const {
+ return llvm::StringSwitch<CPUKind>(Name)
+ .Case("v8", CK_V8)
+ .Case("supersparc", CK_SUPERSPARC)
+ .Case("sparclite", CK_SPARCLITE)
+ .Case("f934", CK_F934)
+ .Case("hypersparc", CK_HYPERSPARC)
+ .Case("sparclite86x", CK_SPARCLITE86X)
+ .Case("sparclet", CK_SPARCLET)
+ .Case("tsc701", CK_TSC701)
+ .Case("v9", CK_V9)
+ .Case("ultrasparc", CK_ULTRASPARC)
+ .Case("ultrasparc3", CK_ULTRASPARC3)
+ .Case("niagara", CK_NIAGARA)
+ .Case("niagara2", CK_NIAGARA2)
+ .Case("niagara3", CK_NIAGARA3)
+ .Case("niagara4", CK_NIAGARA4)
+ .Case("ma2100", CK_MYRIAD2100)
+ .Case("ma2150", CK_MYRIAD2150)
+ .Case("ma2155", CK_MYRIAD2155)
+ .Case("ma2450", CK_MYRIAD2450)
+ .Case("ma2455", CK_MYRIAD2455)
+ .Case("ma2x5x", CK_MYRIAD2x5x)
+ .Case("ma2080", CK_MYRIAD2080)
+ .Case("ma2085", CK_MYRIAD2085)
+ .Case("ma2480", CK_MYRIAD2480)
+ .Case("ma2485", CK_MYRIAD2485)
+ .Case("ma2x8x", CK_MYRIAD2x8x)
+ // FIXME: the myriad2[.n] spellings are obsolete,
+ // but a grace period is needed to allow updating dependent builds.
+ .Case("myriad2", CK_MYRIAD2x5x)
+ .Case("myriad2.1", CK_MYRIAD2100)
+ .Case("myriad2.2", CK_MYRIAD2x5x)
+ .Case("myriad2.3", CK_MYRIAD2x8x)
+ .Case("leon2", CK_LEON2)
+ .Case("at697e", CK_LEON2_AT697E)
+ .Case("at697f", CK_LEON2_AT697F)
+ .Case("leon3", CK_LEON3)
+ .Case("ut699", CK_LEON3_UT699)
+ .Case("gr712rc", CK_LEON3_GR712RC)
+ .Case("leon4", CK_LEON4)
+ .Case("gr740", CK_LEON4_GR740)
+ .Default(CK_GENERIC);
+}
+
+void SparcTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "sparc", Opts);
+ Builder.defineMacro("__REGISTER_PREFIX__", "");
+
+ if (SoftFloat)
+ Builder.defineMacro("SOFT_FLOAT", "1");
+}
+
+void SparcV8TargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ SparcTargetInfo::getTargetDefines(Opts, Builder);
+ switch (getCPUGeneration(CPU)) {
+ case CG_V8:
+ Builder.defineMacro("__sparcv8");
+ if (getTriple().getOS() != llvm::Triple::Solaris)
+ Builder.defineMacro("__sparcv8__");
+ break;
+ case CG_V9:
+ Builder.defineMacro("__sparcv9");
+ if (getTriple().getOS() != llvm::Triple::Solaris) {
+ Builder.defineMacro("__sparcv9__");
+ Builder.defineMacro("__sparc_v9__");
+ }
+ break;
+ }
+ if (getTriple().getVendor() == llvm::Triple::Myriad) {
+ std::string MyriadArchValue, Myriad2Value;
+ Builder.defineMacro("__sparc_v8__");
+ Builder.defineMacro("__leon__");
+ switch (CPU) {
+ case CK_MYRIAD2100:
+ MyriadArchValue = "__ma2100";
+ Myriad2Value = "1";
+ break;
+ case CK_MYRIAD2150:
+ MyriadArchValue = "__ma2150";
+ Myriad2Value = "2";
+ break;
+ case CK_MYRIAD2155:
+ MyriadArchValue = "__ma2155";
+ Myriad2Value = "2";
+ break;
+ case CK_MYRIAD2450:
+ MyriadArchValue = "__ma2450";
+ Myriad2Value = "2";
+ break;
+ case CK_MYRIAD2455:
+ MyriadArchValue = "__ma2455";
+ Myriad2Value = "2";
+ break;
+ case CK_MYRIAD2x5x:
+ Myriad2Value = "2";
+ break;
+ case CK_MYRIAD2080:
+ MyriadArchValue = "__ma2080";
+ Myriad2Value = "3";
+ break;
+ case CK_MYRIAD2085:
+ MyriadArchValue = "__ma2085";
+ Myriad2Value = "3";
+ break;
+ case CK_MYRIAD2480:
+ MyriadArchValue = "__ma2480";
+ Myriad2Value = "3";
+ break;
+ case CK_MYRIAD2485:
+ MyriadArchValue = "__ma2485";
+ Myriad2Value = "3";
+ break;
+ case CK_MYRIAD2x8x:
+ Myriad2Value = "3";
+ break;
+ default:
+ MyriadArchValue = "__ma2100";
+ Myriad2Value = "1";
+ break;
+ }
+ if (!MyriadArchValue.empty()) {
+ Builder.defineMacro(MyriadArchValue, "1");
+ Builder.defineMacro(MyriadArchValue + "__", "1");
+ }
+ Builder.defineMacro("__myriad2__", Myriad2Value);
+ Builder.defineMacro("__myriad2", Myriad2Value);
+ }
+}
+
+void SparcV9TargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ SparcTargetInfo::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("__sparcv9");
+ Builder.defineMacro("__arch64__");
+ // Solaris doesn't need these variants, but the BSDs do.
+ if (getTriple().getOS() != llvm::Triple::Solaris) {
+ Builder.defineMacro("__sparc64__");
+ Builder.defineMacro("__sparc_v9__");
+ Builder.defineMacro("__sparcv9__");
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/Sparc.h b/contrib/llvm/tools/clang/lib/Basic/Targets/Sparc.h
new file mode 100644
index 0000000000000..aacc26119dfbd
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/Sparc.h
@@ -0,0 +1,270 @@
+//===--- Sparc.h - Declare Sparc target feature support -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares Sparc TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_SPARC_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_SPARC_H
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+namespace clang {
+namespace targets {
+// Shared base class for SPARC v8 (32-bit) and SPARC v9 (64-bit).
+class LLVM_LIBRARY_VISIBILITY SparcTargetInfo : public TargetInfo {
+ static const TargetInfo::GCCRegAlias GCCRegAliases[];
+ static const char *const GCCRegNames[];
+ bool SoftFloat;
+
+public:
+ SparcTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple), SoftFloat(false) {}
+
+ int getEHDataRegisterNumber(unsigned RegNo) const override {
+ if (RegNo == 0)
+ return 24;
+ if (RegNo == 1)
+ return 25;
+ return -1;
+ }
+
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) override {
+ // Check if software floating point is enabled
+ auto Feature = std::find(Features.begin(), Features.end(), "+soft-float");
+ if (Feature != Features.end()) {
+ SoftFloat = true;
+ }
+ return true;
+ }
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ bool hasFeature(StringRef Feature) const override;
+
+ bool hasSjLjLowering() const override { return true; }
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override {
+ // FIXME: Implement!
+ return None;
+ }
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::VoidPtrBuiltinVaList;
+ }
+ ArrayRef<const char *> getGCCRegNames() const override;
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const override {
+ // FIXME: Implement!
+ switch (*Name) {
+ case 'I': // Signed 13-bit constant
+ case 'J': // Zero
+ case 'K': // 32-bit constant with the low 12 bits clear
+ case 'L': // A constant in the range supported by movcc (11-bit signed imm)
+ case 'M': // A constant in the range supported by movrcc (19-bit signed imm)
+ case 'N': // Same as 'K' but zext (required for SIMode)
+ case 'O': // The constant 4096
+ return true;
+
+ case 'f':
+ case 'e':
+ info.setAllowsRegister();
+ return true;
+ }
+ return false;
+ }
+ const char *getClobbers() const override {
+ // FIXME: Implement!
+ return "";
+ }
+
+ // No Sparc V7 for now, the backend doesn't support it anyway.
+ enum CPUKind {
+ CK_GENERIC,
+ CK_V8,
+ CK_SUPERSPARC,
+ CK_SPARCLITE,
+ CK_F934,
+ CK_HYPERSPARC,
+ CK_SPARCLITE86X,
+ CK_SPARCLET,
+ CK_TSC701,
+ CK_V9,
+ CK_ULTRASPARC,
+ CK_ULTRASPARC3,
+ CK_NIAGARA,
+ CK_NIAGARA2,
+ CK_NIAGARA3,
+ CK_NIAGARA4,
+ CK_MYRIAD2100,
+ CK_MYRIAD2150,
+ CK_MYRIAD2155,
+ CK_MYRIAD2450,
+ CK_MYRIAD2455,
+ CK_MYRIAD2x5x,
+ CK_MYRIAD2080,
+ CK_MYRIAD2085,
+ CK_MYRIAD2480,
+ CK_MYRIAD2485,
+ CK_MYRIAD2x8x,
+ CK_LEON2,
+ CK_LEON2_AT697E,
+ CK_LEON2_AT697F,
+ CK_LEON3,
+ CK_LEON3_UT699,
+ CK_LEON3_GR712RC,
+ CK_LEON4,
+ CK_LEON4_GR740
+ } CPU = CK_GENERIC;
+
+ enum CPUGeneration {
+ CG_V8,
+ CG_V9,
+ };
+
+ CPUGeneration getCPUGeneration(CPUKind Kind) const {
+ switch (Kind) {
+ case CK_GENERIC:
+ case CK_V8:
+ case CK_SUPERSPARC:
+ case CK_SPARCLITE:
+ case CK_F934:
+ case CK_HYPERSPARC:
+ case CK_SPARCLITE86X:
+ case CK_SPARCLET:
+ case CK_TSC701:
+ case CK_MYRIAD2100:
+ case CK_MYRIAD2150:
+ case CK_MYRIAD2155:
+ case CK_MYRIAD2450:
+ case CK_MYRIAD2455:
+ case CK_MYRIAD2x5x:
+ case CK_MYRIAD2080:
+ case CK_MYRIAD2085:
+ case CK_MYRIAD2480:
+ case CK_MYRIAD2485:
+ case CK_MYRIAD2x8x:
+ case CK_LEON2:
+ case CK_LEON2_AT697E:
+ case CK_LEON2_AT697F:
+ case CK_LEON3:
+ case CK_LEON3_UT699:
+ case CK_LEON3_GR712RC:
+ case CK_LEON4:
+ case CK_LEON4_GR740:
+ return CG_V8;
+ case CK_V9:
+ case CK_ULTRASPARC:
+ case CK_ULTRASPARC3:
+ case CK_NIAGARA:
+ case CK_NIAGARA2:
+ case CK_NIAGARA3:
+ case CK_NIAGARA4:
+ return CG_V9;
+ }
+ llvm_unreachable("Unexpected CPU kind");
+ }
+
+ CPUKind getCPUKind(StringRef Name) const;
+
+ bool isValidCPUName(StringRef Name) const override {
+ return getCPUKind(Name) != CK_GENERIC;
+ }
+
+ bool setCPU(const std::string &Name) override {
+ CPU = getCPUKind(Name);
+ return CPU != CK_GENERIC;
+ }
+};
+
+// SPARC v8 is the 32-bit mode selected by Triple::sparc.
+class LLVM_LIBRARY_VISIBILITY SparcV8TargetInfo : public SparcTargetInfo {
+public:
+ SparcV8TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : SparcTargetInfo(Triple, Opts) {
+ resetDataLayout("E-m:e-p:32:32-i64:64-f128:64-n32-S64");
+ // NetBSD / OpenBSD use long (same as llvm default); everyone else uses int.
+ switch (getTriple().getOS()) {
+ default:
+ SizeType = UnsignedInt;
+ IntPtrType = SignedInt;
+ PtrDiffType = SignedInt;
+ break;
+ case llvm::Triple::NetBSD:
+ case llvm::Triple::OpenBSD:
+ SizeType = UnsignedLong;
+ IntPtrType = SignedLong;
+ PtrDiffType = SignedLong;
+ break;
+ }
+ // Up to 32 bits are lock-free atomic, but we're willing to do atomic ops
+ // on up to 64 bits.
+ MaxAtomicPromoteWidth = 64;
+ MaxAtomicInlineWidth = 32;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ bool hasSjLjLowering() const override { return true; }
+};
+
+// SPARCV8el is the 32-bit little-endian mode selected by Triple::sparcel.
+class LLVM_LIBRARY_VISIBILITY SparcV8elTargetInfo : public SparcV8TargetInfo {
+public:
+ SparcV8elTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : SparcV8TargetInfo(Triple, Opts) {
+ resetDataLayout("e-m:e-p:32:32-i64:64-f128:64-n32-S64");
+ }
+};
+
+// SPARC v9 is the 64-bit mode selected by Triple::sparcv9.
+class LLVM_LIBRARY_VISIBILITY SparcV9TargetInfo : public SparcTargetInfo {
+public:
+ SparcV9TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : SparcTargetInfo(Triple, Opts) {
+ // FIXME: Support Sparc quad-precision long double?
+ resetDataLayout("E-m:e-i64:64-n32:64-S128");
+ // This is an LP64 platform.
+ LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
+
+ // OpenBSD uses long long for int64_t and intmax_t.
+ if (getTriple().getOS() == llvm::Triple::OpenBSD)
+ IntMaxType = SignedLongLong;
+ else
+ IntMaxType = SignedLong;
+ Int64Type = IntMaxType;
+
+ // The SPARCv8 System V ABI has long double 128-bits in size, but 64-bit
+ // aligned. The SPARCv9 SCD 2.4.1 says 16-byte aligned.
+ LongDoubleWidth = 128;
+ LongDoubleAlign = 128;
+ LongDoubleFormat = &llvm::APFloat::IEEEquad();
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ bool isValidCPUName(StringRef Name) const override {
+ return getCPUGeneration(SparcTargetInfo::getCPUKind(Name)) == CG_V9;
+ }
+
+ bool setCPU(const std::string &Name) override {
+ if (!SparcTargetInfo::setCPU(Name))
+ return false;
+ return getCPUGeneration(CPU) == CG_V9;
+ }
+};
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_SPARC_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/SystemZ.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/SystemZ.cpp
new file mode 100644
index 0000000000000..98f3ae2f72b47
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/SystemZ.cpp
@@ -0,0 +1,118 @@
+//===--- SystemZ.cpp - Implement SystemZ target feature support -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements SystemZ TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SystemZ.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+const Builtin::Info SystemZTargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
+#include "clang/Basic/BuiltinsSystemZ.def"
+};
+
+const char *const SystemZTargetInfo::GCCRegNames[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
+ "r11", "r12", "r13", "r14", "r15", "f0", "f2", "f4", "f6", "f1", "f3",
+ "f5", "f7", "f8", "f10", "f12", "f14", "f9", "f11", "f13", "f15"
+};
+
+ArrayRef<const char *> SystemZTargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
+}
+
+bool SystemZTargetInfo::validateAsmConstraint(
+ const char *&Name, TargetInfo::ConstraintInfo &Info) const {
+ switch (*Name) {
+ default:
+ return false;
+
+ case 'a': // Address register
+ case 'd': // Data register (equivalent to 'r')
+ case 'f': // Floating-point register
+ Info.setAllowsRegister();
+ return true;
+
+ case 'I': // Unsigned 8-bit constant
+ case 'J': // Unsigned 12-bit constant
+ case 'K': // Signed 16-bit constant
+ case 'L': // Signed 20-bit displacement (on all targets we support)
+ case 'M': // 0x7fffffff
+ return true;
+
+ case 'Q': // Memory with base and unsigned 12-bit displacement
+ case 'R': // Likewise, plus an index
+ case 'S': // Memory with base and signed 20-bit displacement
+ case 'T': // Likewise, plus an index
+ Info.setAllowsMemory();
+ return true;
+ }
+}
+
+int SystemZTargetInfo::getISARevision(const StringRef &Name) const {
+ return llvm::StringSwitch<int>(Name)
+ .Cases("arch8", "z10", 8)
+ .Cases("arch9", "z196", 9)
+ .Cases("arch10", "zEC12", 10)
+ .Cases("arch11", "z13", 11)
+ .Cases("arch12", "z14", 12)
+ .Default(-1);
+}
+
+bool SystemZTargetInfo::hasFeature(StringRef Feature) const {
+ return llvm::StringSwitch<bool>(Feature)
+ .Case("systemz", true)
+ .Case("arch8", ISARevision >= 8)
+ .Case("arch9", ISARevision >= 9)
+ .Case("arch10", ISARevision >= 10)
+ .Case("arch11", ISARevision >= 11)
+ .Case("arch12", ISARevision >= 12)
+ .Case("htm", HasTransactionalExecution)
+ .Case("vx", HasVector)
+ .Default(false);
+}
+
+void SystemZTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__s390__");
+ Builder.defineMacro("__s390x__");
+ Builder.defineMacro("__zarch__");
+ Builder.defineMacro("__LONG_DOUBLE_128__");
+
+ Builder.defineMacro("__ARCH__", Twine(ISARevision));
+
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
+
+ if (HasTransactionalExecution)
+ Builder.defineMacro("__HTM__");
+ if (HasVector)
+ Builder.defineMacro("__VX__");
+ if (Opts.ZVector)
+ Builder.defineMacro("__VEC__", "10302");
+}
+
+ArrayRef<Builtin::Info> SystemZTargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfo, clang::SystemZ::LastTSBuiltin -
+ Builtin::FirstTSBuiltin);
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/SystemZ.h b/contrib/llvm/tools/clang/lib/Basic/Targets/SystemZ.h
new file mode 100644
index 0000000000000..3023c1d2ea262
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/SystemZ.h
@@ -0,0 +1,145 @@
+//===--- SystemZ.h - Declare SystemZ target feature support -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares SystemZ TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_SYSTEMZ_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_SYSTEMZ_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo {
+
+ static const Builtin::Info BuiltinInfo[];
+ static const char *const GCCRegNames[];
+ std::string CPU;
+ int ISARevision;
+ bool HasTransactionalExecution;
+ bool HasVector;
+
+public:
+ SystemZTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple), CPU("z10"), ISARevision(8),
+ HasTransactionalExecution(false), HasVector(false) {
+ IntMaxType = SignedLong;
+ Int64Type = SignedLong;
+ TLSSupported = true;
+ IntWidth = IntAlign = 32;
+ LongWidth = LongLongWidth = LongAlign = LongLongAlign = 64;
+ PointerWidth = PointerAlign = 64;
+ LongDoubleWidth = 128;
+ LongDoubleAlign = 64;
+ LongDoubleFormat = &llvm::APFloat::IEEEquad();
+ DefaultAlignForAttributeAligned = 64;
+ MinGlobalAlign = 16;
+ resetDataLayout("E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64");
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+
+ ArrayRef<const char *> getGCCRegNames() const override;
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ // No aliases.
+ return None;
+ }
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const override;
+
+ const char *getClobbers() const override {
+ // FIXME: Is this really right?
+ return "";
+ }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::SystemZBuiltinVaList;
+ }
+
+ int getISARevision(const StringRef &Name) const;
+
+ bool isValidCPUName(StringRef Name) const override {
+ return getISARevision(Name) != -1;
+ }
+
+ bool setCPU(const std::string &Name) override {
+ CPU = Name;
+ ISARevision = getISARevision(CPU);
+ return ISARevision != -1;
+ }
+
+ bool
+ initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
+ StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const override {
+ int ISARevision = getISARevision(CPU);
+ if (ISARevision >= 10)
+ Features["transactional-execution"] = true;
+ if (ISARevision >= 11)
+ Features["vector"] = true;
+ if (ISARevision >= 12)
+ Features["vector-enhancements-1"] = true;
+ return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
+ }
+
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) override {
+ HasTransactionalExecution = false;
+ HasVector = false;
+ for (const auto &Feature : Features) {
+ if (Feature == "+transactional-execution")
+ HasTransactionalExecution = true;
+ else if (Feature == "+vector")
+ HasVector = true;
+ }
+ // If we use the vector ABI, vector types are 64-bit aligned.
+ if (HasVector) {
+ MaxVectorAlign = 64;
+ resetDataLayout("E-m:e-i1:8:16-i8:8:16-i64:64-f128:64"
+ "-v128:64-a:8:16-n32:64");
+ }
+ return true;
+ }
+
+ bool hasFeature(StringRef Feature) const override;
+
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
+ switch (CC) {
+ case CC_C:
+ case CC_Swift:
+ case CC_OpenCLKernel:
+ return CCCR_OK;
+ default:
+ return CCCR_Warning;
+ }
+ }
+
+ StringRef getABI() const override {
+ if (HasVector)
+ return "vector";
+ return "";
+ }
+
+ bool useFloat128ManglingForLongDouble() const override { return true; }
+};
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_SYSTEMZ_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/TCE.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/TCE.cpp
new file mode 100644
index 0000000000000..bf89c1dc549eb
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/TCE.cpp
@@ -0,0 +1,35 @@
+//===--- TCE.cpp - Implement TCE target feature support -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements TCE TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TCE.h"
+#include "Targets.h"
+#include "clang/Basic/MacroBuilder.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+void TCETargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "tce", Opts);
+ Builder.defineMacro("__TCE__");
+ Builder.defineMacro("__TCE_V1__");
+}
+
+void TCELETargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "tcele", Opts);
+ Builder.defineMacro("__TCE__");
+ Builder.defineMacro("__TCE_V1__");
+ Builder.defineMacro("__TCELE__");
+ Builder.defineMacro("__TCELE_V1__");
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/TCE.h b/contrib/llvm/tools/clang/lib/Basic/Targets/TCE.h
new file mode 100644
index 0000000000000..be43bed98d80b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/TCE.h
@@ -0,0 +1,123 @@
+//===--- TCE.h - Declare TCE target feature support -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares TCE TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_TCE_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_TCE_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+// llvm and clang cannot be used directly to output native binaries for
+// target, but is used to compile C code to llvm bitcode with correct
+// type and alignment information.
+//
+// TCE uses the llvm bitcode as input and uses it for generating customized
+// target processor and program binary. TCE co-design environment is
+// publicly available in http://tce.cs.tut.fi
+
+static const unsigned TCEOpenCLAddrSpaceMap[] = {
+ 0, // Default
+ 3, // opencl_global
+ 4, // opencl_local
+ 5, // opencl_constant
+ 0, // opencl_private
+ // FIXME: generic has to be added to the target
+ 0, // opencl_generic
+ 0, // cuda_device
+ 0, // cuda_constant
+ 0 // cuda_shared
+};
+
+class LLVM_LIBRARY_VISIBILITY TCETargetInfo : public TargetInfo {
+public:
+ TCETargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple) {
+ TLSSupported = false;
+ IntWidth = 32;
+ LongWidth = LongLongWidth = 32;
+ PointerWidth = 32;
+ IntAlign = 32;
+ LongAlign = LongLongAlign = 32;
+ PointerAlign = 32;
+ SuitableAlign = 32;
+ SizeType = UnsignedInt;
+ IntMaxType = SignedLong;
+ IntPtrType = SignedInt;
+ PtrDiffType = SignedInt;
+ FloatWidth = 32;
+ FloatAlign = 32;
+ DoubleWidth = 32;
+ DoubleAlign = 32;
+ LongDoubleWidth = 32;
+ LongDoubleAlign = 32;
+ FloatFormat = &llvm::APFloat::IEEEsingle();
+ DoubleFormat = &llvm::APFloat::IEEEsingle();
+ LongDoubleFormat = &llvm::APFloat::IEEEsingle();
+ resetDataLayout("E-p:32:32:32-i1:8:8-i8:8:32-"
+ "i16:16:32-i32:32:32-i64:32:32-"
+ "f32:32:32-f64:32:32-v64:32:32-"
+ "v128:32:32-v256:32:32-v512:32:32-"
+ "v1024:32:32-a0:0:32-n32");
+ AddrSpaceMap = &TCEOpenCLAddrSpaceMap;
+ UseAddrSpaceMapMangling = true;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ bool hasFeature(StringRef Feature) const override { return Feature == "tce"; }
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
+
+ const char *getClobbers() const override { return ""; }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::VoidPtrBuiltinVaList;
+ }
+
+ ArrayRef<const char *> getGCCRegNames() const override { return None; }
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const override {
+ return true;
+ }
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ return None;
+ }
+};
+
+class LLVM_LIBRARY_VISIBILITY TCELETargetInfo : public TCETargetInfo {
+public:
+ TCELETargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : TCETargetInfo(Triple, Opts) {
+ BigEndian = false;
+
+ resetDataLayout("e-p:32:32:32-i1:8:8-i8:8:32-"
+ "i16:16:32-i32:32:32-i64:32:32-"
+ "f32:32:32-f64:32:32-v64:32:32-"
+ "v128:32:32-v256:32:32-v512:32:32-"
+ "v1024:32:32-a0:0:32-n32");
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+};
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_TCE_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/WebAssembly.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/WebAssembly.cpp
new file mode 100644
index 0000000000000..915aad4b563b4
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/WebAssembly.cpp
@@ -0,0 +1,96 @@
+//===--- WebAssembly.cpp - Implement WebAssembly target feature support ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements WebAssembly TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "WebAssembly.h"
+#include "Targets.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+const Builtin::Info WebAssemblyTargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
+ {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
+#include "clang/Basic/BuiltinsWebAssembly.def"
+};
+
+bool WebAssemblyTargetInfo::hasFeature(StringRef Feature) const {
+ return llvm::StringSwitch<bool>(Feature)
+ .Case("simd128", SIMDLevel >= SIMD128)
+ .Case("nontrapping-fptoint", HasNontrappingFPToInt)
+ .Default(false);
+}
+
+bool WebAssemblyTargetInfo::isValidCPUName(StringRef Name) const {
+ return llvm::StringSwitch<bool>(Name)
+ .Case("mvp", true)
+ .Case("bleeding-edge", true)
+ .Case("generic", true)
+ .Default(false);
+}
+
+void WebAssemblyTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ defineCPUMacros(Builder, "wasm", /*Tuning=*/false);
+ if (SIMDLevel >= SIMD128)
+ Builder.defineMacro("__wasm_simd128__");
+}
+
+bool WebAssemblyTargetInfo::handleTargetFeatures(
+ std::vector<std::string> &Features, DiagnosticsEngine &Diags) {
+ for (const auto &Feature : Features) {
+ if (Feature == "+simd128") {
+ SIMDLevel = std::max(SIMDLevel, SIMD128);
+ continue;
+ }
+ if (Feature == "-simd128") {
+ SIMDLevel = std::min(SIMDLevel, SIMDEnum(SIMD128 - 1));
+ continue;
+ }
+ if (Feature == "+nontrapping-fptoint") {
+ HasNontrappingFPToInt = true;
+ continue;
+ }
+ if (Feature == "-nontrapping-fptoint") {
+ HasNontrappingFPToInt = false;
+ continue;
+ }
+
+ Diags.Report(diag::err_opt_not_valid_with_opt)
+ << Feature << "-target-feature";
+ return false;
+ }
+ return true;
+}
+
+ArrayRef<Builtin::Info> WebAssemblyTargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfo, clang::WebAssembly::LastTSBuiltin -
+ Builtin::FirstTSBuiltin);
+}
+
+void WebAssembly32TargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);
+ defineCPUMacros(Builder, "wasm32", /*Tuning=*/false);
+}
+
+void WebAssembly64TargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);
+ defineCPUMacros(Builder, "wasm64", /*Tuning=*/false);
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/WebAssembly.h b/contrib/llvm/tools/clang/lib/Basic/Targets/WebAssembly.h
new file mode 100644
index 0000000000000..ee0073d081e0a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/WebAssembly.h
@@ -0,0 +1,148 @@
+//=== WebAssembly.h - Declare WebAssembly target feature support *- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares WebAssembly TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_WEBASSEMBLY_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_WEBASSEMBLY_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY WebAssemblyTargetInfo : public TargetInfo {
+ static const Builtin::Info BuiltinInfo[];
+
+ enum SIMDEnum {
+ NoSIMD,
+ SIMD128,
+ } SIMDLevel;
+
+ bool HasNontrappingFPToInt;
+
+public:
+ explicit WebAssemblyTargetInfo(const llvm::Triple &T, const TargetOptions &)
+ : TargetInfo(T), SIMDLevel(NoSIMD), HasNontrappingFPToInt(false) {
+ NoAsmVariants = true;
+ SuitableAlign = 128;
+ LargeArrayMinWidth = 128;
+ LargeArrayAlign = 128;
+ SimdDefaultAlign = 128;
+ SigAtomicType = SignedLong;
+ LongDoubleWidth = LongDoubleAlign = 128;
+ LongDoubleFormat = &llvm::APFloat::IEEEquad();
+ SizeType = UnsignedInt;
+ PtrDiffType = SignedInt;
+ IntPtrType = SignedInt;
+ }
+
+protected:
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+private:
+ bool
+ initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
+ StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const override {
+ if (CPU == "bleeding-edge") {
+ Features["simd128"] = true;
+ Features["nontrapping-fptoint"] = true;
+ }
+ return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
+ }
+
+ bool hasFeature(StringRef Feature) const final;
+
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) final;
+
+ bool isValidCPUName(StringRef Name) const final;
+
+ bool setCPU(const std::string &Name) final { return isValidCPUName(Name); }
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const final;
+
+ BuiltinVaListKind getBuiltinVaListKind() const final {
+ return VoidPtrBuiltinVaList;
+ }
+
+ ArrayRef<const char *> getGCCRegNames() const final { return None; }
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const final {
+ return None;
+ }
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const final {
+ return false;
+ }
+
+ const char *getClobbers() const final { return ""; }
+
+ bool isCLZForZeroUndef() const final { return false; }
+
+ bool hasInt128Type() const final { return true; }
+
+ IntType getIntTypeByWidth(unsigned BitWidth, bool IsSigned) const final {
+ // WebAssembly prefers long long for explicitly 64-bit integers.
+ return BitWidth == 64 ? (IsSigned ? SignedLongLong : UnsignedLongLong)
+ : TargetInfo::getIntTypeByWidth(BitWidth, IsSigned);
+ }
+
+ IntType getLeastIntTypeByWidth(unsigned BitWidth, bool IsSigned) const final {
+ // WebAssembly uses long long for int_least64_t and int_fast64_t.
+ return BitWidth == 64
+ ? (IsSigned ? SignedLongLong : UnsignedLongLong)
+ : TargetInfo::getLeastIntTypeByWidth(BitWidth, IsSigned);
+ }
+};
+class LLVM_LIBRARY_VISIBILITY WebAssembly32TargetInfo
+ : public WebAssemblyTargetInfo {
+public:
+ explicit WebAssembly32TargetInfo(const llvm::Triple &T,
+ const TargetOptions &Opts)
+ : WebAssemblyTargetInfo(T, Opts) {
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
+ resetDataLayout("e-m:e-p:32:32-i64:64-n32:64-S128");
+ }
+
+protected:
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY WebAssembly64TargetInfo
+ : public WebAssemblyTargetInfo {
+public:
+ explicit WebAssembly64TargetInfo(const llvm::Triple &T,
+ const TargetOptions &Opts)
+ : WebAssemblyTargetInfo(T, Opts) {
+ LongAlign = LongWidth = 64;
+ PointerAlign = PointerWidth = 64;
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
+ SizeType = UnsignedLong;
+ PtrDiffType = SignedLong;
+ IntPtrType = SignedLong;
+ resetDataLayout("e-m:e-p:64:64-i64:64-n32:64-S128");
+ }
+
+protected:
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+};
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_WEBASSEMBLY_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/X86.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/X86.cpp
new file mode 100644
index 0000000000000..7fd9fd0478181
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/X86.cpp
@@ -0,0 +1,1518 @@
+//===--- X86.cpp - Implement X86 target feature support -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements X86 TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "X86.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+
+namespace clang {
+namespace targets {
+
+const Builtin::Info BuiltinInfoX86[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
+#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \
+ {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE},
+#include "clang/Basic/BuiltinsX86.def"
+
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
+#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \
+ {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE},
+#include "clang/Basic/BuiltinsX86_64.def"
+};
+
+static const char *const GCCRegNames[] = {
+ "ax", "dx", "cx", "bx", "si", "di", "bp", "sp",
+ "st", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)",
+ "argp", "flags", "fpcr", "fpsr", "dirflag", "frame", "xmm0", "xmm1",
+ "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "mm0", "mm1",
+ "mm2", "mm3", "mm4", "mm5", "mm6", "mm7", "r8", "r9",
+ "r10", "r11", "r12", "r13", "r14", "r15", "xmm8", "xmm9",
+ "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "ymm0", "ymm1",
+ "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", "ymm8", "ymm9",
+ "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15", "xmm16", "xmm17",
+ "xmm18", "xmm19", "xmm20", "xmm21", "xmm22", "xmm23", "xmm24", "xmm25",
+ "xmm26", "xmm27", "xmm28", "xmm29", "xmm30", "xmm31", "ymm16", "ymm17",
+ "ymm18", "ymm19", "ymm20", "ymm21", "ymm22", "ymm23", "ymm24", "ymm25",
+ "ymm26", "ymm27", "ymm28", "ymm29", "ymm30", "ymm31", "zmm0", "zmm1",
+ "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", "zmm8", "zmm9",
+ "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15", "zmm16", "zmm17",
+ "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", "zmm24", "zmm25",
+ "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31", "k0", "k1",
+ "k2", "k3", "k4", "k5", "k6", "k7",
+ "cr0", "cr2", "cr3", "cr4", "cr8",
+ "dr0", "dr1", "dr2", "dr3", "dr6", "dr7",
+ "bnd0", "bnd1", "bnd2", "bnd3",
+};
+
+const TargetInfo::AddlRegName AddlRegNames[] = {
+ {{"al", "ah", "eax", "rax"}, 0},
+ {{"bl", "bh", "ebx", "rbx"}, 3},
+ {{"cl", "ch", "ecx", "rcx"}, 2},
+ {{"dl", "dh", "edx", "rdx"}, 1},
+ {{"esi", "rsi"}, 4},
+ {{"edi", "rdi"}, 5},
+ {{"esp", "rsp"}, 7},
+ {{"ebp", "rbp"}, 6},
+ {{"r8d", "r8w", "r8b"}, 38},
+ {{"r9d", "r9w", "r9b"}, 39},
+ {{"r10d", "r10w", "r10b"}, 40},
+ {{"r11d", "r11w", "r11b"}, 41},
+ {{"r12d", "r12w", "r12b"}, 42},
+ {{"r13d", "r13w", "r13b"}, 43},
+ {{"r14d", "r14w", "r14b"}, 44},
+ {{"r15d", "r15w", "r15b"}, 45},
+};
+
+} // namespace targets
+} // namespace clang
+
+using namespace clang;
+using namespace clang::targets;
+
+bool X86TargetInfo::setFPMath(StringRef Name) {
+ if (Name == "387") {
+ FPMath = FP_387;
+ return true;
+ }
+ if (Name == "sse") {
+ FPMath = FP_SSE;
+ return true;
+ }
+ return false;
+}
+
+bool X86TargetInfo::initFeatureMap(
+ llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const {
+ // FIXME: This *really* should not be here.
+ // X86_64 always has SSE2.
+ if (getTriple().getArch() == llvm::Triple::x86_64)
+ setFeatureEnabledImpl(Features, "sse2", true);
+
+ const CPUKind Kind = getCPUKind(CPU);
+
+ // Enable X87 for all X86 processors but Lakemont.
+ if (Kind != CK_Lakemont)
+ setFeatureEnabledImpl(Features, "x87", true);
+
+ switch (Kind) {
+ case CK_Generic:
+ case CK_i386:
+ case CK_i486:
+ case CK_i586:
+ case CK_Pentium:
+ case CK_PentiumPro:
+ case CK_Lakemont:
+ break;
+
+ case CK_PentiumMMX:
+ case CK_Pentium2:
+ case CK_K6:
+ case CK_WinChipC6:
+ setFeatureEnabledImpl(Features, "mmx", true);
+ break;
+
+ case CK_Icelake:
+ // TODO: Add icelake features here.
+ LLVM_FALLTHROUGH;
+ case CK_Cannonlake:
+ setFeatureEnabledImpl(Features, "avx512ifma", true);
+ setFeatureEnabledImpl(Features, "avx512vbmi", true);
+ setFeatureEnabledImpl(Features, "sha", true);
+ LLVM_FALLTHROUGH;
+ case CK_SkylakeServer:
+ setFeatureEnabledImpl(Features, "avx512f", true);
+ setFeatureEnabledImpl(Features, "avx512cd", true);
+ setFeatureEnabledImpl(Features, "avx512dq", true);
+ setFeatureEnabledImpl(Features, "avx512bw", true);
+ setFeatureEnabledImpl(Features, "avx512vl", true);
+ setFeatureEnabledImpl(Features, "pku", true);
+ setFeatureEnabledImpl(Features, "clwb", true);
+ LLVM_FALLTHROUGH;
+ case CK_SkylakeClient:
+ setFeatureEnabledImpl(Features, "xsavec", true);
+ setFeatureEnabledImpl(Features, "xsaves", true);
+ setFeatureEnabledImpl(Features, "mpx", true);
+ setFeatureEnabledImpl(Features, "sgx", true);
+ setFeatureEnabledImpl(Features, "clflushopt", true);
+ setFeatureEnabledImpl(Features, "rtm", true);
+ LLVM_FALLTHROUGH;
+ case CK_Broadwell:
+ setFeatureEnabledImpl(Features, "rdseed", true);
+ setFeatureEnabledImpl(Features, "adx", true);
+ LLVM_FALLTHROUGH;
+ case CK_Haswell:
+ setFeatureEnabledImpl(Features, "avx2", true);
+ setFeatureEnabledImpl(Features, "lzcnt", true);
+ setFeatureEnabledImpl(Features, "bmi", true);
+ setFeatureEnabledImpl(Features, "bmi2", true);
+ setFeatureEnabledImpl(Features, "fma", true);
+ setFeatureEnabledImpl(Features, "movbe", true);
+ LLVM_FALLTHROUGH;
+ case CK_IvyBridge:
+ setFeatureEnabledImpl(Features, "rdrnd", true);
+ setFeatureEnabledImpl(Features, "f16c", true);
+ setFeatureEnabledImpl(Features, "fsgsbase", true);
+ LLVM_FALLTHROUGH;
+ case CK_SandyBridge:
+ setFeatureEnabledImpl(Features, "avx", true);
+ setFeatureEnabledImpl(Features, "xsave", true);
+ setFeatureEnabledImpl(Features, "xsaveopt", true);
+ LLVM_FALLTHROUGH;
+ case CK_Westmere:
+ setFeatureEnabledImpl(Features, "aes", true);
+ setFeatureEnabledImpl(Features, "pclmul", true);
+ LLVM_FALLTHROUGH;
+ case CK_Nehalem:
+ setFeatureEnabledImpl(Features, "sse4.2", true);
+ LLVM_FALLTHROUGH;
+ case CK_Penryn:
+ setFeatureEnabledImpl(Features, "sse4.1", true);
+ LLVM_FALLTHROUGH;
+ case CK_Core2:
+ setFeatureEnabledImpl(Features, "ssse3", true);
+ LLVM_FALLTHROUGH;
+ case CK_Yonah:
+ case CK_Prescott:
+ case CK_Nocona:
+ setFeatureEnabledImpl(Features, "sse3", true);
+ setFeatureEnabledImpl(Features, "cx16", true);
+ LLVM_FALLTHROUGH;
+ case CK_PentiumM:
+ case CK_Pentium4:
+ case CK_x86_64:
+ setFeatureEnabledImpl(Features, "sse2", true);
+ LLVM_FALLTHROUGH;
+ case CK_Pentium3:
+ case CK_C3_2:
+ setFeatureEnabledImpl(Features, "sse", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
+ break;
+
+ case CK_Goldmont:
+ setFeatureEnabledImpl(Features, "sha", true);
+ setFeatureEnabledImpl(Features, "rdrnd", true);
+ setFeatureEnabledImpl(Features, "rdseed", true);
+ setFeatureEnabledImpl(Features, "xsave", true);
+ setFeatureEnabledImpl(Features, "xsaveopt", true);
+ setFeatureEnabledImpl(Features, "xsavec", true);
+ setFeatureEnabledImpl(Features, "xsaves", true);
+ setFeatureEnabledImpl(Features, "clflushopt", true);
+ setFeatureEnabledImpl(Features, "mpx", true);
+ setFeatureEnabledImpl(Features, "fsgsbase", true);
+ LLVM_FALLTHROUGH;
+ case CK_Silvermont:
+ setFeatureEnabledImpl(Features, "aes", true);
+ setFeatureEnabledImpl(Features, "pclmul", true);
+ setFeatureEnabledImpl(Features, "sse4.2", true);
+ LLVM_FALLTHROUGH;
+ case CK_Bonnell:
+ setFeatureEnabledImpl(Features, "movbe", true);
+ setFeatureEnabledImpl(Features, "ssse3", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
+ setFeatureEnabledImpl(Features, "cx16", true);
+ break;
+
+ case CK_KNM:
+ // TODO: Add avx5124fmaps/avx5124vnniw.
+ setFeatureEnabledImpl(Features, "avx512vpopcntdq", true);
+ LLVM_FALLTHROUGH;
+ case CK_KNL:
+ setFeatureEnabledImpl(Features, "avx512f", true);
+ setFeatureEnabledImpl(Features, "avx512cd", true);
+ setFeatureEnabledImpl(Features, "avx512er", true);
+ setFeatureEnabledImpl(Features, "avx512pf", true);
+ setFeatureEnabledImpl(Features, "prefetchwt1", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
+ setFeatureEnabledImpl(Features, "rdseed", true);
+ setFeatureEnabledImpl(Features, "adx", true);
+ setFeatureEnabledImpl(Features, "lzcnt", true);
+ setFeatureEnabledImpl(Features, "bmi", true);
+ setFeatureEnabledImpl(Features, "bmi2", true);
+ setFeatureEnabledImpl(Features, "rtm", true);
+ setFeatureEnabledImpl(Features, "fma", true);
+ setFeatureEnabledImpl(Features, "rdrnd", true);
+ setFeatureEnabledImpl(Features, "f16c", true);
+ setFeatureEnabledImpl(Features, "fsgsbase", true);
+ setFeatureEnabledImpl(Features, "aes", true);
+ setFeatureEnabledImpl(Features, "pclmul", true);
+ setFeatureEnabledImpl(Features, "cx16", true);
+ setFeatureEnabledImpl(Features, "xsaveopt", true);
+ setFeatureEnabledImpl(Features, "xsave", true);
+ setFeatureEnabledImpl(Features, "movbe", true);
+ break;
+
+ case CK_K6_2:
+ case CK_K6_3:
+ case CK_WinChip2:
+ case CK_C3:
+ setFeatureEnabledImpl(Features, "3dnow", true);
+ break;
+
+ case CK_AMDFAM10:
+ setFeatureEnabledImpl(Features, "sse4a", true);
+ setFeatureEnabledImpl(Features, "lzcnt", true);
+ setFeatureEnabledImpl(Features, "popcnt", true);
+ LLVM_FALLTHROUGH;
+ case CK_K8SSE3:
+ setFeatureEnabledImpl(Features, "sse3", true);
+ LLVM_FALLTHROUGH;
+ case CK_K8:
+ setFeatureEnabledImpl(Features, "sse2", true);
+ LLVM_FALLTHROUGH;
+ case CK_AthlonXP:
+ setFeatureEnabledImpl(Features, "sse", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
+ LLVM_FALLTHROUGH;
+ case CK_Athlon:
+ case CK_Geode:
+ setFeatureEnabledImpl(Features, "3dnowa", true);
+ break;
+
+ case CK_BTVER2:
+ setFeatureEnabledImpl(Features, "avx", true);
+ setFeatureEnabledImpl(Features, "aes", true);
+ setFeatureEnabledImpl(Features, "pclmul", true);
+ setFeatureEnabledImpl(Features, "bmi", true);
+ setFeatureEnabledImpl(Features, "f16c", true);
+ setFeatureEnabledImpl(Features, "xsaveopt", true);
+ setFeatureEnabledImpl(Features, "movbe", true);
+ LLVM_FALLTHROUGH;
+ case CK_BTVER1:
+ setFeatureEnabledImpl(Features, "ssse3", true);
+ setFeatureEnabledImpl(Features, "sse4a", true);
+ setFeatureEnabledImpl(Features, "lzcnt", true);
+ setFeatureEnabledImpl(Features, "popcnt", true);
+ setFeatureEnabledImpl(Features, "prfchw", true);
+ setFeatureEnabledImpl(Features, "cx16", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
+ break;
+
+ case CK_ZNVER1:
+ setFeatureEnabledImpl(Features, "adx", true);
+ setFeatureEnabledImpl(Features, "aes", true);
+ setFeatureEnabledImpl(Features, "avx2", true);
+ setFeatureEnabledImpl(Features, "bmi", true);
+ setFeatureEnabledImpl(Features, "bmi2", true);
+ setFeatureEnabledImpl(Features, "clflushopt", true);
+ setFeatureEnabledImpl(Features, "clzero", true);
+ setFeatureEnabledImpl(Features, "cx16", true);
+ setFeatureEnabledImpl(Features, "f16c", true);
+ setFeatureEnabledImpl(Features, "fma", true);
+ setFeatureEnabledImpl(Features, "fsgsbase", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
+ setFeatureEnabledImpl(Features, "lzcnt", true);
+ setFeatureEnabledImpl(Features, "mwaitx", true);
+ setFeatureEnabledImpl(Features, "movbe", true);
+ setFeatureEnabledImpl(Features, "pclmul", true);
+ setFeatureEnabledImpl(Features, "popcnt", true);
+ setFeatureEnabledImpl(Features, "prfchw", true);
+ setFeatureEnabledImpl(Features, "rdrnd", true);
+ setFeatureEnabledImpl(Features, "rdseed", true);
+ setFeatureEnabledImpl(Features, "sha", true);
+ setFeatureEnabledImpl(Features, "sse4a", true);
+ setFeatureEnabledImpl(Features, "xsave", true);
+ setFeatureEnabledImpl(Features, "xsavec", true);
+ setFeatureEnabledImpl(Features, "xsaveopt", true);
+ setFeatureEnabledImpl(Features, "xsaves", true);
+ break;
+
+ case CK_BDVER4:
+ setFeatureEnabledImpl(Features, "avx2", true);
+ setFeatureEnabledImpl(Features, "bmi2", true);
+ setFeatureEnabledImpl(Features, "mwaitx", true);
+ LLVM_FALLTHROUGH;
+ case CK_BDVER3:
+ setFeatureEnabledImpl(Features, "fsgsbase", true);
+ setFeatureEnabledImpl(Features, "xsaveopt", true);
+ LLVM_FALLTHROUGH;
+ case CK_BDVER2:
+ setFeatureEnabledImpl(Features, "bmi", true);
+ setFeatureEnabledImpl(Features, "fma", true);
+ setFeatureEnabledImpl(Features, "f16c", true);
+ setFeatureEnabledImpl(Features, "tbm", true);
+ LLVM_FALLTHROUGH;
+ case CK_BDVER1:
+ // xop implies avx, sse4a and fma4.
+ setFeatureEnabledImpl(Features, "xop", true);
+ setFeatureEnabledImpl(Features, "lwp", true);
+ setFeatureEnabledImpl(Features, "lzcnt", true);
+ setFeatureEnabledImpl(Features, "aes", true);
+ setFeatureEnabledImpl(Features, "pclmul", true);
+ setFeatureEnabledImpl(Features, "prfchw", true);
+ setFeatureEnabledImpl(Features, "cx16", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
+ setFeatureEnabledImpl(Features, "xsave", true);
+ break;
+ }
+ if (!TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec))
+ return false;
+
+ // Can't do this earlier because we need to be able to explicitly enable
+ // or disable these features and the things that they depend upon.
+
+ // Enable popcnt if sse4.2 is enabled and popcnt is not explicitly disabled.
+ auto I = Features.find("sse4.2");
+ if (I != Features.end() && I->getValue() &&
+ std::find(FeaturesVec.begin(), FeaturesVec.end(), "-popcnt") ==
+ FeaturesVec.end())
+ Features["popcnt"] = true;
+
+ // Enable prfchw if 3DNow! is enabled and prfchw is not explicitly disabled.
+ I = Features.find("3dnow");
+ if (I != Features.end() && I->getValue() &&
+ std::find(FeaturesVec.begin(), FeaturesVec.end(), "-prfchw") ==
+ FeaturesVec.end())
+ Features["prfchw"] = true;
+
+ // Additionally, if SSE is enabled and mmx is not explicitly disabled,
+ // then enable MMX.
+ I = Features.find("sse");
+ if (I != Features.end() && I->getValue() &&
+ std::find(FeaturesVec.begin(), FeaturesVec.end(), "-mmx") ==
+ FeaturesVec.end())
+ Features["mmx"] = true;
+
+ return true;
+}
+
+void X86TargetInfo::setSSELevel(llvm::StringMap<bool> &Features,
+ X86SSEEnum Level, bool Enabled) {
+ if (Enabled) {
+ switch (Level) {
+ case AVX512F:
+ Features["avx512f"] = true;
+ LLVM_FALLTHROUGH;
+ case AVX2:
+ Features["avx2"] = true;
+ LLVM_FALLTHROUGH;
+ case AVX:
+ Features["avx"] = true;
+ Features["xsave"] = true;
+ LLVM_FALLTHROUGH;
+ case SSE42:
+ Features["sse4.2"] = true;
+ LLVM_FALLTHROUGH;
+ case SSE41:
+ Features["sse4.1"] = true;
+ LLVM_FALLTHROUGH;
+ case SSSE3:
+ Features["ssse3"] = true;
+ LLVM_FALLTHROUGH;
+ case SSE3:
+ Features["sse3"] = true;
+ LLVM_FALLTHROUGH;
+ case SSE2:
+ Features["sse2"] = true;
+ LLVM_FALLTHROUGH;
+ case SSE1:
+ Features["sse"] = true;
+ LLVM_FALLTHROUGH;
+ case NoSSE:
+ break;
+ }
+ return;
+ }
+
+ switch (Level) {
+ case NoSSE:
+ case SSE1:
+ Features["sse"] = false;
+ LLVM_FALLTHROUGH;
+ case SSE2:
+ Features["sse2"] = Features["pclmul"] = Features["aes"] = Features["sha"] =
+ false;
+ LLVM_FALLTHROUGH;
+ case SSE3:
+ Features["sse3"] = false;
+ setXOPLevel(Features, NoXOP, false);
+ LLVM_FALLTHROUGH;
+ case SSSE3:
+ Features["ssse3"] = false;
+ LLVM_FALLTHROUGH;
+ case SSE41:
+ Features["sse4.1"] = false;
+ LLVM_FALLTHROUGH;
+ case SSE42:
+ Features["sse4.2"] = false;
+ LLVM_FALLTHROUGH;
+ case AVX:
+ Features["fma"] = Features["avx"] = Features["f16c"] = Features["xsave"] =
+ Features["xsaveopt"] = false;
+ setXOPLevel(Features, FMA4, false);
+ LLVM_FALLTHROUGH;
+ case AVX2:
+ Features["avx2"] = false;
+ LLVM_FALLTHROUGH;
+ case AVX512F:
+ Features["avx512f"] = Features["avx512cd"] = Features["avx512er"] =
+ Features["avx512pf"] = Features["avx512dq"] = Features["avx512bw"] =
+ Features["avx512vl"] = Features["avx512vbmi"] =
+ Features["avx512ifma"] = Features["avx512vpopcntdq"] = false;
+ break;
+ }
+}
+
+void X86TargetInfo::setMMXLevel(llvm::StringMap<bool> &Features,
+ MMX3DNowEnum Level, bool Enabled) {
+ if (Enabled) {
+ switch (Level) {
+ case AMD3DNowAthlon:
+ Features["3dnowa"] = true;
+ LLVM_FALLTHROUGH;
+ case AMD3DNow:
+ Features["3dnow"] = true;
+ LLVM_FALLTHROUGH;
+ case MMX:
+ Features["mmx"] = true;
+ LLVM_FALLTHROUGH;
+ case NoMMX3DNow:
+ break;
+ }
+ return;
+ }
+
+ switch (Level) {
+ case NoMMX3DNow:
+ case MMX:
+ Features["mmx"] = false;
+ LLVM_FALLTHROUGH;
+ case AMD3DNow:
+ Features["3dnow"] = false;
+ LLVM_FALLTHROUGH;
+ case AMD3DNowAthlon:
+ Features["3dnowa"] = false;
+ break;
+ }
+}
+
+void X86TargetInfo::setXOPLevel(llvm::StringMap<bool> &Features, XOPEnum Level,
+ bool Enabled) {
+ if (Enabled) {
+ switch (Level) {
+ case XOP:
+ Features["xop"] = true;
+ LLVM_FALLTHROUGH;
+ case FMA4:
+ Features["fma4"] = true;
+ setSSELevel(Features, AVX, true);
+ LLVM_FALLTHROUGH;
+ case SSE4A:
+ Features["sse4a"] = true;
+ setSSELevel(Features, SSE3, true);
+ LLVM_FALLTHROUGH;
+ case NoXOP:
+ break;
+ }
+ return;
+ }
+
+ switch (Level) {
+ case NoXOP:
+ case SSE4A:
+ Features["sse4a"] = false;
+ LLVM_FALLTHROUGH;
+ case FMA4:
+ Features["fma4"] = false;
+ LLVM_FALLTHROUGH;
+ case XOP:
+ Features["xop"] = false;
+ break;
+ }
+}
+
+void X86TargetInfo::setFeatureEnabledImpl(llvm::StringMap<bool> &Features,
+ StringRef Name, bool Enabled) {
+ // This is a bit of a hack to deal with the sse4 target feature when used
+ // as part of the target attribute. We handle sse4 correctly everywhere
+ // else. See below for more information on how we handle the sse4 options.
+ if (Name != "sse4")
+ Features[Name] = Enabled;
+
+ if (Name == "mmx") {
+ setMMXLevel(Features, MMX, Enabled);
+ } else if (Name == "sse") {
+ setSSELevel(Features, SSE1, Enabled);
+ } else if (Name == "sse2") {
+ setSSELevel(Features, SSE2, Enabled);
+ } else if (Name == "sse3") {
+ setSSELevel(Features, SSE3, Enabled);
+ } else if (Name == "ssse3") {
+ setSSELevel(Features, SSSE3, Enabled);
+ } else if (Name == "sse4.2") {
+ setSSELevel(Features, SSE42, Enabled);
+ } else if (Name == "sse4.1") {
+ setSSELevel(Features, SSE41, Enabled);
+ } else if (Name == "3dnow") {
+ setMMXLevel(Features, AMD3DNow, Enabled);
+ } else if (Name == "3dnowa") {
+ setMMXLevel(Features, AMD3DNowAthlon, Enabled);
+ } else if (Name == "aes") {
+ if (Enabled)
+ setSSELevel(Features, SSE2, Enabled);
+ } else if (Name == "pclmul") {
+ if (Enabled)
+ setSSELevel(Features, SSE2, Enabled);
+ } else if (Name == "avx") {
+ setSSELevel(Features, AVX, Enabled);
+ } else if (Name == "avx2") {
+ setSSELevel(Features, AVX2, Enabled);
+ } else if (Name == "avx512f") {
+ setSSELevel(Features, AVX512F, Enabled);
+ } else if (Name == "avx512cd" || Name == "avx512er" || Name == "avx512pf" ||
+ Name == "avx512dq" || Name == "avx512bw" || Name == "avx512vl" ||
+ Name == "avx512vbmi" || Name == "avx512ifma" ||
+ Name == "avx512vpopcntdq") {
+ if (Enabled)
+ setSSELevel(Features, AVX512F, Enabled);
+ // Enable BWI instruction if VBMI is being enabled.
+ if (Name == "avx512vbmi" && Enabled)
+ Features["avx512bw"] = true;
+ // Also disable VBMI if BWI is being disabled.
+ if (Name == "avx512bw" && !Enabled)
+ Features["avx512vbmi"] = false;
+ } else if (Name == "fma") {
+ if (Enabled)
+ setSSELevel(Features, AVX, Enabled);
+ } else if (Name == "fma4") {
+ setXOPLevel(Features, FMA4, Enabled);
+ } else if (Name == "xop") {
+ setXOPLevel(Features, XOP, Enabled);
+ } else if (Name == "sse4a") {
+ setXOPLevel(Features, SSE4A, Enabled);
+ } else if (Name == "f16c") {
+ if (Enabled)
+ setSSELevel(Features, AVX, Enabled);
+ } else if (Name == "sha") {
+ if (Enabled)
+ setSSELevel(Features, SSE2, Enabled);
+ } else if (Name == "sse4") {
+ // We can get here via the __target__ attribute since that's not controlled
+ // via the -msse4/-mno-sse4 command line alias. Handle this the same way
+ // here - turn on the sse4.2 if enabled, turn off the sse4.1 level if
+ // disabled.
+ if (Enabled)
+ setSSELevel(Features, SSE42, Enabled);
+ else
+ setSSELevel(Features, SSE41, Enabled);
+ } else if (Name == "xsave") {
+ if (!Enabled)
+ Features["xsaveopt"] = false;
+ } else if (Name == "xsaveopt" || Name == "xsavec" || Name == "xsaves") {
+ if (Enabled)
+ Features["xsave"] = true;
+ }
+}
+
+/// handleTargetFeatures - Perform initialization based on the user
+/// configured set of features.
+bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) {
+ for (const auto &Feature : Features) {
+ if (Feature[0] != '+')
+ continue;
+
+ if (Feature == "+aes") {
+ HasAES = true;
+ } else if (Feature == "+pclmul") {
+ HasPCLMUL = true;
+ } else if (Feature == "+lzcnt") {
+ HasLZCNT = true;
+ } else if (Feature == "+rdrnd") {
+ HasRDRND = true;
+ } else if (Feature == "+fsgsbase") {
+ HasFSGSBASE = true;
+ } else if (Feature == "+bmi") {
+ HasBMI = true;
+ } else if (Feature == "+bmi2") {
+ HasBMI2 = true;
+ } else if (Feature == "+popcnt") {
+ HasPOPCNT = true;
+ } else if (Feature == "+rtm") {
+ HasRTM = true;
+ } else if (Feature == "+prfchw") {
+ HasPRFCHW = true;
+ } else if (Feature == "+rdseed") {
+ HasRDSEED = true;
+ } else if (Feature == "+adx") {
+ HasADX = true;
+ } else if (Feature == "+tbm") {
+ HasTBM = true;
+ } else if (Feature == "+lwp") {
+ HasLWP = true;
+ } else if (Feature == "+fma") {
+ HasFMA = true;
+ } else if (Feature == "+f16c") {
+ HasF16C = true;
+ } else if (Feature == "+avx512cd") {
+ HasAVX512CD = true;
+ } else if (Feature == "+avx512vpopcntdq") {
+ HasAVX512VPOPCNTDQ = true;
+ } else if (Feature == "+avx512er") {
+ HasAVX512ER = true;
+ } else if (Feature == "+avx512pf") {
+ HasAVX512PF = true;
+ } else if (Feature == "+avx512dq") {
+ HasAVX512DQ = true;
+ } else if (Feature == "+avx512bw") {
+ HasAVX512BW = true;
+ } else if (Feature == "+avx512vl") {
+ HasAVX512VL = true;
+ } else if (Feature == "+avx512vbmi") {
+ HasAVX512VBMI = true;
+ } else if (Feature == "+avx512ifma") {
+ HasAVX512IFMA = true;
+ } else if (Feature == "+sha") {
+ HasSHA = true;
+ } else if (Feature == "+mpx") {
+ HasMPX = true;
+ } else if (Feature == "+shstk") {
+ HasSHSTK = true;
+ } else if (Feature == "+ibt") {
+ HasIBT = true;
+ } else if (Feature == "+movbe") {
+ HasMOVBE = true;
+ } else if (Feature == "+sgx") {
+ HasSGX = true;
+ } else if (Feature == "+cx16") {
+ HasCX16 = true;
+ } else if (Feature == "+fxsr") {
+ HasFXSR = true;
+ } else if (Feature == "+xsave") {
+ HasXSAVE = true;
+ } else if (Feature == "+xsaveopt") {
+ HasXSAVEOPT = true;
+ } else if (Feature == "+xsavec") {
+ HasXSAVEC = true;
+ } else if (Feature == "+xsaves") {
+ HasXSAVES = true;
+ } else if (Feature == "+mwaitx") {
+ HasMWAITX = true;
+ } else if (Feature == "+pku") {
+ HasPKU = true;
+ } else if (Feature == "+clflushopt") {
+ HasCLFLUSHOPT = true;
+ } else if (Feature == "+clwb") {
+ HasCLWB = true;
+ } else if (Feature == "+prefetchwt1") {
+ HasPREFETCHWT1 = true;
+ } else if (Feature == "+clzero") {
+ HasCLZERO = true;
+ }
+
+ X86SSEEnum Level = llvm::StringSwitch<X86SSEEnum>(Feature)
+ .Case("+avx512f", AVX512F)
+ .Case("+avx2", AVX2)
+ .Case("+avx", AVX)
+ .Case("+sse4.2", SSE42)
+ .Case("+sse4.1", SSE41)
+ .Case("+ssse3", SSSE3)
+ .Case("+sse3", SSE3)
+ .Case("+sse2", SSE2)
+ .Case("+sse", SSE1)
+ .Default(NoSSE);
+ SSELevel = std::max(SSELevel, Level);
+
+ MMX3DNowEnum ThreeDNowLevel = llvm::StringSwitch<MMX3DNowEnum>(Feature)
+ .Case("+3dnowa", AMD3DNowAthlon)
+ .Case("+3dnow", AMD3DNow)
+ .Case("+mmx", MMX)
+ .Default(NoMMX3DNow);
+ MMX3DNowLevel = std::max(MMX3DNowLevel, ThreeDNowLevel);
+
+ XOPEnum XLevel = llvm::StringSwitch<XOPEnum>(Feature)
+ .Case("+xop", XOP)
+ .Case("+fma4", FMA4)
+ .Case("+sse4a", SSE4A)
+ .Default(NoXOP);
+ XOPLevel = std::max(XOPLevel, XLevel);
+ }
+
+ // LLVM doesn't have a separate switch for fpmath, so only accept it if it
+ // matches the selected sse level.
+ if ((FPMath == FP_SSE && SSELevel < SSE1) ||
+ (FPMath == FP_387 && SSELevel >= SSE1)) {
+ Diags.Report(diag::err_target_unsupported_fpmath)
+ << (FPMath == FP_SSE ? "sse" : "387");
+ return false;
+ }
+
+ SimdDefaultAlign =
+ hasFeature("avx512f") ? 512 : hasFeature("avx") ? 256 : 128;
+ return true;
+}
+
+/// X86TargetInfo::getTargetDefines - Return the set of the X86-specific macro
+/// definitions for this particular subtarget.
+void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ // Target identification.
+ if (getTriple().getArch() == llvm::Triple::x86_64) {
+ Builder.defineMacro("__amd64__");
+ Builder.defineMacro("__amd64");
+ Builder.defineMacro("__x86_64");
+ Builder.defineMacro("__x86_64__");
+ if (getTriple().getArchName() == "x86_64h") {
+ Builder.defineMacro("__x86_64h");
+ Builder.defineMacro("__x86_64h__");
+ }
+ } else {
+ DefineStd(Builder, "i386", Opts);
+ }
+
+ // Subtarget options.
+ // FIXME: We are hard-coding the tune parameters based on the CPU, but they
+ // truly should be based on -mtune options.
+ switch (CPU) {
+ case CK_Generic:
+ break;
+ case CK_i386:
+ // The rest are coming from the i386 define above.
+ Builder.defineMacro("__tune_i386__");
+ break;
+ case CK_i486:
+ case CK_WinChipC6:
+ case CK_WinChip2:
+ case CK_C3:
+ defineCPUMacros(Builder, "i486");
+ break;
+ case CK_PentiumMMX:
+ Builder.defineMacro("__pentium_mmx__");
+ Builder.defineMacro("__tune_pentium_mmx__");
+ LLVM_FALLTHROUGH;
+ case CK_i586:
+ case CK_Pentium:
+ defineCPUMacros(Builder, "i586");
+ defineCPUMacros(Builder, "pentium");
+ break;
+ case CK_Pentium3:
+ case CK_PentiumM:
+ Builder.defineMacro("__tune_pentium3__");
+ LLVM_FALLTHROUGH;
+ case CK_Pentium2:
+ case CK_C3_2:
+ Builder.defineMacro("__tune_pentium2__");
+ LLVM_FALLTHROUGH;
+ case CK_PentiumPro:
+ defineCPUMacros(Builder, "i686");
+ defineCPUMacros(Builder, "pentiumpro");
+ break;
+ case CK_Pentium4:
+ defineCPUMacros(Builder, "pentium4");
+ break;
+ case CK_Yonah:
+ case CK_Prescott:
+ case CK_Nocona:
+ defineCPUMacros(Builder, "nocona");
+ break;
+ case CK_Core2:
+ case CK_Penryn:
+ defineCPUMacros(Builder, "core2");
+ break;
+ case CK_Bonnell:
+ defineCPUMacros(Builder, "atom");
+ break;
+ case CK_Silvermont:
+ defineCPUMacros(Builder, "slm");
+ break;
+ case CK_Goldmont:
+ defineCPUMacros(Builder, "goldmont");
+ break;
+ case CK_Nehalem:
+ case CK_Westmere:
+ case CK_SandyBridge:
+ case CK_IvyBridge:
+ case CK_Haswell:
+ case CK_Broadwell:
+ case CK_SkylakeClient:
+ case CK_SkylakeServer:
+ case CK_Cannonlake:
+ case CK_Icelake:
+ // FIXME: Historically, we defined this legacy name, it would be nice to
+ // remove it at some point. We've never exposed fine-grained names for
+ // recent primary x86 CPUs, and we should keep it that way.
+ defineCPUMacros(Builder, "corei7");
+ break;
+ case CK_KNL:
+ defineCPUMacros(Builder, "knl");
+ break;
+ case CK_KNM:
+ break;
+ case CK_Lakemont:
+ defineCPUMacros(Builder, "i586", /*Tuning*/false);
+ defineCPUMacros(Builder, "pentium", /*Tuning*/false);
+ Builder.defineMacro("__tune_lakemont__");
+ break;
+ case CK_K6_2:
+ Builder.defineMacro("__k6_2__");
+ Builder.defineMacro("__tune_k6_2__");
+ LLVM_FALLTHROUGH;
+ case CK_K6_3:
+ if (CPU != CK_K6_2) { // In case of fallthrough
+ // FIXME: GCC may be enabling these in cases where some other k6
+ // architecture is specified but -m3dnow is explicitly provided. The
+ // exact semantics need to be determined and emulated here.
+ Builder.defineMacro("__k6_3__");
+ Builder.defineMacro("__tune_k6_3__");
+ }
+ LLVM_FALLTHROUGH;
+ case CK_K6:
+ defineCPUMacros(Builder, "k6");
+ break;
+ case CK_Athlon:
+ case CK_AthlonXP:
+ defineCPUMacros(Builder, "athlon");
+ if (SSELevel != NoSSE) {
+ Builder.defineMacro("__athlon_sse__");
+ Builder.defineMacro("__tune_athlon_sse__");
+ }
+ break;
+ case CK_K8:
+ case CK_K8SSE3:
+ case CK_x86_64:
+ defineCPUMacros(Builder, "k8");
+ break;
+ case CK_AMDFAM10:
+ defineCPUMacros(Builder, "amdfam10");
+ break;
+ case CK_BTVER1:
+ defineCPUMacros(Builder, "btver1");
+ break;
+ case CK_BTVER2:
+ defineCPUMacros(Builder, "btver2");
+ break;
+ case CK_BDVER1:
+ defineCPUMacros(Builder, "bdver1");
+ break;
+ case CK_BDVER2:
+ defineCPUMacros(Builder, "bdver2");
+ break;
+ case CK_BDVER3:
+ defineCPUMacros(Builder, "bdver3");
+ break;
+ case CK_BDVER4:
+ defineCPUMacros(Builder, "bdver4");
+ break;
+ case CK_ZNVER1:
+ defineCPUMacros(Builder, "znver1");
+ break;
+ case CK_Geode:
+ defineCPUMacros(Builder, "geode");
+ break;
+ }
+
+ // Target properties.
+ Builder.defineMacro("__REGISTER_PREFIX__", "");
+
+ // Define __NO_MATH_INLINES on linux/x86 so that we don't get inline
+ // functions in glibc header files that use FP Stack inline asm which the
+ // backend can't deal with (PR879).
+ Builder.defineMacro("__NO_MATH_INLINES");
+
+ if (HasAES)
+ Builder.defineMacro("__AES__");
+
+ if (HasPCLMUL)
+ Builder.defineMacro("__PCLMUL__");
+
+ if (HasLZCNT)
+ Builder.defineMacro("__LZCNT__");
+
+ if (HasRDRND)
+ Builder.defineMacro("__RDRND__");
+
+ if (HasFSGSBASE)
+ Builder.defineMacro("__FSGSBASE__");
+
+ if (HasBMI)
+ Builder.defineMacro("__BMI__");
+
+ if (HasBMI2)
+ Builder.defineMacro("__BMI2__");
+
+ if (HasPOPCNT)
+ Builder.defineMacro("__POPCNT__");
+
+ if (HasRTM)
+ Builder.defineMacro("__RTM__");
+
+ if (HasPRFCHW)
+ Builder.defineMacro("__PRFCHW__");
+
+ if (HasRDSEED)
+ Builder.defineMacro("__RDSEED__");
+
+ if (HasADX)
+ Builder.defineMacro("__ADX__");
+
+ if (HasTBM)
+ Builder.defineMacro("__TBM__");
+
+ if (HasLWP)
+ Builder.defineMacro("__LWP__");
+
+ if (HasMWAITX)
+ Builder.defineMacro("__MWAITX__");
+
+ switch (XOPLevel) {
+ case XOP:
+ Builder.defineMacro("__XOP__");
+ LLVM_FALLTHROUGH;
+ case FMA4:
+ Builder.defineMacro("__FMA4__");
+ LLVM_FALLTHROUGH;
+ case SSE4A:
+ Builder.defineMacro("__SSE4A__");
+ LLVM_FALLTHROUGH;
+ case NoXOP:
+ break;
+ }
+
+ if (HasFMA)
+ Builder.defineMacro("__FMA__");
+
+ if (HasF16C)
+ Builder.defineMacro("__F16C__");
+
+ if (HasAVX512CD)
+ Builder.defineMacro("__AVX512CD__");
+ if (HasAVX512VPOPCNTDQ)
+ Builder.defineMacro("__AVX512VPOPCNTDQ__");
+ if (HasAVX512ER)
+ Builder.defineMacro("__AVX512ER__");
+ if (HasAVX512PF)
+ Builder.defineMacro("__AVX512PF__");
+ if (HasAVX512DQ)
+ Builder.defineMacro("__AVX512DQ__");
+ if (HasAVX512BW)
+ Builder.defineMacro("__AVX512BW__");
+ if (HasAVX512VL)
+ Builder.defineMacro("__AVX512VL__");
+ if (HasAVX512VBMI)
+ Builder.defineMacro("__AVX512VBMI__");
+ if (HasAVX512IFMA)
+ Builder.defineMacro("__AVX512IFMA__");
+
+ if (HasSHA)
+ Builder.defineMacro("__SHA__");
+
+ if (HasFXSR)
+ Builder.defineMacro("__FXSR__");
+ if (HasXSAVE)
+ Builder.defineMacro("__XSAVE__");
+ if (HasXSAVEOPT)
+ Builder.defineMacro("__XSAVEOPT__");
+ if (HasXSAVEC)
+ Builder.defineMacro("__XSAVEC__");
+ if (HasXSAVES)
+ Builder.defineMacro("__XSAVES__");
+ if (HasPKU)
+ Builder.defineMacro("__PKU__");
+ if (HasCX16)
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16");
+ if (HasCLFLUSHOPT)
+ Builder.defineMacro("__CLFLUSHOPT__");
+ if (HasCLWB)
+ Builder.defineMacro("__CLWB__");
+ if (HasMPX)
+ Builder.defineMacro("__MPX__");
+ if (HasSHSTK)
+ Builder.defineMacro("__SHSTK__");
+ if (HasSGX)
+ Builder.defineMacro("__SGX__");
+ if (HasPREFETCHWT1)
+ Builder.defineMacro("__PREFETCHWT1__");
+ if (HasCLZERO)
+ Builder.defineMacro("__CLZERO__");
+
+ // Each case falls through to the previous one here.
+ switch (SSELevel) {
+ case AVX512F:
+ Builder.defineMacro("__AVX512F__");
+ LLVM_FALLTHROUGH;
+ case AVX2:
+ Builder.defineMacro("__AVX2__");
+ LLVM_FALLTHROUGH;
+ case AVX:
+ Builder.defineMacro("__AVX__");
+ LLVM_FALLTHROUGH;
+ case SSE42:
+ Builder.defineMacro("__SSE4_2__");
+ LLVM_FALLTHROUGH;
+ case SSE41:
+ Builder.defineMacro("__SSE4_1__");
+ LLVM_FALLTHROUGH;
+ case SSSE3:
+ Builder.defineMacro("__SSSE3__");
+ LLVM_FALLTHROUGH;
+ case SSE3:
+ Builder.defineMacro("__SSE3__");
+ LLVM_FALLTHROUGH;
+ case SSE2:
+ Builder.defineMacro("__SSE2__");
+ Builder.defineMacro("__SSE2_MATH__"); // -mfp-math=sse always implied.
+ LLVM_FALLTHROUGH;
+ case SSE1:
+ Builder.defineMacro("__SSE__");
+ Builder.defineMacro("__SSE_MATH__"); // -mfp-math=sse always implied.
+ LLVM_FALLTHROUGH;
+ case NoSSE:
+ break;
+ }
+
+ if (Opts.MicrosoftExt && getTriple().getArch() == llvm::Triple::x86) {
+ switch (SSELevel) {
+ case AVX512F:
+ case AVX2:
+ case AVX:
+ case SSE42:
+ case SSE41:
+ case SSSE3:
+ case SSE3:
+ case SSE2:
+ Builder.defineMacro("_M_IX86_FP", Twine(2));
+ break;
+ case SSE1:
+ Builder.defineMacro("_M_IX86_FP", Twine(1));
+ break;
+ default:
+ Builder.defineMacro("_M_IX86_FP", Twine(0));
+ break;
+ }
+ }
+
+ // Each case falls through to the previous one here.
+ switch (MMX3DNowLevel) {
+ case AMD3DNowAthlon:
+ Builder.defineMacro("__3dNOW_A__");
+ LLVM_FALLTHROUGH;
+ case AMD3DNow:
+ Builder.defineMacro("__3dNOW__");
+ LLVM_FALLTHROUGH;
+ case MMX:
+ Builder.defineMacro("__MMX__");
+ LLVM_FALLTHROUGH;
+ case NoMMX3DNow:
+ break;
+ }
+
+ if (CPU >= CK_i486) {
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
+ }
+ if (CPU >= CK_i586)
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
+
+ if (HasFloat128)
+ Builder.defineMacro("__SIZEOF_FLOAT128__", "16");
+}
+
+bool X86TargetInfo::isValidFeatureName(StringRef Name) const {
+ return llvm::StringSwitch<bool>(Name)
+ .Case("3dnow", true)
+ .Case("3dnowa", true)
+ .Case("aes", true)
+ .Case("avx", true)
+ .Case("avx2", true)
+ .Case("avx512f", true)
+ .Case("avx512cd", true)
+ .Case("avx512vpopcntdq", true)
+ .Case("avx512er", true)
+ .Case("avx512pf", true)
+ .Case("avx512dq", true)
+ .Case("avx512bw", true)
+ .Case("avx512vl", true)
+ .Case("avx512vbmi", true)
+ .Case("avx512ifma", true)
+ .Case("bmi", true)
+ .Case("bmi2", true)
+ .Case("clflushopt", true)
+ .Case("clwb", true)
+ .Case("clzero", true)
+ .Case("cx16", true)
+ .Case("f16c", true)
+ .Case("fma", true)
+ .Case("fma4", true)
+ .Case("fsgsbase", true)
+ .Case("fxsr", true)
+ .Case("lwp", true)
+ .Case("lzcnt", true)
+ .Case("mmx", true)
+ .Case("movbe", true)
+ .Case("mpx", true)
+ .Case("pclmul", true)
+ .Case("pku", true)
+ .Case("popcnt", true)
+ .Case("prefetchwt1", true)
+ .Case("prfchw", true)
+ .Case("rdrnd", true)
+ .Case("rdseed", true)
+ .Case("rtm", true)
+ .Case("sgx", true)
+ .Case("sha", true)
+ .Case("sse", true)
+ .Case("sse2", true)
+ .Case("sse3", true)
+ .Case("ssse3", true)
+ .Case("sse4", true)
+ .Case("sse4.1", true)
+ .Case("sse4.2", true)
+ .Case("sse4a", true)
+ .Case("tbm", true)
+ .Case("x87", true)
+ .Case("xop", true)
+ .Case("xsave", true)
+ .Case("xsavec", true)
+ .Case("xsaves", true)
+ .Case("xsaveopt", true)
+ .Default(false);
+}
+
+bool X86TargetInfo::hasFeature(StringRef Feature) const {
+ return llvm::StringSwitch<bool>(Feature)
+ .Case("aes", HasAES)
+ .Case("avx", SSELevel >= AVX)
+ .Case("avx2", SSELevel >= AVX2)
+ .Case("avx512f", SSELevel >= AVX512F)
+ .Case("avx512cd", HasAVX512CD)
+ .Case("avx512vpopcntdq", HasAVX512VPOPCNTDQ)
+ .Case("avx512er", HasAVX512ER)
+ .Case("avx512pf", HasAVX512PF)
+ .Case("avx512dq", HasAVX512DQ)
+ .Case("avx512bw", HasAVX512BW)
+ .Case("avx512vl", HasAVX512VL)
+ .Case("avx512vbmi", HasAVX512VBMI)
+ .Case("avx512ifma", HasAVX512IFMA)
+ .Case("bmi", HasBMI)
+ .Case("bmi2", HasBMI2)
+ .Case("clflushopt", HasCLFLUSHOPT)
+ .Case("clwb", HasCLWB)
+ .Case("clzero", HasCLZERO)
+ .Case("cx16", HasCX16)
+ .Case("f16c", HasF16C)
+ .Case("fma", HasFMA)
+ .Case("fma4", XOPLevel >= FMA4)
+ .Case("fsgsbase", HasFSGSBASE)
+ .Case("fxsr", HasFXSR)
+ .Case("lwp", HasLWP)
+ .Case("lzcnt", HasLZCNT)
+ .Case("mm3dnow", MMX3DNowLevel >= AMD3DNow)
+ .Case("mm3dnowa", MMX3DNowLevel >= AMD3DNowAthlon)
+ .Case("mmx", MMX3DNowLevel >= MMX)
+ .Case("movbe", HasMOVBE)
+ .Case("mpx", HasMPX)
+ .Case("shstk", HasSHSTK)
+ .Case("ibt", HasIBT)
+ .Case("pclmul", HasPCLMUL)
+ .Case("pku", HasPKU)
+ .Case("popcnt", HasPOPCNT)
+ .Case("prefetchwt1", HasPREFETCHWT1)
+ .Case("prfchw", HasPRFCHW)
+ .Case("rdrnd", HasRDRND)
+ .Case("rdseed", HasRDSEED)
+ .Case("rtm", HasRTM)
+ .Case("sgx", HasSGX)
+ .Case("sha", HasSHA)
+ .Case("sse", SSELevel >= SSE1)
+ .Case("sse2", SSELevel >= SSE2)
+ .Case("sse3", SSELevel >= SSE3)
+ .Case("ssse3", SSELevel >= SSSE3)
+ .Case("sse4.1", SSELevel >= SSE41)
+ .Case("sse4.2", SSELevel >= SSE42)
+ .Case("sse4a", XOPLevel >= SSE4A)
+ .Case("tbm", HasTBM)
+ .Case("x86", true)
+ .Case("x86_32", getTriple().getArch() == llvm::Triple::x86)
+ .Case("x86_64", getTriple().getArch() == llvm::Triple::x86_64)
+ .Case("xop", XOPLevel >= XOP)
+ .Case("xsave", HasXSAVE)
+ .Case("xsavec", HasXSAVEC)
+ .Case("xsaves", HasXSAVES)
+ .Case("xsaveopt", HasXSAVEOPT)
+ .Default(false);
+}
+
+// We can't use a generic validation scheme for the features accepted here
+// versus subtarget features accepted in the target attribute because the
+// bitfield structure that's initialized in the runtime only supports the
+// below currently rather than the full range of subtarget features. (See
+// X86TargetInfo::hasFeature for a somewhat comprehensive list).
+bool X86TargetInfo::validateCpuSupports(StringRef FeatureStr) const {
+ return llvm::StringSwitch<bool>(FeatureStr)
+#define X86_FEATURE_COMPAT(VAL, ENUM, STR) .Case(STR, true)
+#include "llvm/Support/X86TargetParser.def"
+ .Default(false);
+}
+
+// We can't use a generic validation scheme for the cpus accepted here
+// versus subtarget cpus accepted in the target attribute because the
+// variables intitialized by the runtime only support the below currently
+// rather than the full range of cpus.
+bool X86TargetInfo::validateCpuIs(StringRef FeatureStr) const {
+ return llvm::StringSwitch<bool>(FeatureStr)
+#define X86_VENDOR(ENUM, STRING) .Case(STRING, true)
+#define X86_CPU_TYPE_COMPAT_WITH_ALIAS(ARCHNAME, ENUM, STR, ALIAS) \
+ .Cases(STR, ALIAS, true)
+#define X86_CPU_TYPE_COMPAT(ARCHNAME, ENUM, STR) .Case(STR, true)
+#define X86_CPU_SUBTYPE_COMPAT(ARCHNAME, ENUM, STR) .Case(STR, true)
+#include "llvm/Support/X86TargetParser.def"
+ .Default(false);
+}
+
+bool X86TargetInfo::validateAsmConstraint(
+ const char *&Name, TargetInfo::ConstraintInfo &Info) const {
+ switch (*Name) {
+ default:
+ return false;
+ // Constant constraints.
+ case 'e': // 32-bit signed integer constant for use with sign-extending x86_64
+ // instructions.
+ case 'Z': // 32-bit unsigned integer constant for use with zero-extending
+ // x86_64 instructions.
+ case 's':
+ Info.setRequiresImmediate();
+ return true;
+ case 'I':
+ Info.setRequiresImmediate(0, 31);
+ return true;
+ case 'J':
+ Info.setRequiresImmediate(0, 63);
+ return true;
+ case 'K':
+ Info.setRequiresImmediate(-128, 127);
+ return true;
+ case 'L':
+ Info.setRequiresImmediate({int(0xff), int(0xffff), int(0xffffffff)});
+ return true;
+ case 'M':
+ Info.setRequiresImmediate(0, 3);
+ return true;
+ case 'N':
+ Info.setRequiresImmediate(0, 255);
+ return true;
+ case 'O':
+ Info.setRequiresImmediate(0, 127);
+ return true;
+ // Register constraints.
+ case 'Y': // 'Y' is the first character for several 2-character constraints.
+ // Shift the pointer to the second character of the constraint.
+ Name++;
+ switch (*Name) {
+ default:
+ return false;
+ case 'z':
+ case '0': // First SSE register.
+ case '2':
+ case 't': // Any SSE register, when SSE2 is enabled.
+ case 'i': // Any SSE register, when SSE2 and inter-unit moves enabled.
+ case 'm': // Any MMX register, when inter-unit moves enabled.
+ case 'k': // AVX512 arch mask registers: k1-k7.
+ Info.setAllowsRegister();
+ return true;
+ }
+ case 'f': // Any x87 floating point stack register.
+ // Constraint 'f' cannot be used for output operands.
+ if (Info.ConstraintStr[0] == '=')
+ return false;
+ Info.setAllowsRegister();
+ return true;
+ case 'a': // eax.
+ case 'b': // ebx.
+ case 'c': // ecx.
+ case 'd': // edx.
+ case 'S': // esi.
+ case 'D': // edi.
+ case 'A': // edx:eax.
+ case 't': // Top of floating point stack.
+ case 'u': // Second from top of floating point stack.
+ case 'q': // Any register accessible as [r]l: a, b, c, and d.
+ case 'y': // Any MMX register.
+ case 'v': // Any {X,Y,Z}MM register (Arch & context dependent)
+ case 'x': // Any SSE register.
+ case 'k': // Any AVX512 mask register (same as Yk, additionaly allows k0
+ // for intermideate k reg operations).
+ case 'Q': // Any register accessible as [r]h: a, b, c, and d.
+ case 'R': // "Legacy" registers: ax, bx, cx, dx, di, si, sp, bp.
+ case 'l': // "Index" registers: any general register that can be used as an
+ // index in a base+index memory access.
+ Info.setAllowsRegister();
+ return true;
+ // Floating point constant constraints.
+ case 'C': // SSE floating point constant.
+ case 'G': // x87 floating point constant.
+ return true;
+ }
+}
+
+bool X86TargetInfo::validateOutputSize(StringRef Constraint,
+ unsigned Size) const {
+ // Strip off constraint modifiers.
+ while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
+ Constraint = Constraint.substr(1);
+
+ return validateOperandSize(Constraint, Size);
+}
+
+bool X86TargetInfo::validateInputSize(StringRef Constraint,
+ unsigned Size) const {
+ return validateOperandSize(Constraint, Size);
+}
+
+bool X86TargetInfo::validateOperandSize(StringRef Constraint,
+ unsigned Size) const {
+ switch (Constraint[0]) {
+ default:
+ break;
+ case 'k':
+ // Registers k0-k7 (AVX512) size limit is 64 bit.
+ case 'y':
+ return Size <= 64;
+ case 'f':
+ case 't':
+ case 'u':
+ return Size <= 128;
+ case 'Y':
+ // 'Y' is the first character for several 2-character constraints.
+ switch (Constraint[1]) {
+ default:
+ return false;
+ case 'm':
+ // 'Ym' is synonymous with 'y'.
+ case 'k':
+ return Size <= 64;
+ case 'z':
+ case '0':
+ // XMM0
+ if (SSELevel >= SSE1)
+ return Size <= 128U;
+ return false;
+ case 'i':
+ case 't':
+ case '2':
+ // 'Yi','Yt','Y2' are synonymous with 'x' when SSE2 is enabled.
+ if (SSELevel < SSE2)
+ return false;
+ break;
+ }
+ case 'v':
+ case 'x':
+ if (SSELevel >= AVX512F)
+ // 512-bit zmm registers can be used if target supports AVX512F.
+ return Size <= 512U;
+ else if (SSELevel >= AVX)
+ // 256-bit ymm registers can be used if target supports AVX.
+ return Size <= 256U;
+ return Size <= 128U;
+
+ }
+
+ return true;
+}
+
+std::string X86TargetInfo::convertConstraint(const char *&Constraint) const {
+ switch (*Constraint) {
+ case 'a':
+ return std::string("{ax}");
+ case 'b':
+ return std::string("{bx}");
+ case 'c':
+ return std::string("{cx}");
+ case 'd':
+ return std::string("{dx}");
+ case 'S':
+ return std::string("{si}");
+ case 'D':
+ return std::string("{di}");
+ case 'p': // address
+ return std::string("im");
+ case 't': // top of floating point stack.
+ return std::string("{st}");
+ case 'u': // second from top of floating point stack.
+ return std::string("{st(1)}"); // second from top of floating point stack.
+ case 'Y':
+ switch (Constraint[1]) {
+ default:
+ // Break from inner switch and fall through (copy single char),
+ // continue parsing after copying the current constraint into
+ // the return string.
+ break;
+ case 'k':
+ case 'm':
+ case 'i':
+ case 't':
+ case 'z':
+ case '0':
+ case '2':
+ // "^" hints llvm that this is a 2 letter constraint.
+ // "Constraint++" is used to promote the string iterator
+ // to the next constraint.
+ return std::string("^") + std::string(Constraint++, 2);
+ }
+ LLVM_FALLTHROUGH;
+ default:
+ return std::string(1, *Constraint);
+ }
+}
+
+bool X86TargetInfo::checkCPUKind(CPUKind Kind) const {
+ // Perform any per-CPU checks necessary to determine if this CPU is
+ // acceptable.
+ // FIXME: This results in terrible diagnostics. Clang just says the CPU is
+ // invalid without explaining *why*.
+ switch (Kind) {
+ case CK_Generic:
+ // No processor selected!
+ return false;
+#define PROC(ENUM, STRING, IS64BIT) \
+ case CK_##ENUM: \
+ return IS64BIT || getTriple().getArch() == llvm::Triple::x86;
+#include "clang/Basic/X86Target.def"
+ }
+ llvm_unreachable("Unhandled CPU kind");
+}
+
+X86TargetInfo::CPUKind X86TargetInfo::getCPUKind(StringRef CPU) const {
+ return llvm::StringSwitch<CPUKind>(CPU)
+#define PROC(ENUM, STRING, IS64BIT) .Case(STRING, CK_##ENUM)
+#define PROC_ALIAS(ENUM, ALIAS) .Case(ALIAS, CK_##ENUM)
+#include "clang/Basic/X86Target.def"
+ .Default(CK_Generic);
+}
+
+ArrayRef<const char *> X86TargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
+}
+
+ArrayRef<TargetInfo::AddlRegName> X86TargetInfo::getGCCAddlRegNames() const {
+ return llvm::makeArrayRef(AddlRegNames);
+}
+
+ArrayRef<Builtin::Info> X86_32TargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfoX86, clang::X86::LastX86CommonBuiltin -
+ Builtin::FirstTSBuiltin + 1);
+}
+
+ArrayRef<Builtin::Info> X86_64TargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfoX86,
+ X86::LastTSBuiltin - Builtin::FirstTSBuiltin);
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/X86.h b/contrib/llvm/tools/clang/lib/Basic/Targets/X86.h
new file mode 100644
index 0000000000000..b1811593545e7
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/X86.h
@@ -0,0 +1,801 @@
+//===--- X86.h - Declare X86 target feature support -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares X86 TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_X86_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_X86_H
+
+#include "OSTargets.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+// X86 target abstract base class; x86-32 and x86-64 are very close, so
+// most of the implementation can be shared.
+class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo {
+
+ enum X86SSEEnum {
+ NoSSE,
+ SSE1,
+ SSE2,
+ SSE3,
+ SSSE3,
+ SSE41,
+ SSE42,
+ AVX,
+ AVX2,
+ AVX512F
+ } SSELevel = NoSSE;
+ enum MMX3DNowEnum {
+ NoMMX3DNow,
+ MMX,
+ AMD3DNow,
+ AMD3DNowAthlon
+ } MMX3DNowLevel = NoMMX3DNow;
+ enum XOPEnum { NoXOP, SSE4A, FMA4, XOP } XOPLevel = NoXOP;
+
+ bool HasAES = false;
+ bool HasPCLMUL = false;
+ bool HasLZCNT = false;
+ bool HasRDRND = false;
+ bool HasFSGSBASE = false;
+ bool HasBMI = false;
+ bool HasBMI2 = false;
+ bool HasPOPCNT = false;
+ bool HasRTM = false;
+ bool HasPRFCHW = false;
+ bool HasRDSEED = false;
+ bool HasADX = false;
+ bool HasTBM = false;
+ bool HasLWP = false;
+ bool HasFMA = false;
+ bool HasF16C = false;
+ bool HasAVX512CD = false;
+ bool HasAVX512VPOPCNTDQ = false;
+ bool HasAVX512ER = false;
+ bool HasAVX512PF = false;
+ bool HasAVX512DQ = false;
+ bool HasAVX512BW = false;
+ bool HasAVX512VL = false;
+ bool HasAVX512VBMI = false;
+ bool HasAVX512IFMA = false;
+ bool HasSHA = false;
+ bool HasMPX = false;
+ bool HasSHSTK = false;
+ bool HasIBT = false;
+ bool HasSGX = false;
+ bool HasCX16 = false;
+ bool HasFXSR = false;
+ bool HasXSAVE = false;
+ bool HasXSAVEOPT = false;
+ bool HasXSAVEC = false;
+ bool HasXSAVES = false;
+ bool HasMWAITX = false;
+ bool HasCLZERO = false;
+ bool HasPKU = false;
+ bool HasCLFLUSHOPT = false;
+ bool HasCLWB = false;
+ bool HasMOVBE = false;
+ bool HasPREFETCHWT1 = false;
+
+ /// \brief Enumeration of all of the X86 CPUs supported by Clang.
+ ///
+ /// Each enumeration represents a particular CPU supported by Clang. These
+ /// loosely correspond to the options passed to '-march' or '-mtune' flags.
+ enum CPUKind {
+ CK_Generic,
+#define PROC(ENUM, STRING, IS64BIT) CK_##ENUM,
+#include "clang/Basic/X86Target.def"
+ } CPU = CK_Generic;
+
+ bool checkCPUKind(CPUKind Kind) const;
+
+ CPUKind getCPUKind(StringRef CPU) const;
+
+ enum FPMathKind { FP_Default, FP_SSE, FP_387 } FPMath = FP_Default;
+
+public:
+ X86TargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple) {
+ LongDoubleFormat = &llvm::APFloat::x87DoubleExtended();
+ }
+
+ unsigned getFloatEvalMethod() const override {
+ // X87 evaluates with 80 bits "long double" precision.
+ return SSELevel == NoSSE ? 2 : 0;
+ }
+
+ ArrayRef<const char *> getGCCRegNames() const override;
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ return None;
+ }
+
+ ArrayRef<TargetInfo::AddlRegName> getGCCAddlRegNames() const override;
+
+ bool validateCpuSupports(StringRef Name) const override;
+
+ bool validateCpuIs(StringRef Name) const override;
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const override;
+
+ bool validateGlobalRegisterVariable(StringRef RegName, unsigned RegSize,
+ bool &HasSizeMismatch) const override {
+ // esp and ebp are the only 32-bit registers the x86 backend can currently
+ // handle.
+ if (RegName.equals("esp") || RegName.equals("ebp")) {
+ // Check that the register size is 32-bit.
+ HasSizeMismatch = RegSize != 32;
+ return true;
+ }
+
+ return false;
+ }
+
+ bool validateOutputSize(StringRef Constraint, unsigned Size) const override;
+
+ bool validateInputSize(StringRef Constraint, unsigned Size) const override;
+
+ virtual bool validateOperandSize(StringRef Constraint, unsigned Size) const;
+
+ std::string convertConstraint(const char *&Constraint) const override;
+ const char *getClobbers() const override {
+ return "~{dirflag},~{fpsr},~{flags}";
+ }
+
+ StringRef getConstraintRegister(const StringRef &Constraint,
+ const StringRef &Expression) const override {
+ StringRef::iterator I, E;
+ for (I = Constraint.begin(), E = Constraint.end(); I != E; ++I) {
+ if (isalpha(*I))
+ break;
+ }
+ if (I == E)
+ return "";
+ switch (*I) {
+ // For the register constraints, return the matching register name
+ case 'a':
+ return "ax";
+ case 'b':
+ return "bx";
+ case 'c':
+ return "cx";
+ case 'd':
+ return "dx";
+ case 'S':
+ return "si";
+ case 'D':
+ return "di";
+ // In case the constraint is 'r' we need to return Expression
+ case 'r':
+ return Expression;
+ // Double letters Y<x> constraints
+ case 'Y':
+ if ((++I != E) && ((*I == '0') || (*I == 'z')))
+ return "xmm0";
+ default:
+ break;
+ }
+ return "";
+ }
+
+ bool useFP16ConversionIntrinsics() const override {
+ return false;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ static void setSSELevel(llvm::StringMap<bool> &Features, X86SSEEnum Level,
+ bool Enabled);
+
+ static void setMMXLevel(llvm::StringMap<bool> &Features, MMX3DNowEnum Level,
+ bool Enabled);
+
+ static void setXOPLevel(llvm::StringMap<bool> &Features, XOPEnum Level,
+ bool Enabled);
+
+ void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name,
+ bool Enabled) const override {
+ setFeatureEnabledImpl(Features, Name, Enabled);
+ }
+
+ // This exists purely to cut down on the number of virtual calls in
+ // initFeatureMap which calls this repeatedly.
+ static void setFeatureEnabledImpl(llvm::StringMap<bool> &Features,
+ StringRef Name, bool Enabled);
+
+ bool
+ initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
+ StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const override;
+
+ bool isValidFeatureName(StringRef Name) const override;
+
+ bool hasFeature(StringRef Feature) const override;
+
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) override;
+
+ StringRef getABI() const override {
+ if (getTriple().getArch() == llvm::Triple::x86_64 && SSELevel >= AVX512F)
+ return "avx512";
+ if (getTriple().getArch() == llvm::Triple::x86_64 && SSELevel >= AVX)
+ return "avx";
+ if (getTriple().getArch() == llvm::Triple::x86 &&
+ MMX3DNowLevel == NoMMX3DNow)
+ return "no-mmx";
+ return "";
+ }
+
+ bool isValidCPUName(StringRef Name) const override {
+ return checkCPUKind(getCPUKind(Name));
+ }
+
+ bool setCPU(const std::string &Name) override {
+ return checkCPUKind(CPU = getCPUKind(Name));
+ }
+
+ bool setFPMath(StringRef Name) override;
+
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
+ // Most of the non-ARM calling conventions are i386 conventions.
+ switch (CC) {
+ case CC_X86ThisCall:
+ case CC_X86FastCall:
+ case CC_X86StdCall:
+ case CC_X86VectorCall:
+ case CC_X86RegCall:
+ case CC_C:
+ case CC_Swift:
+ case CC_X86Pascal:
+ case CC_IntelOclBicc:
+ case CC_OpenCLKernel:
+ return CCCR_OK;
+ default:
+ return CCCR_Warning;
+ }
+ }
+
+ CallingConv getDefaultCallingConv(CallingConvMethodType MT) const override {
+ return MT == CCMT_Member ? CC_X86ThisCall : CC_C;
+ }
+
+ bool hasSjLjLowering() const override { return true; }
+
+ void setSupportedOpenCLOpts() override {
+ getSupportedOpenCLOpts().supportAll();
+ }
+};
+
+// X86-32 generic target
+class LLVM_LIBRARY_VISIBILITY X86_32TargetInfo : public X86TargetInfo {
+public:
+ X86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : X86TargetInfo(Triple, Opts) {
+ DoubleAlign = LongLongAlign = 32;
+ LongDoubleWidth = 96;
+ LongDoubleAlign = 32;
+ SuitableAlign = 128;
+ resetDataLayout("e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128");
+ SizeType = UnsignedInt;
+ PtrDiffType = SignedInt;
+ IntPtrType = SignedInt;
+ RegParmMax = 3;
+
+ // Use fpret for all types.
+ RealTypeUsesObjCFPRet =
+ ((1 << TargetInfo::Float) | (1 << TargetInfo::Double) |
+ (1 << TargetInfo::LongDouble));
+
+ // x86-32 has atomics up to 8 bytes
+ // FIXME: Check that we actually have cmpxchg8b before setting
+ // MaxAtomicInlineWidth. (cmpxchg8b is an i586 instruction.)
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
+ }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::CharPtrBuiltinVaList;
+ }
+
+ int getEHDataRegisterNumber(unsigned RegNo) const override {
+ if (RegNo == 0)
+ return 0;
+ if (RegNo == 1)
+ return 2;
+ return -1;
+ }
+
+ bool validateOperandSize(StringRef Constraint, unsigned Size) const override {
+ switch (Constraint[0]) {
+ default:
+ break;
+ case 'R':
+ case 'q':
+ case 'Q':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'S':
+ case 'D':
+ return Size <= 32;
+ case 'A':
+ return Size <= 64;
+ }
+
+ return X86TargetInfo::validateOperandSize(Constraint, Size);
+ }
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY NetBSDI386TargetInfo
+ : public NetBSDTargetInfo<X86_32TargetInfo> {
+public:
+ NetBSDI386TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : NetBSDTargetInfo<X86_32TargetInfo>(Triple, Opts) {}
+
+ unsigned getFloatEvalMethod() const override {
+ unsigned Major, Minor, Micro;
+ getTriple().getOSVersion(Major, Minor, Micro);
+ // New NetBSD uses the default rounding mode.
+ if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 26) || Major == 0)
+ return X86_32TargetInfo::getFloatEvalMethod();
+ // NetBSD before 6.99.26 defaults to "double" rounding.
+ return 1;
+ }
+};
+
+class LLVM_LIBRARY_VISIBILITY OpenBSDI386TargetInfo
+ : public OpenBSDTargetInfo<X86_32TargetInfo> {
+public:
+ OpenBSDI386TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OpenBSDTargetInfo<X86_32TargetInfo>(Triple, Opts) {
+ SizeType = UnsignedLong;
+ IntPtrType = SignedLong;
+ PtrDiffType = SignedLong;
+ }
+};
+
+class LLVM_LIBRARY_VISIBILITY DarwinI386TargetInfo
+ : public DarwinTargetInfo<X86_32TargetInfo> {
+public:
+ DarwinI386TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : DarwinTargetInfo<X86_32TargetInfo>(Triple, Opts) {
+ LongDoubleWidth = 128;
+ LongDoubleAlign = 128;
+ SuitableAlign = 128;
+ MaxVectorAlign = 256;
+ // The watchOS simulator uses the builtin bool type for Objective-C.
+ llvm::Triple T = llvm::Triple(Triple);
+ if (T.isWatchOS())
+ UseSignedCharForObjCBool = false;
+ SizeType = UnsignedLong;
+ IntPtrType = SignedLong;
+ resetDataLayout("e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128");
+ HasAlignMac68kSupport = true;
+ }
+
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) override {
+ if (!DarwinTargetInfo<X86_32TargetInfo>::handleTargetFeatures(Features,
+ Diags))
+ return false;
+ // We now know the features we have: we can decide how to align vectors.
+ MaxVectorAlign =
+ hasFeature("avx512f") ? 512 : hasFeature("avx") ? 256 : 128;
+ return true;
+ }
+};
+
+// x86-32 Windows target
+class LLVM_LIBRARY_VISIBILITY WindowsX86_32TargetInfo
+ : public WindowsTargetInfo<X86_32TargetInfo> {
+public:
+ WindowsX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : WindowsTargetInfo<X86_32TargetInfo>(Triple, Opts) {
+ DoubleAlign = LongLongAlign = 64;
+ bool IsWinCOFF =
+ getTriple().isOSWindows() && getTriple().isOSBinFormatCOFF();
+ resetDataLayout(IsWinCOFF
+ ? "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
+ : "e-m:e-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32");
+ }
+};
+
+// x86-32 Windows Visual Studio target
+class LLVM_LIBRARY_VISIBILITY MicrosoftX86_32TargetInfo
+ : public WindowsX86_32TargetInfo {
+public:
+ MicrosoftX86_32TargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : WindowsX86_32TargetInfo(Triple, Opts) {
+ LongDoubleWidth = LongDoubleAlign = 64;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ WindowsX86_32TargetInfo::getTargetDefines(Opts, Builder);
+ WindowsX86_32TargetInfo::getVisualStudioDefines(Opts, Builder);
+ // The value of the following reflects processor type.
+ // 300=386, 400=486, 500=Pentium, 600=Blend (default)
+ // We lost the original triple, so we use the default.
+ Builder.defineMacro("_M_IX86", "600");
+ }
+};
+
+// x86-32 MinGW target
+class LLVM_LIBRARY_VISIBILITY MinGWX86_32TargetInfo
+ : public WindowsX86_32TargetInfo {
+public:
+ MinGWX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : WindowsX86_32TargetInfo(Triple, Opts) {
+ HasFloat128 = true;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ WindowsX86_32TargetInfo::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("_X86_");
+ }
+};
+
+// x86-32 Cygwin target
+class LLVM_LIBRARY_VISIBILITY CygwinX86_32TargetInfo : public X86_32TargetInfo {
+public:
+ CygwinX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : X86_32TargetInfo(Triple, Opts) {
+ this->WCharType = TargetInfo::UnsignedShort;
+ DoubleAlign = LongLongAlign = 64;
+ resetDataLayout("e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32");
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ X86_32TargetInfo::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("_X86_");
+ Builder.defineMacro("__CYGWIN__");
+ Builder.defineMacro("__CYGWIN32__");
+ addCygMingDefines(Opts, Builder);
+ DefineStd(Builder, "unix", Opts);
+ if (Opts.CPlusPlus)
+ Builder.defineMacro("_GNU_SOURCE");
+ }
+};
+
+// x86-32 Haiku target
+class LLVM_LIBRARY_VISIBILITY HaikuX86_32TargetInfo
+ : public HaikuTargetInfo<X86_32TargetInfo> {
+public:
+ HaikuX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : HaikuTargetInfo<X86_32TargetInfo>(Triple, Opts) {}
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ HaikuTargetInfo<X86_32TargetInfo>::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("__INTEL__");
+ }
+};
+
+// X86-32 MCU target
+class LLVM_LIBRARY_VISIBILITY MCUX86_32TargetInfo : public X86_32TargetInfo {
+public:
+ MCUX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : X86_32TargetInfo(Triple, Opts) {
+ LongDoubleWidth = 64;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
+ resetDataLayout("e-m:e-p:32:32-i64:32-f64:32-f128:32-n8:16:32-a:0:32-S32");
+ WIntType = UnsignedInt;
+ }
+
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
+ // On MCU we support only C calling convention.
+ return CC == CC_C ? CCCR_OK : CCCR_Warning;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ X86_32TargetInfo::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("__iamcu");
+ Builder.defineMacro("__iamcu__");
+ }
+
+ bool allowsLargerPreferedTypeAlignment() const override { return false; }
+};
+
+// x86-32 RTEMS target
+class LLVM_LIBRARY_VISIBILITY RTEMSX86_32TargetInfo : public X86_32TargetInfo {
+public:
+ RTEMSX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : X86_32TargetInfo(Triple, Opts) {
+ SizeType = UnsignedLong;
+ IntPtrType = SignedLong;
+ PtrDiffType = SignedLong;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ X86_32TargetInfo::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("__INTEL__");
+ Builder.defineMacro("__rtems__");
+ }
+};
+
+// x86-64 generic target
+class LLVM_LIBRARY_VISIBILITY X86_64TargetInfo : public X86TargetInfo {
+public:
+ X86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : X86TargetInfo(Triple, Opts) {
+ const bool IsX32 = getTriple().getEnvironment() == llvm::Triple::GNUX32;
+ bool IsWinCOFF =
+ getTriple().isOSWindows() && getTriple().isOSBinFormatCOFF();
+ LongWidth = LongAlign = PointerWidth = PointerAlign = IsX32 ? 32 : 64;
+ LongDoubleWidth = 128;
+ LongDoubleAlign = 128;
+ LargeArrayMinWidth = 128;
+ LargeArrayAlign = 128;
+ SuitableAlign = 128;
+ SizeType = IsX32 ? UnsignedInt : UnsignedLong;
+ PtrDiffType = IsX32 ? SignedInt : SignedLong;
+ IntPtrType = IsX32 ? SignedInt : SignedLong;
+ IntMaxType = IsX32 ? SignedLongLong : SignedLong;
+ Int64Type = IsX32 ? SignedLongLong : SignedLong;
+ RegParmMax = 6;
+
+ // Pointers are 32-bit in x32.
+ resetDataLayout(IsX32
+ ? "e-m:e-p:32:32-i64:64-f80:128-n8:16:32:64-S128"
+ : IsWinCOFF ? "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+ : "e-m:e-i64:64-f80:128-n8:16:32:64-S128");
+
+ // Use fpret only for long double.
+ RealTypeUsesObjCFPRet = (1 << TargetInfo::LongDouble);
+
+ // Use fp2ret for _Complex long double.
+ ComplexLongDoubleUsesFP2Ret = true;
+
+ // Make __builtin_ms_va_list available.
+ HasBuiltinMSVaList = true;
+
+ // x86-64 has atomics up to 16 bytes.
+ MaxAtomicPromoteWidth = 128;
+ MaxAtomicInlineWidth = 64;
+ }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::X86_64ABIBuiltinVaList;
+ }
+
+ int getEHDataRegisterNumber(unsigned RegNo) const override {
+ if (RegNo == 0)
+ return 0;
+ if (RegNo == 1)
+ return 1;
+ return -1;
+ }
+
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
+ switch (CC) {
+ case CC_C:
+ case CC_Swift:
+ case CC_X86VectorCall:
+ case CC_IntelOclBicc:
+ case CC_Win64:
+ case CC_PreserveMost:
+ case CC_PreserveAll:
+ case CC_X86RegCall:
+ case CC_OpenCLKernel:
+ return CCCR_OK;
+ default:
+ return CCCR_Warning;
+ }
+ }
+
+ CallingConv getDefaultCallingConv(CallingConvMethodType MT) const override {
+ return CC_C;
+ }
+
+ // for x32 we need it here explicitly
+ bool hasInt128Type() const override { return true; }
+
+ unsigned getUnwindWordWidth() const override { return 64; }
+
+ unsigned getRegisterWidth() const override { return 64; }
+
+ bool validateGlobalRegisterVariable(StringRef RegName, unsigned RegSize,
+ bool &HasSizeMismatch) const override {
+ // rsp and rbp are the only 64-bit registers the x86 backend can currently
+ // handle.
+ if (RegName.equals("rsp") || RegName.equals("rbp")) {
+ // Check that the register size is 64-bit.
+ HasSizeMismatch = RegSize != 64;
+ return true;
+ }
+
+ // Check if the register is a 32-bit register the backend can handle.
+ return X86TargetInfo::validateGlobalRegisterVariable(RegName, RegSize,
+ HasSizeMismatch);
+ }
+
+ void setMaxAtomicWidth() override {
+ if (hasFeature("cx16"))
+ MaxAtomicInlineWidth = 128;
+ }
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+};
+
+// x86-64 Windows target
+class LLVM_LIBRARY_VISIBILITY WindowsX86_64TargetInfo
+ : public WindowsTargetInfo<X86_64TargetInfo> {
+public:
+ WindowsX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : WindowsTargetInfo<X86_64TargetInfo>(Triple, Opts) {
+ LongWidth = LongAlign = 32;
+ DoubleAlign = LongLongAlign = 64;
+ IntMaxType = SignedLongLong;
+ Int64Type = SignedLongLong;
+ SizeType = UnsignedLongLong;
+ PtrDiffType = SignedLongLong;
+ IntPtrType = SignedLongLong;
+ }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::CharPtrBuiltinVaList;
+ }
+
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
+ switch (CC) {
+ case CC_X86StdCall:
+ case CC_X86ThisCall:
+ case CC_X86FastCall:
+ return CCCR_Ignore;
+ case CC_C:
+ case CC_X86VectorCall:
+ case CC_IntelOclBicc:
+ case CC_PreserveMost:
+ case CC_PreserveAll:
+ case CC_X86_64SysV:
+ case CC_Swift:
+ case CC_X86RegCall:
+ case CC_OpenCLKernel:
+ return CCCR_OK;
+ default:
+ return CCCR_Warning;
+ }
+ }
+};
+
+// x86-64 Windows Visual Studio target
+class LLVM_LIBRARY_VISIBILITY MicrosoftX86_64TargetInfo
+ : public WindowsX86_64TargetInfo {
+public:
+ MicrosoftX86_64TargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : WindowsX86_64TargetInfo(Triple, Opts) {
+ LongDoubleWidth = LongDoubleAlign = 64;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ WindowsX86_64TargetInfo::getTargetDefines(Opts, Builder);
+ WindowsX86_64TargetInfo::getVisualStudioDefines(Opts, Builder);
+ Builder.defineMacro("_M_X64", "100");
+ Builder.defineMacro("_M_AMD64", "100");
+ }
+};
+
+// x86-64 MinGW target
+class LLVM_LIBRARY_VISIBILITY MinGWX86_64TargetInfo
+ : public WindowsX86_64TargetInfo {
+public:
+ MinGWX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : WindowsX86_64TargetInfo(Triple, Opts) {
+ // Mingw64 rounds long double size and alignment up to 16 bytes, but sticks
+ // with x86 FP ops. Weird.
+ LongDoubleWidth = LongDoubleAlign = 128;
+ LongDoubleFormat = &llvm::APFloat::x87DoubleExtended();
+ HasFloat128 = true;
+ }
+};
+
+// x86-64 Cygwin target
+class LLVM_LIBRARY_VISIBILITY CygwinX86_64TargetInfo : public X86_64TargetInfo {
+public:
+ CygwinX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : X86_64TargetInfo(Triple, Opts) {
+ this->WCharType = TargetInfo::UnsignedShort;
+ TLSSupported = false;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ X86_64TargetInfo::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("__x86_64__");
+ Builder.defineMacro("__CYGWIN__");
+ Builder.defineMacro("__CYGWIN64__");
+ addCygMingDefines(Opts, Builder);
+ DefineStd(Builder, "unix", Opts);
+ if (Opts.CPlusPlus)
+ Builder.defineMacro("_GNU_SOURCE");
+ }
+};
+
+class LLVM_LIBRARY_VISIBILITY DarwinX86_64TargetInfo
+ : public DarwinTargetInfo<X86_64TargetInfo> {
+public:
+ DarwinX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : DarwinTargetInfo<X86_64TargetInfo>(Triple, Opts) {
+ Int64Type = SignedLongLong;
+ // The 64-bit iOS simulator uses the builtin bool type for Objective-C.
+ llvm::Triple T = llvm::Triple(Triple);
+ if (T.isiOS())
+ UseSignedCharForObjCBool = false;
+ resetDataLayout("e-m:o-i64:64-f80:128-n8:16:32:64-S128");
+ }
+
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) override {
+ if (!DarwinTargetInfo<X86_64TargetInfo>::handleTargetFeatures(Features,
+ Diags))
+ return false;
+ // We now know the features we have: we can decide how to align vectors.
+ MaxVectorAlign =
+ hasFeature("avx512f") ? 512 : hasFeature("avx") ? 256 : 128;
+ return true;
+ }
+};
+
+class LLVM_LIBRARY_VISIBILITY OpenBSDX86_64TargetInfo
+ : public OpenBSDTargetInfo<X86_64TargetInfo> {
+public:
+ OpenBSDX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OpenBSDTargetInfo<X86_64TargetInfo>(Triple, Opts) {
+ IntMaxType = SignedLongLong;
+ Int64Type = SignedLongLong;
+ }
+};
+
+// x86_32 Android target
+class LLVM_LIBRARY_VISIBILITY AndroidX86_32TargetInfo
+ : public LinuxTargetInfo<X86_32TargetInfo> {
+public:
+ AndroidX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : LinuxTargetInfo<X86_32TargetInfo>(Triple, Opts) {
+ SuitableAlign = 32;
+ LongDoubleWidth = 64;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
+ }
+};
+
+// x86_64 Android target
+class LLVM_LIBRARY_VISIBILITY AndroidX86_64TargetInfo
+ : public LinuxTargetInfo<X86_64TargetInfo> {
+public:
+ AndroidX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : LinuxTargetInfo<X86_64TargetInfo>(Triple, Opts) {
+ LongDoubleFormat = &llvm::APFloat::IEEEquad();
+ }
+
+ bool useFloat128ManglingForLongDouble() const override { return true; }
+};
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_X86_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/XCore.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets/XCore.cpp
new file mode 100644
index 0000000000000..793dca702dae6
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/XCore.cpp
@@ -0,0 +1,38 @@
+//===--- XCore.cpp - Implement XCore target feature support ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements XCore TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "XCore.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "clang/Basic/TargetBuiltins.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+const Builtin::Info XCoreTargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
+ {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
+#include "clang/Basic/BuiltinsXCore.def"
+};
+
+void XCoreTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__XS1B__");
+}
+
+ArrayRef<Builtin::Info> XCoreTargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfo, clang::XCore::LastTSBuiltin -
+ Builtin::FirstTSBuiltin);
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets/XCore.h b/contrib/llvm/tools/clang/lib/Basic/Targets/XCore.h
new file mode 100644
index 0000000000000..346e0eee15b3b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets/XCore.h
@@ -0,0 +1,82 @@
+//===--- XCore.h - Declare XCore target feature support ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares XCore TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_XCORE_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_XCORE_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY XCoreTargetInfo : public TargetInfo {
+ static const Builtin::Info BuiltinInfo[];
+
+public:
+ XCoreTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple) {
+ NoAsmVariants = true;
+ LongLongAlign = 32;
+ SuitableAlign = 32;
+ DoubleAlign = LongDoubleAlign = 32;
+ SizeType = UnsignedInt;
+ PtrDiffType = SignedInt;
+ IntPtrType = SignedInt;
+ WCharType = UnsignedChar;
+ WIntType = UnsignedInt;
+ UseZeroLengthBitfieldAlignment = true;
+ resetDataLayout("e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:32"
+ "-f64:32-a:0:32-n32");
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::VoidPtrBuiltinVaList;
+ }
+
+ const char *getClobbers() const override { return ""; }
+
+ ArrayRef<const char *> getGCCRegNames() const override {
+ static const char *const GCCRegNames[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "cp", "dp", "sp", "lr"
+ };
+ return llvm::makeArrayRef(GCCRegNames);
+ }
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ return None;
+ }
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override {
+ return false;
+ }
+
+ int getEHDataRegisterNumber(unsigned RegNo) const override {
+ // R0=ExceptionPointerRegister R1=ExceptionSelectorRegister
+ return (RegNo < 2) ? RegNo : -1;
+ }
+
+ bool allowsLargerPreferedTypeAlignment() const override { return false; }
+};
+} // namespace targets
+} // namespace clang
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_XCORE_H
diff --git a/contrib/llvm/tools/clang/lib/Basic/Version.cpp b/contrib/llvm/tools/clang/lib/Basic/Version.cpp
index 2c569ff87d8ad..a1a67c2bc144d 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Version.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Version.cpp
@@ -36,7 +36,7 @@ std::string getClangRepositoryPath() {
// If the SVN_REPOSITORY is empty, try to use the SVN keyword. This helps us
// pick up a tag in an SVN export, for example.
- StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_501/final/lib/Basic/Version.cpp $");
+ StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/trunk/lib/Basic/Version.cpp $");
if (URL.empty()) {
URL = SVNRepository.slice(SVNRepository.find(':'),
SVNRepository.find("/lib/Basic"));
diff --git a/contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp b/contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp
index f5db717866a95..9d44597dc3fbb 100644
--- a/contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp
@@ -59,6 +59,7 @@ Status Status::copyWithNewName(const file_status &In, StringRef NewName) {
}
bool Status::equivalent(const Status &Other) const {
+ assert(isStatusKnown() && Other.isStatusKnown());
return getUniqueID() == Other.getUniqueID();
}
bool Status::isDirectory() const {
@@ -243,7 +244,7 @@ public:
RealFSDirIter(const Twine &Path, std::error_code &EC) : Iter(Path, EC) {
if (!EC && Iter != llvm::sys::fs::directory_iterator()) {
llvm::sys::fs::file_status S;
- EC = Iter->status(S);
+ EC = llvm::sys::fs::status(Iter->path(), S, true);
CurrentEntry = Status::copyWithNewName(S, Iter->path());
}
}
@@ -257,7 +258,7 @@ public:
CurrentEntry = Status();
} else {
llvm::sys::fs::file_status S;
- EC = Iter->status(S);
+ EC = llvm::sys::fs::status(Iter->path(), S, true);
CurrentEntry = Status::copyWithNewName(S, Iter->path());
}
return EC;
@@ -492,7 +493,11 @@ std::string InMemoryFileSystem::toString() const {
}
bool InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime,
- std::unique_ptr<llvm::MemoryBuffer> Buffer) {
+ std::unique_ptr<llvm::MemoryBuffer> Buffer,
+ Optional<uint32_t> User,
+ Optional<uint32_t> Group,
+ Optional<llvm::sys::fs::file_type> Type,
+ Optional<llvm::sys::fs::perms> Perms) {
SmallString<128> Path;
P.toVector(Path);
@@ -508,32 +513,42 @@ bool InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime,
return false;
detail::InMemoryDirectory *Dir = Root.get();
- auto I = llvm::sys::path::begin(Path), E = llvm::sys::path::end(Path);
+ auto I = llvm::sys::path::begin(Path), E = sys::path::end(Path);
+ const auto ResolvedUser = User.getValueOr(0);
+ const auto ResolvedGroup = Group.getValueOr(0);
+ const auto ResolvedType = Type.getValueOr(sys::fs::file_type::regular_file);
+ const auto ResolvedPerms = Perms.getValueOr(sys::fs::all_all);
+ // Any intermediate directories we create should be accessible by
+ // the owner, even if Perms says otherwise for the final path.
+ const auto NewDirectoryPerms = ResolvedPerms | sys::fs::owner_all;
while (true) {
StringRef Name = *I;
detail::InMemoryNode *Node = Dir->getChild(Name);
++I;
if (!Node) {
if (I == E) {
- // End of the path, create a new file.
- // FIXME: expose the status details in the interface.
+ // End of the path, create a new file or directory.
Status Stat(P.str(), getNextVirtualUniqueID(),
- llvm::sys::toTimePoint(ModificationTime), 0, 0,
- Buffer->getBufferSize(),
- llvm::sys::fs::file_type::regular_file,
- llvm::sys::fs::all_all);
- Dir->addChild(Name, llvm::make_unique<detail::InMemoryFile>(
- std::move(Stat), std::move(Buffer)));
+ llvm::sys::toTimePoint(ModificationTime), ResolvedUser,
+ ResolvedGroup, Buffer->getBufferSize(), ResolvedType,
+ ResolvedPerms);
+ std::unique_ptr<detail::InMemoryNode> Child;
+ if (ResolvedType == sys::fs::file_type::directory_file) {
+ Child.reset(new detail::InMemoryDirectory(std::move(Stat)));
+ } else {
+ Child.reset(new detail::InMemoryFile(std::move(Stat),
+ std::move(Buffer)));
+ }
+ Dir->addChild(Name, std::move(Child));
return true;
}
// Create a new directory. Use the path up to here.
- // FIXME: expose the status details in the interface.
Status Stat(
StringRef(Path.str().begin(), Name.end() - Path.str().begin()),
- getNextVirtualUniqueID(), llvm::sys::toTimePoint(ModificationTime), 0,
- 0, Buffer->getBufferSize(), llvm::sys::fs::file_type::directory_file,
- llvm::sys::fs::all_all);
+ getNextVirtualUniqueID(), llvm::sys::toTimePoint(ModificationTime),
+ ResolvedUser, ResolvedGroup, Buffer->getBufferSize(),
+ sys::fs::file_type::directory_file, NewDirectoryPerms);
Dir = cast<detail::InMemoryDirectory>(Dir->addChild(
Name, llvm::make_unique<detail::InMemoryDirectory>(std::move(Stat))));
continue;
@@ -557,10 +572,16 @@ bool InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime,
}
bool InMemoryFileSystem::addFileNoOwn(const Twine &P, time_t ModificationTime,
- llvm::MemoryBuffer *Buffer) {
+ llvm::MemoryBuffer *Buffer,
+ Optional<uint32_t> User,
+ Optional<uint32_t> Group,
+ Optional<llvm::sys::fs::file_type> Type,
+ Optional<llvm::sys::fs::perms> Perms) {
return addFile(P, ModificationTime,
llvm::MemoryBuffer::getMemBuffer(
- Buffer->getBuffer(), Buffer->getBufferIdentifier()));
+ Buffer->getBuffer(), Buffer->getBufferIdentifier()),
+ std::move(User), std::move(Group), std::move(Type),
+ std::move(Perms));
}
static ErrorOr<detail::InMemoryNode *>
diff --git a/contrib/llvm/tools/clang/lib/Basic/XRayLists.cpp b/contrib/llvm/tools/clang/lib/Basic/XRayLists.cpp
index 0a439c7af90df..462777d53400f 100644
--- a/contrib/llvm/tools/clang/lib/Basic/XRayLists.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/XRayLists.cpp
@@ -26,11 +26,13 @@ XRayFunctionFilter::ImbueAttribute
XRayFunctionFilter::shouldImbueFunction(StringRef FunctionName) const {
// First apply the always instrument list, than if it isn't an "always" see
// whether it's treated as a "never" instrument function.
- if (AlwaysInstrument->inSection("fun", FunctionName, "arg1"))
+ if (AlwaysInstrument->inSection("xray_always_instrument", "fun", FunctionName,
+ "arg1"))
return ImbueAttribute::ALWAYS_ARG1;
- if (AlwaysInstrument->inSection("fun", FunctionName))
+ if (AlwaysInstrument->inSection("xray_always_instrument", "fun",
+ FunctionName))
return ImbueAttribute::ALWAYS;
- if (NeverInstrument->inSection("fun", FunctionName))
+ if (NeverInstrument->inSection("xray_never_instrument", "fun", FunctionName))
return ImbueAttribute::NEVER;
return ImbueAttribute::NONE;
}
@@ -38,9 +40,11 @@ XRayFunctionFilter::shouldImbueFunction(StringRef FunctionName) const {
XRayFunctionFilter::ImbueAttribute
XRayFunctionFilter::shouldImbueFunctionsInFile(StringRef Filename,
StringRef Category) const {
- if (AlwaysInstrument->inSection("src", Filename, Category))
+ if (AlwaysInstrument->inSection("xray_always_instrument", "src", Filename,
+ Category))
return ImbueAttribute::ALWAYS;
- if (NeverInstrument->inSection("src", Filename, Category))
+ if (NeverInstrument->inSection("xray_never_instrument", "src", Filename,
+ Category))
return ImbueAttribute::NEVER;
return ImbueAttribute::NONE;
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp b/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp
index 513896d986345..2c033e0f7c026 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp
@@ -44,13 +44,14 @@
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
-#include "llvm/Target/TargetSubtargetInfo.h"
+#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/Transforms/Coroutines.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/IPO/AlwaysInliner.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
#include "llvm/Transforms/Instrumentation.h"
+#include "llvm/Transforms/Instrumentation/BoundsChecking.h"
#include "llvm/Transforms/ObjCARC.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Scalar/GVN.h"
@@ -168,7 +169,7 @@ static void addAddDiscriminatorsPass(const PassManagerBuilder &Builder,
static void addBoundsCheckingPass(const PassManagerBuilder &Builder,
legacy::PassManagerBase &PM) {
- PM.add(createBoundsCheckingPass());
+ PM.add(createBoundsCheckingLegacyPass());
}
static void addSanitizerCoveragePass(const PassManagerBuilder &Builder,
@@ -189,6 +190,8 @@ static void addSanitizerCoveragePass(const PassManagerBuilder &Builder,
Opts.TracePCGuard = CGOpts.SanitizeCoverageTracePCGuard;
Opts.NoPrune = CGOpts.SanitizeCoverageNoPrune;
Opts.Inline8bitCounters = CGOpts.SanitizeCoverageInline8bitCounters;
+ Opts.PCTable = CGOpts.SanitizeCoveragePCTable;
+ Opts.StackDepth = CGOpts.SanitizeCoverageStackDepth;
PM.add(createSanitizerCoverageModulePass(Opts));
}
@@ -234,6 +237,11 @@ static void addKernelAddressSanitizerPasses(const PassManagerBuilder &Builder,
/*Recover*/true));
}
+static void addHWAddressSanitizerPasses(const PassManagerBuilder &Builder,
+ legacy::PassManagerBase &PM) {
+ PM.add(createHWAddressSanitizerPass());
+}
+
static void addMemorySanitizerPass(const PassManagerBuilder &Builder,
legacy::PassManagerBase &PM) {
const PassManagerBuilderWrapper &BuilderWrapper =
@@ -334,16 +342,18 @@ static CodeGenOpt::Level getCGOptLevel(const CodeGenOptions &CodeGenOpts) {
}
}
-static llvm::CodeModel::Model getCodeModel(const CodeGenOptions &CodeGenOpts) {
- unsigned CodeModel =
- llvm::StringSwitch<unsigned>(CodeGenOpts.CodeModel)
- .Case("small", llvm::CodeModel::Small)
- .Case("kernel", llvm::CodeModel::Kernel)
- .Case("medium", llvm::CodeModel::Medium)
- .Case("large", llvm::CodeModel::Large)
- .Case("default", llvm::CodeModel::Default)
- .Default(~0u);
+static Optional<llvm::CodeModel::Model>
+getCodeModel(const CodeGenOptions &CodeGenOpts) {
+ unsigned CodeModel = llvm::StringSwitch<unsigned>(CodeGenOpts.CodeModel)
+ .Case("small", llvm::CodeModel::Small)
+ .Case("kernel", llvm::CodeModel::Kernel)
+ .Case("medium", llvm::CodeModel::Medium)
+ .Case("large", llvm::CodeModel::Large)
+ .Case("default", ~1u)
+ .Default(~0u);
assert(CodeModel != ~0u && "invalid code model!");
+ if (CodeModel == ~1u)
+ return None;
return static_cast<llvm::CodeModel::Model>(CodeModel);
}
@@ -419,6 +429,10 @@ static void initTargetOptions(llvm::TargetOptions &Options,
if (LangOpts.SjLjExceptions)
Options.ExceptionModel = llvm::ExceptionHandling::SjLj;
+ if (LangOpts.SEHExceptions)
+ Options.ExceptionModel = llvm::ExceptionHandling::WinEH;
+ if (LangOpts.DWARFExceptions)
+ Options.ExceptionModel = llvm::ExceptionHandling::DwarfCFI;
Options.NoInfsFPMath = CodeGenOpts.NoInfsFPMath;
Options.NoNaNsFPMath = CodeGenOpts.NoNaNsFPMath;
@@ -547,6 +561,13 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM,
addKernelAddressSanitizerPasses);
}
+ if (LangOpts.Sanitize.has(SanitizerKind::HWAddress)) {
+ PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
+ addHWAddressSanitizerPasses);
+ PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
+ addHWAddressSanitizerPasses);
+ }
+
if (LangOpts.Sanitize.has(SanitizerKind::Memory)) {
PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
addMemorySanitizerPass);
@@ -657,7 +678,7 @@ void EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) {
return;
}
- llvm::CodeModel::Model CM = getCodeModel(CodeGenOpts);
+ Optional<llvm::CodeModel::Model> CM = getCodeModel(CodeGenOpts);
std::string FeaturesStr =
llvm::join(TargetOpts.Features.begin(), TargetOpts.Features.end(), ",");
llvm::Reloc::Model RM = getRelocModel(CodeGenOpts);
@@ -840,37 +861,44 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
return;
TheModule->setDataLayout(TM->createDataLayout());
- PGOOptions PGOOpt;
-
- // -fprofile-generate.
- PGOOpt.RunProfileGen = CodeGenOpts.hasProfileIRInstr();
- if (PGOOpt.RunProfileGen)
- PGOOpt.ProfileGenFile = CodeGenOpts.InstrProfileOutput.empty() ?
- DefaultProfileGenName : CodeGenOpts.InstrProfileOutput;
-
- // -fprofile-use.
- if (CodeGenOpts.hasProfileIRUse())
- PGOOpt.ProfileUseFile = CodeGenOpts.ProfileInstrumentUsePath;
+ Optional<PGOOptions> PGOOpt;
- if (!CodeGenOpts.SampleProfileFile.empty())
- PGOOpt.SampleProfileFile = CodeGenOpts.SampleProfileFile;
+ if (CodeGenOpts.hasProfileIRInstr())
+ // -fprofile-generate.
+ PGOOpt = PGOOptions(CodeGenOpts.InstrProfileOutput.empty()
+ ? DefaultProfileGenName
+ : CodeGenOpts.InstrProfileOutput,
+ "", "", true, CodeGenOpts.DebugInfoForProfiling);
+ else if (CodeGenOpts.hasProfileIRUse())
+ // -fprofile-use.
+ PGOOpt = PGOOptions("", CodeGenOpts.ProfileInstrumentUsePath, "", false,
+ CodeGenOpts.DebugInfoForProfiling);
+ else if (!CodeGenOpts.SampleProfileFile.empty())
+ // -fprofile-sample-use
+ PGOOpt = PGOOptions("", "", CodeGenOpts.SampleProfileFile, false,
+ CodeGenOpts.DebugInfoForProfiling);
+ else if (CodeGenOpts.DebugInfoForProfiling)
+ // -fdebug-info-for-profiling
+ PGOOpt = PGOOptions("", "", "", false, true);
- // Only pass a PGO options struct if -fprofile-generate or
- // -fprofile-use were passed on the cmdline.
- PassBuilder PB(TM.get(),
- (PGOOpt.RunProfileGen ||
- !PGOOpt.ProfileUseFile.empty() ||
- !PGOOpt.SampleProfileFile.empty()) ?
- Optional<PGOOptions>(PGOOpt) : None);
+ PassBuilder PB(TM.get(), PGOOpt);
- LoopAnalysisManager LAM;
- FunctionAnalysisManager FAM;
- CGSCCAnalysisManager CGAM;
- ModuleAnalysisManager MAM;
+ LoopAnalysisManager LAM(CodeGenOpts.DebugPassManager);
+ FunctionAnalysisManager FAM(CodeGenOpts.DebugPassManager);
+ CGSCCAnalysisManager CGAM(CodeGenOpts.DebugPassManager);
+ ModuleAnalysisManager MAM(CodeGenOpts.DebugPassManager);
// Register the AA manager first so that our version is the one used.
FAM.registerPass([&] { return PB.buildDefaultAAPipeline(); });
+ // Register the target library analysis directly and give it a customized
+ // preset TLI.
+ Triple TargetTriple(TheModule->getTargetTriple());
+ std::unique_ptr<TargetLibraryInfoImpl> TLII(
+ createTLII(TargetTriple, CodeGenOpts));
+ FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); });
+ MAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); });
+
// Register all the basic analyses with the managers.
PB.registerModuleAnalyses(MAM);
PB.registerCGSCCAnalyses(CGAM);
@@ -888,6 +916,12 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
// Build a minimal pipeline based on the semantics required by Clang,
// which is just that always inlining occurs.
MPM.addPass(AlwaysInlinerPass());
+
+ // At -O0 we directly run necessary sanitizer passes.
+ if (LangOpts.Sanitize.has(SanitizerKind::LocalBounds))
+ MPM.addPass(createModuleToFunctionPassAdaptor(BoundsCheckingPass()));
+
+ // Lastly, add a semantically necessary pass for ThinLTO.
if (IsThinLTO)
MPM.addPass(NameAnonGlobalPass());
} else {
@@ -895,6 +929,14 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
// configure the pipeline.
PassBuilder::OptimizationLevel Level = mapToLevel(CodeGenOpts);
+ // Register callbacks to schedule sanitizer passes at the appropriate part of
+ // the pipeline.
+ if (LangOpts.Sanitize.has(SanitizerKind::LocalBounds))
+ PB.registerScalarOptimizerLateEPCallback(
+ [](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) {
+ FPM.addPass(BoundsCheckingPass());
+ });
+
if (IsThinLTO) {
MPM = PB.buildThinLTOPreLinkDefaultPipeline(
Level, CodeGenOpts.DebugPassManager);
@@ -1062,6 +1104,7 @@ static void runThinLTOBackend(ModuleSummaryIndex *CombinedIndex, Module *M,
initTargetOptions(Conf.Options, CGOpts, TOpts, LOpts, HeaderOpts);
Conf.SampleProfile = std::move(SampleProfile);
Conf.UseNewPM = CGOpts.ExperimentalNewPassManager;
+ Conf.DebugPassManager = CGOpts.DebugPassManager;
switch (Action) {
case Backend_EmitNothing:
Conf.PreCodeGenModuleHook = [](size_t Task, const Module &Mod) {
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGAtomic.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGAtomic.cpp
index a6e6fec206d57..d90c3a53a635d 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGAtomic.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGAtomic.cpp
@@ -15,8 +15,10 @@
#include "CGRecordLayout.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
+#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
#include "clang/CodeGen/CGFunctionInfo.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Operator.h"
@@ -94,9 +96,8 @@ namespace {
BFI.StorageSize = AtomicSizeInBits;
BFI.StorageOffset += OffsetInChars;
LVal = LValue::MakeBitfield(Address(Addr, lvalue.getAlignment()),
- BFI, lvalue.getType(),
- lvalue.getBaseInfo());
- LVal.setTBAAInfo(lvalue.getTBAAInfo());
+ BFI, lvalue.getType(), lvalue.getBaseInfo(),
+ lvalue.getTBAAInfo());
AtomicTy = C.getIntTypeForBitwidth(AtomicSizeInBits, OrigBFI.IsSigned);
if (AtomicTy.isNull()) {
llvm::APInt Size(
@@ -359,13 +360,15 @@ static void emitAtomicCmpXchg(CodeGenFunction &CGF, AtomicExpr *E, bool IsWeak,
Address Val1, Address Val2,
uint64_t Size,
llvm::AtomicOrdering SuccessOrder,
- llvm::AtomicOrdering FailureOrder) {
+ llvm::AtomicOrdering FailureOrder,
+ llvm::SyncScope::ID Scope) {
// Note that cmpxchg doesn't support weak cmpxchg, at least at the moment.
llvm::Value *Expected = CGF.Builder.CreateLoad(Val1);
llvm::Value *Desired = CGF.Builder.CreateLoad(Val2);
llvm::AtomicCmpXchgInst *Pair = CGF.Builder.CreateAtomicCmpXchg(
- Ptr.getPointer(), Expected, Desired, SuccessOrder, FailureOrder);
+ Ptr.getPointer(), Expected, Desired, SuccessOrder, FailureOrder,
+ Scope);
Pair->setVolatile(E->isVolatile());
Pair->setWeak(IsWeak);
@@ -407,7 +410,8 @@ static void emitAtomicCmpXchgFailureSet(CodeGenFunction &CGF, AtomicExpr *E,
Address Val1, Address Val2,
llvm::Value *FailureOrderVal,
uint64_t Size,
- llvm::AtomicOrdering SuccessOrder) {
+ llvm::AtomicOrdering SuccessOrder,
+ llvm::SyncScope::ID Scope) {
llvm::AtomicOrdering FailureOrder;
if (llvm::ConstantInt *FO = dyn_cast<llvm::ConstantInt>(FailureOrderVal)) {
auto FOS = FO->getSExtValue();
@@ -435,7 +439,7 @@ static void emitAtomicCmpXchgFailureSet(CodeGenFunction &CGF, AtomicExpr *E,
llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(SuccessOrder);
}
emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, Size, SuccessOrder,
- FailureOrder);
+ FailureOrder, Scope);
return;
}
@@ -460,13 +464,13 @@ static void emitAtomicCmpXchgFailureSet(CodeGenFunction &CGF, AtomicExpr *E,
// doesn't fold to a constant for the ordering.
CGF.Builder.SetInsertPoint(MonotonicBB);
emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2,
- Size, SuccessOrder, llvm::AtomicOrdering::Monotonic);
+ Size, SuccessOrder, llvm::AtomicOrdering::Monotonic, Scope);
CGF.Builder.CreateBr(ContBB);
if (AcquireBB) {
CGF.Builder.SetInsertPoint(AcquireBB);
emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2,
- Size, SuccessOrder, llvm::AtomicOrdering::Acquire);
+ Size, SuccessOrder, llvm::AtomicOrdering::Acquire, Scope);
CGF.Builder.CreateBr(ContBB);
SI->addCase(CGF.Builder.getInt32((int)llvm::AtomicOrderingCABI::consume),
AcquireBB);
@@ -476,7 +480,7 @@ static void emitAtomicCmpXchgFailureSet(CodeGenFunction &CGF, AtomicExpr *E,
if (SeqCstBB) {
CGF.Builder.SetInsertPoint(SeqCstBB);
emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, Size, SuccessOrder,
- llvm::AtomicOrdering::SequentiallyConsistent);
+ llvm::AtomicOrdering::SequentiallyConsistent, Scope);
CGF.Builder.CreateBr(ContBB);
SI->addCase(CGF.Builder.getInt32((int)llvm::AtomicOrderingCABI::seq_cst),
SeqCstBB);
@@ -488,27 +492,31 @@ static void emitAtomicCmpXchgFailureSet(CodeGenFunction &CGF, AtomicExpr *E,
static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
Address Ptr, Address Val1, Address Val2,
llvm::Value *IsWeak, llvm::Value *FailureOrder,
- uint64_t Size, llvm::AtomicOrdering Order) {
+ uint64_t Size, llvm::AtomicOrdering Order,
+ llvm::SyncScope::ID Scope) {
llvm::AtomicRMWInst::BinOp Op = llvm::AtomicRMWInst::Add;
llvm::Instruction::BinaryOps PostOp = (llvm::Instruction::BinaryOps)0;
switch (E->getOp()) {
case AtomicExpr::AO__c11_atomic_init:
+ case AtomicExpr::AO__opencl_atomic_init:
llvm_unreachable("Already handled!");
case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
+ case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:
emitAtomicCmpXchgFailureSet(CGF, E, false, Dest, Ptr, Val1, Val2,
- FailureOrder, Size, Order);
+ FailureOrder, Size, Order, Scope);
return;
case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
+ case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:
emitAtomicCmpXchgFailureSet(CGF, E, true, Dest, Ptr, Val1, Val2,
- FailureOrder, Size, Order);
+ FailureOrder, Size, Order, Scope);
return;
case AtomicExpr::AO__atomic_compare_exchange:
case AtomicExpr::AO__atomic_compare_exchange_n: {
if (llvm::ConstantInt *IsWeakC = dyn_cast<llvm::ConstantInt>(IsWeak)) {
emitAtomicCmpXchgFailureSet(CGF, E, IsWeakC->getZExtValue(), Dest, Ptr,
- Val1, Val2, FailureOrder, Size, Order);
+ Val1, Val2, FailureOrder, Size, Order, Scope);
} else {
// Create all the relevant BB's
llvm::BasicBlock *StrongBB =
@@ -522,12 +530,12 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
CGF.Builder.SetInsertPoint(StrongBB);
emitAtomicCmpXchgFailureSet(CGF, E, false, Dest, Ptr, Val1, Val2,
- FailureOrder, Size, Order);
+ FailureOrder, Size, Order, Scope);
CGF.Builder.CreateBr(ContBB);
CGF.Builder.SetInsertPoint(WeakBB);
emitAtomicCmpXchgFailureSet(CGF, E, true, Dest, Ptr, Val1, Val2,
- FailureOrder, Size, Order);
+ FailureOrder, Size, Order, Scope);
CGF.Builder.CreateBr(ContBB);
CGF.Builder.SetInsertPoint(ContBB);
@@ -535,26 +543,29 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
return;
}
case AtomicExpr::AO__c11_atomic_load:
+ case AtomicExpr::AO__opencl_atomic_load:
case AtomicExpr::AO__atomic_load_n:
case AtomicExpr::AO__atomic_load: {
llvm::LoadInst *Load = CGF.Builder.CreateLoad(Ptr);
- Load->setAtomic(Order);
+ Load->setAtomic(Order, Scope);
Load->setVolatile(E->isVolatile());
CGF.Builder.CreateStore(Load, Dest);
return;
}
case AtomicExpr::AO__c11_atomic_store:
+ case AtomicExpr::AO__opencl_atomic_store:
case AtomicExpr::AO__atomic_store:
case AtomicExpr::AO__atomic_store_n: {
llvm::Value *LoadVal1 = CGF.Builder.CreateLoad(Val1);
llvm::StoreInst *Store = CGF.Builder.CreateStore(LoadVal1, Ptr);
- Store->setAtomic(Order);
+ Store->setAtomic(Order, Scope);
Store->setVolatile(E->isVolatile());
return;
}
case AtomicExpr::AO__c11_atomic_exchange:
+ case AtomicExpr::AO__opencl_atomic_exchange:
case AtomicExpr::AO__atomic_exchange_n:
case AtomicExpr::AO__atomic_exchange:
Op = llvm::AtomicRMWInst::Xchg;
@@ -564,6 +575,7 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
PostOp = llvm::Instruction::Add;
// Fall through.
case AtomicExpr::AO__c11_atomic_fetch_add:
+ case AtomicExpr::AO__opencl_atomic_fetch_add:
case AtomicExpr::AO__atomic_fetch_add:
Op = llvm::AtomicRMWInst::Add;
break;
@@ -572,14 +584,26 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
PostOp = llvm::Instruction::Sub;
// Fall through.
case AtomicExpr::AO__c11_atomic_fetch_sub:
+ case AtomicExpr::AO__opencl_atomic_fetch_sub:
case AtomicExpr::AO__atomic_fetch_sub:
Op = llvm::AtomicRMWInst::Sub;
break;
+ case AtomicExpr::AO__opencl_atomic_fetch_min:
+ Op = E->getValueType()->isSignedIntegerType() ? llvm::AtomicRMWInst::Min
+ : llvm::AtomicRMWInst::UMin;
+ break;
+
+ case AtomicExpr::AO__opencl_atomic_fetch_max:
+ Op = E->getValueType()->isSignedIntegerType() ? llvm::AtomicRMWInst::Max
+ : llvm::AtomicRMWInst::UMax;
+ break;
+
case AtomicExpr::AO__atomic_and_fetch:
PostOp = llvm::Instruction::And;
// Fall through.
case AtomicExpr::AO__c11_atomic_fetch_and:
+ case AtomicExpr::AO__opencl_atomic_fetch_and:
case AtomicExpr::AO__atomic_fetch_and:
Op = llvm::AtomicRMWInst::And;
break;
@@ -588,6 +612,7 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
PostOp = llvm::Instruction::Or;
// Fall through.
case AtomicExpr::AO__c11_atomic_fetch_or:
+ case AtomicExpr::AO__opencl_atomic_fetch_or:
case AtomicExpr::AO__atomic_fetch_or:
Op = llvm::AtomicRMWInst::Or;
break;
@@ -596,6 +621,7 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
PostOp = llvm::Instruction::Xor;
// Fall through.
case AtomicExpr::AO__c11_atomic_fetch_xor:
+ case AtomicExpr::AO__opencl_atomic_fetch_xor:
case AtomicExpr::AO__atomic_fetch_xor:
Op = llvm::AtomicRMWInst::Xor;
break;
@@ -610,7 +636,7 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
llvm::Value *LoadVal1 = CGF.Builder.CreateLoad(Val1);
llvm::AtomicRMWInst *RMWI =
- CGF.Builder.CreateAtomicRMW(Op, Ptr.getPointer(), LoadVal1, Order);
+ CGF.Builder.CreateAtomicRMW(Op, Ptr.getPointer(), LoadVal1, Order, Scope);
RMWI->setVolatile(E->isVolatile());
// For __atomic_*_fetch operations, perform the operation again to
@@ -633,6 +659,61 @@ EmitValToTemp(CodeGenFunction &CGF, Expr *E) {
return DeclPtr;
}
+static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *Expr, Address Dest,
+ Address Ptr, Address Val1, Address Val2,
+ llvm::Value *IsWeak, llvm::Value *FailureOrder,
+ uint64_t Size, llvm::AtomicOrdering Order,
+ llvm::Value *Scope) {
+ auto ScopeModel = Expr->getScopeModel();
+
+ // LLVM atomic instructions always have synch scope. If clang atomic
+ // expression has no scope operand, use default LLVM synch scope.
+ if (!ScopeModel) {
+ EmitAtomicOp(CGF, Expr, Dest, Ptr, Val1, Val2, IsWeak, FailureOrder, Size,
+ Order, CGF.CGM.getLLVMContext().getOrInsertSyncScopeID(""));
+ return;
+ }
+
+ // Handle constant scope.
+ if (auto SC = dyn_cast<llvm::ConstantInt>(Scope)) {
+ auto SCID = CGF.getTargetHooks().getLLVMSyncScopeID(
+ ScopeModel->map(SC->getZExtValue()), CGF.CGM.getLLVMContext());
+ EmitAtomicOp(CGF, Expr, Dest, Ptr, Val1, Val2, IsWeak, FailureOrder, Size,
+ Order, SCID);
+ return;
+ }
+
+ // Handle non-constant scope.
+ auto &Builder = CGF.Builder;
+ auto Scopes = ScopeModel->getRuntimeValues();
+ llvm::DenseMap<unsigned, llvm::BasicBlock *> BB;
+ for (auto S : Scopes)
+ BB[S] = CGF.createBasicBlock(getAsString(ScopeModel->map(S)), CGF.CurFn);
+
+ llvm::BasicBlock *ContBB =
+ CGF.createBasicBlock("atomic.scope.continue", CGF.CurFn);
+
+ auto *SC = Builder.CreateIntCast(Scope, Builder.getInt32Ty(), false);
+ // If unsupported synch scope is encountered at run time, assume a fallback
+ // synch scope value.
+ auto FallBack = ScopeModel->getFallBackValue();
+ llvm::SwitchInst *SI = Builder.CreateSwitch(SC, BB[FallBack]);
+ for (auto S : Scopes) {
+ auto *B = BB[S];
+ if (S != FallBack)
+ SI->addCase(Builder.getInt32(S), B);
+
+ Builder.SetInsertPoint(B);
+ EmitAtomicOp(CGF, Expr, Dest, Ptr, Val1, Val2, IsWeak, FailureOrder, Size,
+ Order,
+ CGF.getTargetHooks().getLLVMSyncScopeID(ScopeModel->map(S),
+ CGF.getLLVMContext()));
+ Builder.CreateBr(ContBB);
+ }
+
+ Builder.SetInsertPoint(ContBB);
+}
+
static void
AddDirectArgument(CodeGenFunction &CGF, CallArgList &Args,
bool UseOptimizedLibcall, llvm::Value *Val, QualType ValTy,
@@ -663,33 +744,38 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
QualType MemTy = AtomicTy;
if (const AtomicType *AT = AtomicTy->getAs<AtomicType>())
MemTy = AT->getValueType();
- CharUnits sizeChars, alignChars;
- std::tie(sizeChars, alignChars) = getContext().getTypeInfoInChars(AtomicTy);
- uint64_t Size = sizeChars.getQuantity();
- unsigned MaxInlineWidthInBits = getTarget().getMaxAtomicInlineWidth();
- bool UseLibcall = (sizeChars != alignChars ||
- getContext().toBits(sizeChars) > MaxInlineWidthInBits);
-
llvm::Value *IsWeak = nullptr, *OrderFail = nullptr;
Address Val1 = Address::invalid();
Address Val2 = Address::invalid();
Address Dest = Address::invalid();
- Address Ptr(EmitScalarExpr(E->getPtr()), alignChars);
+ Address Ptr = EmitPointerWithAlignment(E->getPtr());
+
+ CharUnits sizeChars, alignChars;
+ std::tie(sizeChars, alignChars) = getContext().getTypeInfoInChars(AtomicTy);
+ uint64_t Size = sizeChars.getQuantity();
+ unsigned MaxInlineWidthInBits = getTarget().getMaxAtomicInlineWidth();
+ bool UseLibcall = ((Ptr.getAlignment() % sizeChars) != 0 ||
+ getContext().toBits(sizeChars) > MaxInlineWidthInBits);
- if (E->getOp() == AtomicExpr::AO__c11_atomic_init) {
+ if (E->getOp() == AtomicExpr::AO__c11_atomic_init ||
+ E->getOp() == AtomicExpr::AO__opencl_atomic_init) {
LValue lvalue = MakeAddrLValue(Ptr, AtomicTy);
EmitAtomicInit(E->getVal1(), lvalue);
return RValue::get(nullptr);
}
llvm::Value *Order = EmitScalarExpr(E->getOrder());
+ llvm::Value *Scope =
+ E->getScopeModel() ? EmitScalarExpr(E->getScope()) : nullptr;
switch (E->getOp()) {
case AtomicExpr::AO__c11_atomic_init:
+ case AtomicExpr::AO__opencl_atomic_init:
llvm_unreachable("Already handled above with EmitAtomicInit!");
case AtomicExpr::AO__c11_atomic_load:
+ case AtomicExpr::AO__opencl_atomic_load:
case AtomicExpr::AO__atomic_load_n:
break;
@@ -708,6 +794,8 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
+ case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:
+ case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:
case AtomicExpr::AO__atomic_compare_exchange_n:
case AtomicExpr::AO__atomic_compare_exchange:
Val1 = EmitPointerWithAlignment(E->getVal1());
@@ -716,12 +804,15 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
else
Val2 = EmitValToTemp(*this, E->getVal2());
OrderFail = EmitScalarExpr(E->getOrderFail());
- if (E->getNumSubExprs() == 6)
+ if (E->getOp() == AtomicExpr::AO__atomic_compare_exchange_n ||
+ E->getOp() == AtomicExpr::AO__atomic_compare_exchange)
IsWeak = EmitScalarExpr(E->getWeak());
break;
case AtomicExpr::AO__c11_atomic_fetch_add:
case AtomicExpr::AO__c11_atomic_fetch_sub:
+ case AtomicExpr::AO__opencl_atomic_fetch_add:
+ case AtomicExpr::AO__opencl_atomic_fetch_sub:
if (MemTy->isPointerType()) {
// For pointer arithmetic, we're required to do a bit of math:
// adding 1 to an int* is not the same as adding 1 to a uintptr_t.
@@ -744,11 +835,18 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
case AtomicExpr::AO__atomic_sub_fetch:
case AtomicExpr::AO__c11_atomic_store:
case AtomicExpr::AO__c11_atomic_exchange:
+ case AtomicExpr::AO__opencl_atomic_store:
+ case AtomicExpr::AO__opencl_atomic_exchange:
case AtomicExpr::AO__atomic_store_n:
case AtomicExpr::AO__atomic_exchange_n:
case AtomicExpr::AO__c11_atomic_fetch_and:
case AtomicExpr::AO__c11_atomic_fetch_or:
case AtomicExpr::AO__c11_atomic_fetch_xor:
+ case AtomicExpr::AO__opencl_atomic_fetch_and:
+ case AtomicExpr::AO__opencl_atomic_fetch_or:
+ case AtomicExpr::AO__opencl_atomic_fetch_xor:
+ case AtomicExpr::AO__opencl_atomic_fetch_min:
+ case AtomicExpr::AO__opencl_atomic_fetch_max:
case AtomicExpr::AO__atomic_fetch_and:
case AtomicExpr::AO__atomic_fetch_or:
case AtomicExpr::AO__atomic_fetch_xor:
@@ -784,18 +882,26 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
bool UseOptimizedLibcall = false;
switch (E->getOp()) {
case AtomicExpr::AO__c11_atomic_init:
+ case AtomicExpr::AO__opencl_atomic_init:
llvm_unreachable("Already handled above with EmitAtomicInit!");
case AtomicExpr::AO__c11_atomic_fetch_add:
+ case AtomicExpr::AO__opencl_atomic_fetch_add:
case AtomicExpr::AO__atomic_fetch_add:
case AtomicExpr::AO__c11_atomic_fetch_and:
+ case AtomicExpr::AO__opencl_atomic_fetch_and:
case AtomicExpr::AO__atomic_fetch_and:
case AtomicExpr::AO__c11_atomic_fetch_or:
+ case AtomicExpr::AO__opencl_atomic_fetch_or:
case AtomicExpr::AO__atomic_fetch_or:
case AtomicExpr::AO__atomic_fetch_nand:
case AtomicExpr::AO__c11_atomic_fetch_sub:
+ case AtomicExpr::AO__opencl_atomic_fetch_sub:
case AtomicExpr::AO__atomic_fetch_sub:
case AtomicExpr::AO__c11_atomic_fetch_xor:
+ case AtomicExpr::AO__opencl_atomic_fetch_xor:
+ case AtomicExpr::AO__opencl_atomic_fetch_min:
+ case AtomicExpr::AO__opencl_atomic_fetch_max:
case AtomicExpr::AO__atomic_fetch_xor:
case AtomicExpr::AO__atomic_add_fetch:
case AtomicExpr::AO__atomic_and_fetch:
@@ -812,6 +918,11 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
case AtomicExpr::AO__c11_atomic_exchange:
case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
+ case AtomicExpr::AO__opencl_atomic_load:
+ case AtomicExpr::AO__opencl_atomic_store:
+ case AtomicExpr::AO__opencl_atomic_exchange:
+ case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:
+ case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:
case AtomicExpr::AO__atomic_load_n:
case AtomicExpr::AO__atomic_load:
case AtomicExpr::AO__atomic_store_n:
@@ -833,7 +944,24 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
getContext().getSizeType());
}
// Atomic address is the first or second parameter
- Args.add(RValue::get(EmitCastToVoidPtr(Ptr.getPointer())),
+ // The OpenCL atomic library functions only accept pointer arguments to
+ // generic address space.
+ auto CastToGenericAddrSpace = [&](llvm::Value *V, QualType PT) {
+ if (!E->isOpenCL())
+ return V;
+ auto AS = PT->getAs<PointerType>()->getPointeeType().getAddressSpace();
+ if (AS == LangAS::opencl_generic)
+ return V;
+ auto DestAS = getContext().getTargetAddressSpace(LangAS::opencl_generic);
+ auto T = V->getType();
+ auto *DestType = T->getPointerElementType()->getPointerTo(DestAS);
+
+ return getTargetHooks().performAddrSpaceCast(
+ *this, V, AS, LangAS::opencl_generic, DestType, false);
+ };
+
+ Args.add(RValue::get(CastToGenericAddrSpace(
+ EmitCastToVoidPtr(Ptr.getPointer()), E->getPtr()->getType())),
getContext().VoidPtrTy);
std::string LibCallName;
@@ -844,6 +972,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
llvm::Instruction::BinaryOps PostOp = (llvm::Instruction::BinaryOps)0;
switch (E->getOp()) {
case AtomicExpr::AO__c11_atomic_init:
+ case AtomicExpr::AO__opencl_atomic_init:
llvm_unreachable("Already handled!");
// There is only one libcall for compare an exchange, because there is no
@@ -855,13 +984,17 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
// int success, int failure)
case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
+ case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:
+ case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:
case AtomicExpr::AO__atomic_compare_exchange:
case AtomicExpr::AO__atomic_compare_exchange_n:
LibCallName = "__atomic_compare_exchange";
RetTy = getContext().BoolTy;
HaveRetTy = true;
- Args.add(RValue::get(EmitCastToVoidPtr(Val1.getPointer())),
- getContext().VoidPtrTy);
+ Args.add(
+ RValue::get(CastToGenericAddrSpace(
+ EmitCastToVoidPtr(Val1.getPointer()), E->getVal1()->getType())),
+ getContext().VoidPtrTy);
AddDirectArgument(*this, Args, UseOptimizedLibcall, Val2.getPointer(),
MemTy, E->getExprLoc(), sizeChars);
Args.add(RValue::get(Order), getContext().IntTy);
@@ -871,6 +1004,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
// int order)
// T __atomic_exchange_N(T *mem, T val, int order)
case AtomicExpr::AO__c11_atomic_exchange:
+ case AtomicExpr::AO__opencl_atomic_exchange:
case AtomicExpr::AO__atomic_exchange_n:
case AtomicExpr::AO__atomic_exchange:
LibCallName = "__atomic_exchange";
@@ -880,6 +1014,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
// void __atomic_store(size_t size, void *mem, void *val, int order)
// void __atomic_store_N(T *mem, T val, int order)
case AtomicExpr::AO__c11_atomic_store:
+ case AtomicExpr::AO__opencl_atomic_store:
case AtomicExpr::AO__atomic_store:
case AtomicExpr::AO__atomic_store_n:
LibCallName = "__atomic_store";
@@ -891,6 +1026,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
// void __atomic_load(size_t size, void *mem, void *return, int order)
// T __atomic_load_N(T *mem, int order)
case AtomicExpr::AO__c11_atomic_load:
+ case AtomicExpr::AO__opencl_atomic_load:
case AtomicExpr::AO__atomic_load:
case AtomicExpr::AO__atomic_load_n:
LibCallName = "__atomic_load";
@@ -901,6 +1037,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
PostOp = llvm::Instruction::Add;
// Fall through.
case AtomicExpr::AO__c11_atomic_fetch_add:
+ case AtomicExpr::AO__opencl_atomic_fetch_add:
case AtomicExpr::AO__atomic_fetch_add:
LibCallName = "__atomic_fetch_add";
AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
@@ -912,6 +1049,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
PostOp = llvm::Instruction::And;
// Fall through.
case AtomicExpr::AO__c11_atomic_fetch_and:
+ case AtomicExpr::AO__opencl_atomic_fetch_and:
case AtomicExpr::AO__atomic_fetch_and:
LibCallName = "__atomic_fetch_and";
AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
@@ -923,6 +1061,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
PostOp = llvm::Instruction::Or;
// Fall through.
case AtomicExpr::AO__c11_atomic_fetch_or:
+ case AtomicExpr::AO__opencl_atomic_fetch_or:
case AtomicExpr::AO__atomic_fetch_or:
LibCallName = "__atomic_fetch_or";
AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
@@ -934,6 +1073,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
PostOp = llvm::Instruction::Sub;
// Fall through.
case AtomicExpr::AO__c11_atomic_fetch_sub:
+ case AtomicExpr::AO__opencl_atomic_fetch_sub:
case AtomicExpr::AO__atomic_fetch_sub:
LibCallName = "__atomic_fetch_sub";
AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
@@ -945,11 +1085,26 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
PostOp = llvm::Instruction::Xor;
// Fall through.
case AtomicExpr::AO__c11_atomic_fetch_xor:
+ case AtomicExpr::AO__opencl_atomic_fetch_xor:
case AtomicExpr::AO__atomic_fetch_xor:
LibCallName = "__atomic_fetch_xor";
AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
MemTy, E->getExprLoc(), sizeChars);
break;
+ case AtomicExpr::AO__opencl_atomic_fetch_min:
+ LibCallName = E->getValueType()->isSignedIntegerType()
+ ? "__atomic_fetch_min"
+ : "__atomic_fetch_umin";
+ AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
+ LoweredMemTy, E->getExprLoc(), sizeChars);
+ break;
+ case AtomicExpr::AO__opencl_atomic_fetch_max:
+ LibCallName = E->getValueType()->isSignedIntegerType()
+ ? "__atomic_fetch_max"
+ : "__atomic_fetch_umax";
+ AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
+ LoweredMemTy, E->getExprLoc(), sizeChars);
+ break;
// T __atomic_nand_fetch_N(T *mem, T val, int order)
// T __atomic_fetch_nand_N(T *mem, T val, int order)
case AtomicExpr::AO__atomic_nand_fetch:
@@ -962,6 +1117,11 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
break;
}
+ if (E->isOpenCL()) {
+ LibCallName = std::string("__opencl") +
+ StringRef(LibCallName).drop_front(1).str();
+
+ }
// Optimized functions have the size in their name.
if (UseOptimizedLibcall)
LibCallName += "_" + llvm::utostr(Size);
@@ -982,6 +1142,8 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
// order is always the last parameter
Args.add(RValue::get(Order),
getContext().IntTy);
+ if (E->isOpenCL())
+ Args.add(RValue::get(Scope), getContext().IntTy);
// PostOp is only needed for the atomic_*_fetch operations, and
// thus is only needed for and implemented in the
@@ -1018,9 +1180,11 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
}
bool IsStore = E->getOp() == AtomicExpr::AO__c11_atomic_store ||
+ E->getOp() == AtomicExpr::AO__opencl_atomic_store ||
E->getOp() == AtomicExpr::AO__atomic_store ||
E->getOp() == AtomicExpr::AO__atomic_store_n;
bool IsLoad = E->getOp() == AtomicExpr::AO__c11_atomic_load ||
+ E->getOp() == AtomicExpr::AO__opencl_atomic_load ||
E->getOp() == AtomicExpr::AO__atomic_load ||
E->getOp() == AtomicExpr::AO__atomic_load_n;
@@ -1032,37 +1196,38 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
switch ((llvm::AtomicOrderingCABI)ord) {
case llvm::AtomicOrderingCABI::relaxed:
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
- llvm::AtomicOrdering::Monotonic);
+ llvm::AtomicOrdering::Monotonic, Scope);
break;
case llvm::AtomicOrderingCABI::consume:
case llvm::AtomicOrderingCABI::acquire:
if (IsStore)
break; // Avoid crashing on code with undefined behavior
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
- llvm::AtomicOrdering::Acquire);
+ llvm::AtomicOrdering::Acquire, Scope);
break;
case llvm::AtomicOrderingCABI::release:
if (IsLoad)
break; // Avoid crashing on code with undefined behavior
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
- llvm::AtomicOrdering::Release);
+ llvm::AtomicOrdering::Release, Scope);
break;
case llvm::AtomicOrderingCABI::acq_rel:
if (IsLoad || IsStore)
break; // Avoid crashing on code with undefined behavior
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
- llvm::AtomicOrdering::AcquireRelease);
+ llvm::AtomicOrdering::AcquireRelease, Scope);
break;
case llvm::AtomicOrderingCABI::seq_cst:
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
- llvm::AtomicOrdering::SequentiallyConsistent);
+ llvm::AtomicOrdering::SequentiallyConsistent, Scope);
break;
}
if (RValTy->isVoidType())
return RValue::get(nullptr);
return convertTempToRValue(
- Builder.CreateBitCast(Dest, ConvertTypeForMem(RValTy)->getPointerTo()),
+ Builder.CreateBitCast(Dest, ConvertTypeForMem(RValTy)->getPointerTo(
+ Dest.getAddressSpace())),
RValTy, E->getExprLoc());
}
@@ -1091,13 +1256,13 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
// Emit all the different atomics
Builder.SetInsertPoint(MonotonicBB);
- EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail,
- Size, llvm::AtomicOrdering::Monotonic);
+ EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
+ llvm::AtomicOrdering::Monotonic, Scope);
Builder.CreateBr(ContBB);
if (!IsStore) {
Builder.SetInsertPoint(AcquireBB);
- EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail,
- Size, llvm::AtomicOrdering::Acquire);
+ EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
+ llvm::AtomicOrdering::Acquire, Scope);
Builder.CreateBr(ContBB);
SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::consume),
AcquireBB);
@@ -1106,23 +1271,23 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
}
if (!IsLoad) {
Builder.SetInsertPoint(ReleaseBB);
- EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail,
- Size, llvm::AtomicOrdering::Release);
+ EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
+ llvm::AtomicOrdering::Release, Scope);
Builder.CreateBr(ContBB);
SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::release),
ReleaseBB);
}
if (!IsLoad && !IsStore) {
Builder.SetInsertPoint(AcqRelBB);
- EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail,
- Size, llvm::AtomicOrdering::AcquireRelease);
+ EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
+ llvm::AtomicOrdering::AcquireRelease, Scope);
Builder.CreateBr(ContBB);
SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::acq_rel),
AcqRelBB);
}
Builder.SetInsertPoint(SeqCstBB);
- EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail,
- Size, llvm::AtomicOrdering::SequentiallyConsistent);
+ EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
+ llvm::AtomicOrdering::SequentiallyConsistent, Scope);
Builder.CreateBr(ContBB);
SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::seq_cst),
SeqCstBB);
@@ -1134,7 +1299,8 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
assert(Atomics.getValueSizeInBits() <= Atomics.getAtomicSizeInBits());
return convertTempToRValue(
- Builder.CreateBitCast(Dest, ConvertTypeForMem(RValTy)->getPointerTo()),
+ Builder.CreateBitCast(Dest, ConvertTypeForMem(RValTy)->getPointerTo(
+ Dest.getAddressSpace())),
RValTy, E->getExprLoc());
}
@@ -1181,15 +1347,15 @@ RValue AtomicInfo::convertAtomicTempToRValue(Address addr,
if (LVal.isBitField())
return CGF.EmitLoadOfBitfieldLValue(
LValue::MakeBitfield(addr, LVal.getBitFieldInfo(), LVal.getType(),
- LVal.getBaseInfo()), loc);
+ LVal.getBaseInfo(), TBAAAccessInfo()), loc);
if (LVal.isVectorElt())
return CGF.EmitLoadOfLValue(
LValue::MakeVectorElt(addr, LVal.getVectorIdx(), LVal.getType(),
- LVal.getBaseInfo()), loc);
+ LVal.getBaseInfo(), TBAAAccessInfo()), loc);
assert(LVal.isExtVectorElt());
return CGF.EmitLoadOfExtVectorElementLValue(LValue::MakeExtVectorElt(
addr, LVal.getExtVectorElts(), LVal.getType(),
- LVal.getBaseInfo()));
+ LVal.getBaseInfo(), TBAAAccessInfo()));
}
RValue AtomicInfo::ConvertIntToValueOrAtomic(llvm::Value *IntVal,
@@ -1260,8 +1426,7 @@ llvm::Value *AtomicInfo::EmitAtomicLoadOp(llvm::AtomicOrdering AO,
// Other decoration.
if (IsVolatile)
Load->setVolatile(true);
- if (LVal.getTBAAInfo())
- CGF.CGM.DecorateInstructionWithTBAA(Load, LVal.getTBAAInfo());
+ CGF.CGM.DecorateInstructionWithTBAA(Load, LVal.getTBAAInfo());
return Load;
}
@@ -1506,29 +1671,30 @@ EmitAtomicUpdateValue(CodeGenFunction &CGF, AtomicInfo &Atomics, RValue OldRVal,
UpdateLVal =
LValue::MakeBitfield(Ptr, AtomicLVal.getBitFieldInfo(),
AtomicLVal.getType(),
- AtomicLVal.getBaseInfo());
+ AtomicLVal.getBaseInfo(),
+ AtomicLVal.getTBAAInfo());
DesiredLVal =
LValue::MakeBitfield(DesiredAddr, AtomicLVal.getBitFieldInfo(),
- AtomicLVal.getType(),
- AtomicLVal.getBaseInfo());
+ AtomicLVal.getType(), AtomicLVal.getBaseInfo(),
+ AtomicLVal.getTBAAInfo());
} else if (AtomicLVal.isVectorElt()) {
UpdateLVal = LValue::MakeVectorElt(Ptr, AtomicLVal.getVectorIdx(),
AtomicLVal.getType(),
- AtomicLVal.getBaseInfo());
+ AtomicLVal.getBaseInfo(),
+ AtomicLVal.getTBAAInfo());
DesiredLVal = LValue::MakeVectorElt(
DesiredAddr, AtomicLVal.getVectorIdx(), AtomicLVal.getType(),
- AtomicLVal.getBaseInfo());
+ AtomicLVal.getBaseInfo(), AtomicLVal.getTBAAInfo());
} else {
assert(AtomicLVal.isExtVectorElt());
UpdateLVal = LValue::MakeExtVectorElt(Ptr, AtomicLVal.getExtVectorElts(),
AtomicLVal.getType(),
- AtomicLVal.getBaseInfo());
+ AtomicLVal.getBaseInfo(),
+ AtomicLVal.getTBAAInfo());
DesiredLVal = LValue::MakeExtVectorElt(
DesiredAddr, AtomicLVal.getExtVectorElts(), AtomicLVal.getType(),
- AtomicLVal.getBaseInfo());
+ AtomicLVal.getBaseInfo(), AtomicLVal.getTBAAInfo());
}
- UpdateLVal.setTBAAInfo(AtomicLVal.getTBAAInfo());
- DesiredLVal.setTBAAInfo(AtomicLVal.getTBAAInfo());
UpRVal = CGF.EmitLoadOfLValue(UpdateLVal, SourceLocation());
}
// Store new value in the corresponding memory area
@@ -1611,20 +1777,19 @@ static void EmitAtomicUpdateValue(CodeGenFunction &CGF, AtomicInfo &Atomics,
if (AtomicLVal.isBitField()) {
DesiredLVal =
LValue::MakeBitfield(DesiredAddr, AtomicLVal.getBitFieldInfo(),
- AtomicLVal.getType(),
- AtomicLVal.getBaseInfo());
+ AtomicLVal.getType(), AtomicLVal.getBaseInfo(),
+ AtomicLVal.getTBAAInfo());
} else if (AtomicLVal.isVectorElt()) {
DesiredLVal =
LValue::MakeVectorElt(DesiredAddr, AtomicLVal.getVectorIdx(),
- AtomicLVal.getType(),
- AtomicLVal.getBaseInfo());
+ AtomicLVal.getType(), AtomicLVal.getBaseInfo(),
+ AtomicLVal.getTBAAInfo());
} else {
assert(AtomicLVal.isExtVectorElt());
DesiredLVal = LValue::MakeExtVectorElt(
DesiredAddr, AtomicLVal.getExtVectorElts(), AtomicLVal.getType(),
- AtomicLVal.getBaseInfo());
+ AtomicLVal.getBaseInfo(), AtomicLVal.getTBAAInfo());
}
- DesiredLVal.setTBAAInfo(AtomicLVal.getTBAAInfo());
// Store new value in the corresponding memory area
assert(UpdateRVal.isScalar());
CGF.EmitStoreThroughLValue(UpdateRVal, DesiredLVal);
@@ -1777,8 +1942,7 @@ void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest,
// Other decoration.
if (IsVolatile)
store->setVolatile(true);
- if (dest.getTBAAInfo())
- CGM.DecorateInstructionWithTBAA(store, dest.getTBAAInfo());
+ CGM.DecorateInstructionWithTBAA(store, dest.getTBAAInfo());
return;
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp
index 1810489578798..5f73d4cf79137 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp
@@ -14,10 +14,13 @@
#include "CGBlocks.h"
#include "CGDebugInfo.h"
#include "CGObjCRuntime.h"
+#include "CGOpenCLRuntime.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
-#include "clang/CodeGen/ConstantInitBuilder.h"
+#include "ConstantEmitter.h"
+#include "TargetInfo.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/CodeGen/ConstantInitBuilder.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/DataLayout.h"
@@ -290,7 +293,7 @@ static llvm::Constant *tryCaptureAsConstant(CodeGenModule &CGM,
const Expr *init = var->getInit();
if (!init) return nullptr;
- return CGM.EmitConstantInit(*var, CGF);
+ return ConstantEmitter(CGM, CGF).tryEmitAbstractForInitializer(*var);
}
/// Get the low bit of a nonzero character count. This is the
@@ -301,21 +304,57 @@ static CharUnits getLowBit(CharUnits v) {
static void initializeForBlockHeader(CodeGenModule &CGM, CGBlockInfo &info,
SmallVectorImpl<llvm::Type*> &elementTypes) {
- // The header is basically 'struct { void *; int; int; void *; void *; }'.
- // Assert that that struct is packed.
- assert(CGM.getIntSize() <= CGM.getPointerSize());
- assert(CGM.getIntAlign() <= CGM.getPointerAlign());
- assert((2 * CGM.getIntSize()).isMultipleOf(CGM.getPointerAlign()));
-
- info.BlockAlign = CGM.getPointerAlign();
- info.BlockSize = 3 * CGM.getPointerSize() + 2 * CGM.getIntSize();
assert(elementTypes.empty());
- elementTypes.push_back(CGM.VoidPtrTy);
- elementTypes.push_back(CGM.IntTy);
- elementTypes.push_back(CGM.IntTy);
- elementTypes.push_back(CGM.VoidPtrTy);
- elementTypes.push_back(CGM.getBlockDescriptorType());
+ if (CGM.getLangOpts().OpenCL) {
+ // The header is basically 'struct { int; int; generic void *;
+ // custom_fields; }'. Assert that struct is packed.
+ auto GenericAS =
+ CGM.getContext().getTargetAddressSpace(LangAS::opencl_generic);
+ auto GenPtrAlign =
+ CharUnits::fromQuantity(CGM.getTarget().getPointerAlign(GenericAS) / 8);
+ auto GenPtrSize =
+ CharUnits::fromQuantity(CGM.getTarget().getPointerWidth(GenericAS) / 8);
+ assert(CGM.getIntSize() <= GenPtrSize);
+ assert(CGM.getIntAlign() <= GenPtrAlign);
+ assert((2 * CGM.getIntSize()).isMultipleOf(GenPtrAlign));
+ elementTypes.push_back(CGM.IntTy); /* total size */
+ elementTypes.push_back(CGM.IntTy); /* align */
+ elementTypes.push_back(
+ CGM.getOpenCLRuntime()
+ .getGenericVoidPointerType()); /* invoke function */
+ unsigned Offset =
+ 2 * CGM.getIntSize().getQuantity() + GenPtrSize.getQuantity();
+ unsigned BlockAlign = GenPtrAlign.getQuantity();
+ if (auto *Helper =
+ CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
+ for (auto I : Helper->getCustomFieldTypes()) /* custom fields */ {
+ // TargetOpenCLBlockHelp needs to make sure the struct is packed.
+ // If necessary, add padding fields to the custom fields.
+ unsigned Align = CGM.getDataLayout().getABITypeAlignment(I);
+ if (BlockAlign < Align)
+ BlockAlign = Align;
+ assert(Offset % Align == 0);
+ Offset += CGM.getDataLayout().getTypeAllocSize(I);
+ elementTypes.push_back(I);
+ }
+ }
+ info.BlockAlign = CharUnits::fromQuantity(BlockAlign);
+ info.BlockSize = CharUnits::fromQuantity(Offset);
+ } else {
+ // The header is basically 'struct { void *; int; int; void *; void *; }'.
+ // Assert that that struct is packed.
+ assert(CGM.getIntSize() <= CGM.getPointerSize());
+ assert(CGM.getIntAlign() <= CGM.getPointerAlign());
+ assert((2 * CGM.getIntSize()).isMultipleOf(CGM.getPointerAlign()));
+ info.BlockAlign = CGM.getPointerAlign();
+ info.BlockSize = 3 * CGM.getPointerSize() + 2 * CGM.getIntSize();
+ elementTypes.push_back(CGM.VoidPtrTy);
+ elementTypes.push_back(CGM.IntTy);
+ elementTypes.push_back(CGM.IntTy);
+ elementTypes.push_back(CGM.VoidPtrTy);
+ elementTypes.push_back(CGM.getBlockDescriptorType());
+ }
}
static QualType getCaptureFieldType(const CodeGenFunction &CGF,
@@ -340,8 +379,12 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
SmallVector<llvm::Type*, 8> elementTypes;
initializeForBlockHeader(CGM, info, elementTypes);
-
- if (!block->hasCaptures()) {
+ bool hasNonConstantCustomFields = false;
+ if (auto *OpenCLHelper =
+ CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper())
+ hasNonConstantCustomFields =
+ !OpenCLHelper->areAllCustomFieldValuesConstant(info);
+ if (!block->hasCaptures() && !hasNonConstantCustomFields) {
info.StructureType =
llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true);
info.CanBeGlobal = true;
@@ -697,16 +740,27 @@ void CodeGenFunction::destroyBlockInfos(CGBlockInfo *head) {
}
/// Emit a block literal expression in the current function.
-llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) {
+llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr,
+ llvm::Function **InvokeF) {
// If the block has no captures, we won't have a pre-computed
// layout for it.
if (!blockExpr->getBlockDecl()->hasCaptures()) {
- if (llvm::Constant *Block = CGM.getAddrOfGlobalBlockIfEmitted(blockExpr))
+ // The block literal is emitted as a global variable, and the block invoke
+ // function has to be extracted from its initializer.
+ if (llvm::Constant *Block = CGM.getAddrOfGlobalBlockIfEmitted(blockExpr)) {
+ if (InvokeF) {
+ auto *GV = cast<llvm::GlobalVariable>(
+ cast<llvm::Constant>(Block)->stripPointerCasts());
+ auto *BlockInit = cast<llvm::ConstantStruct>(GV->getInitializer());
+ *InvokeF = cast<llvm::Function>(
+ BlockInit->getAggregateElement(2)->stripPointerCasts());
+ }
return Block;
+ }
CGBlockInfo blockInfo(blockExpr->getBlockDecl(), CurFn->getName());
computeBlockInfo(CGM, this, blockInfo);
blockInfo.BlockExpression = blockExpr;
- return EmitBlockLiteral(blockInfo);
+ return EmitBlockLiteral(blockInfo, InvokeF);
}
// Find the block info for this block and take ownership of it.
@@ -715,44 +769,59 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) {
blockExpr->getBlockDecl()));
blockInfo->BlockExpression = blockExpr;
- return EmitBlockLiteral(*blockInfo);
+ return EmitBlockLiteral(*blockInfo, InvokeF);
}
-llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
+llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo,
+ llvm::Function **InvokeF) {
+ bool IsOpenCL = CGM.getContext().getLangOpts().OpenCL;
+ auto GenVoidPtrTy =
+ IsOpenCL ? CGM.getOpenCLRuntime().getGenericVoidPointerType() : VoidPtrTy;
+ LangAS GenVoidPtrAddr = IsOpenCL ? LangAS::opencl_generic : LangAS::Default;
+ auto GenVoidPtrSize = CharUnits::fromQuantity(
+ CGM.getTarget().getPointerWidth(
+ CGM.getContext().getTargetAddressSpace(GenVoidPtrAddr)) /
+ 8);
// Using the computed layout, generate the actual block function.
bool isLambdaConv = blockInfo.getBlockDecl()->isConversionFromLambda();
- llvm::Constant *blockFn
- = CodeGenFunction(CGM, true).GenerateBlockFunction(CurGD, blockInfo,
- LocalDeclMap,
- isLambdaConv);
- blockFn = llvm::ConstantExpr::getBitCast(blockFn, VoidPtrTy);
+ CodeGenFunction BlockCGF{CGM, true};
+ BlockCGF.SanOpts = SanOpts;
+ auto *InvokeFn = BlockCGF.GenerateBlockFunction(
+ CurGD, blockInfo, LocalDeclMap, isLambdaConv, blockInfo.CanBeGlobal);
+ if (InvokeF)
+ *InvokeF = InvokeFn;
+ auto *blockFn = llvm::ConstantExpr::getPointerCast(InvokeFn, GenVoidPtrTy);
// If there is nothing to capture, we can emit this as a global block.
if (blockInfo.CanBeGlobal)
- return buildGlobalBlock(CGM, blockInfo, blockFn);
+ return CGM.getAddrOfGlobalBlockIfEmitted(blockInfo.BlockExpression);
// Otherwise, we have to emit this as a local block.
- llvm::Constant *isa =
- (!CGM.getContext().getLangOpts().OpenCL)
- ? CGM.getNSConcreteStackBlock()
- : CGM.getNullPointer(VoidPtrPtrTy,
- CGM.getContext().getPointerType(
- QualType(CGM.getContext().VoidPtrTy)));
- isa = llvm::ConstantExpr::getBitCast(isa, VoidPtrTy);
-
- // Build the block descriptor.
- llvm::Constant *descriptor = buildBlockDescriptor(CGM, blockInfo);
-
Address blockAddr = blockInfo.LocalAddress;
assert(blockAddr.isValid() && "block has no address!");
- // Compute the initial on-stack block flags.
- BlockFlags flags = BLOCK_HAS_SIGNATURE;
- if (blockInfo.HasCapturedVariableLayout) flags |= BLOCK_HAS_EXTENDED_LAYOUT;
- if (blockInfo.NeedsCopyDispose) flags |= BLOCK_HAS_COPY_DISPOSE;
- if (blockInfo.HasCXXObject) flags |= BLOCK_HAS_CXX_OBJ;
- if (blockInfo.UsesStret) flags |= BLOCK_USE_STRET;
+ llvm::Constant *isa;
+ llvm::Constant *descriptor;
+ BlockFlags flags;
+ if (!IsOpenCL) {
+ isa = llvm::ConstantExpr::getBitCast(CGM.getNSConcreteStackBlock(),
+ VoidPtrTy);
+
+ // Build the block descriptor.
+ descriptor = buildBlockDescriptor(CGM, blockInfo);
+
+ // Compute the initial on-stack block flags.
+ flags = BLOCK_HAS_SIGNATURE;
+ if (blockInfo.HasCapturedVariableLayout)
+ flags |= BLOCK_HAS_EXTENDED_LAYOUT;
+ if (blockInfo.NeedsCopyDispose)
+ flags |= BLOCK_HAS_COPY_DISPOSE;
+ if (blockInfo.HasCXXObject)
+ flags |= BLOCK_HAS_CXX_OBJ;
+ if (blockInfo.UsesStret)
+ flags |= BLOCK_USE_STRET;
+ }
auto projectField =
[&](unsigned index, CharUnits offset, const Twine &name) -> Address {
@@ -776,13 +845,33 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
index++;
};
- addHeaderField(isa, getPointerSize(), "block.isa");
- addHeaderField(llvm::ConstantInt::get(IntTy, flags.getBitMask()),
- getIntSize(), "block.flags");
- addHeaderField(llvm::ConstantInt::get(IntTy, 0),
- getIntSize(), "block.reserved");
- addHeaderField(blockFn, getPointerSize(), "block.invoke");
- addHeaderField(descriptor, getPointerSize(), "block.descriptor");
+ if (!IsOpenCL) {
+ addHeaderField(isa, getPointerSize(), "block.isa");
+ addHeaderField(llvm::ConstantInt::get(IntTy, flags.getBitMask()),
+ getIntSize(), "block.flags");
+ addHeaderField(llvm::ConstantInt::get(IntTy, 0), getIntSize(),
+ "block.reserved");
+ } else {
+ addHeaderField(
+ llvm::ConstantInt::get(IntTy, blockInfo.BlockSize.getQuantity()),
+ getIntSize(), "block.size");
+ addHeaderField(
+ llvm::ConstantInt::get(IntTy, blockInfo.BlockAlign.getQuantity()),
+ getIntSize(), "block.align");
+ }
+ addHeaderField(blockFn, GenVoidPtrSize, "block.invoke");
+ if (!IsOpenCL)
+ addHeaderField(descriptor, getPointerSize(), "block.descriptor");
+ else if (auto *Helper =
+ CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
+ for (auto I : Helper->getCustomFieldValues(*this, blockInfo)) {
+ addHeaderField(
+ I.first,
+ CharUnits::fromQuantity(
+ CGM.getDataLayout().getTypeAllocSize(I.first->getType())),
+ I.second);
+ }
+ }
}
// Finally, capture all the values into the block.
@@ -917,9 +1006,8 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
// FIXME: Pass a specific location for the expr init so that the store is
// attributed to a reasonable location - otherwise it may be attributed to
// locations of subexpressions in the initialization.
- LValueBaseInfo BaseInfo(AlignmentSource::Decl, false);
EmitExprAsInit(&l2r, &BlockFieldPseudoVar,
- MakeAddrLValue(blockField, type, BaseInfo),
+ MakeAddrLValue(blockField, type, AlignmentSource::Decl),
/*captured by init*/ false);
}
@@ -978,21 +1066,38 @@ llvm::Type *CodeGenModule::getGenericBlockLiteralType() {
llvm::Type *BlockDescPtrTy = getBlockDescriptorType();
- // struct __block_literal_generic {
- // void *__isa;
- // int __flags;
- // int __reserved;
- // void (*__invoke)(void *);
- // struct __block_descriptor *__descriptor;
- // };
- GenericBlockLiteralType =
- llvm::StructType::create("struct.__block_literal_generic", VoidPtrTy,
- IntTy, IntTy, VoidPtrTy, BlockDescPtrTy);
+ if (getLangOpts().OpenCL) {
+ // struct __opencl_block_literal_generic {
+ // int __size;
+ // int __align;
+ // __generic void *__invoke;
+ // /* custom fields */
+ // };
+ SmallVector<llvm::Type *, 8> StructFields(
+ {IntTy, IntTy, getOpenCLRuntime().getGenericVoidPointerType()});
+ if (auto *Helper = getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
+ for (auto I : Helper->getCustomFieldTypes())
+ StructFields.push_back(I);
+ }
+ GenericBlockLiteralType = llvm::StructType::create(
+ StructFields, "struct.__opencl_block_literal_generic");
+ } else {
+ // struct __block_literal_generic {
+ // void *__isa;
+ // int __flags;
+ // int __reserved;
+ // void (*__invoke)(void *);
+ // struct __block_descriptor *__descriptor;
+ // };
+ GenericBlockLiteralType =
+ llvm::StructType::create("struct.__block_literal_generic", VoidPtrTy,
+ IntTy, IntTy, VoidPtrTy, BlockDescPtrTy);
+ }
return GenericBlockLiteralType;
}
-RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
+RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
ReturnValueSlot ReturnValue) {
const BlockPointerType *BPT =
E->getCallee()->getType()->getAs<BlockPointerType>();
@@ -1017,8 +1122,8 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
// Get the function pointer from the literal.
llvm::Value *FuncPtr =
- Builder.CreateStructGEP(CGM.getGenericBlockLiteralType(), BlockPtr, 3);
-
+ Builder.CreateStructGEP(CGM.getGenericBlockLiteralType(), BlockPtr,
+ CGM.getLangOpts().OpenCL ? 2 : 3);
// Add the block literal.
CallArgList Args;
@@ -1026,8 +1131,7 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
QualType VoidPtrQualTy = getContext().VoidPtrTy;
llvm::Type *GenericVoidPtrTy = VoidPtrTy;
if (getLangOpts().OpenCL) {
- GenericVoidPtrTy = Builder.getInt8PtrTy(
- getContext().getTargetAddressSpace(LangAS::opencl_generic));
+ GenericVoidPtrTy = CGM.getOpenCLRuntime().getGenericVoidPointerType();
VoidPtrQualTy =
getContext().getPointerType(getContext().getAddrSpaceQualType(
getContext().VoidTy, LangAS::opencl_generic));
@@ -1052,7 +1156,7 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
llvm::Type *BlockFTy = CGM.getTypes().GetFunctionType(FnInfo);
llvm::Type *BlockFTyPtr = llvm::PointerType::getUnqual(BlockFTy);
- Func = Builder.CreateBitCast(Func, BlockFTyPtr);
+ Func = Builder.CreatePointerCast(Func, BlockFTyPtr);
// Prepare the callee.
CGCallee Callee(CGCalleeInfo(), Func);
@@ -1087,8 +1191,8 @@ Address CodeGenFunction::GetAddrOfBlockDecl(const VarDecl *variable,
variable->getName());
}
- if (auto refType = capture.fieldType()->getAs<ReferenceType>())
- addr = EmitLoadOfReference(addr, refType);
+ if (capture.fieldType()->isReferenceType())
+ addr = EmitLoadOfReference(MakeAddrLValue(addr, capture.fieldType()));
return addr;
}
@@ -1113,17 +1217,14 @@ CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *BE,
computeBlockInfo(*this, nullptr, blockInfo);
// Using that metadata, generate the actual block function.
- llvm::Constant *blockFn;
{
CodeGenFunction::DeclMapTy LocalDeclMap;
- blockFn = CodeGenFunction(*this).GenerateBlockFunction(GlobalDecl(),
- blockInfo,
- LocalDeclMap,
- false);
+ CodeGenFunction(*this).GenerateBlockFunction(
+ GlobalDecl(), blockInfo, LocalDeclMap,
+ /*IsLambdaConversionToBlock*/ false, /*BuildGlobalBlock*/ true);
}
- blockFn = llvm::ConstantExpr::getBitCast(blockFn, VoidPtrTy);
- return buildGlobalBlock(*this, blockInfo, blockFn);
+ return getAddrOfGlobalBlockIfEmitted(BE);
}
static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
@@ -1140,27 +1241,37 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
ConstantInitBuilder builder(CGM);
auto fields = builder.beginStruct();
- // isa
- fields.add((!CGM.getContext().getLangOpts().OpenCL)
- ? CGM.getNSConcreteGlobalBlock()
- : CGM.getNullPointer(CGM.VoidPtrPtrTy,
- CGM.getContext().getPointerType(QualType(
- CGM.getContext().VoidPtrTy))));
+ bool IsOpenCL = CGM.getLangOpts().OpenCL;
+ if (!IsOpenCL) {
+ // isa
+ fields.add(CGM.getNSConcreteGlobalBlock());
+
+ // __flags
+ BlockFlags flags = BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE;
+ if (blockInfo.UsesStret)
+ flags |= BLOCK_USE_STRET;
- // __flags
- BlockFlags flags = BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE;
- if (blockInfo.UsesStret) flags |= BLOCK_USE_STRET;
-
- fields.addInt(CGM.IntTy, flags.getBitMask());
+ fields.addInt(CGM.IntTy, flags.getBitMask());
- // Reserved
- fields.addInt(CGM.IntTy, 0);
+ // Reserved
+ fields.addInt(CGM.IntTy, 0);
+ } else {
+ fields.addInt(CGM.IntTy, blockInfo.BlockSize.getQuantity());
+ fields.addInt(CGM.IntTy, blockInfo.BlockAlign.getQuantity());
+ }
// Function
fields.add(blockFn);
- // Descriptor
- fields.add(buildBlockDescriptor(CGM, blockInfo));
+ if (!IsOpenCL) {
+ // Descriptor
+ fields.add(buildBlockDescriptor(CGM, blockInfo));
+ } else if (auto *Helper =
+ CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
+ for (auto I : Helper->getCustomFieldValues(CGM, blockInfo)) {
+ fields.add(I);
+ }
+ }
unsigned AddrSpace = 0;
if (CGM.getContext().getLangOpts().OpenCL)
@@ -1184,20 +1295,17 @@ void CodeGenFunction::setBlockContextParameter(const ImplicitParamDecl *D,
llvm::Value *arg) {
assert(BlockInfo && "not emitting prologue of block invocation function?!");
- llvm::Value *localAddr = nullptr;
- if (CGM.getCodeGenOpts().OptimizationLevel == 0) {
- // Allocate a stack slot to let the debug info survive the RA.
- Address alloc = CreateMemTemp(D->getType(), D->getName() + ".addr");
- Builder.CreateStore(arg, alloc);
- localAddr = Builder.CreateLoad(alloc);
- }
-
+ // Allocate a stack slot like for any local variable to guarantee optimal
+ // debug info at -O0. The mem2reg pass will eliminate it when optimizing.
+ Address alloc = CreateMemTemp(D->getType(), D->getName() + ".addr");
+ Builder.CreateStore(arg, alloc);
if (CGDebugInfo *DI = getDebugInfo()) {
if (CGM.getCodeGenOpts().getDebugInfo() >=
codegenoptions::LimitedDebugInfo) {
DI->setLocation(D->getLocation());
- DI->EmitDeclareOfBlockLiteralArgVariable(*BlockInfo, arg, argNum,
- localAddr, Builder);
+ DI->EmitDeclareOfBlockLiteralArgVariable(
+ *BlockInfo, D->getName(), argNum,
+ cast<llvm::AllocaInst>(alloc.getPointer()), Builder);
}
}
@@ -1225,7 +1333,8 @@ llvm::Function *
CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
const CGBlockInfo &blockInfo,
const DeclMapTy &ldm,
- bool IsLambdaConversionToBlock) {
+ bool IsLambdaConversionToBlock,
+ bool BuildGlobalBlock) {
const BlockDecl *blockDecl = blockInfo.getBlockDecl();
CurGD = GD;
@@ -1284,6 +1393,14 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
fnLLVMType, llvm::GlobalValue::InternalLinkage, name, &CGM.getModule());
CGM.SetInternalFunctionAttributes(blockDecl, fn, fnInfo);
+ if (BuildGlobalBlock) {
+ auto GenVoidPtrTy = getContext().getLangOpts().OpenCL
+ ? CGM.getOpenCLRuntime().getGenericVoidPointerType()
+ : VoidPtrTy;
+ buildGlobalBlock(CGM, blockInfo,
+ llvm::ConstantExpr::getPointerCast(fn, GenVoidPtrTy));
+ }
+
// Begin generating the function.
StartFunction(blockDecl, fnType->getReturnType(), fn, fnInfo, args,
blockDecl->getLocation(),
@@ -1529,10 +1646,8 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
CGM.SetInternalFunctionAttributes(nullptr, Fn, FI);
- auto NL = ApplyDebugLocation::CreateEmpty(*this);
StartFunction(FD, C.VoidTy, Fn, FI, args);
- // Create a scope with an artificial location for the body of this function.
- auto AL = ApplyDebugLocation::CreateArtificial(*this);
+ ApplyDebugLocation NL{*this, blockInfo.getBlockExpr()->getLocStart()};
llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo();
Address src = GetAddrOfLocalVar(&SrcDecl);
@@ -1701,10 +1816,8 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) {
CGM.SetInternalFunctionAttributes(nullptr, Fn, FI);
- // Create a scope with an artificial location for the body of this function.
- auto NL = ApplyDebugLocation::CreateEmpty(*this);
StartFunction(FD, C.VoidTy, Fn, FI, args);
- auto AL = ApplyDebugLocation::CreateArtificial(*this);
+ ApplyDebugLocation NL{*this, blockInfo.getBlockExpr()->getLocStart()};
llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo();
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGBuilder.h b/contrib/llvm/tools/clang/lib/CodeGen/CGBuilder.h
index 42f9a428bb3a7..61fe4aac3afa2 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGBuilder.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGBuilder.h
@@ -145,6 +145,13 @@ public:
Addr.getAlignment());
}
+ using CGBuilderBaseTy::CreateAddrSpaceCast;
+ Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty,
+ const llvm::Twine &Name = "") {
+ return Address(CreateAddrSpaceCast(Addr.getPointer(), Ty, Name),
+ Addr.getAlignment());
+ }
+
/// Cast the element type of the given address to a different type,
/// preserving information like the alignment and address space.
Address CreateElementBitCast(Address Addr, llvm::Type *Ty,
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp
index f3527b0f39d13..3ecd1c6697d71 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp
@@ -16,6 +16,7 @@
#include "CGOpenCLRuntime.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
+#include "ConstantEmitter.h"
#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
@@ -29,6 +30,9 @@
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/MDBuilder.h"
+#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/ScopedPrinter.h"
+#include "llvm/Support/TargetParser.h"
#include <sstream>
using namespace clang;
@@ -641,6 +645,287 @@ struct CallObjCArcUse final : EHScopeStack::Cleanup {
};
}
+Value *CodeGenFunction::EmitCheckedArgForBuiltin(const Expr *E,
+ BuiltinCheckKind Kind) {
+ assert((Kind == BCK_CLZPassedZero || Kind == BCK_CTZPassedZero)
+ && "Unsupported builtin check kind");
+
+ Value *ArgValue = EmitScalarExpr(E);
+ if (!SanOpts.has(SanitizerKind::Builtin) || !getTarget().isCLZForZeroUndef())
+ return ArgValue;
+
+ SanitizerScope SanScope(this);
+ Value *Cond = Builder.CreateICmpNE(
+ ArgValue, llvm::Constant::getNullValue(ArgValue->getType()));
+ EmitCheck(std::make_pair(Cond, SanitizerKind::Builtin),
+ SanitizerHandler::InvalidBuiltin,
+ {EmitCheckSourceLocation(E->getExprLoc()),
+ llvm::ConstantInt::get(Builder.getInt8Ty(), Kind)},
+ None);
+ return ArgValue;
+}
+
+/// Get the argument type for arguments to os_log_helper.
+static CanQualType getOSLogArgType(ASTContext &C, int Size) {
+ QualType UnsignedTy = C.getIntTypeForBitwidth(Size * 8, /*Signed=*/false);
+ return C.getCanonicalType(UnsignedTy);
+}
+
+llvm::Function *CodeGenFunction::generateBuiltinOSLogHelperFunction(
+ const analyze_os_log::OSLogBufferLayout &Layout,
+ CharUnits BufferAlignment) {
+ ASTContext &Ctx = getContext();
+
+ llvm::SmallString<64> Name;
+ {
+ raw_svector_ostream OS(Name);
+ OS << "__os_log_helper";
+ OS << "_" << BufferAlignment.getQuantity();
+ OS << "_" << int(Layout.getSummaryByte());
+ OS << "_" << int(Layout.getNumArgsByte());
+ for (const auto &Item : Layout.Items)
+ OS << "_" << int(Item.getSizeByte()) << "_"
+ << int(Item.getDescriptorByte());
+ }
+
+ if (llvm::Function *F = CGM.getModule().getFunction(Name))
+ return F;
+
+ llvm::SmallVector<ImplicitParamDecl, 4> Params;
+ Params.emplace_back(Ctx, nullptr, SourceLocation(), &Ctx.Idents.get("buffer"),
+ Ctx.VoidPtrTy, ImplicitParamDecl::Other);
+
+ for (unsigned int I = 0, E = Layout.Items.size(); I < E; ++I) {
+ char Size = Layout.Items[I].getSizeByte();
+ if (!Size)
+ continue;
+
+ Params.emplace_back(
+ Ctx, nullptr, SourceLocation(),
+ &Ctx.Idents.get(std::string("arg") + llvm::to_string(I)),
+ getOSLogArgType(Ctx, Size), ImplicitParamDecl::Other);
+ }
+
+ FunctionArgList Args;
+ for (auto &P : Params)
+ Args.push_back(&P);
+
+ // The helper function has linkonce_odr linkage to enable the linker to merge
+ // identical functions. To ensure the merging always happens, 'noinline' is
+ // attached to the function when compiling with -Oz.
+ const CGFunctionInfo &FI =
+ CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Args);
+ llvm::FunctionType *FuncTy = CGM.getTypes().GetFunctionType(FI);
+ llvm::Function *Fn = llvm::Function::Create(
+ FuncTy, llvm::GlobalValue::LinkOnceODRLinkage, Name, &CGM.getModule());
+ Fn->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ CGM.SetLLVMFunctionAttributes(nullptr, FI, Fn);
+ CGM.SetLLVMFunctionAttributesForDefinition(nullptr, Fn);
+
+ // Attach 'noinline' at -Oz.
+ if (CGM.getCodeGenOpts().OptimizeSize == 2)
+ Fn->addFnAttr(llvm::Attribute::NoInline);
+
+ auto NL = ApplyDebugLocation::CreateEmpty(*this);
+ IdentifierInfo *II = &Ctx.Idents.get(Name);
+ FunctionDecl *FD = FunctionDecl::Create(
+ Ctx, Ctx.getTranslationUnitDecl(), SourceLocation(), SourceLocation(), II,
+ Ctx.VoidTy, nullptr, SC_PrivateExtern, false, false);
+
+ StartFunction(FD, Ctx.VoidTy, Fn, FI, Args);
+
+ // Create a scope with an artificial location for the body of this function.
+ auto AL = ApplyDebugLocation::CreateArtificial(*this);
+
+ CharUnits Offset;
+ Address BufAddr(Builder.CreateLoad(GetAddrOfLocalVar(&Params[0]), "buf"),
+ BufferAlignment);
+ Builder.CreateStore(Builder.getInt8(Layout.getSummaryByte()),
+ Builder.CreateConstByteGEP(BufAddr, Offset++, "summary"));
+ Builder.CreateStore(Builder.getInt8(Layout.getNumArgsByte()),
+ Builder.CreateConstByteGEP(BufAddr, Offset++, "numArgs"));
+
+ unsigned I = 1;
+ for (const auto &Item : Layout.Items) {
+ Builder.CreateStore(
+ Builder.getInt8(Item.getDescriptorByte()),
+ Builder.CreateConstByteGEP(BufAddr, Offset++, "argDescriptor"));
+ Builder.CreateStore(
+ Builder.getInt8(Item.getSizeByte()),
+ Builder.CreateConstByteGEP(BufAddr, Offset++, "argSize"));
+
+ CharUnits Size = Item.size();
+ if (!Size.getQuantity())
+ continue;
+
+ Address Arg = GetAddrOfLocalVar(&Params[I]);
+ Address Addr = Builder.CreateConstByteGEP(BufAddr, Offset, "argData");
+ Addr = Builder.CreateBitCast(Addr, Arg.getPointer()->getType(),
+ "argDataCast");
+ Builder.CreateStore(Builder.CreateLoad(Arg), Addr);
+ Offset += Size;
+ ++I;
+ }
+
+ FinishFunction();
+
+ return Fn;
+}
+
+RValue CodeGenFunction::emitBuiltinOSLogFormat(const CallExpr &E) {
+ assert(E.getNumArgs() >= 2 &&
+ "__builtin_os_log_format takes at least 2 arguments");
+ ASTContext &Ctx = getContext();
+ analyze_os_log::OSLogBufferLayout Layout;
+ analyze_os_log::computeOSLogBufferLayout(Ctx, &E, Layout);
+ Address BufAddr = EmitPointerWithAlignment(E.getArg(0));
+ llvm::SmallVector<llvm::Value *, 4> RetainableOperands;
+
+ // Ignore argument 1, the format string. It is not currently used.
+ CallArgList Args;
+ Args.add(RValue::get(BufAddr.getPointer()), Ctx.VoidPtrTy);
+
+ for (const auto &Item : Layout.Items) {
+ int Size = Item.getSizeByte();
+ if (!Size)
+ continue;
+
+ llvm::Value *ArgVal;
+
+ if (const Expr *TheExpr = Item.getExpr()) {
+ ArgVal = EmitScalarExpr(TheExpr, /*Ignore*/ false);
+
+ // Check if this is a retainable type.
+ if (TheExpr->getType()->isObjCRetainableType()) {
+ assert(getEvaluationKind(TheExpr->getType()) == TEK_Scalar &&
+ "Only scalar can be a ObjC retainable type");
+ // Check if the object is constant, if not, save it in
+ // RetainableOperands.
+ if (!isa<Constant>(ArgVal))
+ RetainableOperands.push_back(ArgVal);
+ }
+ } else {
+ ArgVal = Builder.getInt32(Item.getConstValue().getQuantity());
+ }
+
+ unsigned ArgValSize =
+ CGM.getDataLayout().getTypeSizeInBits(ArgVal->getType());
+ llvm::IntegerType *IntTy = llvm::Type::getIntNTy(getLLVMContext(),
+ ArgValSize);
+ ArgVal = Builder.CreateBitOrPointerCast(ArgVal, IntTy);
+ CanQualType ArgTy = getOSLogArgType(Ctx, Size);
+ // If ArgVal has type x86_fp80, zero-extend ArgVal.
+ ArgVal = Builder.CreateZExtOrBitCast(ArgVal, ConvertType(ArgTy));
+ Args.add(RValue::get(ArgVal), ArgTy);
+ }
+
+ const CGFunctionInfo &FI =
+ CGM.getTypes().arrangeBuiltinFunctionCall(Ctx.VoidTy, Args);
+ llvm::Function *F = CodeGenFunction(CGM).generateBuiltinOSLogHelperFunction(
+ Layout, BufAddr.getAlignment());
+ EmitCall(FI, CGCallee::forDirect(F), ReturnValueSlot(), Args);
+
+ // Push a clang.arc.use cleanup for each object in RetainableOperands. The
+ // cleanup will cause the use to appear after the final log call, keeping
+ // the object valid while it’s held in the log buffer. Note that if there’s
+ // a release cleanup on the object, it will already be active; since
+ // cleanups are emitted in reverse order, the use will occur before the
+ // object is released.
+ if (!RetainableOperands.empty() && getLangOpts().ObjCAutoRefCount &&
+ CGM.getCodeGenOpts().OptimizationLevel != 0)
+ for (llvm::Value *Object : RetainableOperands)
+ pushFullExprCleanup<CallObjCArcUse>(getARCCleanupKind(), Object);
+
+ return RValue::get(BufAddr.getPointer());
+}
+
+/// Determine if a binop is a checked mixed-sign multiply we can specialize.
+static bool isSpecialMixedSignMultiply(unsigned BuiltinID,
+ WidthAndSignedness Op1Info,
+ WidthAndSignedness Op2Info,
+ WidthAndSignedness ResultInfo) {
+ return BuiltinID == Builtin::BI__builtin_mul_overflow &&
+ Op1Info.Width == Op2Info.Width && Op1Info.Width >= ResultInfo.Width &&
+ Op1Info.Signed != Op2Info.Signed;
+}
+
+/// Emit a checked mixed-sign multiply. This is a cheaper specialization of
+/// the generic checked-binop irgen.
+static RValue
+EmitCheckedMixedSignMultiply(CodeGenFunction &CGF, const clang::Expr *Op1,
+ WidthAndSignedness Op1Info, const clang::Expr *Op2,
+ WidthAndSignedness Op2Info,
+ const clang::Expr *ResultArg, QualType ResultQTy,
+ WidthAndSignedness ResultInfo) {
+ assert(isSpecialMixedSignMultiply(Builtin::BI__builtin_mul_overflow, Op1Info,
+ Op2Info, ResultInfo) &&
+ "Not a mixed-sign multipliction we can specialize");
+
+ // Emit the signed and unsigned operands.
+ const clang::Expr *SignedOp = Op1Info.Signed ? Op1 : Op2;
+ const clang::Expr *UnsignedOp = Op1Info.Signed ? Op2 : Op1;
+ llvm::Value *Signed = CGF.EmitScalarExpr(SignedOp);
+ llvm::Value *Unsigned = CGF.EmitScalarExpr(UnsignedOp);
+
+ llvm::Type *OpTy = Signed->getType();
+ llvm::Value *Zero = llvm::Constant::getNullValue(OpTy);
+ Address ResultPtr = CGF.EmitPointerWithAlignment(ResultArg);
+ llvm::Type *ResTy = ResultPtr.getElementType();
+
+ // Take the absolute value of the signed operand.
+ llvm::Value *IsNegative = CGF.Builder.CreateICmpSLT(Signed, Zero);
+ llvm::Value *AbsOfNegative = CGF.Builder.CreateSub(Zero, Signed);
+ llvm::Value *AbsSigned =
+ CGF.Builder.CreateSelect(IsNegative, AbsOfNegative, Signed);
+
+ // Perform a checked unsigned multiplication.
+ llvm::Value *UnsignedOverflow;
+ llvm::Value *UnsignedResult =
+ EmitOverflowIntrinsic(CGF, llvm::Intrinsic::umul_with_overflow, AbsSigned,
+ Unsigned, UnsignedOverflow);
+
+ llvm::Value *Overflow, *Result;
+ if (ResultInfo.Signed) {
+ // Signed overflow occurs if the result is greater than INT_MAX or lesser
+ // than INT_MIN, i.e when |Result| > (INT_MAX + IsNegative).
+ auto IntMax = llvm::APInt::getSignedMaxValue(ResultInfo.Width)
+ .zextOrSelf(Op1Info.Width);
+ llvm::Value *MaxResult =
+ CGF.Builder.CreateAdd(llvm::ConstantInt::get(OpTy, IntMax),
+ CGF.Builder.CreateZExt(IsNegative, OpTy));
+ llvm::Value *SignedOverflow =
+ CGF.Builder.CreateICmpUGT(UnsignedResult, MaxResult);
+ Overflow = CGF.Builder.CreateOr(UnsignedOverflow, SignedOverflow);
+
+ // Prepare the signed result (possibly by negating it).
+ llvm::Value *NegativeResult = CGF.Builder.CreateNeg(UnsignedResult);
+ llvm::Value *SignedResult =
+ CGF.Builder.CreateSelect(IsNegative, NegativeResult, UnsignedResult);
+ Result = CGF.Builder.CreateTrunc(SignedResult, ResTy);
+ } else {
+ // Unsigned overflow occurs if the result is < 0 or greater than UINT_MAX.
+ llvm::Value *Underflow = CGF.Builder.CreateAnd(
+ IsNegative, CGF.Builder.CreateIsNotNull(UnsignedResult));
+ Overflow = CGF.Builder.CreateOr(UnsignedOverflow, Underflow);
+ if (ResultInfo.Width < Op1Info.Width) {
+ auto IntMax =
+ llvm::APInt::getMaxValue(ResultInfo.Width).zext(Op1Info.Width);
+ llvm::Value *TruncOverflow = CGF.Builder.CreateICmpUGT(
+ UnsignedResult, llvm::ConstantInt::get(OpTy, IntMax));
+ Overflow = CGF.Builder.CreateOr(Overflow, TruncOverflow);
+ }
+
+ Result = CGF.Builder.CreateTrunc(UnsignedResult, ResTy);
+ }
+ assert(Overflow && Result && "Missing overflow or result");
+
+ bool isVolatile =
+ ResultArg->getType()->getPointeeType().isVolatileQualified();
+ CGF.Builder.CreateStore(CGF.EmitToMemory(Result, ResultQTy), ResultPtr,
+ isVolatile);
+ return RValue::get(Overflow);
+}
+
RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
unsigned BuiltinID, const CallExpr *E,
ReturnValueSlot ReturnValue) {
@@ -656,11 +941,196 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
Result.Val.getFloat()));
}
+ // There are LLVM math intrinsics/instructions corresponding to math library
+ // functions except the LLVM op will never set errno while the math library
+ // might. Also, math builtins have the same semantics as their math library
+ // twins. Thus, we can transform math library and builtin calls to their
+ // LLVM counterparts if the call is marked 'const' (known to never set errno).
+ if (FD->hasAttr<ConstAttr>()) {
+ switch (BuiltinID) {
+ case Builtin::BIceil:
+ case Builtin::BIceilf:
+ case Builtin::BIceill:
+ case Builtin::BI__builtin_ceil:
+ case Builtin::BI__builtin_ceilf:
+ case Builtin::BI__builtin_ceill:
+ return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::ceil));
+
+ case Builtin::BIcopysign:
+ case Builtin::BIcopysignf:
+ case Builtin::BIcopysignl:
+ case Builtin::BI__builtin_copysign:
+ case Builtin::BI__builtin_copysignf:
+ case Builtin::BI__builtin_copysignl:
+ return RValue::get(emitBinaryBuiltin(*this, E, Intrinsic::copysign));
+
+ case Builtin::BIcos:
+ case Builtin::BIcosf:
+ case Builtin::BIcosl:
+ case Builtin::BI__builtin_cos:
+ case Builtin::BI__builtin_cosf:
+ case Builtin::BI__builtin_cosl:
+ return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::cos));
+
+ case Builtin::BIexp:
+ case Builtin::BIexpf:
+ case Builtin::BIexpl:
+ case Builtin::BI__builtin_exp:
+ case Builtin::BI__builtin_expf:
+ case Builtin::BI__builtin_expl:
+ return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::exp));
+
+ case Builtin::BIexp2:
+ case Builtin::BIexp2f:
+ case Builtin::BIexp2l:
+ case Builtin::BI__builtin_exp2:
+ case Builtin::BI__builtin_exp2f:
+ case Builtin::BI__builtin_exp2l:
+ return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::exp2));
+
+ case Builtin::BIfabs:
+ case Builtin::BIfabsf:
+ case Builtin::BIfabsl:
+ case Builtin::BI__builtin_fabs:
+ case Builtin::BI__builtin_fabsf:
+ case Builtin::BI__builtin_fabsl:
+ return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::fabs));
+
+ case Builtin::BIfloor:
+ case Builtin::BIfloorf:
+ case Builtin::BIfloorl:
+ case Builtin::BI__builtin_floor:
+ case Builtin::BI__builtin_floorf:
+ case Builtin::BI__builtin_floorl:
+ return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::floor));
+
+ case Builtin::BIfma:
+ case Builtin::BIfmaf:
+ case Builtin::BIfmal:
+ case Builtin::BI__builtin_fma:
+ case Builtin::BI__builtin_fmaf:
+ case Builtin::BI__builtin_fmal:
+ return RValue::get(emitTernaryBuiltin(*this, E, Intrinsic::fma));
+
+ case Builtin::BIfmax:
+ case Builtin::BIfmaxf:
+ case Builtin::BIfmaxl:
+ case Builtin::BI__builtin_fmax:
+ case Builtin::BI__builtin_fmaxf:
+ case Builtin::BI__builtin_fmaxl:
+ return RValue::get(emitBinaryBuiltin(*this, E, Intrinsic::maxnum));
+
+ case Builtin::BIfmin:
+ case Builtin::BIfminf:
+ case Builtin::BIfminl:
+ case Builtin::BI__builtin_fmin:
+ case Builtin::BI__builtin_fminf:
+ case Builtin::BI__builtin_fminl:
+ return RValue::get(emitBinaryBuiltin(*this, E, Intrinsic::minnum));
+
+ // fmod() is a special-case. It maps to the frem instruction rather than an
+ // LLVM intrinsic.
+ case Builtin::BIfmod:
+ case Builtin::BIfmodf:
+ case Builtin::BIfmodl:
+ case Builtin::BI__builtin_fmod:
+ case Builtin::BI__builtin_fmodf:
+ case Builtin::BI__builtin_fmodl: {
+ Value *Arg1 = EmitScalarExpr(E->getArg(0));
+ Value *Arg2 = EmitScalarExpr(E->getArg(1));
+ return RValue::get(Builder.CreateFRem(Arg1, Arg2, "fmod"));
+ }
+
+ case Builtin::BIlog:
+ case Builtin::BIlogf:
+ case Builtin::BIlogl:
+ case Builtin::BI__builtin_log:
+ case Builtin::BI__builtin_logf:
+ case Builtin::BI__builtin_logl:
+ return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::log));
+
+ case Builtin::BIlog10:
+ case Builtin::BIlog10f:
+ case Builtin::BIlog10l:
+ case Builtin::BI__builtin_log10:
+ case Builtin::BI__builtin_log10f:
+ case Builtin::BI__builtin_log10l:
+ return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::log10));
+
+ case Builtin::BIlog2:
+ case Builtin::BIlog2f:
+ case Builtin::BIlog2l:
+ case Builtin::BI__builtin_log2:
+ case Builtin::BI__builtin_log2f:
+ case Builtin::BI__builtin_log2l:
+ return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::log2));
+
+ case Builtin::BInearbyint:
+ case Builtin::BInearbyintf:
+ case Builtin::BInearbyintl:
+ case Builtin::BI__builtin_nearbyint:
+ case Builtin::BI__builtin_nearbyintf:
+ case Builtin::BI__builtin_nearbyintl:
+ return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::nearbyint));
+
+ case Builtin::BIpow:
+ case Builtin::BIpowf:
+ case Builtin::BIpowl:
+ case Builtin::BI__builtin_pow:
+ case Builtin::BI__builtin_powf:
+ case Builtin::BI__builtin_powl:
+ return RValue::get(emitBinaryBuiltin(*this, E, Intrinsic::pow));
+
+ case Builtin::BIrint:
+ case Builtin::BIrintf:
+ case Builtin::BIrintl:
+ case Builtin::BI__builtin_rint:
+ case Builtin::BI__builtin_rintf:
+ case Builtin::BI__builtin_rintl:
+ return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::rint));
+
+ case Builtin::BIround:
+ case Builtin::BIroundf:
+ case Builtin::BIroundl:
+ case Builtin::BI__builtin_round:
+ case Builtin::BI__builtin_roundf:
+ case Builtin::BI__builtin_roundl:
+ return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::round));
+
+ case Builtin::BIsin:
+ case Builtin::BIsinf:
+ case Builtin::BIsinl:
+ case Builtin::BI__builtin_sin:
+ case Builtin::BI__builtin_sinf:
+ case Builtin::BI__builtin_sinl:
+ return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::sin));
+
+ case Builtin::BIsqrt:
+ case Builtin::BIsqrtf:
+ case Builtin::BIsqrtl:
+ case Builtin::BI__builtin_sqrt:
+ case Builtin::BI__builtin_sqrtf:
+ case Builtin::BI__builtin_sqrtl:
+ return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::sqrt));
+
+ case Builtin::BItrunc:
+ case Builtin::BItruncf:
+ case Builtin::BItruncl:
+ case Builtin::BI__builtin_trunc:
+ case Builtin::BI__builtin_truncf:
+ case Builtin::BI__builtin_truncl:
+ return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::trunc));
+
+ default:
+ break;
+ }
+ }
+
switch (BuiltinID) {
- default: break; // Handle intrinsics and libm functions below.
+ default: break;
case Builtin::BI__builtin___CFStringMakeConstantString:
case Builtin::BI__builtin___NSStringMakeConstantString:
- return RValue::get(CGM.EmitConstantExpr(E, E->getType(), nullptr));
+ return RValue::get(ConstantEmitter(*this).emitAbstract(E, E->getType()));
case Builtin::BI__builtin_stdarg_start:
case Builtin::BI__builtin_va_start:
case Builtin::BI__va_start:
@@ -696,64 +1166,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
return RValue::get(Result);
}
- case Builtin::BI__builtin_fabs:
- case Builtin::BI__builtin_fabsf:
- case Builtin::BI__builtin_fabsl: {
- return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::fabs));
- }
- case Builtin::BI__builtin_fmod:
- case Builtin::BI__builtin_fmodf:
- case Builtin::BI__builtin_fmodl: {
- Value *Arg1 = EmitScalarExpr(E->getArg(0));
- Value *Arg2 = EmitScalarExpr(E->getArg(1));
- Value *Result = Builder.CreateFRem(Arg1, Arg2, "fmod");
- return RValue::get(Result);
- }
- case Builtin::BI__builtin_copysign:
- case Builtin::BI__builtin_copysignf:
- case Builtin::BI__builtin_copysignl: {
- return RValue::get(emitBinaryBuiltin(*this, E, Intrinsic::copysign));
- }
- case Builtin::BI__builtin_ceil:
- case Builtin::BI__builtin_ceilf:
- case Builtin::BI__builtin_ceill: {
- return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::ceil));
- }
- case Builtin::BI__builtin_floor:
- case Builtin::BI__builtin_floorf:
- case Builtin::BI__builtin_floorl: {
- return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::floor));
- }
- case Builtin::BI__builtin_trunc:
- case Builtin::BI__builtin_truncf:
- case Builtin::BI__builtin_truncl: {
- return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::trunc));
- }
- case Builtin::BI__builtin_rint:
- case Builtin::BI__builtin_rintf:
- case Builtin::BI__builtin_rintl: {
- return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::rint));
- }
- case Builtin::BI__builtin_nearbyint:
- case Builtin::BI__builtin_nearbyintf:
- case Builtin::BI__builtin_nearbyintl: {
- return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::nearbyint));
- }
- case Builtin::BI__builtin_round:
- case Builtin::BI__builtin_roundf:
- case Builtin::BI__builtin_roundl: {
- return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::round));
- }
- case Builtin::BI__builtin_fmin:
- case Builtin::BI__builtin_fminf:
- case Builtin::BI__builtin_fminl: {
- return RValue::get(emitBinaryBuiltin(*this, E, Intrinsic::minnum));
- }
- case Builtin::BI__builtin_fmax:
- case Builtin::BI__builtin_fmaxf:
- case Builtin::BI__builtin_fmaxl: {
- return RValue::get(emitBinaryBuiltin(*this, E, Intrinsic::maxnum));
- }
case Builtin::BI__builtin_conj:
case Builtin::BI__builtin_conjf:
case Builtin::BI__builtin_conjl: {
@@ -792,7 +1204,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BI__builtin_ctz:
case Builtin::BI__builtin_ctzl:
case Builtin::BI__builtin_ctzll: {
- Value *ArgValue = EmitScalarExpr(E->getArg(0));
+ Value *ArgValue = EmitCheckedArgForBuiltin(E->getArg(0), BCK_CTZPassedZero);
llvm::Type *ArgType = ArgValue->getType();
Value *F = CGM.getIntrinsic(Intrinsic::cttz, ArgType);
@@ -809,7 +1221,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BI__builtin_clz:
case Builtin::BI__builtin_clzl:
case Builtin::BI__builtin_clzll: {
- Value *ArgValue = EmitScalarExpr(E->getArg(0));
+ Value *ArgValue = EmitCheckedArgForBuiltin(E->getArg(0), BCK_CLZPassedZero);
llvm::Type *ArgType = ArgValue->getType();
Value *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
@@ -1234,7 +1646,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(0)->getType(),
E->getArg(0)->getExprLoc(), FD, 0);
Builder.CreateMemSet(Dest, Builder.getInt8(0), SizeVal, false);
- return RValue::get(Dest.getPointer());
+ return RValue::get(nullptr);
}
case Builtin::BImemcpy:
case Builtin::BI__builtin_memcpy: {
@@ -1346,8 +1758,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
llvm::ConstantInt::get(Int32Ty, Offset)));
}
case Builtin::BI__builtin_return_address: {
- Value *Depth =
- CGM.EmitConstantExpr(E->getArg(0), getContext().UnsignedIntTy, this);
+ Value *Depth = ConstantEmitter(*this).emitAbstract(E->getArg(0),
+ getContext().UnsignedIntTy);
Value *F = CGM.getIntrinsic(Intrinsic::returnaddress);
return RValue::get(Builder.CreateCall(F, Depth));
}
@@ -1356,8 +1768,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
return RValue::get(Builder.CreateCall(F, Builder.getInt32(0)));
}
case Builtin::BI__builtin_frame_address: {
- Value *Depth =
- CGM.EmitConstantExpr(E->getArg(0), getContext().UnsignedIntTy, this);
+ Value *Depth = ConstantEmitter(*this).emitAbstract(E->getArg(0),
+ getContext().UnsignedIntTy);
Value *F = CGM.getIntrinsic(Intrinsic::frameaddress);
return RValue::get(Builder.CreateCall(F, Depth));
}
@@ -1875,56 +2287,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
return RValue::get(nullptr);
}
- // Library functions with special handling.
- case Builtin::BIsqrt:
- case Builtin::BIsqrtf:
- case Builtin::BIsqrtl: {
- // Transform a call to sqrt* into a @llvm.sqrt.* intrinsic call, but only
- // in finite- or unsafe-math mode (the intrinsic has different semantics
- // for handling negative numbers compared to the library function, so
- // -fmath-errno=0 is not enough).
- if (!FD->hasAttr<ConstAttr>())
- break;
- if (!(CGM.getCodeGenOpts().UnsafeFPMath ||
- CGM.getCodeGenOpts().NoNaNsFPMath))
- break;
- Value *Arg0 = EmitScalarExpr(E->getArg(0));
- llvm::Type *ArgType = Arg0->getType();
- Value *F = CGM.getIntrinsic(Intrinsic::sqrt, ArgType);
- return RValue::get(Builder.CreateCall(F, Arg0));
- }
-
- case Builtin::BI__builtin_pow:
- case Builtin::BI__builtin_powf:
- case Builtin::BI__builtin_powl:
- case Builtin::BIpow:
- case Builtin::BIpowf:
- case Builtin::BIpowl: {
- // Transform a call to pow* into a @llvm.pow.* intrinsic call.
- if (!FD->hasAttr<ConstAttr>())
- break;
- Value *Base = EmitScalarExpr(E->getArg(0));
- Value *Exponent = EmitScalarExpr(E->getArg(1));
- llvm::Type *ArgType = Base->getType();
- Value *F = CGM.getIntrinsic(Intrinsic::pow, ArgType);
- return RValue::get(Builder.CreateCall(F, {Base, Exponent}));
- }
-
- case Builtin::BIfma:
- case Builtin::BIfmaf:
- case Builtin::BIfmal:
- case Builtin::BI__builtin_fma:
- case Builtin::BI__builtin_fmaf:
- case Builtin::BI__builtin_fmal: {
- // Rewrite fma to intrinsic.
- Value *FirstArg = EmitScalarExpr(E->getArg(0));
- llvm::Type *ArgType = FirstArg->getType();
- Value *F = CGM.getIntrinsic(Intrinsic::fma, ArgType);
- return RValue::get(
- Builder.CreateCall(F, {FirstArg, EmitScalarExpr(E->getArg(1)),
- EmitScalarExpr(E->getArg(2))}));
- }
-
case Builtin::BI__builtin_signbit:
case Builtin::BI__builtin_signbitf:
case Builtin::BI__builtin_signbitl: {
@@ -1932,6 +2294,28 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
Builder.CreateZExt(EmitSignBit(*this, EmitScalarExpr(E->getArg(0))),
ConvertType(E->getType())));
}
+ case Builtin::BI__annotation: {
+ // Re-encode each wide string to UTF8 and make an MDString.
+ SmallVector<Metadata *, 1> Strings;
+ for (const Expr *Arg : E->arguments()) {
+ const auto *Str = cast<StringLiteral>(Arg->IgnoreParenCasts());
+ assert(Str->getCharByteWidth() == 2);
+ StringRef WideBytes = Str->getBytes();
+ std::string StrUtf8;
+ if (!convertUTF16ToUTF8String(
+ makeArrayRef(WideBytes.data(), WideBytes.size()), StrUtf8)) {
+ CGM.ErrorUnsupported(E, "non-UTF16 __annotation argument");
+ continue;
+ }
+ Strings.push_back(llvm::MDString::get(getLLVMContext(), StrUtf8));
+ }
+
+ // Build and MDTuple of MDStrings and emit the intrinsic call.
+ llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::codeview_annotation, {});
+ MDTuple *StrTuple = MDTuple::get(getLLVMContext(), Strings);
+ Builder.CreateCall(F, MetadataAsValue::get(getLLVMContext(), StrTuple));
+ return RValue::getIgnored();
+ }
case Builtin::BI__builtin_annotation: {
llvm::Value *AnnVal = EmitScalarExpr(E->getArg(0));
llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::annotation,
@@ -2026,6 +2410,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
getIntegerWidthAndSignedness(CGM.getContext(), RightArg->getType());
WidthAndSignedness ResultInfo =
getIntegerWidthAndSignedness(CGM.getContext(), ResultQTy);
+
+ // Handle mixed-sign multiplication as a special case, because adding
+ // runtime or backend support for our generic irgen would be too expensive.
+ if (isSpecialMixedSignMultiply(BuiltinID, LeftInfo, RightInfo, ResultInfo))
+ return EmitCheckedMixedSignMultiply(*this, LeftArg, LeftInfo, RightArg,
+ RightInfo, ResultArg, ResultQTy,
+ ResultInfo);
+
WidthAndSignedness EncompassingInfo =
EncompassingIntegerType({LeftInfo, RightInfo, ResultInfo});
@@ -2560,12 +2952,17 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
// The most basic form of the call with parameters:
// queue_t, kernel_enqueue_flags_t, ndrange_t, block(void)
Name = "__enqueue_kernel_basic";
- llvm::Type *ArgTys[] = {QueueTy, Int32Ty, RangeTy, GenericVoidPtrTy};
+ llvm::Type *ArgTys[] = {QueueTy, Int32Ty, RangeTy, GenericVoidPtrTy,
+ GenericVoidPtrTy};
llvm::FunctionType *FTy = llvm::FunctionType::get(
- Int32Ty, llvm::ArrayRef<llvm::Type *>(ArgTys, 4), false);
+ Int32Ty, llvm::ArrayRef<llvm::Type *>(ArgTys), false);
- llvm::Value *Block = Builder.CreatePointerCast(
- EmitScalarExpr(E->getArg(3)), GenericVoidPtrTy);
+ auto Info =
+ CGM.getOpenCLRuntime().emitOpenCLEnqueuedBlock(*this, E->getArg(3));
+ llvm::Value *Kernel =
+ Builder.CreatePointerCast(Info.Kernel, GenericVoidPtrTy);
+ llvm::Value *Block =
+ Builder.CreatePointerCast(Info.BlockArg, GenericVoidPtrTy);
AttrBuilder B;
B.addAttribute(Attribute::ByVal);
@@ -2574,33 +2971,58 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
auto RTCall =
Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name, ByValAttrSet),
- {Queue, Flags, Range, Block});
+ {Queue, Flags, Range, Kernel, Block});
RTCall->setAttributes(ByValAttrSet);
return RValue::get(RTCall);
}
assert(NumArgs >= 5 && "Invalid enqueue_kernel signature");
+ // Create a temporary array to hold the sizes of local pointer arguments
+ // for the block. \p First is the position of the first size argument.
+ auto CreateArrayForSizeVar = [=](unsigned First) {
+ auto *AT = llvm::ArrayType::get(SizeTy, NumArgs - First);
+ auto *Arr = Builder.CreateAlloca(AT);
+ llvm::Value *Ptr;
+ // Each of the following arguments specifies the size of the corresponding
+ // argument passed to the enqueued block.
+ auto *Zero = llvm::ConstantInt::get(IntTy, 0);
+ for (unsigned I = First; I < NumArgs; ++I) {
+ auto *Index = llvm::ConstantInt::get(IntTy, I - First);
+ auto *GEP = Builder.CreateGEP(Arr, {Zero, Index});
+ if (I == First)
+ Ptr = GEP;
+ auto *V =
+ Builder.CreateZExtOrTrunc(EmitScalarExpr(E->getArg(I)), SizeTy);
+ Builder.CreateAlignedStore(
+ V, GEP, CGM.getDataLayout().getPrefTypeAlignment(SizeTy));
+ }
+ return Ptr;
+ };
+
// Could have events and/or vaargs.
if (E->getArg(3)->getType()->isBlockPointerType()) {
// No events passed, but has variadic arguments.
Name = "__enqueue_kernel_vaargs";
- llvm::Value *Block = Builder.CreatePointerCast(
- EmitScalarExpr(E->getArg(3)), GenericVoidPtrTy);
+ auto Info =
+ CGM.getOpenCLRuntime().emitOpenCLEnqueuedBlock(*this, E->getArg(3));
+ llvm::Value *Kernel =
+ Builder.CreatePointerCast(Info.Kernel, GenericVoidPtrTy);
+ auto *Block = Builder.CreatePointerCast(Info.BlockArg, GenericVoidPtrTy);
+ auto *PtrToSizeArray = CreateArrayForSizeVar(4);
+
// Create a vector of the arguments, as well as a constant value to
// express to the runtime the number of variadic arguments.
- std::vector<llvm::Value *> Args = {Queue, Flags, Range, Block,
- ConstantInt::get(IntTy, NumArgs - 4)};
- std::vector<llvm::Type *> ArgTys = {QueueTy, IntTy, RangeTy,
- GenericVoidPtrTy, IntTy};
-
- // Each of the following arguments specifies the size of the corresponding
- // argument passed to the enqueued block.
- for (unsigned I = 4/*Position of the first size arg*/; I < NumArgs; ++I)
- Args.push_back(
- Builder.CreateZExtOrTrunc(EmitScalarExpr(E->getArg(I)), SizeTy));
+ std::vector<llvm::Value *> Args = {
+ Queue, Flags, Range,
+ Kernel, Block, ConstantInt::get(IntTy, NumArgs - 4),
+ PtrToSizeArray};
+ std::vector<llvm::Type *> ArgTys = {
+ QueueTy, IntTy, RangeTy,
+ GenericVoidPtrTy, GenericVoidPtrTy, IntTy,
+ PtrToSizeArray->getType()};
llvm::FunctionType *FTy = llvm::FunctionType::get(
- Int32Ty, llvm::ArrayRef<llvm::Type *>(ArgTys), true);
+ Int32Ty, llvm::ArrayRef<llvm::Type *>(ArgTys), false);
return RValue::get(
Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name),
llvm::ArrayRef<llvm::Value *>(Args)));
@@ -2621,15 +3043,19 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
// Convert to generic address space.
EventList = Builder.CreatePointerCast(EventList, EventPtrTy);
ClkEvent = Builder.CreatePointerCast(ClkEvent, EventPtrTy);
- llvm::Value *Block = Builder.CreatePointerCast(
- EmitScalarExpr(E->getArg(6)), GenericVoidPtrTy);
+ auto Info =
+ CGM.getOpenCLRuntime().emitOpenCLEnqueuedBlock(*this, E->getArg(6));
+ llvm::Value *Kernel =
+ Builder.CreatePointerCast(Info.Kernel, GenericVoidPtrTy);
+ llvm::Value *Block =
+ Builder.CreatePointerCast(Info.BlockArg, GenericVoidPtrTy);
std::vector<llvm::Type *> ArgTys = {
- QueueTy, Int32Ty, RangeTy, Int32Ty,
- EventPtrTy, EventPtrTy, GenericVoidPtrTy};
+ QueueTy, Int32Ty, RangeTy, Int32Ty,
+ EventPtrTy, EventPtrTy, GenericVoidPtrTy, GenericVoidPtrTy};
- std::vector<llvm::Value *> Args = {Queue, Flags, Range, NumEvents,
- EventList, ClkEvent, Block};
+ std::vector<llvm::Value *> Args = {Queue, Flags, Range, NumEvents,
+ EventList, ClkEvent, Kernel, Block};
if (NumArgs == 7) {
// Has events but no variadics.
@@ -2646,14 +3072,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
ArgTys.push_back(Int32Ty);
Name = "__enqueue_kernel_events_vaargs";
- // Each of the following arguments specifies the size of the corresponding
- // argument passed to the enqueued block.
- for (unsigned I = 7/*Position of the first size arg*/; I < NumArgs; ++I)
- Args.push_back(
- Builder.CreateZExtOrTrunc(EmitScalarExpr(E->getArg(I)), SizeTy));
+ auto *PtrToSizeArray = CreateArrayForSizeVar(7);
+ Args.push_back(PtrToSizeArray);
+ ArgTys.push_back(PtrToSizeArray->getType());
llvm::FunctionType *FTy = llvm::FunctionType::get(
- Int32Ty, llvm::ArrayRef<llvm::Type *>(ArgTys), true);
+ Int32Ty, llvm::ArrayRef<llvm::Type *>(ArgTys), false);
return RValue::get(
Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name),
llvm::ArrayRef<llvm::Value *>(Args)));
@@ -2665,24 +3089,70 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BIget_kernel_work_group_size: {
llvm::Type *GenericVoidPtrTy = Builder.getInt8PtrTy(
getContext().getTargetAddressSpace(LangAS::opencl_generic));
- Value *Arg = EmitScalarExpr(E->getArg(0));
- Arg = Builder.CreatePointerCast(Arg, GenericVoidPtrTy);
+ auto Info =
+ CGM.getOpenCLRuntime().emitOpenCLEnqueuedBlock(*this, E->getArg(0));
+ Value *Kernel = Builder.CreatePointerCast(Info.Kernel, GenericVoidPtrTy);
+ Value *Arg = Builder.CreatePointerCast(Info.BlockArg, GenericVoidPtrTy);
return RValue::get(Builder.CreateCall(
CGM.CreateRuntimeFunction(
- llvm::FunctionType::get(IntTy, GenericVoidPtrTy, false),
+ llvm::FunctionType::get(IntTy, {GenericVoidPtrTy, GenericVoidPtrTy},
+ false),
"__get_kernel_work_group_size_impl"),
- Arg));
+ {Kernel, Arg}));
}
case Builtin::BIget_kernel_preferred_work_group_size_multiple: {
llvm::Type *GenericVoidPtrTy = Builder.getInt8PtrTy(
getContext().getTargetAddressSpace(LangAS::opencl_generic));
- Value *Arg = EmitScalarExpr(E->getArg(0));
- Arg = Builder.CreatePointerCast(Arg, GenericVoidPtrTy);
+ auto Info =
+ CGM.getOpenCLRuntime().emitOpenCLEnqueuedBlock(*this, E->getArg(0));
+ Value *Kernel = Builder.CreatePointerCast(Info.Kernel, GenericVoidPtrTy);
+ Value *Arg = Builder.CreatePointerCast(Info.BlockArg, GenericVoidPtrTy);
return RValue::get(Builder.CreateCall(
CGM.CreateRuntimeFunction(
- llvm::FunctionType::get(IntTy, GenericVoidPtrTy, false),
+ llvm::FunctionType::get(IntTy, {GenericVoidPtrTy, GenericVoidPtrTy},
+ false),
"__get_kernel_preferred_work_group_multiple_impl"),
- Arg));
+ {Kernel, Arg}));
+ }
+ case Builtin::BIget_kernel_max_sub_group_size_for_ndrange:
+ case Builtin::BIget_kernel_sub_group_count_for_ndrange: {
+ llvm::Type *GenericVoidPtrTy = Builder.getInt8PtrTy(
+ getContext().getTargetAddressSpace(LangAS::opencl_generic));
+ LValue NDRangeL = EmitAggExprToLValue(E->getArg(0));
+ llvm::Value *NDRange = NDRangeL.getAddress().getPointer();
+ auto Info =
+ CGM.getOpenCLRuntime().emitOpenCLEnqueuedBlock(*this, E->getArg(1));
+ Value *Kernel = Builder.CreatePointerCast(Info.Kernel, GenericVoidPtrTy);
+ Value *Block = Builder.CreatePointerCast(Info.BlockArg, GenericVoidPtrTy);
+ const char *Name =
+ BuiltinID == Builtin::BIget_kernel_max_sub_group_size_for_ndrange
+ ? "__get_kernel_max_sub_group_size_for_ndrange_impl"
+ : "__get_kernel_sub_group_count_for_ndrange_impl";
+ return RValue::get(Builder.CreateCall(
+ CGM.CreateRuntimeFunction(
+ llvm::FunctionType::get(
+ IntTy, {NDRange->getType(), GenericVoidPtrTy, GenericVoidPtrTy},
+ false),
+ Name),
+ {NDRange, Kernel, Block}));
+ }
+
+ case Builtin::BI__builtin_store_half:
+ case Builtin::BI__builtin_store_halff: {
+ Value *Val = EmitScalarExpr(E->getArg(0));
+ Address Address = EmitPointerWithAlignment(E->getArg(1));
+ Value *HalfVal = Builder.CreateFPTrunc(Val, Builder.getHalfTy());
+ return RValue::get(Builder.CreateStore(HalfVal, Address));
+ }
+ case Builtin::BI__builtin_load_half: {
+ Address Address = EmitPointerWithAlignment(E->getArg(0));
+ Value *HalfVal = Builder.CreateLoad(Address);
+ return RValue::get(Builder.CreateFPExt(HalfVal, Builder.getDoubleTy()));
+ }
+ case Builtin::BI__builtin_load_halff: {
+ Address Address = EmitPointerWithAlignment(E->getArg(0));
+ Value *HalfVal = Builder.CreateLoad(Address);
+ return RValue::get(Builder.CreateFPExt(HalfVal, Builder.getFloatTy()));
}
case Builtin::BIprintf:
if (getTarget().getTriple().isNVPTX())
@@ -2699,69 +3169,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
// Fall through - it's already mapped to the intrinsic by GCCBuiltin.
break;
}
- case Builtin::BI__builtin_os_log_format: {
- assert(E->getNumArgs() >= 2 &&
- "__builtin_os_log_format takes at least 2 arguments");
- analyze_os_log::OSLogBufferLayout Layout;
- analyze_os_log::computeOSLogBufferLayout(CGM.getContext(), E, Layout);
- Address BufAddr = EmitPointerWithAlignment(E->getArg(0));
- // Ignore argument 1, the format string. It is not currently used.
- CharUnits Offset;
- Builder.CreateStore(
- Builder.getInt8(Layout.getSummaryByte()),
- Builder.CreateConstByteGEP(BufAddr, Offset++, "summary"));
- Builder.CreateStore(
- Builder.getInt8(Layout.getNumArgsByte()),
- Builder.CreateConstByteGEP(BufAddr, Offset++, "numArgs"));
-
- llvm::SmallVector<llvm::Value *, 4> RetainableOperands;
- for (const auto &Item : Layout.Items) {
- Builder.CreateStore(
- Builder.getInt8(Item.getDescriptorByte()),
- Builder.CreateConstByteGEP(BufAddr, Offset++, "argDescriptor"));
- Builder.CreateStore(
- Builder.getInt8(Item.getSizeByte()),
- Builder.CreateConstByteGEP(BufAddr, Offset++, "argSize"));
- Address Addr = Builder.CreateConstByteGEP(BufAddr, Offset);
- if (const Expr *TheExpr = Item.getExpr()) {
- Addr = Builder.CreateElementBitCast(
- Addr, ConvertTypeForMem(TheExpr->getType()));
- // Check if this is a retainable type.
- if (TheExpr->getType()->isObjCRetainableType()) {
- assert(getEvaluationKind(TheExpr->getType()) == TEK_Scalar &&
- "Only scalar can be a ObjC retainable type");
- llvm::Value *SV = EmitScalarExpr(TheExpr, /*Ignore*/ false);
- RValue RV = RValue::get(SV);
- LValue LV = MakeAddrLValue(Addr, TheExpr->getType());
- EmitStoreThroughLValue(RV, LV);
- // Check if the object is constant, if not, save it in
- // RetainableOperands.
- if (!isa<Constant>(SV))
- RetainableOperands.push_back(SV);
- } else {
- EmitAnyExprToMem(TheExpr, Addr, Qualifiers(), /*isInit*/ true);
- }
- } else {
- Addr = Builder.CreateElementBitCast(Addr, Int32Ty);
- Builder.CreateStore(
- Builder.getInt32(Item.getConstValue().getQuantity()), Addr);
- }
- Offset += Item.size();
- }
-
- // Push a clang.arc.use cleanup for each object in RetainableOperands. The
- // cleanup will cause the use to appear after the final log call, keeping
- // the object valid while it's held in the log buffer. Note that if there's
- // a release cleanup on the object, it will already be active; since
- // cleanups are emitted in reverse order, the use will occur before the
- // object is released.
- if (!RetainableOperands.empty() && getLangOpts().ObjCAutoRefCount &&
- CGM.getCodeGenOpts().OptimizationLevel != 0)
- for (llvm::Value *object : RetainableOperands)
- pushFullExprCleanup<CallObjCArcUse>(getARCCleanupKind(), object);
-
- return RValue::get(BufAddr.getPointer());
- }
+ case Builtin::BI__builtin_os_log_format:
+ return emitBuiltinOSLogFormat(*E);
case Builtin::BI__builtin_os_log_format_buffer_size: {
analyze_os_log::OSLogBufferLayout Layout;
@@ -2773,10 +3182,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BI__xray_customevent: {
if (!ShouldXRayInstrumentFunction())
return RValue::getIgnored();
- if (const auto *XRayAttr = CurFuncDecl->getAttr<XRayInstrumentAttr>()) {
- if (XRayAttr->neverXRayInstrument())
+ if (const auto *XRayAttr = CurFuncDecl->getAttr<XRayInstrumentAttr>())
+ if (XRayAttr->neverXRayInstrument() && !AlwaysEmitXRayCustomEvents())
return RValue::getIgnored();
- }
+
Function *F = CGM.getIntrinsic(Intrinsic::xray_customevent);
auto FTy = F->getFunctionType();
auto Arg0 = E->getArg(0);
@@ -2954,6 +3363,8 @@ static Value *EmitTargetArchBuiltinExpr(CodeGenFunction *CGF,
case llvm::Triple::wasm32:
case llvm::Triple::wasm64:
return CGF->EmitWebAssemblyBuiltinExpr(BuiltinID, E);
+ case llvm::Triple::hexagon:
+ return CGF->EmitHexagonBuiltinExpr(BuiltinID, E);
default:
return nullptr;
}
@@ -4397,8 +4808,8 @@ static bool HasExtraNeonArgument(unsigned BuiltinID) {
case NEON::BI__builtin_neon_vsha1cq_u32:
case NEON::BI__builtin_neon_vsha1pq_u32:
case NEON::BI__builtin_neon_vsha1mq_u32:
- case ARM::BI_MoveToCoprocessor:
- case ARM::BI_MoveToCoprocessor2:
+ case clang::ARM::BI_MoveToCoprocessor:
+ case clang::ARM::BI_MoveToCoprocessor2:
return false;
}
return true;
@@ -7153,6 +7564,19 @@ static Value *EmitX86MaskedLoad(CodeGenFunction &CGF,
return CGF.Builder.CreateMaskedLoad(Ops[0], Align, MaskVec, Ops[1]);
}
+static Value *EmitX86MaskLogic(CodeGenFunction &CGF, Instruction::BinaryOps Opc,
+ unsigned NumElts, SmallVectorImpl<Value *> &Ops,
+ bool InvertLHS = false) {
+ Value *LHS = getMaskVecValue(CGF, Ops[0], NumElts);
+ Value *RHS = getMaskVecValue(CGF, Ops[1], NumElts);
+
+ if (InvertLHS)
+ LHS = CGF.Builder.CreateNot(LHS);
+
+ return CGF.Builder.CreateBitCast(CGF.Builder.CreateBinOp(Opc, LHS, RHS),
+ CGF.Builder.getIntNTy(std::max(NumElts, 8U)));
+}
+
static Value *EmitX86SubVectorBroadcast(CodeGenFunction &CGF,
SmallVectorImpl<Value *> &Ops,
llvm::Type *DstTy,
@@ -7229,6 +7653,18 @@ static Value *EmitX86MaskedCompare(CodeGenFunction &CGF, unsigned CC,
std::max(NumElts, 8U)));
}
+static Value *EmitX86Abs(CodeGenFunction &CGF, ArrayRef<Value *> Ops) {
+
+ llvm::Type *Ty = Ops[0]->getType();
+ Value *Zero = llvm::Constant::getNullValue(Ty);
+ Value *Sub = CGF.Builder.CreateSub(Zero, Ops[0]);
+ Value *Cmp = CGF.Builder.CreateICmp(ICmpInst::ICMP_SGT, Ops[0], Zero);
+ Value *Res = CGF.Builder.CreateSelect(Cmp, Ops[0], Sub);
+ if (Ops.size() == 1)
+ return Res;
+ return EmitX86Select(CGF, Ops[2], Res, Ops[1]);
+}
+
static Value *EmitX86MinMax(CodeGenFunction &CGF, ICmpInst::Predicate Pred,
ArrayRef<Value *> Ops) {
Value *Cmp = CGF.Builder.CreateICmp(Pred, Ops[0], Ops[1]);
@@ -7248,8 +7684,118 @@ static Value *EmitX86SExtMask(CodeGenFunction &CGF, Value *Op,
return CGF.Builder.CreateSExt(Mask, DstTy, "vpmovm2");
}
+Value *CodeGenFunction::EmitX86CpuIs(const CallExpr *E) {
+ const Expr *CPUExpr = E->getArg(0)->IgnoreParenCasts();
+ StringRef CPUStr = cast<clang::StringLiteral>(CPUExpr)->getString();
+ return EmitX86CpuIs(CPUStr);
+}
+
+Value *CodeGenFunction::EmitX86CpuIs(StringRef CPUStr) {
+
+ llvm::Type *Int32Ty = Builder.getInt32Ty();
+
+ // Matching the struct layout from the compiler-rt/libgcc structure that is
+ // filled in:
+ // unsigned int __cpu_vendor;
+ // unsigned int __cpu_type;
+ // unsigned int __cpu_subtype;
+ // unsigned int __cpu_features[1];
+ llvm::Type *STy = llvm::StructType::get(Int32Ty, Int32Ty, Int32Ty,
+ llvm::ArrayType::get(Int32Ty, 1));
+
+ // Grab the global __cpu_model.
+ llvm::Constant *CpuModel = CGM.CreateRuntimeVariable(STy, "__cpu_model");
+
+ // Calculate the index needed to access the correct field based on the
+ // range. Also adjust the expected value.
+ unsigned Index;
+ unsigned Value;
+ std::tie(Index, Value) = StringSwitch<std::pair<unsigned, unsigned>>(CPUStr)
+#define X86_VENDOR(ENUM, STRING) \
+ .Case(STRING, {0u, static_cast<unsigned>(llvm::X86::ENUM)})
+#define X86_CPU_TYPE_COMPAT_WITH_ALIAS(ARCHNAME, ENUM, STR, ALIAS) \
+ .Cases(STR, ALIAS, {1u, static_cast<unsigned>(llvm::X86::ENUM)})
+#define X86_CPU_TYPE_COMPAT(ARCHNAME, ENUM, STR) \
+ .Case(STR, {1u, static_cast<unsigned>(llvm::X86::ENUM)})
+#define X86_CPU_SUBTYPE_COMPAT(ARCHNAME, ENUM, STR) \
+ .Case(STR, {2u, static_cast<unsigned>(llvm::X86::ENUM)})
+#include "llvm/Support/X86TargetParser.def"
+ .Default({0, 0});
+ assert(Value != 0 && "Invalid CPUStr passed to CpuIs");
+
+ // Grab the appropriate field from __cpu_model.
+ llvm::Value *Idxs[] = {ConstantInt::get(Int32Ty, 0),
+ ConstantInt::get(Int32Ty, Index)};
+ llvm::Value *CpuValue = Builder.CreateGEP(STy, CpuModel, Idxs);
+ CpuValue = Builder.CreateAlignedLoad(CpuValue, CharUnits::fromQuantity(4));
+
+ // Check the value of the field against the requested value.
+ return Builder.CreateICmpEQ(CpuValue,
+ llvm::ConstantInt::get(Int32Ty, Value));
+}
+
+Value *CodeGenFunction::EmitX86CpuSupports(const CallExpr *E) {
+ const Expr *FeatureExpr = E->getArg(0)->IgnoreParenCasts();
+ StringRef FeatureStr = cast<StringLiteral>(FeatureExpr)->getString();
+ return EmitX86CpuSupports(FeatureStr);
+}
+
+Value *CodeGenFunction::EmitX86CpuSupports(ArrayRef<StringRef> FeatureStrs) {
+ // Processor features and mapping to processor feature value.
+
+ uint32_t FeaturesMask = 0;
+
+ for (const StringRef &FeatureStr : FeatureStrs) {
+ unsigned Feature =
+ StringSwitch<unsigned>(FeatureStr)
+#define X86_FEATURE_COMPAT(VAL, ENUM, STR) .Case(STR, VAL)
+#include "llvm/Support/X86TargetParser.def"
+ ;
+ FeaturesMask |= (1U << Feature);
+ }
+
+ // Matching the struct layout from the compiler-rt/libgcc structure that is
+ // filled in:
+ // unsigned int __cpu_vendor;
+ // unsigned int __cpu_type;
+ // unsigned int __cpu_subtype;
+ // unsigned int __cpu_features[1];
+ llvm::Type *STy = llvm::StructType::get(Int32Ty, Int32Ty, Int32Ty,
+ llvm::ArrayType::get(Int32Ty, 1));
+
+ // Grab the global __cpu_model.
+ llvm::Constant *CpuModel = CGM.CreateRuntimeVariable(STy, "__cpu_model");
+
+ // Grab the first (0th) element from the field __cpu_features off of the
+ // global in the struct STy.
+ Value *Idxs[] = {ConstantInt::get(Int32Ty, 0), ConstantInt::get(Int32Ty, 3),
+ ConstantInt::get(Int32Ty, 0)};
+ Value *CpuFeatures = Builder.CreateGEP(STy, CpuModel, Idxs);
+ Value *Features =
+ Builder.CreateAlignedLoad(CpuFeatures, CharUnits::fromQuantity(4));
+
+ // Check the value of the bit corresponding to the feature requested.
+ Value *Bitset = Builder.CreateAnd(
+ Features, llvm::ConstantInt::get(Int32Ty, FeaturesMask));
+ return Builder.CreateICmpNE(Bitset, llvm::ConstantInt::get(Int32Ty, 0));
+}
+
+Value *CodeGenFunction::EmitX86CpuInit() {
+ llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy,
+ /*Variadic*/ false);
+ llvm::Constant *Func = CGM.CreateRuntimeFunction(FTy, "__cpu_indicator_init");
+ return Builder.CreateCall(Func);
+}
+
Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
const CallExpr *E) {
+ if (BuiltinID == X86::BI__builtin_cpu_is)
+ return EmitX86CpuIs(E);
+ if (BuiltinID == X86::BI__builtin_cpu_supports)
+ return EmitX86CpuSupports(E);
+ if (BuiltinID == X86::BI__builtin_cpu_init)
+ return EmitX86CpuInit();
+
SmallVector<Value*, 4> Ops;
// Find out if any arguments are required to be integer constant expressions.
@@ -7300,110 +7846,6 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
switch (BuiltinID) {
default: return nullptr;
- case X86::BI__builtin_cpu_supports: {
- const Expr *FeatureExpr = E->getArg(0)->IgnoreParenCasts();
- StringRef FeatureStr = cast<StringLiteral>(FeatureExpr)->getString();
-
- // TODO: When/if this becomes more than x86 specific then use a TargetInfo
- // based mapping.
- // Processor features and mapping to processor feature value.
- enum X86Features {
- CMOV = 0,
- MMX,
- POPCNT,
- SSE,
- SSE2,
- SSE3,
- SSSE3,
- SSE4_1,
- SSE4_2,
- AVX,
- AVX2,
- SSE4_A,
- FMA4,
- XOP,
- FMA,
- AVX512F,
- BMI,
- BMI2,
- AES,
- PCLMUL,
- AVX512VL,
- AVX512BW,
- AVX512DQ,
- AVX512CD,
- AVX512ER,
- AVX512PF,
- AVX512VBMI,
- AVX512IFMA,
- AVX5124VNNIW, // TODO implement this fully
- AVX5124FMAPS, // TODO implement this fully
- AVX512VPOPCNTDQ,
- MAX
- };
-
- X86Features Feature =
- StringSwitch<X86Features>(FeatureStr)
- .Case("cmov", X86Features::CMOV)
- .Case("mmx", X86Features::MMX)
- .Case("popcnt", X86Features::POPCNT)
- .Case("sse", X86Features::SSE)
- .Case("sse2", X86Features::SSE2)
- .Case("sse3", X86Features::SSE3)
- .Case("ssse3", X86Features::SSSE3)
- .Case("sse4.1", X86Features::SSE4_1)
- .Case("sse4.2", X86Features::SSE4_2)
- .Case("avx", X86Features::AVX)
- .Case("avx2", X86Features::AVX2)
- .Case("sse4a", X86Features::SSE4_A)
- .Case("fma4", X86Features::FMA4)
- .Case("xop", X86Features::XOP)
- .Case("fma", X86Features::FMA)
- .Case("avx512f", X86Features::AVX512F)
- .Case("bmi", X86Features::BMI)
- .Case("bmi2", X86Features::BMI2)
- .Case("aes", X86Features::AES)
- .Case("pclmul", X86Features::PCLMUL)
- .Case("avx512vl", X86Features::AVX512VL)
- .Case("avx512bw", X86Features::AVX512BW)
- .Case("avx512dq", X86Features::AVX512DQ)
- .Case("avx512cd", X86Features::AVX512CD)
- .Case("avx512er", X86Features::AVX512ER)
- .Case("avx512pf", X86Features::AVX512PF)
- .Case("avx512vbmi", X86Features::AVX512VBMI)
- .Case("avx512ifma", X86Features::AVX512IFMA)
- .Case("avx512vpopcntdq", X86Features::AVX512VPOPCNTDQ)
- .Default(X86Features::MAX);
- assert(Feature != X86Features::MAX && "Invalid feature!");
-
- // Matching the struct layout from the compiler-rt/libgcc structure that is
- // filled in:
- // unsigned int __cpu_vendor;
- // unsigned int __cpu_type;
- // unsigned int __cpu_subtype;
- // unsigned int __cpu_features[1];
- llvm::Type *STy = llvm::StructType::get(Int32Ty, Int32Ty, Int32Ty,
- llvm::ArrayType::get(Int32Ty, 1));
-
- // Grab the global __cpu_model.
- llvm::Constant *CpuModel = CGM.CreateRuntimeVariable(STy, "__cpu_model");
-
- // Grab the first (0th) element from the field __cpu_features off of the
- // global in the struct STy.
- Value *Idxs[] = {
- ConstantInt::get(Int32Ty, 0),
- ConstantInt::get(Int32Ty, 3),
- ConstantInt::get(Int32Ty, 0)
- };
- Value *CpuFeatures = Builder.CreateGEP(STy, CpuModel, Idxs);
- Value *Features = Builder.CreateAlignedLoad(CpuFeatures,
- CharUnits::fromQuantity(4));
-
- // Check the value of the bit corresponding to the feature requested.
- Value *Bitset = Builder.CreateAnd(
- Features, llvm::ConstantInt::get(Int32Ty, 1ULL << Feature));
- return Builder.CreateICmpNE(Bitset, llvm::ConstantInt::get(Int32Ty, 0));
- }
case X86::BI_mm_prefetch: {
Value *Address = Ops[0];
Value *RW = ConstantInt::get(Int32Ty, 0);
@@ -7526,6 +7968,10 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
case X86::BI__builtin_ia32_storesd128_mask: {
return EmitX86MaskedStore(*this, Ops, 16);
}
+ case X86::BI__builtin_ia32_vpopcntd_128:
+ case X86::BI__builtin_ia32_vpopcntq_128:
+ case X86::BI__builtin_ia32_vpopcntd_256:
+ case X86::BI__builtin_ia32_vpopcntq_256:
case X86::BI__builtin_ia32_vpopcntd_512:
case X86::BI__builtin_ia32_vpopcntq_512: {
llvm::Type *ResultType = ConvertType(E->getType());
@@ -7669,6 +8115,45 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
return EmitX86Select(*this, Ops[4], Align, Ops[3]);
}
+ case X86::BI__builtin_ia32_vperm2f128_pd256:
+ case X86::BI__builtin_ia32_vperm2f128_ps256:
+ case X86::BI__builtin_ia32_vperm2f128_si256:
+ case X86::BI__builtin_ia32_permti256: {
+ unsigned Imm = cast<llvm::ConstantInt>(Ops[2])->getZExtValue();
+ unsigned NumElts = Ops[0]->getType()->getVectorNumElements();
+
+ // This takes a very simple approach since there are two lanes and a
+ // shuffle can have 2 inputs. So we reserve the first input for the first
+ // lane and the second input for the second lane. This may result in
+ // duplicate sources, but this can be dealt with in the backend.
+
+ Value *OutOps[2];
+ uint32_t Indices[8];
+ for (unsigned l = 0; l != 2; ++l) {
+ // Determine the source for this lane.
+ if (Imm & (1 << ((l * 4) + 3)))
+ OutOps[l] = llvm::ConstantAggregateZero::get(Ops[0]->getType());
+ else if (Imm & (1 << ((l * 4) + 1)))
+ OutOps[l] = Ops[1];
+ else
+ OutOps[l] = Ops[0];
+
+ for (unsigned i = 0; i != NumElts/2; ++i) {
+ // Start with ith element of the source for this lane.
+ unsigned Idx = (l * NumElts) + i;
+ // If bit 0 of the immediate half is set, switch to the high half of
+ // the source.
+ if (Imm & (1 << (l * 4)))
+ Idx += NumElts/2;
+ Indices[(l * (NumElts/2)) + i] = Idx;
+ }
+ }
+
+ return Builder.CreateShuffleVector(OutOps[0], OutOps[1],
+ makeArrayRef(Indices, NumElts),
+ "vperm");
+ }
+
case X86::BI__builtin_ia32_movnti:
case X86::BI__builtin_ia32_movnti64:
case X86::BI__builtin_ia32_movntsd:
@@ -7714,32 +8199,6 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
case X86::BI__builtin_ia32_selectpd_256:
case X86::BI__builtin_ia32_selectpd_512:
return EmitX86Select(*this, Ops[0], Ops[1], Ops[2]);
- case X86::BI__builtin_ia32_pcmpeqb128_mask:
- case X86::BI__builtin_ia32_pcmpeqb256_mask:
- case X86::BI__builtin_ia32_pcmpeqb512_mask:
- case X86::BI__builtin_ia32_pcmpeqw128_mask:
- case X86::BI__builtin_ia32_pcmpeqw256_mask:
- case X86::BI__builtin_ia32_pcmpeqw512_mask:
- case X86::BI__builtin_ia32_pcmpeqd128_mask:
- case X86::BI__builtin_ia32_pcmpeqd256_mask:
- case X86::BI__builtin_ia32_pcmpeqd512_mask:
- case X86::BI__builtin_ia32_pcmpeqq128_mask:
- case X86::BI__builtin_ia32_pcmpeqq256_mask:
- case X86::BI__builtin_ia32_pcmpeqq512_mask:
- return EmitX86MaskedCompare(*this, 0, false, Ops);
- case X86::BI__builtin_ia32_pcmpgtb128_mask:
- case X86::BI__builtin_ia32_pcmpgtb256_mask:
- case X86::BI__builtin_ia32_pcmpgtb512_mask:
- case X86::BI__builtin_ia32_pcmpgtw128_mask:
- case X86::BI__builtin_ia32_pcmpgtw256_mask:
- case X86::BI__builtin_ia32_pcmpgtw512_mask:
- case X86::BI__builtin_ia32_pcmpgtd128_mask:
- case X86::BI__builtin_ia32_pcmpgtd256_mask:
- case X86::BI__builtin_ia32_pcmpgtd512_mask:
- case X86::BI__builtin_ia32_pcmpgtq128_mask:
- case X86::BI__builtin_ia32_pcmpgtq256_mask:
- case X86::BI__builtin_ia32_pcmpgtq512_mask:
- return EmitX86MaskedCompare(*this, 6, true, Ops);
case X86::BI__builtin_ia32_cmpb128_mask:
case X86::BI__builtin_ia32_cmpb256_mask:
case X86::BI__builtin_ia32_cmpb512_mask:
@@ -7771,6 +8230,22 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
return EmitX86MaskedCompare(*this, CC, false, Ops);
}
+ case X86::BI__builtin_ia32_kandhi:
+ return EmitX86MaskLogic(*this, Instruction::And, 16, Ops);
+ case X86::BI__builtin_ia32_kandnhi:
+ return EmitX86MaskLogic(*this, Instruction::And, 16, Ops, true);
+ case X86::BI__builtin_ia32_korhi:
+ return EmitX86MaskLogic(*this, Instruction::Or, 16, Ops);
+ case X86::BI__builtin_ia32_kxnorhi:
+ return EmitX86MaskLogic(*this, Instruction::Xor, 16, Ops, true);
+ case X86::BI__builtin_ia32_kxorhi:
+ return EmitX86MaskLogic(*this, Instruction::Xor, 16, Ops);
+ case X86::BI__builtin_ia32_knothi: {
+ Ops[0] = getMaskVecValue(*this, Ops[0], 16);
+ return Builder.CreateBitCast(Builder.CreateNot(Ops[0]),
+ Builder.getInt16Ty());
+ }
+
case X86::BI__builtin_ia32_vplzcntd_128_mask:
case X86::BI__builtin_ia32_vplzcntd_256_mask:
case X86::BI__builtin_ia32_vplzcntd_512_mask:
@@ -7783,6 +8258,20 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
Ops[1]);
}
+ case X86::BI__builtin_ia32_pabsb128:
+ case X86::BI__builtin_ia32_pabsw128:
+ case X86::BI__builtin_ia32_pabsd128:
+ case X86::BI__builtin_ia32_pabsb256:
+ case X86::BI__builtin_ia32_pabsw256:
+ case X86::BI__builtin_ia32_pabsd256:
+ case X86::BI__builtin_ia32_pabsq128_mask:
+ case X86::BI__builtin_ia32_pabsq256_mask:
+ case X86::BI__builtin_ia32_pabsb512_mask:
+ case X86::BI__builtin_ia32_pabsw512_mask:
+ case X86::BI__builtin_ia32_pabsd512_mask:
+ case X86::BI__builtin_ia32_pabsq512_mask:
+ return EmitX86Abs(*this, Ops);
+
case X86::BI__builtin_ia32_pmaxsb128:
case X86::BI__builtin_ia32_pmaxsw128:
case X86::BI__builtin_ia32_pmaxsd128:
@@ -8071,6 +8560,45 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement, E);
case X86::BI_InterlockedIncrement64:
return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement, E);
+ case X86::BI_InterlockedCompareExchange128: {
+ // InterlockedCompareExchange128 doesn't directly refer to 128bit ints,
+ // instead it takes pointers to 64bit ints for Destination and
+ // ComparandResult, and exchange is taken as two 64bit ints (high & low).
+ // The previous value is written to ComparandResult, and success is
+ // returned.
+
+ llvm::Type *Int128Ty = Builder.getInt128Ty();
+ llvm::Type *Int128PtrTy = Int128Ty->getPointerTo();
+
+ Value *Destination =
+ Builder.CreateBitCast(EmitScalarExpr(E->getArg(0)), Int128PtrTy);
+ Value *ExchangeHigh128 =
+ Builder.CreateZExt(EmitScalarExpr(E->getArg(1)), Int128Ty);
+ Value *ExchangeLow128 =
+ Builder.CreateZExt(EmitScalarExpr(E->getArg(2)), Int128Ty);
+ Address ComparandResult(
+ Builder.CreateBitCast(EmitScalarExpr(E->getArg(3)), Int128PtrTy),
+ getContext().toCharUnitsFromBits(128));
+
+ Value *Exchange = Builder.CreateOr(
+ Builder.CreateShl(ExchangeHigh128, 64, "", false, false),
+ ExchangeLow128);
+
+ Value *Comparand = Builder.CreateLoad(ComparandResult);
+
+ AtomicCmpXchgInst *CXI =
+ Builder.CreateAtomicCmpXchg(Destination, Comparand, Exchange,
+ AtomicOrdering::SequentiallyConsistent,
+ AtomicOrdering::SequentiallyConsistent);
+ CXI->setVolatile(true);
+
+ // Write the result back to the inout pointer.
+ Builder.CreateStore(Builder.CreateExtractValue(CXI, 0), ComparandResult);
+
+ // Get the success boolean and zero extend it to i8.
+ Value *Success = Builder.CreateExtractValue(CXI, 1);
+ return Builder.CreateZExt(Success, ConvertType(E->getType()));
+ }
case X86::BI_AddressOfReturnAddress: {
Value *F = CGM.getIntrinsic(Intrinsic::addressofreturnaddress);
@@ -8680,6 +9208,15 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID,
CI->setConvergent();
return CI;
}
+ case AMDGPU::BI__builtin_amdgcn_read_exec_lo:
+ case AMDGPU::BI__builtin_amdgcn_read_exec_hi: {
+ StringRef RegName = BuiltinID == AMDGPU::BI__builtin_amdgcn_read_exec_lo ?
+ "exec_lo" : "exec_hi";
+ CallInst *CI = cast<CallInst>(
+ EmitSpecialRegisterBuiltin(*this, E, Int32Ty, Int32Ty, true, RegName));
+ CI->setConvergent();
+ return CI;
+ }
// amdgcn workitem
case AMDGPU::BI__builtin_amdgcn_workitem_id_x:
@@ -9129,6 +9666,16 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID,
return Builder.CreateCall(FnALAF32, {Ptr, Val});
}
+ case NVPTX::BI__nvvm_atom_add_gen_d: {
+ Value *Ptr = EmitScalarExpr(E->getArg(0));
+ Value *Val = EmitScalarExpr(E->getArg(1));
+ // atomicrmw only deals with integer arguments, so we need to use
+ // LLVM's nvvm_atomic_load_add_f64 intrinsic.
+ Value *FnALAF64 =
+ CGM.getIntrinsic(Intrinsic::nvvm_atomic_load_add_f64, Ptr->getType());
+ return Builder.CreateCall(FnALAF64, {Ptr, Val});
+ }
+
case NVPTX::BI__nvvm_atom_inc_gen_ui: {
Value *Ptr = EmitScalarExpr(E->getArg(0));
Value *Val = EmitScalarExpr(E->getArg(1));
@@ -9282,6 +9829,219 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID,
{Ptr->getType()->getPointerElementType(), Ptr->getType()}),
{Ptr, EmitScalarExpr(E->getArg(1)), EmitScalarExpr(E->getArg(2))});
}
+ case NVPTX::BI__nvvm_match_all_sync_i32p:
+ case NVPTX::BI__nvvm_match_all_sync_i64p: {
+ Value *Mask = EmitScalarExpr(E->getArg(0));
+ Value *Val = EmitScalarExpr(E->getArg(1));
+ Address PredOutPtr = EmitPointerWithAlignment(E->getArg(2));
+ Value *ResultPair = Builder.CreateCall(
+ CGM.getIntrinsic(BuiltinID == NVPTX::BI__nvvm_match_all_sync_i32p
+ ? Intrinsic::nvvm_match_all_sync_i32p
+ : Intrinsic::nvvm_match_all_sync_i64p),
+ {Mask, Val});
+ Value *Pred = Builder.CreateZExt(Builder.CreateExtractValue(ResultPair, 1),
+ PredOutPtr.getElementType());
+ Builder.CreateStore(Pred, PredOutPtr);
+ return Builder.CreateExtractValue(ResultPair, 0);
+ }
+ case NVPTX::BI__hmma_m16n16k16_ld_a:
+ case NVPTX::BI__hmma_m16n16k16_ld_b:
+ case NVPTX::BI__hmma_m16n16k16_ld_c_f16:
+ case NVPTX::BI__hmma_m16n16k16_ld_c_f32: {
+ Address Dst = EmitPointerWithAlignment(E->getArg(0));
+ Value *Src = EmitScalarExpr(E->getArg(1));
+ Value *Ldm = EmitScalarExpr(E->getArg(2));
+ llvm::APSInt isColMajorArg;
+ if (!E->getArg(3)->isIntegerConstantExpr(isColMajorArg, getContext()))
+ return nullptr;
+ bool isColMajor = isColMajorArg.getSExtValue();
+ unsigned IID;
+ unsigned NumResults;
+ switch (BuiltinID) {
+ case NVPTX::BI__hmma_m16n16k16_ld_a:
+ IID = isColMajor ? Intrinsic::nvvm_wmma_load_a_f16_col_stride
+ : Intrinsic::nvvm_wmma_load_a_f16_row_stride;
+ NumResults = 8;
+ break;
+ case NVPTX::BI__hmma_m16n16k16_ld_b:
+ IID = isColMajor ? Intrinsic::nvvm_wmma_load_b_f16_col_stride
+ : Intrinsic::nvvm_wmma_load_b_f16_row_stride;
+ NumResults = 8;
+ break;
+ case NVPTX::BI__hmma_m16n16k16_ld_c_f16:
+ IID = isColMajor ? Intrinsic::nvvm_wmma_load_c_f16_col_stride
+ : Intrinsic::nvvm_wmma_load_c_f16_row_stride;
+ NumResults = 4;
+ break;
+ case NVPTX::BI__hmma_m16n16k16_ld_c_f32:
+ IID = isColMajor ? Intrinsic::nvvm_wmma_load_c_f32_col_stride
+ : Intrinsic::nvvm_wmma_load_c_f32_row_stride;
+ NumResults = 8;
+ break;
+ default:
+ llvm_unreachable("Unexpected builtin ID.");
+ }
+ Value *Result =
+ Builder.CreateCall(CGM.getIntrinsic(IID),
+ {Builder.CreatePointerCast(Src, VoidPtrTy), Ldm});
+
+ // Save returned values.
+ for (unsigned i = 0; i < NumResults; ++i) {
+ Builder.CreateAlignedStore(
+ Builder.CreateBitCast(Builder.CreateExtractValue(Result, i),
+ Dst.getElementType()),
+ Builder.CreateGEP(Dst.getPointer(), llvm::ConstantInt::get(IntTy, i)),
+ CharUnits::fromQuantity(4));
+ }
+ return Result;
+ }
+
+ case NVPTX::BI__hmma_m16n16k16_st_c_f16:
+ case NVPTX::BI__hmma_m16n16k16_st_c_f32: {
+ Value *Dst = EmitScalarExpr(E->getArg(0));
+ Address Src = EmitPointerWithAlignment(E->getArg(1));
+ Value *Ldm = EmitScalarExpr(E->getArg(2));
+ llvm::APSInt isColMajorArg;
+ if (!E->getArg(3)->isIntegerConstantExpr(isColMajorArg, getContext()))
+ return nullptr;
+ bool isColMajor = isColMajorArg.getSExtValue();
+ unsigned IID;
+ unsigned NumResults = 8;
+ // PTX Instructions (and LLVM instrinsics) are defined for slice _d_, yet
+ // for some reason nvcc builtins use _c_.
+ switch (BuiltinID) {
+ case NVPTX::BI__hmma_m16n16k16_st_c_f16:
+ IID = isColMajor ? Intrinsic::nvvm_wmma_store_d_f16_col_stride
+ : Intrinsic::nvvm_wmma_store_d_f16_row_stride;
+ NumResults = 4;
+ break;
+ case NVPTX::BI__hmma_m16n16k16_st_c_f32:
+ IID = isColMajor ? Intrinsic::nvvm_wmma_store_d_f32_col_stride
+ : Intrinsic::nvvm_wmma_store_d_f32_row_stride;
+ break;
+ default:
+ llvm_unreachable("Unexpected builtin ID.");
+ }
+ Function *Intrinsic = CGM.getIntrinsic(IID);
+ llvm::Type *ParamType = Intrinsic->getFunctionType()->getParamType(1);
+ SmallVector<Value *, 10> Values;
+ Values.push_back(Builder.CreatePointerCast(Dst, VoidPtrTy));
+ for (unsigned i = 0; i < NumResults; ++i) {
+ Value *V = Builder.CreateAlignedLoad(
+ Builder.CreateGEP(Src.getPointer(), llvm::ConstantInt::get(IntTy, i)),
+ CharUnits::fromQuantity(4));
+ Values.push_back(Builder.CreateBitCast(V, ParamType));
+ }
+ Values.push_back(Ldm);
+ Value *Result = Builder.CreateCall(Intrinsic, Values);
+ return Result;
+ }
+
+ // BI__hmma_m16n16k16_mma_<Dtype><CType>(d, a, b, c, layout, satf)
+ // --> Intrinsic::nvvm_wmma_mma_sync<layout A,B><DType><CType><Satf>
+ case NVPTX::BI__hmma_m16n16k16_mma_f16f16:
+ case NVPTX::BI__hmma_m16n16k16_mma_f32f16:
+ case NVPTX::BI__hmma_m16n16k16_mma_f32f32:
+ case NVPTX::BI__hmma_m16n16k16_mma_f16f32: {
+ Address Dst = EmitPointerWithAlignment(E->getArg(0));
+ Address SrcA = EmitPointerWithAlignment(E->getArg(1));
+ Address SrcB = EmitPointerWithAlignment(E->getArg(2));
+ Address SrcC = EmitPointerWithAlignment(E->getArg(3));
+ llvm::APSInt LayoutArg;
+ if (!E->getArg(4)->isIntegerConstantExpr(LayoutArg, getContext()))
+ return nullptr;
+ int Layout = LayoutArg.getSExtValue();
+ if (Layout < 0 || Layout > 3)
+ return nullptr;
+ llvm::APSInt SatfArg;
+ if (!E->getArg(5)->isIntegerConstantExpr(SatfArg, getContext()))
+ return nullptr;
+ bool Satf = SatfArg.getSExtValue();
+
+ // clang-format off
+#define MMA_VARIANTS(type) {{ \
+ Intrinsic::nvvm_wmma_mma_sync_row_row_##type, \
+ Intrinsic::nvvm_wmma_mma_sync_row_row_##type##_satfinite, \
+ Intrinsic::nvvm_wmma_mma_sync_row_col_##type, \
+ Intrinsic::nvvm_wmma_mma_sync_row_col_##type##_satfinite, \
+ Intrinsic::nvvm_wmma_mma_sync_col_row_##type, \
+ Intrinsic::nvvm_wmma_mma_sync_col_row_##type##_satfinite, \
+ Intrinsic::nvvm_wmma_mma_sync_col_col_##type, \
+ Intrinsic::nvvm_wmma_mma_sync_col_col_##type##_satfinite \
+ }}
+ // clang-format on
+
+ auto getMMAIntrinsic = [Layout, Satf](std::array<unsigned, 8> Variants) {
+ unsigned Index = Layout * 2 + Satf;
+ assert(Index < 8);
+ return Variants[Index];
+ };
+ unsigned IID;
+ unsigned NumEltsC;
+ unsigned NumEltsD;
+ switch (BuiltinID) {
+ case NVPTX::BI__hmma_m16n16k16_mma_f16f16:
+ IID = getMMAIntrinsic(MMA_VARIANTS(f16_f16));
+ NumEltsC = 4;
+ NumEltsD = 4;
+ break;
+ case NVPTX::BI__hmma_m16n16k16_mma_f32f16:
+ IID = getMMAIntrinsic(MMA_VARIANTS(f32_f16));
+ NumEltsC = 4;
+ NumEltsD = 8;
+ break;
+ case NVPTX::BI__hmma_m16n16k16_mma_f16f32:
+ IID = getMMAIntrinsic(MMA_VARIANTS(f16_f32));
+ NumEltsC = 8;
+ NumEltsD = 4;
+ break;
+ case NVPTX::BI__hmma_m16n16k16_mma_f32f32:
+ IID = getMMAIntrinsic(MMA_VARIANTS(f32_f32));
+ NumEltsC = 8;
+ NumEltsD = 8;
+ break;
+ default:
+ llvm_unreachable("Unexpected builtin ID.");
+ }
+#undef MMA_VARIANTS
+
+ SmallVector<Value *, 24> Values;
+ Function *Intrinsic = CGM.getIntrinsic(IID);
+ llvm::Type *ABType = Intrinsic->getFunctionType()->getParamType(0);
+ // Load A
+ for (unsigned i = 0; i < 8; ++i) {
+ Value *V = Builder.CreateAlignedLoad(
+ Builder.CreateGEP(SrcA.getPointer(),
+ llvm::ConstantInt::get(IntTy, i)),
+ CharUnits::fromQuantity(4));
+ Values.push_back(Builder.CreateBitCast(V, ABType));
+ }
+ // Load B
+ for (unsigned i = 0; i < 8; ++i) {
+ Value *V = Builder.CreateAlignedLoad(
+ Builder.CreateGEP(SrcB.getPointer(),
+ llvm::ConstantInt::get(IntTy, i)),
+ CharUnits::fromQuantity(4));
+ Values.push_back(Builder.CreateBitCast(V, ABType));
+ }
+ // Load C
+ llvm::Type *CType = Intrinsic->getFunctionType()->getParamType(16);
+ for (unsigned i = 0; i < NumEltsC; ++i) {
+ Value *V = Builder.CreateAlignedLoad(
+ Builder.CreateGEP(SrcC.getPointer(),
+ llvm::ConstantInt::get(IntTy, i)),
+ CharUnits::fromQuantity(4));
+ Values.push_back(Builder.CreateBitCast(V, CType));
+ }
+ Value *Result = Builder.CreateCall(Intrinsic, Values);
+ llvm::Type *DType = Dst.getElementType();
+ for (unsigned i = 0; i < NumEltsD; ++i)
+ Builder.CreateAlignedStore(
+ Builder.CreateBitCast(Builder.CreateExtractValue(Result, i), DType),
+ Builder.CreateGEP(Dst.getPointer(), llvm::ConstantInt::get(IntTy, i)),
+ CharUnits::fromQuantity(4));
+ return Result;
+ }
default:
return nullptr;
}
@@ -9315,3 +10075,58 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID,
return nullptr;
}
}
+
+Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID,
+ const CallExpr *E) {
+ SmallVector<llvm::Value *, 4> Ops;
+ Intrinsic::ID ID = Intrinsic::not_intrinsic;
+
+ switch (BuiltinID) {
+ case Hexagon::BI__builtin_HEXAGON_V6_vaddcarry:
+ case Hexagon::BI__builtin_HEXAGON_V6_vaddcarry_128B: {
+ Address Dest = EmitPointerWithAlignment(E->getArg(2));
+ unsigned Size;
+ if (BuiltinID == Hexagon::BI__builtin_HEXAGON_V6_vaddcarry) {
+ Size = 512;
+ ID = Intrinsic::hexagon_V6_vaddcarry;
+ } else {
+ Size = 1024;
+ ID = Intrinsic::hexagon_V6_vaddcarry_128B;
+ }
+ Dest = Builder.CreateBitCast(Dest,
+ llvm::VectorType::get(Builder.getInt1Ty(), Size)->getPointerTo(0));
+ LoadInst *QLd = Builder.CreateLoad(Dest);
+ Ops = { EmitScalarExpr(E->getArg(0)), EmitScalarExpr(E->getArg(1)), QLd };
+ llvm::Value *Result = Builder.CreateCall(CGM.getIntrinsic(ID), Ops);
+ llvm::Value *Vprd = Builder.CreateExtractValue(Result, 1);
+ llvm::Value *Base = Builder.CreateBitCast(EmitScalarExpr(E->getArg(2)),
+ Vprd->getType()->getPointerTo(0));
+ Builder.CreateAlignedStore(Vprd, Base, Dest.getAlignment());
+ return Builder.CreateExtractValue(Result, 0);
+ }
+ case Hexagon::BI__builtin_HEXAGON_V6_vsubcarry:
+ case Hexagon::BI__builtin_HEXAGON_V6_vsubcarry_128B: {
+ Address Dest = EmitPointerWithAlignment(E->getArg(2));
+ unsigned Size;
+ if (BuiltinID == Hexagon::BI__builtin_HEXAGON_V6_vsubcarry) {
+ Size = 512;
+ ID = Intrinsic::hexagon_V6_vsubcarry;
+ } else {
+ Size = 1024;
+ ID = Intrinsic::hexagon_V6_vsubcarry_128B;
+ }
+ Dest = Builder.CreateBitCast(Dest,
+ llvm::VectorType::get(Builder.getInt1Ty(), Size)->getPointerTo(0));
+ LoadInst *QLd = Builder.CreateLoad(Dest);
+ Ops = { EmitScalarExpr(E->getArg(0)), EmitScalarExpr(E->getArg(1)), QLd };
+ llvm::Value *Result = Builder.CreateCall(CGM.getIntrinsic(ID), Ops);
+ llvm::Value *Vprd = Builder.CreateExtractValue(Result, 1);
+ llvm::Value *Base = Builder.CreateBitCast(EmitScalarExpr(E->getArg(2)),
+ Vprd->getType()->getPointerTo(0));
+ Builder.CreateAlignedStore(Vprd, Base, Dest.getAlignment());
+ return Builder.CreateExtractValue(Result, 0);
+ }
+ } // switch
+
+ return nullptr;
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCXX.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCXX.cpp
index 0f3141ab76d0d..5ef4dc45fba12 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCXX.cpp
@@ -110,16 +110,14 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
return true;
return TryEmitDefinitionAsAlias(GlobalDecl(D, Dtor_Base),
- GlobalDecl(BaseD, Dtor_Base),
- false);
+ GlobalDecl(BaseD, Dtor_Base));
}
/// Try to emit a definition as a global alias for another definition.
/// If \p InEveryTU is true, we know that an equivalent alias can be produced
/// in every translation unit.
bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
- GlobalDecl TargetDecl,
- bool InEveryTU) {
+ GlobalDecl TargetDecl) {
if (!getCodeGenOpts().CXXCtorDtorAliases)
return true;
@@ -134,11 +132,6 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
llvm::GlobalValue::LinkageTypes TargetLinkage =
getFunctionLinkage(TargetDecl);
- // available_externally definitions aren't real definitions, so we cannot
- // create an alias to one.
- if (TargetLinkage == llvm::GlobalValue::AvailableExternallyLinkage)
- return true;
-
// Check if we have it already.
StringRef MangledName = getMangledName(AliasDecl);
llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
@@ -161,7 +154,14 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
// Instead of creating as alias to a linkonce_odr, replace all of the uses
// of the aliasee.
- if (llvm::GlobalValue::isDiscardableIfUnused(Linkage)) {
+ if (llvm::GlobalValue::isDiscardableIfUnused(Linkage) &&
+ !(TargetLinkage == llvm::GlobalValue::AvailableExternallyLinkage &&
+ TargetDecl.getDecl()->hasAttr<AlwaysInlineAttr>())) {
+ // FIXME: An extern template instantiation will create functions with
+ // linkage "AvailableExternally". In libc++, some classes also define
+ // members with attribute "AlwaysInline" and expect no reference to
+ // be generated. It is desirable to reenable this optimisation after
+ // corresponding LLVM changes.
addReplacement(MangledName, Aliasee);
return false;
}
@@ -176,13 +176,11 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
return true;
}
- if (!InEveryTU) {
- // If we don't have a definition for the destructor yet, don't
- // emit. We can't emit aliases to declarations; that's just not
- // how aliases work.
- if (Ref->isDeclaration())
- return true;
- }
+ // If we don't have a definition for the destructor yet or the definition is
+ // avaialable_externally, don't emit an alias. We can't emit aliases to
+ // declarations; that's just not how aliases work.
+ if (Ref->isDeclarationForLinker())
+ return true;
// Don't create an alias to a linker weak symbol. This avoids producing
// different COMDATs in different TUs. Another option would be to
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp
index 033258643ddf9..a27c3e9d27e39 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp
@@ -149,12 +149,15 @@ void CGCXXABI::buildThisParam(CodeGenFunction &CGF, FunctionArgList &params) {
}
}
-void CGCXXABI::EmitThisParam(CodeGenFunction &CGF) {
+llvm::Value *CGCXXABI::loadIncomingCXXThis(CodeGenFunction &CGF) {
+ return CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getThisDecl(CGF)),
+ "this");
+}
+
+void CGCXXABI::setCXXABIThisValue(CodeGenFunction &CGF, llvm::Value *ThisPtr) {
/// Initialize the 'this' slot.
assert(getThisDecl(CGF) && "no 'this' variable for function");
- CGF.CXXABIThisValue
- = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getThisDecl(CGF)),
- "this");
+ CGF.CXXABIThisValue = ThisPtr;
}
void CGCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.h b/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.h
index 7b912e3aca576..83426dc3a03c7 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.h
@@ -73,9 +73,10 @@ protected:
return CGF.CXXStructorImplicitParamValue;
}
- /// Perform prolog initialization of the parameter variable suitable
- /// for 'this' emitted by buildThisParam.
- void EmitThisParam(CodeGenFunction &CGF);
+ /// Loads the incoming C++ this pointer as it was passed by the caller.
+ llvm::Value *loadIncomingCXXThis(CodeGenFunction &CGF);
+
+ void setCXXABIThisValue(CodeGenFunction &CGF, llvm::Value *ThisPtr);
ASTContext &getContext() const { return CGM.getContext(); }
@@ -358,13 +359,6 @@ public:
return CharUnits::Zero();
}
- /// Perform ABI-specific "this" parameter adjustment in a virtual function
- /// prologue.
- virtual llvm::Value *adjustThisParameterInVirtualFunctionPrologue(
- CodeGenFunction &CGF, GlobalDecl GD, llvm::Value *This) {
- return This;
- }
-
/// Emit the ABI-specific prolog for the function.
virtual void EmitInstanceFunctionProlog(CodeGenFunction &CGF) = 0;
@@ -588,6 +582,13 @@ public:
/// Emit a single constructor/destructor with the given type from a C++
/// constructor Decl.
virtual void emitCXXStructor(const CXXMethodDecl *MD, StructorType Type) = 0;
+
+ /// Load a vtable from This, an object of polymorphic type RD, or from one of
+ /// its virtual bases if it does not have its own vtable. Returns the vtable
+ /// and the class from which the vtable was loaded.
+ virtual std::pair<llvm::Value *, const CXXRecordDecl *>
+ LoadVTablePtr(CodeGenFunction &CGF, Address This,
+ const CXXRecordDecl *RD) = 0;
};
// Create an instance of a C++ ABI class:
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp
index 316bf44cb1c3d..c3709bf2e447e 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp
@@ -455,11 +455,15 @@ const CGFunctionInfo &
CodeGenTypes::arrangeObjCMessageSendSignature(const ObjCMethodDecl *MD,
QualType receiverType) {
SmallVector<CanQualType, 16> argTys;
+ SmallVector<FunctionProtoType::ExtParameterInfo, 4> extParamInfos(2);
argTys.push_back(Context.getCanonicalParamType(receiverType));
argTys.push_back(Context.getCanonicalParamType(Context.getObjCSelType()));
// FIXME: Kill copy?
for (const auto *I : MD->parameters()) {
argTys.push_back(Context.getCanonicalParamType(I->getType()));
+ auto extParamInfo = FunctionProtoType::ExtParameterInfo().withIsNoEscape(
+ I->hasAttr<NoEscapeAttr>());
+ extParamInfos.push_back(extParamInfo);
}
FunctionType::ExtInfo einfo;
@@ -475,7 +479,7 @@ CodeGenTypes::arrangeObjCMessageSendSignature(const ObjCMethodDecl *MD,
return arrangeLLVMFunctionInfo(
GetReturnType(MD->getReturnType()), /*instanceMethod=*/false,
- /*chainCall=*/false, argTys, einfo, {}, required);
+ /*chainCall=*/false, argTys, einfo, extParamInfos, required);
}
const CGFunctionInfo &
@@ -1223,14 +1227,15 @@ static llvm::Value *CreateCoercedLoad(Address Src, llvm::Type *Ty,
//
// FIXME: Assert that we aren't truncating non-padding bits when have access
// to that information.
- Src = CGF.Builder.CreateBitCast(Src, llvm::PointerType::getUnqual(Ty));
+ Src = CGF.Builder.CreateBitCast(Src,
+ Ty->getPointerTo(Src.getAddressSpace()));
return CGF.Builder.CreateLoad(Src);
}
// Otherwise do coercion through memory. This is stupid, but simple.
Address Tmp = CreateTempAllocaForCoercion(CGF, Ty, Src.getAlignment());
- Address Casted = CGF.Builder.CreateBitCast(Tmp, CGF.Int8PtrTy);
- Address SrcCasted = CGF.Builder.CreateBitCast(Src, CGF.Int8PtrTy);
+ Address Casted = CGF.Builder.CreateBitCast(Tmp, CGF.AllocaInt8PtrTy);
+ Address SrcCasted = CGF.Builder.CreateBitCast(Src, CGF.AllocaInt8PtrTy);
CGF.Builder.CreateMemCpy(Casted, SrcCasted,
llvm::ConstantInt::get(CGF.IntPtrTy, SrcSize),
false);
@@ -1311,8 +1316,8 @@ static void CreateCoercedStore(llvm::Value *Src,
// to that information.
Address Tmp = CreateTempAllocaForCoercion(CGF, SrcTy, Dst.getAlignment());
CGF.Builder.CreateStore(Src, Tmp);
- Address Casted = CGF.Builder.CreateBitCast(Tmp, CGF.Int8PtrTy);
- Address DstCasted = CGF.Builder.CreateBitCast(Dst, CGF.Int8PtrTy);
+ Address Casted = CGF.Builder.CreateBitCast(Tmp, CGF.AllocaInt8PtrTy);
+ Address DstCasted = CGF.Builder.CreateBitCast(Dst, CGF.AllocaInt8PtrTy);
CGF.Builder.CreateMemCpy(DstCasted, Casted,
llvm::ConstantInt::get(CGF.IntPtrTy, DstSize),
false);
@@ -1734,10 +1739,15 @@ void CodeGenModule::ConstructDefaultFnAttrList(StringRef Name, bool HasOptnone,
llvm::toStringRef(CodeGenOpts.CorrectlyRoundedDivSqrt));
// TODO: Reciprocal estimate codegen options should apply to instructions?
- std::vector<std::string> &Recips = getTarget().getTargetOpts().Reciprocals;
+ const std::vector<std::string> &Recips = CodeGenOpts.Reciprocals;
if (!Recips.empty())
FuncAttrs.addAttribute("reciprocal-estimates",
- llvm::join(Recips.begin(), Recips.end(), ","));
+ llvm::join(Recips, ","));
+
+ if (!CodeGenOpts.PreferVectorWidth.empty() &&
+ CodeGenOpts.PreferVectorWidth != "none")
+ FuncAttrs.addAttribute("prefer-vector-width",
+ CodeGenOpts.PreferVectorWidth);
if (CodeGenOpts.StackRealignment)
FuncAttrs.addAttribute("stackrealign");
@@ -1745,13 +1755,16 @@ void CodeGenModule::ConstructDefaultFnAttrList(StringRef Name, bool HasOptnone,
FuncAttrs.addAttribute("backchain");
}
- if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice) {
- // Conservatively, mark all functions and calls in CUDA as convergent
- // (meaning, they may call an intrinsically convergent op, such as
- // __syncthreads(), and so can't have certain optimizations applied around
- // them). LLVM will remove this attribute where it safely can.
+ if (getLangOpts().assumeFunctionsAreConvergent()) {
+ // Conservatively, mark all functions and calls in CUDA and OpenCL as
+ // convergent (meaning, they may call an intrinsically convergent op, such
+ // as __syncthreads() / barrier(), and so can't have certain optimizations
+ // applied around them). LLVM will remove this attribute where it safely
+ // can.
FuncAttrs.addAttribute(llvm::Attribute::Convergent);
+ }
+ if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice) {
// Exceptions aren't supported in CUDA device code.
FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
@@ -1847,6 +1860,16 @@ void CodeGenModule::ConstructAttributeList(
!(TargetDecl && TargetDecl->hasAttr<NoSplitStackAttr>()))
FuncAttrs.addAttribute("split-stack");
+ // Add NonLazyBind attribute to function declarations when -fno-plt
+ // is used.
+ if (TargetDecl && CodeGenOpts.NoPLT) {
+ if (auto *Fn = dyn_cast<FunctionDecl>(TargetDecl)) {
+ if (!Fn->isDefined() && !AttrOnCallSite) {
+ FuncAttrs.addAttribute(llvm::Attribute::NonLazyBind);
+ }
+ }
+ }
+
if (!AttrOnCallSite) {
bool DisableTailCalls =
CodeGenOpts.DisableTailCalls ||
@@ -1859,13 +1882,13 @@ void CodeGenModule::ConstructAttributeList(
// we have a decl for the function and it has a target attribute then
// parse that and add it to the feature set.
StringRef TargetCPU = getTarget().getTargetOpts().CPU;
+ std::vector<std::string> Features;
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl);
if (FD && FD->hasAttr<TargetAttr>()) {
llvm::StringMap<bool> FeatureMap;
getFunctionFeatureMap(FeatureMap, FD);
// Produce the canonical string for this set of features.
- std::vector<std::string> Features;
for (llvm::StringMap<bool>::const_iterator it = FeatureMap.begin(),
ie = FeatureMap.end();
it != ie; ++it)
@@ -1877,28 +1900,22 @@ void CodeGenModule::ConstructAttributeList(
// the function.
const auto *TD = FD->getAttr<TargetAttr>();
TargetAttr::ParsedTargetAttr ParsedAttr = TD->parse();
- if (ParsedAttr.Architecture != "")
+ if (ParsedAttr.Architecture != "" &&
+ getTarget().isValidCPUName(ParsedAttr.Architecture))
TargetCPU = ParsedAttr.Architecture;
- if (TargetCPU != "")
- FuncAttrs.addAttribute("target-cpu", TargetCPU);
- if (!Features.empty()) {
- std::sort(Features.begin(), Features.end());
- FuncAttrs.addAttribute(
- "target-features",
- llvm::join(Features.begin(), Features.end(), ","));
- }
} else {
// Otherwise just add the existing target cpu and target features to the
// function.
- std::vector<std::string> &Features = getTarget().getTargetOpts().Features;
- if (TargetCPU != "")
- FuncAttrs.addAttribute("target-cpu", TargetCPU);
- if (!Features.empty()) {
- std::sort(Features.begin(), Features.end());
- FuncAttrs.addAttribute(
- "target-features",
- llvm::join(Features.begin(), Features.end(), ","));
- }
+ Features = getTarget().getTargetOpts().Features;
+ }
+
+ if (TargetCPU != "")
+ FuncAttrs.addAttribute("target-cpu", TargetCPU);
+ if (!Features.empty()) {
+ std::sort(Features.begin(), Features.end());
+ FuncAttrs.addAttribute(
+ "target-features",
+ llvm::join(Features, ","));
}
}
@@ -2092,6 +2109,9 @@ void CodeGenModule::ConstructAttributeList(
break;
}
+ if (FI.getExtParameterInfo(ArgNo).isNoEscape())
+ Attrs.addAttribute(llvm::Attribute::NoCapture);
+
if (Attrs.hasAttributes()) {
unsigned FirstIRArg, NumIRArgs;
std::tie(FirstIRArg, NumIRArgs) = IRFunctionArgs.getIRArgs(ArgNo);
@@ -3054,7 +3074,8 @@ static void emitWriteback(CodeGenFunction &CGF,
// If the argument wasn't provably non-null, we need to null check
// before doing the store.
- bool provablyNonNull = llvm::isKnownNonNull(srcAddr.getPointer());
+ bool provablyNonNull = llvm::isKnownNonZero(srcAddr.getPointer(),
+ CGF.CGM.getDataLayout());
if (!provablyNonNull) {
llvm::BasicBlock *writebackBB = CGF.createBasicBlock("icr.writeback");
contBB = CGF.createBasicBlock("icr.done");
@@ -3194,7 +3215,8 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args,
// If the address is *not* known to be non-null, we need to switch.
llvm::Value *finalArgument;
- bool provablyNonNull = llvm::isKnownNonNull(srcAddr.getPointer());
+ bool provablyNonNull = llvm::isKnownNonZero(srcAddr.getPointer(),
+ CGF.CGM.getDataLayout());
if (provablyNonNull) {
finalArgument = temp.getPointer();
} else {
@@ -3946,7 +3968,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
Builder.CreateMemCpy(TempAlloca, Src, SrcSize);
Src = TempAlloca;
} else {
- Src = Builder.CreateBitCast(Src, llvm::PointerType::getUnqual(STy));
+ Src = Builder.CreateBitCast(Src,
+ STy->getPointerTo(Src.getAddressSpace()));
}
auto SrcLayout = CGM.getDataLayout().getStructLayout(STy);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp
index 50d702c622688..a6915071ec174 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp
@@ -129,14 +129,16 @@ Address
CodeGenFunction::EmitCXXMemberDataPointerAddress(const Expr *E, Address base,
llvm::Value *memberPtr,
const MemberPointerType *memberPtrType,
- LValueBaseInfo *BaseInfo) {
+ LValueBaseInfo *BaseInfo,
+ TBAAAccessInfo *TBAAInfo) {
// Ask the ABI to compute the actual address.
llvm::Value *ptr =
CGM.getCXXABI().EmitMemberDataPointerAddress(*this, E, base,
memberPtr, memberPtrType);
QualType memberType = memberPtrType->getPointeeType();
- CharUnits memberAlign = getNaturalTypeAlignment(memberType, BaseInfo);
+ CharUnits memberAlign = getNaturalTypeAlignment(memberType, BaseInfo,
+ TBAAInfo);
memberAlign =
CGM.getDynamicOffsetAlignment(base.getAlignment(),
memberPtrType->getClass()->getAsCXXRecordDecl(),
@@ -1413,10 +1415,11 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
// possible to delegate the destructor body to the complete
// destructor. Do so.
if (DtorType == Dtor_Deleting) {
+ RunCleanupsScope DtorEpilogue(*this);
EnterDtorCleanups(Dtor, Dtor_Deleting);
- EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false,
- /*Delegating=*/false, LoadCXXThisAddress());
- PopCleanupBlock();
+ if (HaveInsertPoint())
+ EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false,
+ /*Delegating=*/false, LoadCXXThisAddress());
return;
}
@@ -1512,6 +1515,13 @@ void CodeGenFunction::emitImplicitAssignmentOperatorBody(FunctionArgList &Args)
}
namespace {
+ llvm::Value *LoadThisForDtorDelete(CodeGenFunction &CGF,
+ const CXXDestructorDecl *DD) {
+ if (Expr *ThisArg = DD->getOperatorDeleteThisArg())
+ return CGF.EmitScalarExpr(ThisArg);
+ return CGF.LoadCXXThis();
+ }
+
/// Call the operator delete associated with the current destructor.
struct CallDtorDelete final : EHScopeStack::Cleanup {
CallDtorDelete() {}
@@ -1519,11 +1529,38 @@ namespace {
void Emit(CodeGenFunction &CGF, Flags flags) override {
const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl);
const CXXRecordDecl *ClassDecl = Dtor->getParent();
- CGF.EmitDeleteCall(Dtor->getOperatorDelete(), CGF.LoadCXXThis(),
+ CGF.EmitDeleteCall(Dtor->getOperatorDelete(),
+ LoadThisForDtorDelete(CGF, Dtor),
CGF.getContext().getTagDeclType(ClassDecl));
}
};
+ void EmitConditionalDtorDeleteCall(CodeGenFunction &CGF,
+ llvm::Value *ShouldDeleteCondition,
+ bool ReturnAfterDelete) {
+ llvm::BasicBlock *callDeleteBB = CGF.createBasicBlock("dtor.call_delete");
+ llvm::BasicBlock *continueBB = CGF.createBasicBlock("dtor.continue");
+ llvm::Value *ShouldCallDelete
+ = CGF.Builder.CreateIsNull(ShouldDeleteCondition);
+ CGF.Builder.CreateCondBr(ShouldCallDelete, continueBB, callDeleteBB);
+
+ CGF.EmitBlock(callDeleteBB);
+ const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl);
+ const CXXRecordDecl *ClassDecl = Dtor->getParent();
+ CGF.EmitDeleteCall(Dtor->getOperatorDelete(),
+ LoadThisForDtorDelete(CGF, Dtor),
+ CGF.getContext().getTagDeclType(ClassDecl));
+ assert(Dtor->getOperatorDelete()->isDestroyingOperatorDelete() ==
+ ReturnAfterDelete &&
+ "unexpected value for ReturnAfterDelete");
+ if (ReturnAfterDelete)
+ CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
+ else
+ CGF.Builder.CreateBr(continueBB);
+
+ CGF.EmitBlock(continueBB);
+ }
+
struct CallDtorDeleteConditional final : EHScopeStack::Cleanup {
llvm::Value *ShouldDeleteCondition;
@@ -1534,20 +1571,8 @@ namespace {
}
void Emit(CodeGenFunction &CGF, Flags flags) override {
- llvm::BasicBlock *callDeleteBB = CGF.createBasicBlock("dtor.call_delete");
- llvm::BasicBlock *continueBB = CGF.createBasicBlock("dtor.continue");
- llvm::Value *ShouldCallDelete
- = CGF.Builder.CreateIsNull(ShouldDeleteCondition);
- CGF.Builder.CreateCondBr(ShouldCallDelete, continueBB, callDeleteBB);
-
- CGF.EmitBlock(callDeleteBB);
- const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl);
- const CXXRecordDecl *ClassDecl = Dtor->getParent();
- CGF.EmitDeleteCall(Dtor->getOperatorDelete(), CGF.LoadCXXThis(),
- CGF.getContext().getTagDeclType(ClassDecl));
- CGF.Builder.CreateBr(continueBB);
-
- CGF.EmitBlock(continueBB);
+ EmitConditionalDtorDeleteCall(CGF, ShouldDeleteCondition,
+ /*ReturnAfterDelete*/false);
}
};
@@ -1577,6 +1602,7 @@ namespace {
static void EmitSanitizerDtorCallback(CodeGenFunction &CGF, llvm::Value *Ptr,
CharUnits::QuantityType PoisonSize) {
+ CodeGenFunction::SanitizerScope SanScope(&CGF);
// Pass in void pointer and size of region as arguments to runtime
// function
llvm::Value *Args[] = {CGF.Builder.CreateBitCast(Ptr, CGF.VoidPtrTy),
@@ -1705,6 +1731,9 @@ namespace {
/// \brief Emit all code that comes at the end of class's
/// destructor. This is to call destructors on members and base classes
/// in reverse order of their construction.
+///
+/// For a deleting destructor, this also handles the case where a destroying
+/// operator delete completely overrides the definition.
void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD,
CXXDtorType DtorType) {
assert((!DD->isTrivial() || DD->hasAttr<DLLExportAttr>()) &&
@@ -1717,11 +1746,23 @@ void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD,
"operator delete missing - EnterDtorCleanups");
if (CXXStructorImplicitParamValue) {
// If there is an implicit param to the deleting dtor, it's a boolean
- // telling whether we should call delete at the end of the dtor.
- EHStack.pushCleanup<CallDtorDeleteConditional>(
- NormalAndEHCleanup, CXXStructorImplicitParamValue);
+ // telling whether this is a deleting destructor.
+ if (DD->getOperatorDelete()->isDestroyingOperatorDelete())
+ EmitConditionalDtorDeleteCall(*this, CXXStructorImplicitParamValue,
+ /*ReturnAfterDelete*/true);
+ else
+ EHStack.pushCleanup<CallDtorDeleteConditional>(
+ NormalAndEHCleanup, CXXStructorImplicitParamValue);
} else {
- EHStack.pushCleanup<CallDtorDelete>(NormalAndEHCleanup);
+ if (DD->getOperatorDelete()->isDestroyingOperatorDelete()) {
+ const CXXRecordDecl *ClassDecl = DD->getParent();
+ EmitDeleteCall(DD->getOperatorDelete(),
+ LoadThisForDtorDelete(*this, DD),
+ getContext().getTagDeclType(ClassDecl));
+ EmitBranchThroughCleanup(ReturnBlock);
+ } else {
+ EHStack.pushCleanup<CallDtorDelete>(NormalAndEHCleanup);
+ }
}
return;
}
@@ -2382,7 +2423,8 @@ void CodeGenFunction::InitializeVTablePointer(const VPtr &Vptr) {
VTableAddressPoint = Builder.CreateBitCast(VTableAddressPoint, VTablePtrTy);
llvm::StoreInst *Store = Builder.CreateStore(VTableAddressPoint, VTableField);
- CGM.DecorateInstructionWithTBAA(Store, CGM.getTBAAInfoForVTablePtr());
+ TBAAAccessInfo TBAAInfo = CGM.getTBAAVTablePtrAccessInfo(VTablePtrTy);
+ CGM.DecorateInstructionWithTBAA(Store, TBAAInfo);
if (CGM.getCodeGenOpts().OptimizationLevel > 0 &&
CGM.getCodeGenOpts().StrictVTablePointers)
CGM.DecorateInstructionWithInvariantGroup(Store, Vptr.VTableClass);
@@ -2476,7 +2518,8 @@ llvm::Value *CodeGenFunction::GetVTablePtr(Address This,
const CXXRecordDecl *RD) {
Address VTablePtrSrc = Builder.CreateElementBitCast(This, VTableTy);
llvm::Instruction *VTable = Builder.CreateLoad(VTablePtrSrc, "vtable");
- CGM.DecorateInstructionWithTBAA(VTable, CGM.getTBAAInfoForVTablePtr());
+ TBAAAccessInfo TBAAInfo = CGM.getTBAAVTablePtrAccessInfo(VTableTy);
+ CGM.DecorateInstructionWithTBAA(VTable, TBAAInfo);
if (CGM.getCodeGenOpts().OptimizationLevel > 0 &&
CGM.getCodeGenOpts().StrictVTablePointers)
@@ -2523,8 +2566,10 @@ LeastDerivedClassWithSameLayout(const CXXRecordDecl *RD) {
void CodeGenFunction::EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD,
llvm::Value *VTable,
SourceLocation Loc) {
- if (CGM.getCodeGenOpts().WholeProgramVTables &&
- CGM.HasHiddenLTOVisibility(RD)) {
+ if (SanOpts.has(SanitizerKind::CFIVCall))
+ EmitVTablePtrCheckForCall(RD, VTable, CodeGenFunction::CFITCK_VCall, Loc);
+ else if (CGM.getCodeGenOpts().WholeProgramVTables &&
+ CGM.HasHiddenLTOVisibility(RD)) {
llvm::Metadata *MD =
CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0));
llvm::Value *TypeId =
@@ -2536,9 +2581,6 @@ void CodeGenFunction::EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD,
{CastedVTable, TypeId});
Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::assume), TypeTest);
}
-
- if (SanOpts.has(SanitizerKind::CFIVCall))
- EmitVTablePtrCheckForCall(RD, VTable, CodeGenFunction::CFITCK_VCall, Loc);
}
void CodeGenFunction::EmitVTablePtrCheckForCall(const CXXRecordDecl *RD,
@@ -2585,8 +2627,9 @@ void CodeGenFunction::EmitVTablePtrCheckForCast(QualType T,
EmitBlock(CheckBlock);
}
- llvm::Value *VTable =
- GetVTablePtr(Address(Derived, getPointerAlign()), Int8PtrTy, ClassDecl);
+ llvm::Value *VTable;
+ std::tie(VTable, ClassDecl) = CGM.getCXXABI().LoadVTablePtr(
+ *this, Address(Derived, getPointerAlign()), ClassDecl);
EmitVTablePtrCheck(ClassDecl, VTable, TCK, Loc);
@@ -2604,28 +2647,34 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,
!CGM.HasHiddenLTOVisibility(RD))
return;
- std::string TypeName = RD->getQualifiedNameAsString();
- if (getContext().getSanitizerBlacklist().isBlacklistedType(TypeName))
- return;
-
- SanitizerScope SanScope(this);
+ SanitizerMask M;
llvm::SanitizerStatKind SSK;
switch (TCK) {
case CFITCK_VCall:
+ M = SanitizerKind::CFIVCall;
SSK = llvm::SanStat_CFI_VCall;
break;
case CFITCK_NVCall:
+ M = SanitizerKind::CFINVCall;
SSK = llvm::SanStat_CFI_NVCall;
break;
case CFITCK_DerivedCast:
+ M = SanitizerKind::CFIDerivedCast;
SSK = llvm::SanStat_CFI_DerivedCast;
break;
case CFITCK_UnrelatedCast:
+ M = SanitizerKind::CFIUnrelatedCast;
SSK = llvm::SanStat_CFI_UnrelatedCast;
break;
case CFITCK_ICall:
llvm_unreachable("not expecting CFITCK_ICall");
}
+
+ std::string TypeName = RD->getQualifiedNameAsString();
+ if (getContext().getSanitizerBlacklist().isBlacklistedType(M, TypeName))
+ return;
+
+ SanitizerScope SanScope(this);
EmitSanitizerStatReport(SSK);
llvm::Metadata *MD =
@@ -2636,24 +2685,6 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,
llvm::Value *TypeTest = Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::type_test), {CastedVTable, TypeId});
- SanitizerMask M;
- switch (TCK) {
- case CFITCK_VCall:
- M = SanitizerKind::CFIVCall;
- break;
- case CFITCK_NVCall:
- M = SanitizerKind::CFINVCall;
- break;
- case CFITCK_DerivedCast:
- M = SanitizerKind::CFIDerivedCast;
- break;
- case CFITCK_UnrelatedCast:
- M = SanitizerKind::CFIUnrelatedCast;
- break;
- case CFITCK_ICall:
- llvm_unreachable("not expecting CFITCK_ICall");
- }
-
llvm::Constant *StaticData[] = {
llvm::ConstantInt::get(Int8Ty, TCK),
EmitCheckSourceLocation(Loc),
@@ -2688,7 +2719,8 @@ bool CodeGenFunction::ShouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *RD) {
return false;
std::string TypeName = RD->getQualifiedNameAsString();
- return !getContext().getSanitizerBlacklist().isBlacklistedType(TypeName);
+ return !getContext().getSanitizerBlacklist().isBlacklistedType(
+ SanitizerKind::CFIVCall, TypeName);
}
llvm::Value *CodeGenFunction::EmitVTableTypeCheckedLoad(
@@ -2745,9 +2777,12 @@ void CodeGenFunction::EmitForwardingCallToLambda(
RValue RV = EmitCall(calleeFnInfo, callee, returnSlot, callArgs);
// If necessary, copy the returned value into the slot.
- if (!resultType->isVoidType() && returnSlot.isNull())
+ if (!resultType->isVoidType() && returnSlot.isNull()) {
+ if (getLangOpts().ObjCAutoRefCount && resultType->isObjCRetainableType()) {
+ RV = RValue::get(EmitARCRetainAutoreleasedReturnValue(RV.getScalarVal()));
+ }
EmitReturnOfRValue(RV, resultType);
- else
+ } else
EmitBranchThroughCleanup(ReturnBlock);
}
@@ -2755,6 +2790,15 @@ void CodeGenFunction::EmitLambdaBlockInvokeBody() {
const BlockDecl *BD = BlockInfo->getBlockDecl();
const VarDecl *variable = BD->capture_begin()->getVariable();
const CXXRecordDecl *Lambda = variable->getType()->getAsCXXRecordDecl();
+ const CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator();
+
+ if (CallOp->isVariadic()) {
+ // FIXME: Making this work correctly is nasty because it requires either
+ // cloning the body of the call operator or making the call operator
+ // forward.
+ CGM.ErrorUnsupported(CurCodeDecl, "lambda conversion to variadic function");
+ return;
+ }
// Start building arguments for forwarding call
CallArgList CallArgs;
@@ -2769,18 +2813,7 @@ void CodeGenFunction::EmitLambdaBlockInvokeBody() {
assert(!Lambda->isGenericLambda() &&
"generic lambda interconversion to block not implemented");
- EmitForwardingCallToLambda(Lambda->getLambdaCallOperator(), CallArgs);
-}
-
-void CodeGenFunction::EmitLambdaToBlockPointerBody(FunctionArgList &Args) {
- if (cast<CXXMethodDecl>(CurCodeDecl)->isVariadic()) {
- // FIXME: Making this work correctly is nasty because it requires either
- // cloning the body of the call operator or making the call operator forward.
- CGM.ErrorUnsupported(CurCodeDecl, "lambda conversion to variadic function");
- return;
- }
-
- EmitFunctionBody(Args, cast<FunctionDecl>(CurGD.getDecl())->getBody());
+ EmitForwardingCallToLambda(CallOp, CallArgs);
}
void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD) {
@@ -2813,7 +2846,7 @@ void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD) {
EmitForwardingCallToLambda(CallOp, CallArgs);
}
-void CodeGenFunction::EmitLambdaStaticInvokeFunction(const CXXMethodDecl *MD) {
+void CodeGenFunction::EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD) {
if (MD->isVariadic()) {
// FIXME: Making this work correctly is nasty because it requires either
// cloning the body of the call operator or making the call operator forward.
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp
index b5453bc11e305..22055b2cb9029 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp
@@ -1096,7 +1096,7 @@ void CodeGenFunction::EmitBranchThroughCleanup(JumpDest Dest) {
break;
}
- // Otherwise, tell the scope that there's a jump propoagating
+ // Otherwise, tell the scope that there's a jump propagating
// through it. If this isn't new information, all the rest of
// the work has been done before.
if (!Scope.addBranchThrough(Dest.getBlock()))
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCoroutine.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCoroutine.cpp
index a65faa602b331..5842e7b3ff93c 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCoroutine.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCoroutine.cpp
@@ -181,10 +181,8 @@ static LValueOrRValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Co
auto *SaveCall = Builder.CreateCall(CoroSave, {NullPtr});
auto *SuspendRet = CGF.EmitScalarExpr(S.getSuspendExpr());
- if (SuspendRet != nullptr) {
+ if (SuspendRet != nullptr && SuspendRet->getType()->isIntegerTy(1)) {
// Veto suspension if requested by bool returning await_suspend.
- assert(SuspendRet->getType()->isIntegerTy(1) &&
- "Sema should have already checked that it is void or bool");
BasicBlock *RealSuspendBlock =
CGF.createBasicBlock(Prefix + Twine(".suspend.bool"));
CGF.Builder.CreateCondBr(SuspendRet, RealSuspendBlock, ReadyBlock);
@@ -234,6 +232,13 @@ RValue CodeGenFunction::EmitCoyieldExpr(const CoyieldExpr &E,
void CodeGenFunction::EmitCoreturnStmt(CoreturnStmt const &S) {
++CurCoro.Data->CoreturnCount;
+ const Expr *RV = S.getOperand();
+ if (RV && RV->getType()->isVoidType()) {
+ // Make sure to evaluate the expression of a co_return with a void
+ // expression for side effects.
+ RunCleanupsScope cleanupScope(*this);
+ EmitIgnoredExpr(RV);
+ }
EmitStmt(S.getPromiseCall());
EmitBranchThroughCleanup(CurCoro.Data->FinalJD);
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp
index 18b1d10a921d1..caea41ec0e037 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -18,6 +18,7 @@
#include "CGRecordLayout.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
+#include "ConstantEmitter.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclObjC.h"
@@ -28,6 +29,7 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Version.h"
#include "clang/Frontend/CodeGenOptions.h"
+#include "clang/Frontend/FrontendOptions.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/ModuleMap.h"
#include "clang/Lex/PreprocessorOptions.h"
@@ -95,6 +97,10 @@ void ApplyDebugLocation::init(SourceLocation TemporaryLocation,
}
OriginalLocation = CGF->Builder.getCurrentDebugLocation();
+
+ if (OriginalLocation && !DI->CGM.getExpressionLocationsEnabled())
+ return;
+
if (TemporaryLocation.isValid()) {
DI->EmitLocation(CGF->Builder, TemporaryLocation);
return;
@@ -218,6 +224,19 @@ llvm::DIScope *CGDebugInfo::getContextDescriptor(const Decl *Context,
return Default;
}
+PrintingPolicy CGDebugInfo::getPrintingPolicy() const {
+ PrintingPolicy PP = CGM.getContext().getPrintingPolicy();
+
+ // If we're emitting codeview, it's important to try to match MSVC's naming so
+ // that visualizers written for MSVC will trigger for our class names. In
+ // particular, we can't have spaces between arguments of standard templates
+ // like basic_string and vector.
+ if (CGM.getCodeGenOpts().EmitCodeView)
+ PP.MSVCFormatting = true;
+
+ return PP;
+}
+
StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) {
assert(FD && "Invalid FunctionDecl!");
IdentifierInfo *FII = FD->getIdentifier();
@@ -238,18 +257,15 @@ StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) {
SmallString<128> NS;
llvm::raw_svector_ostream OS(NS);
- PrintingPolicy Policy(CGM.getLangOpts());
- Policy.MSVCFormatting = CGM.getCodeGenOpts().EmitCodeView;
if (!UseQualifiedName)
FD->printName(OS);
else
- FD->printQualifiedName(OS, Policy);
+ FD->printQualifiedName(OS, getPrintingPolicy());
// Add any template specialization args.
if (Info) {
const TemplateArgumentList *TArgs = Info->TemplateArguments;
- TemplateSpecializationType::PrintTemplateArgumentList(OS, TArgs->asArray(),
- Policy);
+ printTemplateArgumentList(OS, TArgs->asArray(), getPrintingPolicy());
}
// Copy this name on the side and use its reference.
@@ -296,7 +312,7 @@ StringRef CGDebugInfo::getClassName(const RecordDecl *RD) {
if (isa<ClassTemplateSpecializationDecl>(RD)) {
SmallString<128> Name;
llvm::raw_svector_ostream OS(Name);
- RD->getNameForDiagnostic(OS, CGM.getContext().getPrintingPolicy(),
+ RD->getNameForDiagnostic(OS, getPrintingPolicy(),
/*Qualified*/ false);
// Copy this name on the side and use its reference.
@@ -483,6 +499,16 @@ void CGDebugInfo::CreateCompileUnit() {
llvm::sys::path::append(MainFileDirSS, MainFileName);
MainFileName = MainFileDirSS.str();
}
+ // If the main file name provided is identical to the input file name, and
+ // if the input file is a preprocessed source, use the module name for
+ // debug info. The module name comes from the name specified in the first
+ // linemarker if the input is a preprocessed source.
+ if (MainFile->getName() == MainFileName &&
+ FrontendOptions::getInputKindForExtension(
+ MainFile->getName().rsplit('.').second)
+ .isPreprocessed())
+ MainFileName = CGM.getModule().getName().str();
+
CSKind = computeChecksum(SM.getMainFileID(), Checksum);
}
@@ -527,16 +553,16 @@ void CGDebugInfo::CreateCompileUnit() {
// Create new compile unit.
// FIXME - Eliminate TheCU.
+ auto &CGOpts = CGM.getCodeGenOpts();
TheCU = DBuilder.createCompileUnit(
LangTag,
DBuilder.createFile(remapDIPath(MainFileName),
remapDIPath(getCurrentDirname()), CSKind, Checksum),
- Producer, LO.Optimize, CGM.getCodeGenOpts().DwarfDebugFlags, RuntimeVers,
- CGM.getCodeGenOpts().EnableSplitDwarf
- ? ""
- : CGM.getCodeGenOpts().SplitDwarfFile,
- EmissionKind, 0 /* DWOid */, CGM.getCodeGenOpts().SplitDwarfInlining,
- CGM.getCodeGenOpts().DebugInfoForProfiling);
+ Producer, LO.Optimize || CGOpts.PrepareForLTO || CGOpts.EmitSummaryIndex,
+ CGOpts.DwarfDebugFlags, RuntimeVers,
+ CGOpts.EnableSplitDwarf ? "" : CGOpts.SplitDwarfFile, EmissionKind,
+ 0 /* DWOid */, CGOpts.SplitDwarfInlining, CGOpts.DebugInfoForProfiling,
+ CGOpts.GnuPubnames);
}
llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
@@ -645,6 +671,7 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
case BuiltinType::Half:
case BuiltinType::Float:
case BuiltinType::LongDouble:
+ case BuiltinType::Float16:
case BuiltinType::Float128:
case BuiltinType::Double:
// FIXME: For targets where long double and __float128 have the same size,
@@ -805,6 +832,10 @@ CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty,
llvm::DICompositeType *RetTy = DBuilder.createReplaceableCompositeType(
getTagForRecord(RD), RDName, Ctx, DefUnit, Line, 0, Size, Align,
llvm::DINode::FlagFwdDecl, FullName);
+ if (CGM.getCodeGenOpts().DebugFwdTemplateParams)
+ if (auto *TSpecial = dyn_cast<ClassTemplateSpecializationDecl>(RD))
+ DBuilder.replaceArrays(RetTy, llvm::DINodeArray(),
+ CollectCXXTemplateParams(TSpecial, DefUnit));
ReplaceMap.emplace_back(
std::piecewise_construct, std::make_tuple(Ty),
std::make_tuple(static_cast<llvm::Metadata *>(RetTy)));
@@ -909,12 +940,8 @@ llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty,
SmallString<128> NS;
llvm::raw_svector_ostream OS(NS);
- Ty->getTemplateName().print(OS, CGM.getContext().getPrintingPolicy(),
- /*qualified*/ false);
-
- TemplateSpecializationType::PrintTemplateArgumentList(
- OS, Ty->template_arguments(),
- CGM.getContext().getPrintingPolicy());
+ Ty->getTemplateName().print(OS, getPrintingPolicy(), /*qualified*/ false);
+ printTemplateArgumentList(OS, Ty->template_arguments(), getPrintingPolicy());
auto *AliasDecl = cast<TypeAliasTemplateDecl>(
Ty->getTemplateName().getAsTemplateDecl())->getTemplatedDecl();
@@ -1174,13 +1201,13 @@ void CGDebugInfo::CollectRecordNormalField(
elements.push_back(FieldType);
}
-void CGDebugInfo::CollectRecordNestedRecord(
- const RecordDecl *RD, SmallVectorImpl<llvm::Metadata *> &elements) {
- QualType Ty = CGM.getContext().getTypeDeclType(RD);
+void CGDebugInfo::CollectRecordNestedType(
+ const TypeDecl *TD, SmallVectorImpl<llvm::Metadata *> &elements) {
+ QualType Ty = CGM.getContext().getTypeDeclType(TD);
// Injected class names are not considered nested records.
if (isa<InjectedClassNameType>(Ty))
return;
- SourceLocation Loc = RD->getLocation();
+ SourceLocation Loc = TD->getLocation();
llvm::DIType *nestedType = getOrCreateType(Ty, getOrCreateFile(Loc));
elements.push_back(nestedType);
}
@@ -1196,9 +1223,9 @@ void CGDebugInfo::CollectRecordFields(
else {
const ASTRecordLayout &layout = CGM.getContext().getASTRecordLayout(record);
- // Debug info for nested records is included in the member list only for
+ // Debug info for nested types is included in the member list only for
// CodeView.
- bool IncludeNestedRecords = CGM.getCodeGenOpts().EmitCodeView;
+ bool IncludeNestedTypes = CGM.getCodeGenOpts().EmitCodeView;
// Field number for non-static fields.
unsigned fieldNo = 0;
@@ -1225,10 +1252,12 @@ void CGDebugInfo::CollectRecordFields(
// Bump field number for next field.
++fieldNo;
- } else if (const auto *nestedRec = dyn_cast<CXXRecordDecl>(I))
- if (IncludeNestedRecords && !nestedRec->isImplicit() &&
- nestedRec->getDeclContext() == record)
- CollectRecordNestedRecord(nestedRec, elements);
+ } else if (IncludeNestedTypes) {
+ if (const auto *nestedType = dyn_cast<TypeDecl>(I))
+ if (!nestedType->isImplicit() &&
+ nestedType->getDeclContext() == record)
+ CollectRecordNestedType(nestedType, elements);
+ }
}
}
@@ -1366,7 +1395,7 @@ llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction(
// C++ ABI does not include all virtual methods from non-primary bases in
// the vtable for the most derived class. For example, if C inherits from
// A and B, C's primary vftable will not include B's virtual methods.
- if (Method->begin_overridden_methods() == Method->end_overridden_methods())
+ if (Method->size_overridden_methods() == 0)
Flags |= llvm::DINode::FlagIntroducedVirtual;
// The 'this' adjustment accounts for both the virtual and non-virtual
@@ -1379,6 +1408,8 @@ llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction(
ContainingType = RecordTy;
}
+ if (Method->isStatic())
+ Flags |= llvm::DINode::FlagStaticMember;
if (Method->isImplicit())
Flags |= llvm::DINode::FlagArtificial;
Flags |= getAccessFlag(Method->getAccess(), Method->getParent());
@@ -1590,7 +1621,7 @@ CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList,
QualType T = E->getType();
if (E->isGLValue())
T = CGM.getContext().getLValueReferenceType(T);
- llvm::Constant *V = CGM.EmitConstantExpr(E, T);
+ llvm::Constant *V = ConstantEmitter(CGM).emitAbstract(E, T);
assert(V && "Expression in template argument isn't constant");
llvm::DIType *TTy = getOrCreateType(T, Unit);
TemplateParams.push_back(DBuilder.createTemplateValueParameter(
@@ -1766,6 +1797,29 @@ static bool isClassOrMethodDLLImport(const CXXRecordDecl *RD) {
return false;
}
+/// Does a type definition exist in an imported clang module?
+static bool isDefinedInClangModule(const RecordDecl *RD) {
+ // Only definitions that where imported from an AST file come from a module.
+ if (!RD || !RD->isFromASTFile())
+ return false;
+ // Anonymous entities cannot be addressed. Treat them as not from module.
+ if (!RD->isExternallyVisible() && RD->getName().empty())
+ return false;
+ if (auto *CXXDecl = dyn_cast<CXXRecordDecl>(RD)) {
+ if (!CXXDecl->isCompleteDefinition())
+ return false;
+ auto TemplateKind = CXXDecl->getTemplateSpecializationKind();
+ if (TemplateKind != TSK_Undeclared) {
+ // This is a template, check the origin of the first member.
+ if (CXXDecl->field_begin() == CXXDecl->field_end())
+ return TemplateKind == TSK_ExplicitInstantiationDeclaration;
+ if (!CXXDecl->field_begin()->isFromASTFile())
+ return false;
+ }
+ }
+ return true;
+}
+
void CGDebugInfo::completeClassData(const RecordDecl *RD) {
if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RD))
if (CXXRD->isDynamicClass() &&
@@ -1773,6 +1827,10 @@ void CGDebugInfo::completeClassData(const RecordDecl *RD) {
llvm::GlobalValue::AvailableExternallyLinkage &&
!isClassOrMethodDLLImport(CXXRD))
return;
+
+ if (DebugTypeExtRefs && isDefinedInClangModule(RD->getDefinition()))
+ return;
+
completeClass(RD);
}
@@ -1799,29 +1857,6 @@ static bool hasExplicitMemberDefinition(CXXRecordDecl::method_iterator I,
return false;
}
-/// Does a type definition exist in an imported clang module?
-static bool isDefinedInClangModule(const RecordDecl *RD) {
- // Only definitions that where imported from an AST file come from a module.
- if (!RD || !RD->isFromASTFile())
- return false;
- // Anonymous entities cannot be addressed. Treat them as not from module.
- if (!RD->isExternallyVisible() && RD->getName().empty())
- return false;
- if (auto *CXXDecl = dyn_cast<CXXRecordDecl>(RD)) {
- if (!CXXDecl->isCompleteDefinition())
- return false;
- auto TemplateKind = CXXDecl->getTemplateSpecializationKind();
- if (TemplateKind != TSK_Undeclared) {
- // This is a template, check the origin of the first member.
- if (CXXDecl->field_begin() == CXXDecl->field_end())
- return TemplateKind == TSK_ExplicitInstantiationDeclaration;
- if (!CXXDecl->field_begin()->isFromASTFile())
- return false;
- }
- }
- return true;
-}
-
static bool shouldOmitDefinition(codegenoptions::DebugInfoKind DebugKind,
bool DebugTypeExtRefs, const RecordDecl *RD,
const LangOptions &LangOpts) {
@@ -3655,9 +3690,9 @@ bool operator<(const BlockLayoutChunk &l, const BlockLayoutChunk &r) {
}
void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
- llvm::Value *Arg,
+ StringRef Name,
unsigned ArgNo,
- llvm::Value *LocalAddr,
+ llvm::AllocaInst *Alloca,
CGBuilderTy &Builder) {
assert(DebugKind >= codegenoptions::LimitedDebugInfo);
ASTContext &C = CGM.getContext();
@@ -3789,19 +3824,11 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
// Create the descriptor for the parameter.
auto *debugVar = DBuilder.createParameterVariable(
- scope, Arg->getName(), ArgNo, tunit, line, type,
+ scope, Name, ArgNo, tunit, line, type,
CGM.getLangOpts().Optimize, flags);
- if (LocalAddr) {
- // Insert an llvm.dbg.value into the current block.
- DBuilder.insertDbgValueIntrinsic(
- LocalAddr, 0, debugVar, DBuilder.createExpression(),
- llvm::DebugLoc::get(line, column, scope, CurInlinedAt),
- Builder.GetInsertBlock());
- }
-
// Insert an llvm.dbg.declare into the current block.
- DBuilder.insertDeclare(Arg, debugVar, DBuilder.createExpression(),
+ DBuilder.insertDeclare(Alloca, debugVar, DBuilder.createExpression(),
llvm::DebugLoc::get(line, column, scope, CurInlinedAt),
Builder.GetInsertBlock());
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h
index 39249c7cf4da2..4f7b7f2a0d9c4 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h
@@ -278,8 +278,8 @@ class CGDebugInfo {
llvm::DIFile *F,
SmallVectorImpl<llvm::Metadata *> &E,
llvm::DIType *RecordTy, const RecordDecl *RD);
- void CollectRecordNestedRecord(const RecordDecl *RD,
- SmallVectorImpl<llvm::Metadata *> &E);
+ void CollectRecordNestedType(const TypeDecl *RD,
+ SmallVectorImpl<llvm::Metadata *> &E);
void CollectRecordFields(const RecordDecl *Decl, llvm::DIFile *F,
SmallVectorImpl<llvm::Metadata *> &E,
llvm::DICompositeType *RecordTy);
@@ -398,8 +398,8 @@ public:
/// Emit call to \c llvm.dbg.declare for the block-literal argument
/// to a block invocation function.
void EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
- llvm::Value *Arg, unsigned ArgNo,
- llvm::Value *LocalAddr,
+ StringRef Name, unsigned ArgNo,
+ llvm::AllocaInst *LocalAddr,
CGBuilderTy &Builder);
/// Emit information about a global variable.
@@ -558,6 +558,9 @@ private:
unsigned LineNo, StringRef LinkageName,
llvm::GlobalVariable *Var, llvm::DIScope *DContext);
+ /// Get the printing policy for producing names for debug info.
+ PrintingPolicy getPrintingPolicy() const;
+
/// Get function name for the given FunctionDecl. If the name is
/// constructed on demand (e.g., C++ destructor) then the name is
/// stored on the side.
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp
index 23517867437c7..04585a8afbb65 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp
@@ -19,6 +19,7 @@
#include "CGOpenMPRuntime.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
+#include "ConstantEmitter.h"
#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CharUnits.h"
@@ -161,6 +162,10 @@ void CodeGenFunction::EmitVarDecl(const VarDecl &D) {
// needs to be emitted like a static variable, e.g. a function-scope
// variable in constant address space in OpenCL.
if (D.getStorageDuration() != SD_Automatic) {
+ // Static sampler variables translated to function calls.
+ if (D.getType()->isSamplerT())
+ return;
+
llvm::GlobalValue::LinkageTypes Linkage =
CGM.getLLVMLinkageVarDefinition(&D, /*isConstant=*/false);
@@ -221,7 +226,7 @@ llvm::Constant *CodeGenModule::getOrCreateStaticVarDecl(
Name = getStaticDeclName(*this, D);
llvm::Type *LTy = getTypes().ConvertTypeForMem(Ty);
- unsigned AS = GetGlobalVarAddressSpace(&D);
+ LangAS AS = GetGlobalVarAddressSpace(&D);
unsigned TargetAS = getContext().getTargetAddressSpace(AS);
// Local address space cannot have an initializer.
@@ -235,7 +240,7 @@ llvm::Constant *CodeGenModule::getOrCreateStaticVarDecl(
getModule(), LTy, Ty.isConstant(getContext()), Linkage, Init, Name,
nullptr, llvm::GlobalVariable::NotThreadLocal, TargetAS);
GV->setAlignment(getContext().getDeclAlign(&D).getQuantity());
- setGlobalVisibility(GV, &D);
+ setGlobalVisibility(GV, &D, ForDefinition);
if (supportsCOMDAT() && GV->isWeakForLinker())
GV->setComdat(TheModule.getOrInsertComdat(GV->getName()));
@@ -251,7 +256,7 @@ llvm::Constant *CodeGenModule::getOrCreateStaticVarDecl(
}
// Make sure the result is of the correct type.
- unsigned ExpectedAS = Ty.getAddressSpace();
+ LangAS ExpectedAS = Ty.getAddressSpace();
llvm::Constant *Addr = GV;
if (AS != ExpectedAS) {
Addr = getTargetCodeGenInfo().performAddrSpaceCast(
@@ -307,7 +312,8 @@ static bool hasNontrivialDestruction(QualType T) {
llvm::GlobalVariable *
CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D,
llvm::GlobalVariable *GV) {
- llvm::Constant *Init = CGM.EmitConstantInit(D, this);
+ ConstantEmitter emitter(*this);
+ llvm::Constant *Init = emitter.tryEmitForInitializer(D);
// If constant emission failed, then this should be a C++ static
// initializer.
@@ -355,6 +361,8 @@ CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D,
GV->setConstant(CGM.isTypeConstant(D.getType(), true));
GV->setInitializer(Init);
+ emitter.finalize(GV);
+
if (hasNontrivialDestruction(D.getType()) && HaveInsertPoint()) {
// We have a constant initializer, but a nontrivial destructor. We still
// need to perform a guarded "initialization" in order to register the
@@ -952,7 +960,9 @@ void CodeGenFunction::EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr) {
CodeGenFunction::AutoVarEmission
CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
QualType Ty = D.getType();
- assert(Ty.getAddressSpace() == LangAS::Default);
+ assert(
+ Ty.getAddressSpace() == LangAS::Default ||
+ (Ty.getAddressSpace() == LangAS::opencl_private && getLangOpts().OpenCL));
AutoVarEmission emission(D);
@@ -1236,7 +1246,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
llvm::Constant *constant = nullptr;
if (emission.IsConstantAggregate || D.isConstexpr()) {
assert(!capturedByInit && "constant init contains a capturing block?");
- constant = CGM.EmitConstantInit(D, this);
+ constant = ConstantEmitter(*this).tryEmitAbstractForInitializer(D);
}
if (!constant) {
@@ -1260,7 +1270,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
llvm::ConstantInt::get(IntPtrTy,
getContext().getTypeSizeInChars(type).getQuantity());
- llvm::Type *BP = Int8PtrTy;
+ llvm::Type *BP = AllocaInt8PtrTy;
if (Loc.getType() != BP)
Loc = Builder.CreateBitCast(Loc, BP);
@@ -1786,24 +1796,6 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg,
setBlockContextParameter(IPD, ArgNo, Arg.getDirectValue());
return;
}
-
- // Apply any prologue 'this' adjustments required by the ABI. Be careful to
- // handle the case where 'this' is passed indirectly as part of an inalloca
- // struct.
- if (const CXXMethodDecl *MD =
- dyn_cast_or_null<CXXMethodDecl>(CurCodeDecl)) {
- if (MD->isVirtual() && IPD == CXXABIThisDecl) {
- llvm::Value *This = Arg.isIndirect()
- ? Builder.CreateLoad(Arg.getIndirectAddress())
- : Arg.getDirectValue();
- This = CGM.getCXXABI().adjustThisParameterInVirtualFunctionPrologue(
- *this, CurGD, This);
- if (Arg.isIndirect())
- Builder.CreateStore(This, Arg.getIndirectAddress());
- else
- Arg = ParamValue::forDirect(This);
- }
- }
}
Address DeclPtr = Address::invalid();
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp
index d8768bee2cdf4..0429978317021 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp
@@ -18,6 +18,7 @@
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/MDBuilder.h"
#include "llvm/Support/Path.h"
using namespace clang;
@@ -259,6 +260,43 @@ void CodeGenFunction::EmitCXXGuardedInit(const VarDecl &D,
CGM.getCXXABI().EmitGuardedInit(*this, D, DeclPtr, PerformInit);
}
+void CodeGenFunction::EmitCXXGuardedInitBranch(llvm::Value *NeedsInit,
+ llvm::BasicBlock *InitBlock,
+ llvm::BasicBlock *NoInitBlock,
+ GuardKind Kind,
+ const VarDecl *D) {
+ assert((Kind == GuardKind::TlsGuard || D) && "no guarded variable");
+
+ // A guess at how many times we will enter the initialization of a
+ // variable, depending on the kind of variable.
+ static const uint64_t InitsPerTLSVar = 1024;
+ static const uint64_t InitsPerLocalVar = 1024 * 1024;
+
+ llvm::MDNode *Weights;
+ if (Kind == GuardKind::VariableGuard && !D->isLocalVarDecl()) {
+ // For non-local variables, don't apply any weighting for now. Due to our
+ // use of COMDATs, we expect there to be at most one initialization of the
+ // variable per DSO, but we have no way to know how many DSOs will try to
+ // initialize the variable.
+ Weights = nullptr;
+ } else {
+ uint64_t NumInits;
+ // FIXME: For the TLS case, collect and use profiling information to
+ // determine a more accurate brach weight.
+ if (Kind == GuardKind::TlsGuard || D->getTLSKind())
+ NumInits = InitsPerTLSVar;
+ else
+ NumInits = InitsPerLocalVar;
+
+ // The probability of us entering the initializer is
+ // 1 / (total number of times we attempt to initialize the variable).
+ llvm::MDBuilder MDHelper(CGM.getLLVMContext());
+ Weights = MDHelper.createBranchWeights(1, NumInits - 1);
+ }
+
+ Builder.CreateCondBr(NeedsInit, InitBlock, NoInitBlock, Weights);
+}
+
llvm::Function *CodeGenModule::CreateGlobalInitOrDestructFunction(
llvm::FunctionType *FTy, const Twine &Name, const CGFunctionInfo &FI,
SourceLocation Loc, bool TLS) {
@@ -278,17 +316,29 @@ llvm::Function *CodeGenModule::CreateGlobalInitOrDestructFunction(
if (!getLangOpts().Exceptions)
Fn->setDoesNotThrow();
- if (!isInSanitizerBlacklist(Fn, Loc)) {
- if (getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address |
- SanitizerKind::KernelAddress))
- Fn->addFnAttr(llvm::Attribute::SanitizeAddress);
- if (getLangOpts().Sanitize.has(SanitizerKind::Thread))
- Fn->addFnAttr(llvm::Attribute::SanitizeThread);
- if (getLangOpts().Sanitize.has(SanitizerKind::Memory))
- Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
- if (getLangOpts().Sanitize.has(SanitizerKind::SafeStack))
- Fn->addFnAttr(llvm::Attribute::SafeStack);
- }
+ if (getLangOpts().Sanitize.has(SanitizerKind::Address) &&
+ !isInSanitizerBlacklist(SanitizerKind::Address, Fn, Loc))
+ Fn->addFnAttr(llvm::Attribute::SanitizeAddress);
+
+ if (getLangOpts().Sanitize.has(SanitizerKind::KernelAddress) &&
+ !isInSanitizerBlacklist(SanitizerKind::KernelAddress, Fn, Loc))
+ Fn->addFnAttr(llvm::Attribute::SanitizeAddress);
+
+ if (getLangOpts().Sanitize.has(SanitizerKind::HWAddress) &&
+ !isInSanitizerBlacklist(SanitizerKind::HWAddress, Fn, Loc))
+ Fn->addFnAttr(llvm::Attribute::SanitizeHWAddress);
+
+ if (getLangOpts().Sanitize.has(SanitizerKind::Thread) &&
+ !isInSanitizerBlacklist(SanitizerKind::Thread, Fn, Loc))
+ Fn->addFnAttr(llvm::Attribute::SanitizeThread);
+
+ if (getLangOpts().Sanitize.has(SanitizerKind::Memory) &&
+ !isInSanitizerBlacklist(SanitizerKind::Memory, Fn, Loc))
+ Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
+
+ if (getLangOpts().Sanitize.has(SanitizerKind::SafeStack) &&
+ !isInSanitizerBlacklist(SanitizerKind::SafeStack, Fn, Loc))
+ Fn->addFnAttr(llvm::Attribute::SafeStack);
return Fn;
}
@@ -449,16 +499,12 @@ CodeGenModule::EmitCXXGlobalInitFunc() {
PrioritizedCXXGlobalInits.clear();
}
- SmallString<128> FileName;
- SourceManager &SM = Context.getSourceManager();
- if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
- // Include the filename in the symbol name. Including "sub_" matches gcc and
- // makes sure these symbols appear lexicographically behind the symbols with
- // priority emitted above.
- FileName = llvm::sys::path::filename(MainFile->getName());
- } else {
+ // Include the filename in the symbol name. Including "sub_" matches gcc and
+ // makes sure these symbols appear lexicographically behind the symbols with
+ // priority emitted above.
+ SmallString<128> FileName = llvm::sys::path::filename(getModule().getName());
+ if (FileName.empty())
FileName = "<null>";
- }
for (size_t i = 0; i < FileName.size(); ++i) {
// Replace everything that's not [a-zA-Z0-9._] with a _. This set happens
@@ -539,7 +585,8 @@ CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
"guard.uninitialized");
llvm::BasicBlock *InitBlock = createBasicBlock("init");
ExitBlock = createBasicBlock("exit");
- Builder.CreateCondBr(Uninit, InitBlock, ExitBlock);
+ EmitCXXGuardedInitBranch(Uninit, InitBlock, ExitBlock,
+ GuardKind::TlsGuard, nullptr);
EmitBlock(InitBlock);
// Mark as initialized before initializing anything else. If the
// initializers use previously-initialized thread_local vars, that's
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp
index 40ae0921098cb..6c9d9f170ace6 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp
@@ -15,6 +15,7 @@
#include "CGCXXABI.h"
#include "CGCleanup.h"
#include "CGObjCRuntime.h"
+#include "ConstantEmitter.h"
#include "TargetInfo.h"
#include "clang/AST/Mangle.h"
#include "clang/AST/StmtCXX.h"
@@ -111,17 +112,11 @@ EHPersonality::MSVC_C_specific_handler = { "__C_specific_handler", nullptr };
const EHPersonality
EHPersonality::MSVC_CxxFrameHandler3 = { "__CxxFrameHandler3", nullptr };
-/// On Win64, use libgcc's SEH personality function. We fall back to dwarf on
-/// other platforms, unless the user asked for SjLj exceptions.
-static bool useLibGCCSEHPersonality(const llvm::Triple &T) {
- return T.isOSWindows() && T.getArch() == llvm::Triple::x86_64;
-}
-
static const EHPersonality &getCPersonality(const llvm::Triple &T,
const LangOptions &L) {
if (L.SjLjExceptions)
return EHPersonality::GNU_C_SJLJ;
- else if (useLibGCCSEHPersonality(T))
+ if (L.SEHExceptions)
return EHPersonality::GNU_C_SEH;
return EHPersonality::GNU_C;
}
@@ -143,7 +138,7 @@ static const EHPersonality &getObjCPersonality(const llvm::Triple &T,
case ObjCRuntime::ObjFW:
if (L.SjLjExceptions)
return EHPersonality::GNU_ObjC_SJLJ;
- else if (useLibGCCSEHPersonality(T))
+ if (L.SEHExceptions)
return EHPersonality::GNU_ObjC_SEH;
return EHPersonality::GNU_ObjC;
}
@@ -154,7 +149,7 @@ static const EHPersonality &getCXXPersonality(const llvm::Triple &T,
const LangOptions &L) {
if (L.SjLjExceptions)
return EHPersonality::GNU_CPlusPlus_SJLJ;
- else if (useLibGCCSEHPersonality(T))
+ if (L.SEHExceptions)
return EHPersonality::GNU_CPlusPlus_SEH;
return EHPersonality::GNU_CPlusPlus;
}
@@ -164,26 +159,27 @@ static const EHPersonality &getCXXPersonality(const llvm::Triple &T,
static const EHPersonality &getObjCXXPersonality(const llvm::Triple &T,
const LangOptions &L) {
switch (L.ObjCRuntime.getKind()) {
+ // In the fragile ABI, just use C++ exception handling and hope
+ // they're not doing crazy exception mixing.
+ case ObjCRuntime::FragileMacOSX:
+ return getCXXPersonality(T, L);
+
// The ObjC personality defers to the C++ personality for non-ObjC
// handlers. Unlike the C++ case, we use the same personality
// function on targets using (backend-driven) SJLJ EH.
case ObjCRuntime::MacOSX:
case ObjCRuntime::iOS:
case ObjCRuntime::WatchOS:
- return EHPersonality::NeXT_ObjC;
+ return getObjCPersonality(T, L);
- // In the fragile ABI, just use C++ exception handling and hope
- // they're not doing crazy exception mixing.
- case ObjCRuntime::FragileMacOSX:
- return getCXXPersonality(T, L);
+ case ObjCRuntime::GNUstep:
+ return EHPersonality::GNU_ObjCXX;
// The GCC runtime's personality function inherently doesn't support
- // mixed EH. Use the C++ personality just to avoid returning null.
+ // mixed EH. Use the ObjC personality just to avoid returning null.
case ObjCRuntime::GCC:
case ObjCRuntime::ObjFW:
return getObjCPersonality(T, L);
- case ObjCRuntime::GNUstep:
- return EHPersonality::GNU_ObjCXX;
}
llvm_unreachable("bad runtime kind");
}
@@ -209,8 +205,9 @@ const EHPersonality &EHPersonality::get(CodeGenModule &CGM,
if (T.isWindowsMSVCEnvironment() && !L.ObjC1) {
if (L.SjLjExceptions)
return EHPersonality::GNU_CPlusPlus_SJLJ;
- else
- return EHPersonality::MSVC_CxxFrameHandler3;
+ if (L.DWARFExceptions)
+ return EHPersonality::GNU_CPlusPlus;
+ return EHPersonality::MSVC_CxxFrameHandler3;
}
if (L.CPlusPlus && L.ObjC1)
@@ -224,7 +221,12 @@ const EHPersonality &EHPersonality::get(CodeGenModule &CGM,
}
const EHPersonality &EHPersonality::get(CodeGenFunction &CGF) {
- return get(CGF.CGM, dyn_cast_or_null<FunctionDecl>(CGF.CurCodeDecl));
+ const auto *FD = CGF.CurCodeDecl;
+ // For outlined finallys and filters, use the SEH personality in case they
+ // contain more SEH. This mostly only affects finallys. Filters could
+ // hypothetically use gnu statement expressions to sneak in nested SEH.
+ FD = FD ? FD : CGF.CurSEHParent;
+ return get(CGF.CGM, dyn_cast_or_null<FunctionDecl>(FD));
}
static llvm::Constant *getPersonalityFn(CodeGenModule &CGM,
@@ -1800,7 +1802,8 @@ void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S) {
// "catch i8* null". We can't do this on x86 because the filter has to save
// the exception code.
llvm::Constant *C =
- CGM.EmitConstantExpr(Except->getFilterExpr(), getContext().IntTy, this);
+ ConstantEmitter(*this).tryEmitAbstract(Except->getFilterExpr(),
+ getContext().IntTy);
if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86 && C &&
C->isOneValue()) {
CatchScope->setCatchAllHandler(0, createBasicBlock("__except"));
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp
index 63c7b3d10bf90..98740e8f9aabe 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp
@@ -20,6 +20,7 @@
#include "CGRecordLayout.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
+#include "ConstantEmitter.h"
#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
@@ -48,7 +49,7 @@ using namespace CodeGen;
llvm::Value *CodeGenFunction::EmitCastToVoidPtr(llvm::Value *value) {
unsigned addressSpace =
- cast<llvm::PointerType>(value->getType())->getAddressSpace();
+ cast<llvm::PointerType>(value->getType())->getAddressSpace();
llvm::PointerType *destType = Int8PtrTy;
if (addressSpace)
@@ -73,12 +74,15 @@ Address CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, CharUnits Align,
// cast alloca to the default address space when necessary.
if (CastToDefaultAddrSpace && getASTAllocaAddressSpace() != LangAS::Default) {
auto DestAddrSpace = getContext().getTargetAddressSpace(LangAS::Default);
- auto CurIP = Builder.saveIP();
- Builder.SetInsertPoint(AllocaInsertPt);
+ llvm::IRBuilderBase::InsertPointGuard IPG(Builder);
+ // When ArraySize is nullptr, alloca is inserted at AllocaInsertPt,
+ // otherwise alloca is inserted at the current insertion point of the
+ // builder.
+ if (!ArraySize)
+ Builder.SetInsertPoint(AllocaInsertPt);
V = getTargetHooks().performAddrSpaceCast(
*this, V, getASTAllocaAddressSpace(), LangAS::Default,
Ty->getPointerTo(DestAddrSpace), /*non-null*/ true);
- Builder.restoreIP(CurIP);
}
return Address(V, Align);
@@ -356,7 +360,7 @@ static Address createReferenceTemporary(CodeGenFunction &CGF,
if (CGF.CGM.getCodeGenOpts().MergeAllConstants &&
(Ty->isArrayType() || Ty->isRecordType()) &&
CGF.CGM.isTypeConstant(Ty, true))
- if (llvm::Constant *Init = CGF.CGM.EmitConstantExpr(Inner, Ty, &CGF)) {
+ if (auto Init = ConstantEmitter(CGF).tryEmitAbstract(Inner, Ty)) {
if (auto AddrSpace = CGF.getTarget().getConstantAddressSpace()) {
auto AS = AddrSpace.getValue();
auto *GV = new llvm::GlobalVariable(
@@ -411,14 +415,12 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
// dynamic initialization or a cleanup and we can just return the address
// of the temporary.
if (Var->hasInitializer())
- return MakeAddrLValue(Object, M->getType(),
- LValueBaseInfo(AlignmentSource::Decl, false));
+ return MakeAddrLValue(Object, M->getType(), AlignmentSource::Decl);
Var->setInitializer(CGM.EmitNullConstant(E->getType()));
}
LValue RefTempDst = MakeAddrLValue(Object, M->getType(),
- LValueBaseInfo(AlignmentSource::Decl,
- false));
+ AlignmentSource::Decl);
switch (getEvaluationKind(E->getType())) {
default: llvm_unreachable("expected scalar or aggregate expression");
@@ -505,8 +507,7 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
break;
case SubobjectAdjustment::FieldAdjustment: {
- LValue LV = MakeAddrLValue(Object, E->getType(),
- LValueBaseInfo(AlignmentSource::Decl, false));
+ LValue LV = MakeAddrLValue(Object, E->getType(), AlignmentSource::Decl);
LV = EmitLValueForField(LV, Adjustment.Field);
assert(LV.isSimple() &&
"materialized temporary field is not a simple lvalue");
@@ -523,8 +524,7 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
}
}
- return MakeAddrLValue(Object, M->getType(),
- LValueBaseInfo(AlignmentSource::Decl, false));
+ return MakeAddrLValue(Object, M->getType(), AlignmentSource::Decl);
}
RValue
@@ -568,6 +568,19 @@ static llvm::Value *emitHash16Bytes(CGBuilderTy &Builder, llvm::Value *Low,
return Builder.CreateMul(B1, KMul);
}
+bool CodeGenFunction::isNullPointerAllowed(TypeCheckKind TCK) {
+ return TCK == TCK_DowncastPointer || TCK == TCK_Upcast ||
+ TCK == TCK_UpcastToVirtualBase;
+}
+
+bool CodeGenFunction::isVptrCheckRequired(TypeCheckKind TCK, QualType Ty) {
+ CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
+ return (RD && RD->hasDefinition() && RD->isDynamicClass()) &&
+ (TCK == TCK_MemberAccess || TCK == TCK_MemberCall ||
+ TCK == TCK_DowncastPointer || TCK == TCK_DowncastReference ||
+ TCK == TCK_UpcastToVirtualBase);
+}
+
bool CodeGenFunction::sanitizePerformTypeCheck() const {
return SanOpts.has(SanitizerKind::Null) |
SanOpts.has(SanitizerKind::Alignment) |
@@ -604,20 +617,22 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
auto PtrToAlloca =
dyn_cast<llvm::AllocaInst>(Ptr->stripPointerCastsNoFollowAliases());
- bool AllowNullPointers = TCK == TCK_DowncastPointer || TCK == TCK_Upcast ||
- TCK == TCK_UpcastToVirtualBase;
+ llvm::Value *True = llvm::ConstantInt::getTrue(getLLVMContext());
+ llvm::Value *IsNonNull = nullptr;
+ bool IsGuaranteedNonNull =
+ SkippedChecks.has(SanitizerKind::Null) || PtrToAlloca;
+ bool AllowNullPointers = isNullPointerAllowed(TCK);
if ((SanOpts.has(SanitizerKind::Null) || AllowNullPointers) &&
- !SkippedChecks.has(SanitizerKind::Null) && !PtrToAlloca) {
+ !IsGuaranteedNonNull) {
// The glvalue must not be an empty glvalue.
- llvm::Value *IsNonNull = Builder.CreateIsNotNull(Ptr);
+ IsNonNull = Builder.CreateIsNotNull(Ptr);
// The IR builder can constant-fold the null check if the pointer points to
// a constant.
- bool PtrIsNonNull =
- IsNonNull == llvm::ConstantInt::getTrue(getLLVMContext());
+ IsGuaranteedNonNull = IsNonNull == True;
// Skip the null check if the pointer is known to be non-null.
- if (!PtrIsNonNull) {
+ if (!IsGuaranteedNonNull) {
if (AllowNullPointers) {
// When performing pointer casts, it's OK if the value is null.
// Skip the remaining checks in that case.
@@ -652,6 +667,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
}
uint64_t AlignVal = 0;
+ llvm::Value *PtrAsInt = nullptr;
if (SanOpts.has(SanitizerKind::Alignment) &&
!SkippedChecks.has(SanitizerKind::Alignment)) {
@@ -662,12 +678,13 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
// The glvalue must be suitably aligned.
if (AlignVal > 1 &&
(!PtrToAlloca || PtrToAlloca->getAlignment() < AlignVal)) {
- llvm::Value *Align =
- Builder.CreateAnd(Builder.CreatePtrToInt(Ptr, IntPtrTy),
- llvm::ConstantInt::get(IntPtrTy, AlignVal - 1));
+ PtrAsInt = Builder.CreatePtrToInt(Ptr, IntPtrTy);
+ llvm::Value *Align = Builder.CreateAnd(
+ PtrAsInt, llvm::ConstantInt::get(IntPtrTy, AlignVal - 1));
llvm::Value *Aligned =
- Builder.CreateICmpEQ(Align, llvm::ConstantInt::get(IntPtrTy, 0));
- Checks.push_back(std::make_pair(Aligned, SanitizerKind::Alignment));
+ Builder.CreateICmpEQ(Align, llvm::ConstantInt::get(IntPtrTy, 0));
+ if (Aligned != True)
+ Checks.push_back(std::make_pair(Aligned, SanitizerKind::Alignment));
}
}
@@ -679,7 +696,8 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
EmitCheckSourceLocation(Loc), EmitCheckTypeDescriptor(Ty),
llvm::ConstantInt::get(Int8Ty, AlignVal ? llvm::Log2_64(AlignVal) : 1),
llvm::ConstantInt::get(Int8Ty, TCK)};
- EmitCheck(Checks, SanitizerHandler::TypeMismatch, StaticData, Ptr);
+ EmitCheck(Checks, SanitizerHandler::TypeMismatch, StaticData,
+ PtrAsInt ? PtrAsInt : Ptr);
}
// If possible, check that the vptr indicates that there is a subobject of
@@ -690,13 +708,20 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
// The program has undefined behavior if:
// -- the [pointer or glvalue] is used to access a non-static data member
// or call a non-static member function
- CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
if (SanOpts.has(SanitizerKind::Vptr) &&
- !SkippedChecks.has(SanitizerKind::Vptr) &&
- (TCK == TCK_MemberAccess || TCK == TCK_MemberCall ||
- TCK == TCK_DowncastPointer || TCK == TCK_DowncastReference ||
- TCK == TCK_UpcastToVirtualBase) &&
- RD && RD->hasDefinition() && RD->isDynamicClass()) {
+ !SkippedChecks.has(SanitizerKind::Vptr) && isVptrCheckRequired(TCK, Ty)) {
+ // Ensure that the pointer is non-null before loading it. If there is no
+ // compile-time guarantee, reuse the run-time null check or emit a new one.
+ if (!IsGuaranteedNonNull) {
+ if (!IsNonNull)
+ IsNonNull = Builder.CreateIsNotNull(Ptr);
+ if (!Done)
+ Done = createBasicBlock("vptr.null");
+ llvm::BasicBlock *VptrNotNull = createBasicBlock("vptr.not.null");
+ Builder.CreateCondBr(IsNonNull, VptrNotNull, Done);
+ EmitBlock(VptrNotNull);
+ }
+
// Compute a hash of the mangled name of the type.
//
// FIXME: This is not guaranteed to be deterministic! Move to a
@@ -709,7 +734,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
// Blacklist based on the mangled type.
if (!CGM.getContext().getSanitizerBlacklist().isBlacklistedType(
- Out.str())) {
+ SanitizerKind::Vptr, Out.str())) {
llvm::hash_code TypeHash = hash_value(Out.str());
// Load the vptr, and compute hash_16_bytes(TypeHash, vptr).
@@ -789,6 +814,45 @@ static bool isFlexibleArrayMemberExpr(const Expr *E) {
return false;
}
+llvm::Value *CodeGenFunction::LoadPassedObjectSize(const Expr *E,
+ QualType EltTy) {
+ ASTContext &C = getContext();
+ uint64_t EltSize = C.getTypeSizeInChars(EltTy).getQuantity();
+ if (!EltSize)
+ return nullptr;
+
+ auto *ArrayDeclRef = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts());
+ if (!ArrayDeclRef)
+ return nullptr;
+
+ auto *ParamDecl = dyn_cast<ParmVarDecl>(ArrayDeclRef->getDecl());
+ if (!ParamDecl)
+ return nullptr;
+
+ auto *POSAttr = ParamDecl->getAttr<PassObjectSizeAttr>();
+ if (!POSAttr)
+ return nullptr;
+
+ // Don't load the size if it's a lower bound.
+ int POSType = POSAttr->getType();
+ if (POSType != 0 && POSType != 1)
+ return nullptr;
+
+ // Find the implicit size parameter.
+ auto PassedSizeIt = SizeArguments.find(ParamDecl);
+ if (PassedSizeIt == SizeArguments.end())
+ return nullptr;
+
+ const ImplicitParamDecl *PassedSizeDecl = PassedSizeIt->second;
+ assert(LocalDeclMap.count(PassedSizeDecl) && "Passed size not loadable");
+ Address AddrOfSize = LocalDeclMap.find(PassedSizeDecl)->second;
+ llvm::Value *SizeInBytes = EmitLoadOfScalar(AddrOfSize, /*Volatile=*/false,
+ C.getSizeType(), E->getExprLoc());
+ llvm::Value *SizeOfElement =
+ llvm::ConstantInt::get(SizeInBytes->getType(), EltSize);
+ return Builder.CreateUDiv(SizeInBytes, SizeOfElement);
+}
+
/// If Base is known to point to the start of an array, return the length of
/// that array. Return 0 if the length cannot be determined.
static llvm::Value *getArrayIndexingBound(
@@ -810,9 +874,16 @@ static llvm::Value *getArrayIndexingBound(
return CGF.Builder.getInt(CAT->getSize());
else if (const auto *VAT = dyn_cast<VariableArrayType>(AT))
return CGF.getVLASize(VAT).first;
+ // Ignore pass_object_size here. It's not applicable on decayed pointers.
}
}
+ QualType EltTy{Base->getType()->getPointeeOrArrayElementType(), 0};
+ if (llvm::Value *POS = CGF.LoadPassedObjectSize(Base, EltTy)) {
+ IndexedType = Base->getType();
+ return POS;
+ }
+
return nullptr;
}
@@ -894,7 +965,8 @@ void CodeGenModule::EmitExplicitCastExprType(const ExplicitCastExpr *E,
/// EmitPointerWithAlignment - Given an expression of pointer type, try to
/// derive a more accurate bound on the alignment of the pointer.
Address CodeGenFunction::EmitPointerWithAlignment(const Expr *E,
- LValueBaseInfo *BaseInfo) {
+ LValueBaseInfo *BaseInfo,
+ TBAAAccessInfo *TBAAInfo) {
// We allow this with ObjC object pointers because of fragile ABIs.
assert(E->getType()->isPointerType() ||
E->getType()->isObjCObjectPointerType());
@@ -909,24 +981,35 @@ Address CodeGenFunction::EmitPointerWithAlignment(const Expr *E,
// Non-converting casts (but not C's implicit conversion from void*).
case CK_BitCast:
case CK_NoOp:
+ case CK_AddressSpaceConversion:
if (auto PtrTy = CE->getSubExpr()->getType()->getAs<PointerType>()) {
if (PtrTy->getPointeeType()->isVoidType())
break;
- LValueBaseInfo InnerInfo;
- Address Addr = EmitPointerWithAlignment(CE->getSubExpr(), &InnerInfo);
- if (BaseInfo) *BaseInfo = InnerInfo;
+ LValueBaseInfo InnerBaseInfo;
+ TBAAAccessInfo InnerTBAAInfo;
+ Address Addr = EmitPointerWithAlignment(CE->getSubExpr(),
+ &InnerBaseInfo,
+ &InnerTBAAInfo);
+ if (BaseInfo) *BaseInfo = InnerBaseInfo;
+ if (TBAAInfo) *TBAAInfo = InnerTBAAInfo;
- // If this is an explicit bitcast, and the source l-value is
- // opaque, honor the alignment of the casted-to type.
- if (isa<ExplicitCastExpr>(CE) &&
- InnerInfo.getAlignmentSource() != AlignmentSource::Decl) {
- LValueBaseInfo ExpInfo;
+ if (isa<ExplicitCastExpr>(CE)) {
+ LValueBaseInfo TargetTypeBaseInfo;
+ TBAAAccessInfo TargetTypeTBAAInfo;
CharUnits Align = getNaturalPointeeTypeAlignment(E->getType(),
- &ExpInfo);
- if (BaseInfo)
- BaseInfo->mergeForCast(ExpInfo);
- Addr = Address(Addr.getPointer(), Align);
+ &TargetTypeBaseInfo,
+ &TargetTypeTBAAInfo);
+ if (TBAAInfo)
+ *TBAAInfo = CGM.mergeTBAAInfoForCast(*TBAAInfo,
+ TargetTypeTBAAInfo);
+ // If the source l-value is opaque, honor the alignment of the
+ // casted-to type.
+ if (InnerBaseInfo.getAlignmentSource() != AlignmentSource::Decl) {
+ if (BaseInfo)
+ BaseInfo->mergeForCast(TargetTypeBaseInfo);
+ Addr = Address(Addr.getPointer(), Align);
+ }
}
if (SanOpts.has(SanitizerKind::CFIUnrelatedCast) &&
@@ -937,19 +1020,22 @@ Address CodeGenFunction::EmitPointerWithAlignment(const Expr *E,
CodeGenFunction::CFITCK_UnrelatedCast,
CE->getLocStart());
}
-
- return Builder.CreateBitCast(Addr, ConvertType(E->getType()));
+ return CE->getCastKind() != CK_AddressSpaceConversion
+ ? Builder.CreateBitCast(Addr, ConvertType(E->getType()))
+ : Builder.CreateAddrSpaceCast(Addr,
+ ConvertType(E->getType()));
}
break;
// Array-to-pointer decay.
case CK_ArrayToPointerDecay:
- return EmitArrayToPointerDecay(CE->getSubExpr(), BaseInfo);
+ return EmitArrayToPointerDecay(CE->getSubExpr(), BaseInfo, TBAAInfo);
// Derived-to-base conversions.
case CK_UncheckedDerivedToBase:
case CK_DerivedToBase: {
- Address Addr = EmitPointerWithAlignment(CE->getSubExpr(), BaseInfo);
+ Address Addr = EmitPointerWithAlignment(CE->getSubExpr(), BaseInfo,
+ TBAAInfo);
auto Derived = CE->getSubExpr()->getType()->getPointeeCXXRecordDecl();
return GetAddressOfBaseClass(Addr, Derived,
CE->path_begin(), CE->path_end(),
@@ -969,6 +1055,7 @@ Address CodeGenFunction::EmitPointerWithAlignment(const Expr *E,
if (UO->getOpcode() == UO_AddrOf) {
LValue LV = EmitLValue(UO->getSubExpr());
if (BaseInfo) *BaseInfo = LV.getBaseInfo();
+ if (TBAAInfo) *TBAAInfo = LV.getTBAAInfo();
return LV.getAddress();
}
}
@@ -976,7 +1063,8 @@ Address CodeGenFunction::EmitPointerWithAlignment(const Expr *E,
// TODO: conditional operators, comma.
// Otherwise, use the alignment of the type.
- CharUnits Align = getNaturalPointeeTypeAlignment(E->getType(), BaseInfo);
+ CharUnits Align = getNaturalPointeeTypeAlignment(E->getType(), BaseInfo,
+ TBAAInfo);
return Address(EmitScalarExpr(E), Align);
}
@@ -1145,8 +1233,7 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
llvm::Value *V = LV.getPointer();
Scope.ForceCleanup({&V});
return LValue::MakeAddr(Address(V, LV.getAlignment()), LV.getType(),
- getContext(), LV.getBaseInfo(),
- LV.getTBAAInfo());
+ getContext(), LV.getBaseInfo(), LV.getTBAAInfo());
}
// FIXME: Is it possible to create an ExprWithCleanups that produces a
// bitfield lvalue or some other non-simple lvalue?
@@ -1303,7 +1390,8 @@ CodeGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) {
return ConstantEmission();
// Emit as a constant.
- llvm::Constant *C = CGM.EmitConstantValue(result.Val, resultType, this);
+ auto C = ConstantEmitter(*this).emitAbstract(refExpr->getLocation(),
+ result.Val, resultType);
// Make sure we emit a debug reference to the global variable.
// This should probably fire even for
@@ -1322,13 +1410,30 @@ CodeGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) {
return ConstantEmission::forValue(C);
}
+static DeclRefExpr *tryToConvertMemberExprToDeclRefExpr(CodeGenFunction &CGF,
+ const MemberExpr *ME) {
+ if (auto *VD = dyn_cast<VarDecl>(ME->getMemberDecl())) {
+ // Try to emit static variable member expressions as DREs.
+ return DeclRefExpr::Create(
+ CGF.getContext(), NestedNameSpecifierLoc(), SourceLocation(), VD,
+ /*RefersToEnclosingVariableOrCapture=*/false, ME->getExprLoc(),
+ ME->getType(), ME->getValueKind());
+ }
+ return nullptr;
+}
+
+CodeGenFunction::ConstantEmission
+CodeGenFunction::tryEmitAsConstant(const MemberExpr *ME) {
+ if (DeclRefExpr *DRE = tryToConvertMemberExprToDeclRefExpr(*this, ME))
+ return tryEmitAsConstant(DRE);
+ return ConstantEmission();
+}
+
llvm::Value *CodeGenFunction::EmitLoadOfScalar(LValue lvalue,
SourceLocation Loc) {
return EmitLoadOfScalar(lvalue.getAddress(), lvalue.isVolatile(),
lvalue.getType(), Loc, lvalue.getBaseInfo(),
- lvalue.getTBAAInfo(),
- lvalue.getTBAABaseType(), lvalue.getTBAAOffset(),
- lvalue.isNontemporal());
+ lvalue.getTBAAInfo(), lvalue.isNontemporal());
}
static bool hasBooleanRepresentation(QualType Ty) {
@@ -1412,17 +1517,17 @@ bool CodeGenFunction::EmitScalarRangeCheck(llvm::Value *Value, QualType Ty,
if (!getRangeForType(*this, Ty, Min, End, /*StrictEnums=*/true, IsBool))
return true;
+ auto &Ctx = getLLVMContext();
SanitizerScope SanScope(this);
llvm::Value *Check;
--End;
if (!Min) {
- Check = Builder.CreateICmpULE(
- Value, llvm::ConstantInt::get(getLLVMContext(), End));
+ Check = Builder.CreateICmpULE(Value, llvm::ConstantInt::get(Ctx, End));
} else {
- llvm::Value *Upper = Builder.CreateICmpSLE(
- Value, llvm::ConstantInt::get(getLLVMContext(), End));
- llvm::Value *Lower = Builder.CreateICmpSGE(
- Value, llvm::ConstantInt::get(getLLVMContext(), Min));
+ llvm::Value *Upper =
+ Builder.CreateICmpSLE(Value, llvm::ConstantInt::get(Ctx, End));
+ llvm::Value *Lower =
+ Builder.CreateICmpSGE(Value, llvm::ConstantInt::get(Ctx, Min));
Check = Builder.CreateAnd(Upper, Lower);
}
llvm::Constant *StaticArgs[] = {EmitCheckSourceLocation(Loc),
@@ -1438,9 +1543,7 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile,
QualType Ty,
SourceLocation Loc,
LValueBaseInfo BaseInfo,
- llvm::MDNode *TBAAInfo,
- QualType TBAABaseType,
- uint64_t TBAAOffset,
+ TBAAAccessInfo TBAAInfo,
bool isNontemporal) {
if (!CGM.getCodeGenOpts().PreserveVec3Type) {
// For better performance, handle vector loads differently.
@@ -1480,14 +1583,8 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile,
Load->getContext(), llvm::ConstantAsMetadata::get(Builder.getInt32(1)));
Load->setMetadata(CGM.getModule().getMDKindID("nontemporal"), Node);
}
- if (TBAAInfo) {
- bool MayAlias = BaseInfo.getMayAlias();
- llvm::MDNode *TBAA = MayAlias
- ? CGM.getTBAAInfo(getContext().CharTy)
- : CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo, TBAAOffset);
- if (TBAA)
- CGM.DecorateInstructionWithTBAA(Load, TBAA, MayAlias);
- }
+
+ CGM.DecorateInstructionWithTBAA(Load, TBAAInfo);
if (EmitScalarRangeCheck(Load, Ty, Loc)) {
// In order to prevent the optimizer from throwing away the check, don't
@@ -1527,11 +1624,8 @@ llvm::Value *CodeGenFunction::EmitFromMemory(llvm::Value *Value, QualType Ty) {
void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, Address Addr,
bool Volatile, QualType Ty,
LValueBaseInfo BaseInfo,
- llvm::MDNode *TBAAInfo,
- bool isInit, QualType TBAABaseType,
- uint64_t TBAAOffset,
- bool isNontemporal) {
-
+ TBAAAccessInfo TBAAInfo,
+ bool isInit, bool isNontemporal) {
if (!CGM.getCodeGenOpts().PreserveVec3Type) {
// Handle vectors differently to get better performance.
if (Ty->isVectorType()) {
@@ -1571,22 +1665,15 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, Address Addr,
llvm::ConstantAsMetadata::get(Builder.getInt32(1)));
Store->setMetadata(CGM.getModule().getMDKindID("nontemporal"), Node);
}
- if (TBAAInfo) {
- bool MayAlias = BaseInfo.getMayAlias();
- llvm::MDNode *TBAA = MayAlias
- ? CGM.getTBAAInfo(getContext().CharTy)
- : CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo, TBAAOffset);
- if (TBAA)
- CGM.DecorateInstructionWithTBAA(Store, TBAA, MayAlias);
- }
+
+ CGM.DecorateInstructionWithTBAA(Store, TBAAInfo);
}
void CodeGenFunction::EmitStoreOfScalar(llvm::Value *value, LValue lvalue,
bool isInit) {
EmitStoreOfScalar(value, lvalue.getAddress(), lvalue.isVolatile(),
lvalue.getType(), lvalue.getBaseInfo(),
- lvalue.getTBAAInfo(), isInit, lvalue.getTBAABaseType(),
- lvalue.getTBAAOffset(), lvalue.isNontemporal());
+ lvalue.getTBAAInfo(), isInit, lvalue.isNontemporal());
}
/// EmitLoadOfLValue - Given an expression that represents a value lvalue, this
@@ -2116,39 +2203,48 @@ static LValue EmitThreadPrivateVarDeclLValue(
llvm::Type *RealVarTy, SourceLocation Loc) {
Addr = CGF.CGM.getOpenMPRuntime().getAddrOfThreadPrivate(CGF, VD, Addr, Loc);
Addr = CGF.Builder.CreateElementBitCast(Addr, RealVarTy);
- LValueBaseInfo BaseInfo(AlignmentSource::Decl, false);
- return CGF.MakeAddrLValue(Addr, T, BaseInfo);
+ return CGF.MakeAddrLValue(Addr, T, AlignmentSource::Decl);
}
-Address CodeGenFunction::EmitLoadOfReference(Address Addr,
- const ReferenceType *RefTy,
- LValueBaseInfo *BaseInfo) {
- llvm::Value *Ptr = Builder.CreateLoad(Addr);
- return Address(Ptr, getNaturalTypeAlignment(RefTy->getPointeeType(),
- BaseInfo, /*forPointee*/ true));
+Address
+CodeGenFunction::EmitLoadOfReference(LValue RefLVal,
+ LValueBaseInfo *PointeeBaseInfo,
+ TBAAAccessInfo *PointeeTBAAInfo) {
+ llvm::LoadInst *Load = Builder.CreateLoad(RefLVal.getAddress(),
+ RefLVal.isVolatile());
+ CGM.DecorateInstructionWithTBAA(Load, RefLVal.getTBAAInfo());
+
+ CharUnits Align = getNaturalTypeAlignment(RefLVal.getType()->getPointeeType(),
+ PointeeBaseInfo, PointeeTBAAInfo,
+ /* forPointeeType= */ true);
+ return Address(Load, Align);
}
-LValue CodeGenFunction::EmitLoadOfReferenceLValue(Address RefAddr,
- const ReferenceType *RefTy) {
- LValueBaseInfo BaseInfo;
- Address Addr = EmitLoadOfReference(RefAddr, RefTy, &BaseInfo);
- return MakeAddrLValue(Addr, RefTy->getPointeeType(), BaseInfo);
+LValue CodeGenFunction::EmitLoadOfReferenceLValue(LValue RefLVal) {
+ LValueBaseInfo PointeeBaseInfo;
+ TBAAAccessInfo PointeeTBAAInfo;
+ Address PointeeAddr = EmitLoadOfReference(RefLVal, &PointeeBaseInfo,
+ &PointeeTBAAInfo);
+ return MakeAddrLValue(PointeeAddr, RefLVal.getType()->getPointeeType(),
+ PointeeBaseInfo, PointeeTBAAInfo);
}
Address CodeGenFunction::EmitLoadOfPointer(Address Ptr,
const PointerType *PtrTy,
- LValueBaseInfo *BaseInfo) {
+ LValueBaseInfo *BaseInfo,
+ TBAAAccessInfo *TBAAInfo) {
llvm::Value *Addr = Builder.CreateLoad(Ptr);
return Address(Addr, getNaturalTypeAlignment(PtrTy->getPointeeType(),
- BaseInfo,
+ BaseInfo, TBAAInfo,
/*forPointeeType=*/true));
}
LValue CodeGenFunction::EmitLoadOfPointerLValue(Address PtrAddr,
const PointerType *PtrTy) {
LValueBaseInfo BaseInfo;
- Address Addr = EmitLoadOfPointer(PtrAddr, PtrTy, &BaseInfo);
- return MakeAddrLValue(Addr, PtrTy->getPointeeType(), BaseInfo);
+ TBAAAccessInfo TBAAInfo;
+ Address Addr = EmitLoadOfPointer(PtrAddr, PtrTy, &BaseInfo, &TBAAInfo);
+ return MakeAddrLValue(Addr, PtrTy->getPointeeType(), BaseInfo, TBAAInfo);
}
static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF,
@@ -2165,18 +2261,15 @@ static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF,
V = EmitBitCastOfLValueToProperType(CGF, V, RealVarTy);
CharUnits Alignment = CGF.getContext().getDeclAlign(VD);
Address Addr(V, Alignment);
- LValue LV;
// Emit reference to the private copy of the variable if it is an OpenMP
// threadprivate variable.
if (CGF.getLangOpts().OpenMP && VD->hasAttr<OMPThreadPrivateDeclAttr>())
return EmitThreadPrivateVarDeclLValue(CGF, VD, T, Addr, RealVarTy,
E->getExprLoc());
- if (auto RefTy = VD->getType()->getAs<ReferenceType>()) {
- LV = CGF.EmitLoadOfReferenceLValue(Addr, RefTy);
- } else {
- LValueBaseInfo BaseInfo(AlignmentSource::Decl, false);
- LV = CGF.MakeAddrLValue(Addr, T, BaseInfo);
- }
+ LValue LV = VD->getType()->isReferenceType() ?
+ CGF.EmitLoadOfReferenceLValue(Addr, VD->getType(),
+ AlignmentSource::Decl) :
+ CGF.MakeAddrLValue(Addr, T, AlignmentSource::Decl);
setObjCGCLValueClass(CGF.getContext(), E, LV);
return LV;
}
@@ -2209,8 +2302,8 @@ static LValue EmitFunctionDeclLValue(CodeGenFunction &CGF,
const Expr *E, const FunctionDecl *FD) {
llvm::Value *V = EmitFunctionDeclPointer(CGF.CGM, FD);
CharUnits Alignment = CGF.getContext().getDeclAlign(FD);
- LValueBaseInfo BaseInfo(AlignmentSource::Decl, false);
- return CGF.MakeAddrLValue(V, E->getType(), Alignment, BaseInfo);
+ return CGF.MakeAddrLValue(V, E->getType(), Alignment,
+ AlignmentSource::Decl);
}
static LValue EmitCapturedFieldLValue(CodeGenFunction &CGF, const FieldDecl *FD,
@@ -2265,44 +2358,52 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
VD->isUsableInConstantExpressions(getContext()) &&
VD->checkInitIsICE() &&
// Do not emit if it is private OpenMP variable.
- !(E->refersToEnclosingVariableOrCapture() && CapturedStmtInfo &&
- LocalDeclMap.count(VD))) {
+ !(E->refersToEnclosingVariableOrCapture() &&
+ ((CapturedStmtInfo &&
+ (LocalDeclMap.count(VD->getCanonicalDecl()) ||
+ CapturedStmtInfo->lookup(VD->getCanonicalDecl()))) ||
+ LambdaCaptureFields.lookup(VD->getCanonicalDecl()) ||
+ isa<BlockDecl>(CurCodeDecl)))) {
llvm::Constant *Val =
- CGM.EmitConstantValue(*VD->evaluateValue(), VD->getType(), this);
+ ConstantEmitter(*this).emitAbstract(E->getLocation(),
+ *VD->evaluateValue(),
+ VD->getType());
assert(Val && "failed to emit reference constant expression");
// FIXME: Eventually we will want to emit vector element references.
// Should we be using the alignment of the constant pointer we emitted?
- CharUnits Alignment = getNaturalTypeAlignment(E->getType(), nullptr,
- /*pointee*/ true);
- LValueBaseInfo BaseInfo(AlignmentSource::Decl, false);
- return MakeAddrLValue(Address(Val, Alignment), T, BaseInfo);
+ CharUnits Alignment = getNaturalTypeAlignment(E->getType(),
+ /* BaseInfo= */ nullptr,
+ /* TBAAInfo= */ nullptr,
+ /* forPointeeType= */ true);
+ return MakeAddrLValue(Address(Val, Alignment), T, AlignmentSource::Decl);
}
// Check for captured variables.
if (E->refersToEnclosingVariableOrCapture()) {
+ VD = VD->getCanonicalDecl();
if (auto *FD = LambdaCaptureFields.lookup(VD))
return EmitCapturedFieldLValue(*this, FD, CXXABIThisValue);
else if (CapturedStmtInfo) {
auto I = LocalDeclMap.find(VD);
if (I != LocalDeclMap.end()) {
- if (auto RefTy = VD->getType()->getAs<ReferenceType>())
- return EmitLoadOfReferenceLValue(I->second, RefTy);
+ if (VD->getType()->isReferenceType())
+ return EmitLoadOfReferenceLValue(I->second, VD->getType(),
+ AlignmentSource::Decl);
return MakeAddrLValue(I->second, T);
}
LValue CapLVal =
EmitCapturedFieldLValue(*this, CapturedStmtInfo->lookup(VD),
CapturedStmtInfo->getContextValue());
- bool MayAlias = CapLVal.getBaseInfo().getMayAlias();
return MakeAddrLValue(
Address(CapLVal.getPointer(), getContext().getDeclAlign(VD)),
- CapLVal.getType(), LValueBaseInfo(AlignmentSource::Decl, MayAlias));
+ CapLVal.getType(), LValueBaseInfo(AlignmentSource::Decl),
+ CapLVal.getTBAAInfo());
}
assert(isa<BlockDecl>(CurCodeDecl));
Address addr = GetAddrOfBlockDecl(VD, VD->hasAttr<BlocksAttr>());
- LValueBaseInfo BaseInfo(AlignmentSource::Decl, false);
- return MakeAddrLValue(addr, T, BaseInfo);
+ return MakeAddrLValue(addr, T, AlignmentSource::Decl);
}
}
@@ -2316,8 +2417,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
if (ND->hasAttr<WeakRefAttr>()) {
const auto *VD = cast<ValueDecl>(ND);
ConstantAddress Aliasee = CGM.GetWeakRefReference(VD);
- return MakeAddrLValue(Aliasee, T,
- LValueBaseInfo(AlignmentSource::Decl, false));
+ return MakeAddrLValue(Aliasee, T, AlignmentSource::Decl);
}
if (const auto *VD = dyn_cast<VarDecl>(ND)) {
@@ -2359,13 +2459,9 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
}
// Drill into reference types.
- LValue LV;
- if (auto RefTy = VD->getType()->getAs<ReferenceType>()) {
- LV = EmitLoadOfReferenceLValue(addr, RefTy);
- } else {
- LValueBaseInfo BaseInfo(AlignmentSource::Decl, false);
- LV = MakeAddrLValue(addr, T, BaseInfo);
- }
+ LValue LV = VD->getType()->isReferenceType() ?
+ EmitLoadOfReferenceLValue(addr, VD->getType(), AlignmentSource::Decl) :
+ MakeAddrLValue(addr, T, AlignmentSource::Decl);
bool isLocalStorage = VD->hasLocalStorage();
@@ -2410,8 +2506,10 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
assert(!T.isNull() && "CodeGenFunction::EmitUnaryOpLValue: Illegal type");
LValueBaseInfo BaseInfo;
- Address Addr = EmitPointerWithAlignment(E->getSubExpr(), &BaseInfo);
- LValue LV = MakeAddrLValue(Addr, T, BaseInfo);
+ TBAAAccessInfo TBAAInfo;
+ Address Addr = EmitPointerWithAlignment(E->getSubExpr(), &BaseInfo,
+ &TBAAInfo);
+ LValue LV = MakeAddrLValue(Addr, T, BaseInfo, TBAAInfo);
LV.getQuals().setAddressSpace(ExprTy.getAddressSpace());
// We should not generate __weak write barrier on indirect reference
@@ -2443,7 +2541,8 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
(E->getOpcode() == UO_Real
? emitAddrOfRealComponent(LV.getAddress(), LV.getType())
: emitAddrOfImagComponent(LV.getAddress(), LV.getType()));
- LValue ElemLV = MakeAddrLValue(Component, T, LV.getBaseInfo());
+ LValue ElemLV = MakeAddrLValue(Component, T, LV.getBaseInfo(),
+ CGM.getTBAAInfoForSubobject(LV, T));
ElemLV.getQuals().addQualifiers(LV.getQuals());
return ElemLV;
}
@@ -2463,14 +2562,12 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
LValue CodeGenFunction::EmitStringLiteralLValue(const StringLiteral *E) {
return MakeAddrLValue(CGM.GetAddrOfConstantStringFromLiteral(E),
- E->getType(),
- LValueBaseInfo(AlignmentSource::Decl, false));
+ E->getType(), AlignmentSource::Decl);
}
LValue CodeGenFunction::EmitObjCEncodeExprLValue(const ObjCEncodeExpr *E) {
return MakeAddrLValue(CGM.GetAddrOfConstantStringFromObjCEncode(E),
- E->getType(),
- LValueBaseInfo(AlignmentSource::Decl, false));
+ E->getType(), AlignmentSource::Decl);
}
LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
@@ -2482,7 +2579,6 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
StringRef NameItems[] = {
PredefinedExpr::getIdentTypeName(E->getIdentType()), FnName};
std::string GVName = llvm::join(NameItems, NameItems + 2, ".");
- LValueBaseInfo BaseInfo(AlignmentSource::Decl, false);
if (auto *BD = dyn_cast<BlockDecl>(CurCodeDecl)) {
std::string Name = SL->getString();
if (!Name.empty()) {
@@ -2491,14 +2587,14 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
if (Discriminator)
Name += "_" + Twine(Discriminator + 1).str();
auto C = CGM.GetAddrOfConstantCString(Name, GVName.c_str());
- return MakeAddrLValue(C, E->getType(), BaseInfo);
+ return MakeAddrLValue(C, E->getType(), AlignmentSource::Decl);
} else {
auto C = CGM.GetAddrOfConstantCString(FnName, GVName.c_str());
- return MakeAddrLValue(C, E->getType(), BaseInfo);
+ return MakeAddrLValue(C, E->getType(), AlignmentSource::Decl);
}
}
auto C = CGM.GetAddrOfConstantStringFromLiteral(SL, GVName);
- return MakeAddrLValue(C, E->getType(), BaseInfo);
+ return MakeAddrLValue(C, E->getType(), AlignmentSource::Decl);
}
/// Emit a type description suitable for use by a runtime sanitizer library. The
@@ -2556,6 +2652,9 @@ llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) {
llvm::Value *CodeGenFunction::EmitCheckValue(llvm::Value *V) {
llvm::Type *TargetTy = IntPtrTy;
+ if (V->getType() == TargetTy)
+ return V;
+
// Floating-point types which fit into intptr_t are bitcast to integers
// and then passed directly (after zero-extension, if necessary).
if (V->getType()->isFloatingPointTy()) {
@@ -2685,13 +2784,16 @@ static void emitCheckHandlerCall(CodeGenFunction &CGF,
assert(IsFatal || RecoverKind != CheckRecoverableKind::Unrecoverable);
bool NeedsAbortSuffix =
IsFatal && RecoverKind != CheckRecoverableKind::Unrecoverable;
+ bool MinimalRuntime = CGF.CGM.getCodeGenOpts().SanitizeMinimalRuntime;
const SanitizerHandlerInfo &CheckInfo = SanitizerHandlers[CheckHandler];
const StringRef CheckName = CheckInfo.Name;
- std::string FnName =
- ("__ubsan_handle_" + CheckName +
- (CheckInfo.Version ? "_v" + llvm::utostr(CheckInfo.Version) : "") +
- (NeedsAbortSuffix ? "_abort" : ""))
- .str();
+ std::string FnName = "__ubsan_handle_" + CheckName.str();
+ if (CheckInfo.Version && !MinimalRuntime)
+ FnName += "_v" + llvm::utostr(CheckInfo.Version);
+ if (MinimalRuntime)
+ FnName += "_minimal";
+ if (NeedsAbortSuffix)
+ FnName += "_abort";
bool MayReturn =
!IsFatal || RecoverKind == CheckRecoverableKind::AlwaysRecoverable;
@@ -2723,7 +2825,7 @@ void CodeGenFunction::EmitCheck(
assert(IsSanitizerScope);
assert(Checked.size() > 0);
assert(CheckHandler >= 0 &&
- CheckHandler < sizeof(SanitizerHandlers) / sizeof(*SanitizerHandlers));
+ size_t(CheckHandler) < llvm::array_lengthof(SanitizerHandlers));
const StringRef CheckName = SanitizerHandlers[CheckHandler].Name;
llvm::Value *FatalCond = nullptr;
@@ -2778,24 +2880,26 @@ void CodeGenFunction::EmitCheck(
// representing operand values.
SmallVector<llvm::Value *, 4> Args;
SmallVector<llvm::Type *, 4> ArgTypes;
- Args.reserve(DynamicArgs.size() + 1);
- ArgTypes.reserve(DynamicArgs.size() + 1);
+ if (!CGM.getCodeGenOpts().SanitizeMinimalRuntime) {
+ Args.reserve(DynamicArgs.size() + 1);
+ ArgTypes.reserve(DynamicArgs.size() + 1);
- // Emit handler arguments and create handler function type.
- if (!StaticArgs.empty()) {
- llvm::Constant *Info = llvm::ConstantStruct::getAnon(StaticArgs);
- auto *InfoPtr =
- new llvm::GlobalVariable(CGM.getModule(), Info->getType(), false,
- llvm::GlobalVariable::PrivateLinkage, Info);
- InfoPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
- CGM.getSanitizerMetadata()->disableSanitizerForGlobal(InfoPtr);
- Args.push_back(Builder.CreateBitCast(InfoPtr, Int8PtrTy));
- ArgTypes.push_back(Int8PtrTy);
- }
+ // Emit handler arguments and create handler function type.
+ if (!StaticArgs.empty()) {
+ llvm::Constant *Info = llvm::ConstantStruct::getAnon(StaticArgs);
+ auto *InfoPtr =
+ new llvm::GlobalVariable(CGM.getModule(), Info->getType(), false,
+ llvm::GlobalVariable::PrivateLinkage, Info);
+ InfoPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
+ CGM.getSanitizerMetadata()->disableSanitizerForGlobal(InfoPtr);
+ Args.push_back(Builder.CreateBitCast(InfoPtr, Int8PtrTy));
+ ArgTypes.push_back(Int8PtrTy);
+ }
- for (size_t i = 0, n = DynamicArgs.size(); i != n; ++i) {
- Args.push_back(EmitCheckValue(DynamicArgs[i]));
- ArgTypes.push_back(IntPtrTy);
+ for (size_t i = 0, n = DynamicArgs.size(); i != n; ++i) {
+ Args.push_back(EmitCheckValue(DynamicArgs[i]));
+ ArgTypes.push_back(IntPtrTy);
+ }
}
llvm::FunctionType *FnType =
@@ -3005,14 +3109,14 @@ llvm::CallInst *CodeGenFunction::EmitTrapCall(llvm::Intrinsic::ID IntrID) {
}
Address CodeGenFunction::EmitArrayToPointerDecay(const Expr *E,
- LValueBaseInfo *BaseInfo) {
+ LValueBaseInfo *BaseInfo,
+ TBAAAccessInfo *TBAAInfo) {
assert(E->getType()->isArrayType() &&
"Array to pointer decay must have array source type!");
// Expressions of array type can't be bitfields or vector elements.
LValue LV = EmitLValue(E);
Address Addr = LV.getAddress();
- if (BaseInfo) *BaseInfo = LV.getBaseInfo();
// If the array type was an incomplete type, we need to make sure
// the decay ends up being the right type.
@@ -3027,7 +3131,15 @@ Address CodeGenFunction::EmitArrayToPointerDecay(const Expr *E,
Addr = Builder.CreateStructGEP(Addr, 0, CharUnits::Zero(), "arraydecay");
}
+ // The result of this decay conversion points to an array element within the
+ // base lvalue. However, since TBAA currently does not support representing
+ // accesses to elements of member arrays, we conservatively represent accesses
+ // to the pointee object as if it had no any base lvalue specified.
+ // TODO: Support TBAA for member arrays.
QualType EltType = E->getType()->castAsArrayTypeUnsafe()->getElementType();
+ if (BaseInfo) *BaseInfo = LV.getBaseInfo();
+ if (TBAAInfo) *TBAAInfo = CGM.getTBAAAccessInfo(EltType);
+
return Builder.CreateElementBitCast(Addr, ConvertTypeForMem(EltType));
}
@@ -3152,9 +3264,8 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
LValue LHS = EmitLValue(E->getBase());
auto *Idx = EmitIdxAfterBase(/*Promote*/false);
assert(LHS.isSimple() && "Can only subscript lvalue vectors here!");
- return LValue::MakeVectorElt(LHS.getAddress(), Idx,
- E->getBase()->getType(),
- LHS.getBaseInfo());
+ return LValue::MakeVectorElt(LHS.getAddress(), Idx, E->getBase()->getType(),
+ LHS.getBaseInfo(), TBAAAccessInfo());
}
// All the other cases basically behave like simple offsetting.
@@ -3168,17 +3279,19 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
QualType EltType = LV.getType()->castAs<VectorType>()->getElementType();
Addr = emitArraySubscriptGEP(*this, Addr, Idx, EltType, /*inbounds*/ true,
SignedIndices, E->getExprLoc());
- return MakeAddrLValue(Addr, EltType, LV.getBaseInfo());
+ return MakeAddrLValue(Addr, EltType, LV.getBaseInfo(),
+ CGM.getTBAAInfoForSubobject(LV, EltType));
}
- LValueBaseInfo BaseInfo;
+ LValueBaseInfo EltBaseInfo;
+ TBAAAccessInfo EltTBAAInfo;
Address Addr = Address::invalid();
if (const VariableArrayType *vla =
getContext().getAsVariableArrayType(E->getType())) {
// The base must be a pointer, which is not an aggregate. Emit
// it. It needs to be emitted first in case it's what captures
// the VLA bounds.
- Addr = EmitPointerWithAlignment(E->getBase(), &BaseInfo);
+ Addr = EmitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo);
auto *Idx = EmitIdxAfterBase(/*Promote*/true);
// The element count here is the total number of non-VLA elements.
@@ -3202,7 +3315,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
// Indexing over an interface, as in "NSString *P; P[4];"
// Emit the base pointer.
- Addr = EmitPointerWithAlignment(E->getBase(), &BaseInfo);
+ Addr = EmitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo);
auto *Idx = EmitIdxAfterBase(/*Promote*/true);
CharUnits InterfaceSize = getContext().getTypeSizeInChars(OIT);
@@ -3249,19 +3362,18 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
*this, ArrayLV.getAddress(), {CGM.getSize(CharUnits::Zero()), Idx},
E->getType(), !getLangOpts().isSignedOverflowDefined(), SignedIndices,
E->getExprLoc());
- BaseInfo = ArrayLV.getBaseInfo();
+ EltBaseInfo = ArrayLV.getBaseInfo();
+ EltTBAAInfo = CGM.getTBAAInfoForSubobject(ArrayLV, E->getType());
} else {
// The base must be a pointer; emit it with an estimate of its alignment.
- Addr = EmitPointerWithAlignment(E->getBase(), &BaseInfo);
+ Addr = EmitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo);
auto *Idx = EmitIdxAfterBase(/*Promote*/true);
Addr = emitArraySubscriptGEP(*this, Addr, Idx, E->getType(),
!getLangOpts().isSignedOverflowDefined(),
SignedIndices, E->getExprLoc());
}
- LValue LV = MakeAddrLValue(Addr, E->getType(), BaseInfo);
-
- // TODO: Preserve/extend path TBAA metadata?
+ LValue LV = MakeAddrLValue(Addr, E->getType(), EltBaseInfo, EltTBAAInfo);
if (getLangOpts().ObjC1 &&
getLangOpts().getGC() != LangOptions::NonGC) {
@@ -3273,6 +3385,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
static Address emitOMPArraySectionBase(CodeGenFunction &CGF, const Expr *Base,
LValueBaseInfo &BaseInfo,
+ TBAAAccessInfo &TBAAInfo,
QualType BaseTy, QualType ElTy,
bool IsLowerBound) {
LValue BaseLVal;
@@ -3299,12 +3412,15 @@ static Address emitOMPArraySectionBase(CodeGenFunction &CGF, const Expr *Base,
return CGF.Builder.CreateElementBitCast(Addr,
CGF.ConvertTypeForMem(ElTy));
}
- LValueBaseInfo TypeInfo;
- CharUnits Align = CGF.getNaturalTypeAlignment(ElTy, &TypeInfo);
- BaseInfo.mergeForCast(TypeInfo);
+ LValueBaseInfo TypeBaseInfo;
+ TBAAAccessInfo TypeTBAAInfo;
+ CharUnits Align = CGF.getNaturalTypeAlignment(ElTy, &TypeBaseInfo,
+ &TypeTBAAInfo);
+ BaseInfo.mergeForCast(TypeBaseInfo);
+ TBAAInfo = CGF.CGM.mergeTBAAInfoForCast(TBAAInfo, TypeTBAAInfo);
return Address(CGF.Builder.CreateLoad(BaseLVal.getAddress()), Align);
}
- return CGF.EmitPointerWithAlignment(Base, &BaseInfo);
+ return CGF.EmitPointerWithAlignment(Base, &BaseInfo, &TBAAInfo);
}
LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E,
@@ -3404,13 +3520,14 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E,
Address EltPtr = Address::invalid();
LValueBaseInfo BaseInfo;
+ TBAAAccessInfo TBAAInfo;
if (auto *VLA = getContext().getAsVariableArrayType(ResultExprTy)) {
// The base must be a pointer, which is not an aggregate. Emit
// it. It needs to be emitted first in case it's what captures
// the VLA bounds.
Address Base =
- emitOMPArraySectionBase(*this, E->getBase(), BaseInfo, BaseTy,
- VLA->getElementType(), IsLowerBound);
+ emitOMPArraySectionBase(*this, E->getBase(), BaseInfo, TBAAInfo,
+ BaseTy, VLA->getElementType(), IsLowerBound);
// The element count here is the total number of non-VLA elements.
llvm::Value *NumElements = getVLASize(VLA).first;
@@ -3446,15 +3563,17 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E,
ResultExprTy, !getLangOpts().isSignedOverflowDefined(),
/*SignedIndices=*/false, E->getExprLoc());
BaseInfo = ArrayLV.getBaseInfo();
+ TBAAInfo = CGM.getTBAAInfoForSubobject(ArrayLV, ResultExprTy);
} else {
Address Base = emitOMPArraySectionBase(*this, E->getBase(), BaseInfo,
- BaseTy, ResultExprTy, IsLowerBound);
+ TBAAInfo, BaseTy, ResultExprTy,
+ IsLowerBound);
EltPtr = emitArraySubscriptGEP(*this, Base, Idx, ResultExprTy,
!getLangOpts().isSignedOverflowDefined(),
/*SignedIndices=*/false, E->getExprLoc());
}
- return MakeAddrLValue(EltPtr, ResultExprTy, BaseInfo);
+ return MakeAddrLValue(EltPtr, ResultExprTy, BaseInfo, TBAAInfo);
}
LValue CodeGenFunction::
@@ -3467,9 +3586,10 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
// If it is a pointer to a vector, emit the address and form an lvalue with
// it.
LValueBaseInfo BaseInfo;
- Address Ptr = EmitPointerWithAlignment(E->getBase(), &BaseInfo);
+ TBAAAccessInfo TBAAInfo;
+ Address Ptr = EmitPointerWithAlignment(E->getBase(), &BaseInfo, &TBAAInfo);
const PointerType *PT = E->getBase()->getType()->getAs<PointerType>();
- Base = MakeAddrLValue(Ptr, PT->getPointeeType(), BaseInfo);
+ Base = MakeAddrLValue(Ptr, PT->getPointeeType(), BaseInfo, TBAAInfo);
Base.getQuals().removeObjCGCAttr();
} else if (E->getBase()->isGLValue()) {
// Otherwise, if the base is an lvalue ( as in the case of foo.x.x),
@@ -3486,7 +3606,7 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
Address VecMem = CreateMemTemp(E->getBase()->getType());
Builder.CreateStore(Vec, VecMem);
Base = MakeAddrLValue(VecMem, E->getBase()->getType(),
- LValueBaseInfo(AlignmentSource::Decl, false));
+ AlignmentSource::Decl);
}
QualType type =
@@ -3500,7 +3620,7 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
llvm::Constant *CV =
llvm::ConstantDataVector::get(getLLVMContext(), Indices);
return LValue::MakeExtVectorElt(Base.getAddress(), CV, type,
- Base.getBaseInfo());
+ Base.getBaseInfo(), TBAAAccessInfo());
}
assert(Base.isExtVectorElt() && "Can only subscript lvalue vec elts here!");
@@ -3511,16 +3631,22 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
CElts.push_back(BaseElts->getAggregateElement(Indices[i]));
llvm::Constant *CV = llvm::ConstantVector::get(CElts);
return LValue::MakeExtVectorElt(Base.getExtVectorAddress(), CV, type,
- Base.getBaseInfo());
+ Base.getBaseInfo(), TBAAAccessInfo());
}
LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
+ if (DeclRefExpr *DRE = tryToConvertMemberExprToDeclRefExpr(*this, E)) {
+ EmitIgnoredExpr(E->getBase());
+ return EmitDeclRefLValue(DRE);
+ }
+
Expr *BaseExpr = E->getBase();
// If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar.
LValue BaseLV;
if (E->isArrow()) {
LValueBaseInfo BaseInfo;
- Address Addr = EmitPointerWithAlignment(BaseExpr, &BaseInfo);
+ TBAAAccessInfo TBAAInfo;
+ Address Addr = EmitPointerWithAlignment(BaseExpr, &BaseInfo, &TBAAInfo);
QualType PtrTy = BaseExpr->getType()->getPointeeType();
SanitizerSet SkippedChecks;
bool IsBaseCXXThis = IsWrappedCXXThis(BaseExpr);
@@ -3530,7 +3656,7 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
SkippedChecks.set(SanitizerKind::Null, true);
EmitTypeCheck(TCK_MemberAccess, E->getExprLoc(), Addr.getPointer(), PtrTy,
/*Alignment=*/CharUnits::Zero(), SkippedChecks);
- BaseLV = MakeAddrLValue(Addr, PtrTy, BaseInfo);
+ BaseLV = MakeAddrLValue(Addr, PtrTy, BaseInfo, TBAAInfo);
} else
BaseLV = EmitCheckedLValue(BaseExpr, TCK_MemberAccess);
@@ -3541,9 +3667,6 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
return LV;
}
- if (auto *VD = dyn_cast<VarDecl>(ND))
- return EmitGlobalVarDeclLValue(*this, E, VD);
-
if (const auto *FD = dyn_cast<FunctionDecl>(ND))
return EmitFunctionDeclLValue(*this, E, FD);
@@ -3610,15 +3733,6 @@ static bool hasAnyVptr(const QualType Type, const ASTContext &Context) {
LValue CodeGenFunction::EmitLValueForField(LValue base,
const FieldDecl *field) {
LValueBaseInfo BaseInfo = base.getBaseInfo();
- AlignmentSource fieldAlignSource =
- getFieldAlignmentSource(BaseInfo.getAlignmentSource());
- LValueBaseInfo FieldBaseInfo(fieldAlignSource, BaseInfo.getMayAlias());
-
- QualType type = field->getType();
- const RecordDecl *rec = field->getParent();
- if (rec->isUnion() || rec->hasAttr<MayAliasAttr>() || type->isVectorType())
- FieldBaseInfo.setMayAlias(true);
- bool mayAlias = FieldBaseInfo.getMayAlias();
if (field->isBitField()) {
const CGRecordLayout &RL =
@@ -3638,19 +3752,53 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
QualType fieldType =
field->getType().withCVRQualifiers(base.getVRQualifiers());
- return LValue::MakeBitfield(Addr, Info, fieldType, FieldBaseInfo);
+ // TODO: Support TBAA for bit fields.
+ LValueBaseInfo FieldBaseInfo(BaseInfo.getAlignmentSource());
+ return LValue::MakeBitfield(Addr, Info, fieldType, FieldBaseInfo,
+ TBAAAccessInfo());
+ }
+
+ // Fields of may-alias structures are may-alias themselves.
+ // FIXME: this should get propagated down through anonymous structs
+ // and unions.
+ QualType FieldType = field->getType();
+ const RecordDecl *rec = field->getParent();
+ AlignmentSource BaseAlignSource = BaseInfo.getAlignmentSource();
+ LValueBaseInfo FieldBaseInfo(getFieldAlignmentSource(BaseAlignSource));
+ TBAAAccessInfo FieldTBAAInfo;
+ if (base.getTBAAInfo().isMayAlias() ||
+ rec->hasAttr<MayAliasAttr>() || FieldType->isVectorType()) {
+ FieldTBAAInfo = TBAAAccessInfo::getMayAliasInfo();
+ } else if (rec->isUnion()) {
+ // TODO: Support TBAA for unions.
+ FieldTBAAInfo = TBAAAccessInfo::getMayAliasInfo();
+ } else {
+ // If no base type been assigned for the base access, then try to generate
+ // one for this base lvalue.
+ FieldTBAAInfo = base.getTBAAInfo();
+ if (!FieldTBAAInfo.BaseType) {
+ FieldTBAAInfo.BaseType = CGM.getTBAABaseTypeInfo(base.getType());
+ assert(!FieldTBAAInfo.Offset &&
+ "Nonzero offset for an access with no base type!");
+ }
+
+ // Adjust offset to be relative to the base type.
+ const ASTRecordLayout &Layout =
+ getContext().getASTRecordLayout(field->getParent());
+ unsigned CharWidth = getContext().getCharWidth();
+ if (FieldTBAAInfo.BaseType)
+ FieldTBAAInfo.Offset +=
+ Layout.getFieldOffset(field->getFieldIndex()) / CharWidth;
+
+ // Update the final access type.
+ FieldTBAAInfo.AccessType = CGM.getTBAATypeInfo(FieldType);
}
Address addr = base.getAddress();
- unsigned cvr = base.getVRQualifiers();
- bool TBAAPath = CGM.getCodeGenOpts().StructPathTBAA;
+ unsigned RecordCVR = base.getVRQualifiers();
if (rec->isUnion()) {
// For unions, there is no pointer adjustment.
- assert(!type->isReferenceType() && "union has reference member");
- // TODO: handle path-aware TBAA for union.
- TBAAPath = false;
-
- const auto FieldType = field->getType();
+ assert(!FieldType->isReferenceType() && "union has reference member");
if (CGM.getCodeGenOpts().StrictVTablePointers &&
hasAnyVptr(FieldType, getContext()))
// Because unions can easily skip invariant.barriers, we need to add
@@ -3662,34 +3810,16 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
addr = emitAddrOfFieldStorage(*this, addr, field);
// If this is a reference field, load the reference right now.
- if (const ReferenceType *refType = type->getAs<ReferenceType>()) {
- llvm::LoadInst *load = Builder.CreateLoad(addr, "ref");
- if (cvr & Qualifiers::Volatile) load->setVolatile(true);
-
- // Loading the reference will disable path-aware TBAA.
- TBAAPath = false;
- if (CGM.shouldUseTBAA()) {
- llvm::MDNode *tbaa;
- if (mayAlias)
- tbaa = CGM.getTBAAInfo(getContext().CharTy);
- else
- tbaa = CGM.getTBAAInfo(type);
- if (tbaa)
- CGM.DecorateInstructionWithTBAA(load, tbaa);
- }
-
- mayAlias = false;
- type = refType->getPointeeType();
-
- CharUnits alignment =
- getNaturalTypeAlignment(type, &FieldBaseInfo, /*pointee*/ true);
- FieldBaseInfo.setMayAlias(false);
- addr = Address(load, alignment);
+ if (FieldType->isReferenceType()) {
+ LValue RefLVal = MakeAddrLValue(addr, FieldType, FieldBaseInfo,
+ FieldTBAAInfo);
+ if (RecordCVR & Qualifiers::Volatile)
+ RefLVal.getQuals().setVolatile(true);
+ addr = EmitLoadOfReference(RefLVal, &FieldBaseInfo, &FieldTBAAInfo);
- // Qualifiers on the struct don't apply to the referencee, and
- // we'll pick up CVR from the actual type later, so reset these
- // additional qualifiers now.
- cvr = 0;
+ // Qualifiers on the struct don't apply to the referencee.
+ RecordCVR = 0;
+ FieldType = FieldType->getPointeeType();
}
}
@@ -3697,36 +3827,19 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
// for both unions and structs. A union needs a bitcast, a struct element
// will need a bitcast if the LLVM type laid out doesn't match the desired
// type.
- addr = Builder.CreateElementBitCast(addr,
- CGM.getTypes().ConvertTypeForMem(type),
- field->getName());
+ addr = Builder.CreateElementBitCast(
+ addr, CGM.getTypes().ConvertTypeForMem(FieldType), field->getName());
if (field->hasAttr<AnnotateAttr>())
addr = EmitFieldAnnotations(field, addr);
- LValue LV = MakeAddrLValue(addr, type, FieldBaseInfo);
- LV.getQuals().addCVRQualifiers(cvr);
- if (TBAAPath) {
- const ASTRecordLayout &Layout =
- getContext().getASTRecordLayout(field->getParent());
- // Set the base type to be the base type of the base LValue and
- // update offset to be relative to the base type.
- LV.setTBAABaseType(mayAlias ? getContext().CharTy : base.getTBAABaseType());
- LV.setTBAAOffset(mayAlias ? 0 : base.getTBAAOffset() +
- Layout.getFieldOffset(field->getFieldIndex()) /
- getContext().getCharWidth());
- }
+ LValue LV = MakeAddrLValue(addr, FieldType, FieldBaseInfo, FieldTBAAInfo);
+ LV.getQuals().addCVRQualifiers(RecordCVR);
// __weak attribute on a field is ignored.
if (LV.getQuals().getObjCGCAttr() == Qualifiers::Weak)
LV.getQuals().removeObjCGCAttr();
- // Fields of may_alias structs act like 'char' for TBAA purposes.
- // FIXME: this should get propagated down through anonymous structs
- // and unions.
- if (mayAlias && LV.getTBAAInfo())
- LV.setTBAAInfo(CGM.getTBAAInfo(getContext().CharTy));
-
return LV;
}
@@ -3744,19 +3857,20 @@ CodeGenFunction::EmitLValueForFieldInitialization(LValue Base,
llvm::Type *llvmType = ConvertTypeForMem(FieldType);
V = Builder.CreateElementBitCast(V, llvmType, Field->getName());
- // TODO: access-path TBAA?
+ // TODO: Generate TBAA information that describes this access as a structure
+ // member access and not just an access to an object of the field's type. This
+ // should be similar to what we do in EmitLValueForField().
LValueBaseInfo BaseInfo = Base.getBaseInfo();
- LValueBaseInfo FieldBaseInfo(
- getFieldAlignmentSource(BaseInfo.getAlignmentSource()),
- BaseInfo.getMayAlias());
- return MakeAddrLValue(V, FieldType, FieldBaseInfo);
+ AlignmentSource FieldAlignSource = BaseInfo.getAlignmentSource();
+ LValueBaseInfo FieldBaseInfo(getFieldAlignmentSource(FieldAlignSource));
+ return MakeAddrLValue(V, FieldType, FieldBaseInfo,
+ CGM.getTBAAInfoForSubobject(Base, FieldType));
}
LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr *E){
- LValueBaseInfo BaseInfo(AlignmentSource::Decl, false);
if (E->isFileScope()) {
ConstantAddress GlobalPtr = CGM.GetAddrOfConstantCompoundLiteral(E);
- return MakeAddrLValue(GlobalPtr, E->getType(), BaseInfo);
+ return MakeAddrLValue(GlobalPtr, E->getType(), AlignmentSource::Decl);
}
if (E->getType()->isVariablyModifiedType())
// make sure to emit the VLA size.
@@ -3764,7 +3878,7 @@ LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr *E){
Address DeclPtr = CreateMemTemp(E->getType(), ".compoundliteral");
const Expr *InitExpr = E->getInitializer();
- LValue Result = MakeAddrLValue(DeclPtr, E->getType(), BaseInfo);
+ LValue Result = MakeAddrLValue(DeclPtr, E->getType(), AlignmentSource::Decl);
EmitAnyExprToMem(InitExpr, DeclPtr, E->getType().getQualifiers(),
/*Init*/ true);
@@ -3863,10 +3977,10 @@ EmitConditionalOperatorLValue(const AbstractConditionalOperator *expr) {
AlignmentSource alignSource =
std::max(lhs->getBaseInfo().getAlignmentSource(),
rhs->getBaseInfo().getAlignmentSource());
- bool MayAlias = lhs->getBaseInfo().getMayAlias() ||
- rhs->getBaseInfo().getMayAlias();
- return MakeAddrLValue(result, expr->getType(),
- LValueBaseInfo(alignSource, MayAlias));
+ TBAAAccessInfo TBAAInfo = CGM.mergeTBAAInfoForConditionalOperator(
+ lhs->getTBAAInfo(), rhs->getTBAAInfo());
+ return MakeAddrLValue(result, expr->getType(), LValueBaseInfo(alignSource),
+ TBAAInfo);
} else {
assert((lhs || rhs) &&
"both operands of glvalue conditional are throw-expressions?");
@@ -3964,7 +4078,11 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
This, DerivedClassDecl, E->path_begin(), E->path_end(),
/*NullCheckValue=*/false, E->getExprLoc());
- return MakeAddrLValue(Base, E->getType(), LV.getBaseInfo());
+ // TODO: Support accesses to members of base classes in TBAA. For now, we
+ // conservatively pretend that the complete object is of the base class
+ // type.
+ return MakeAddrLValue(Base, E->getType(), LV.getBaseInfo(),
+ CGM.getTBAAInfoForSubobject(LV, E->getType()));
}
case CK_ToUnion:
return EmitAggExprToLValue(E);
@@ -3991,7 +4109,8 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
/*MayBeNull=*/false,
CFITCK_DerivedCast, E->getLocStart());
- return MakeAddrLValue(Derived, E->getType(), LV.getBaseInfo());
+ return MakeAddrLValue(Derived, E->getType(), LV.getBaseInfo(),
+ CGM.getTBAAInfoForSubobject(LV, E->getType()));
}
case CK_LValueBitCast: {
// This must be a reinterpret_cast (or c-style equivalent).
@@ -4007,13 +4126,15 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
/*MayBeNull=*/false,
CFITCK_UnrelatedCast, E->getLocStart());
- return MakeAddrLValue(V, E->getType(), LV.getBaseInfo());
+ return MakeAddrLValue(V, E->getType(), LV.getBaseInfo(),
+ CGM.getTBAAInfoForSubobject(LV, E->getType()));
}
case CK_ObjCObjectLValueCast: {
LValue LV = EmitLValue(E->getSubExpr());
Address V = Builder.CreateElementBitCast(LV.getAddress(),
ConvertType(E->getType()));
- return MakeAddrLValue(V, E->getType(), LV.getBaseInfo());
+ return MakeAddrLValue(V, E->getType(), LV.getBaseInfo(),
+ CGM.getTBAAInfoForSubobject(LV, E->getType()));
}
case CK_ZeroToOCLQueue:
llvm_unreachable("NULL to OpenCL queue lvalue cast is not valid");
@@ -4202,7 +4323,7 @@ LValue CodeGenFunction::EmitCallExprLValue(const CallExpr *E) {
if (!RV.isScalar())
return MakeAddrLValue(RV.getAggregateAddress(), E->getType(),
- LValueBaseInfo(AlignmentSource::Decl, false));
+ AlignmentSource::Decl);
assert(E->getCallReturnType(getContext())->isReferenceType() &&
"Can't have a scalar return unless the return type is a "
@@ -4221,8 +4342,7 @@ LValue CodeGenFunction::EmitCXXConstructLValue(const CXXConstructExpr *E) {
&& "binding l-value to type which needs a temporary");
AggValueSlot Slot = CreateAggTemp(E->getType());
EmitCXXConstructExpr(E, Slot);
- return MakeAddrLValue(Slot.getAddress(), E->getType(),
- LValueBaseInfo(AlignmentSource::Decl, false));
+ return MakeAddrLValue(Slot.getAddress(), E->getType(), AlignmentSource::Decl);
}
LValue
@@ -4237,7 +4357,7 @@ Address CodeGenFunction::EmitCXXUuidofExpr(const CXXUuidofExpr *E) {
LValue CodeGenFunction::EmitCXXUuidofLValue(const CXXUuidofExpr *E) {
return MakeAddrLValue(EmitCXXUuidofExpr(E), E->getType(),
- LValueBaseInfo(AlignmentSource::Decl, false));
+ AlignmentSource::Decl);
}
LValue
@@ -4246,16 +4366,14 @@ CodeGenFunction::EmitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *E) {
Slot.setExternallyDestructed();
EmitAggExpr(E->getSubExpr(), Slot);
EmitCXXTemporary(E->getTemporary(), E->getType(), Slot.getAddress());
- return MakeAddrLValue(Slot.getAddress(), E->getType(),
- LValueBaseInfo(AlignmentSource::Decl, false));
+ return MakeAddrLValue(Slot.getAddress(), E->getType(), AlignmentSource::Decl);
}
LValue
CodeGenFunction::EmitLambdaLValue(const LambdaExpr *E) {
AggValueSlot Slot = CreateAggTemp(E->getType(), "temp.lvalue");
EmitLambdaExpr(E, Slot);
- return MakeAddrLValue(Slot.getAddress(), E->getType(),
- LValueBaseInfo(AlignmentSource::Decl, false));
+ return MakeAddrLValue(Slot.getAddress(), E->getType(), AlignmentSource::Decl);
}
LValue CodeGenFunction::EmitObjCMessageExprLValue(const ObjCMessageExpr *E) {
@@ -4263,7 +4381,7 @@ LValue CodeGenFunction::EmitObjCMessageExprLValue(const ObjCMessageExpr *E) {
if (!RV.isScalar())
return MakeAddrLValue(RV.getAggregateAddress(), E->getType(),
- LValueBaseInfo(AlignmentSource::Decl, false));
+ AlignmentSource::Decl);
assert(E->getMethodDecl()->getReturnType()->isReferenceType() &&
"Can't have a scalar return unless the return type is a "
@@ -4275,8 +4393,7 @@ LValue CodeGenFunction::EmitObjCMessageExprLValue(const ObjCMessageExpr *E) {
LValue CodeGenFunction::EmitObjCSelectorLValue(const ObjCSelectorExpr *E) {
Address V =
CGM.getObjCRuntime().GetAddrOfSelector(*this, E->getSelector());
- return MakeAddrLValue(V, E->getType(),
- LValueBaseInfo(AlignmentSource::Decl, false));
+ return MakeAddrLValue(V, E->getType(), AlignmentSource::Decl);
}
llvm::Value *CodeGenFunction::EmitIvarOffset(const ObjCInterfaceDecl *Interface,
@@ -4320,7 +4437,7 @@ LValue CodeGenFunction::EmitStmtExprLValue(const StmtExpr *E) {
// Can only get l-value for message expression returning aggregate type
RValue RV = EmitAnyExprToTemp(E);
return MakeAddrLValue(RV.getAggregateAddress(), E->getType(),
- LValueBaseInfo(AlignmentSource::Decl, false));
+ AlignmentSource::Decl);
}
RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee,
@@ -4358,10 +4475,7 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee
SanitizerScope SanScope(this);
llvm::Constant *FTRTTIConst =
CGM.GetAddrOfRTTIDescriptor(QualType(FnType, 0), /*ForEH=*/true);
- llvm::Type *PrefixStructTyElems[] = {
- PrefixSig->getType(),
- FTRTTIConst->getType()
- };
+ llvm::Type *PrefixStructTyElems[] = {PrefixSig->getType(), Int32Ty};
llvm::StructType *PrefixStructTy = llvm::StructType::get(
CGM.getLLVMContext(), PrefixStructTyElems, /*isPacked=*/true);
@@ -4382,8 +4496,10 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee
EmitBlock(TypeCheck);
llvm::Value *CalleeRTTIPtr =
Builder.CreateConstGEP2_32(PrefixStructTy, CalleePrefixStruct, 0, 1);
- llvm::Value *CalleeRTTI =
+ llvm::Value *CalleeRTTIEncoded =
Builder.CreateAlignedLoad(CalleeRTTIPtr, getPointerAlign());
+ llvm::Value *CalleeRTTI =
+ DecodeAddrUsedInPrologue(CalleePtr, CalleeRTTIEncoded);
llvm::Value *CalleeRTTIMatch =
Builder.CreateICmpEQ(CalleeRTTI, FTRTTIConst);
llvm::Constant *StaticData[] = {
@@ -4405,7 +4521,12 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee
SanitizerScope SanScope(this);
EmitSanitizerStatReport(llvm::SanStat_CFI_ICall);
- llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(QualType(FnType, 0));
+ llvm::Metadata *MD;
+ if (CGM.getCodeGenOpts().SanitizeCfiICallGeneralizePointers)
+ MD = CGM.CreateMetadataIdentifierGeneralized(QualType(FnType, 0));
+ else
+ MD = CGM.CreateMetadataIdentifierForType(QualType(FnType, 0));
+
llvm::Value *TypeId = llvm::MetadataAsValue::get(getLLVMContext(), MD);
llvm::Value *CalleePtr = Callee.getFunctionPointer();
@@ -4513,10 +4634,12 @@ EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E) {
= E->getRHS()->getType()->getAs<MemberPointerType>();
LValueBaseInfo BaseInfo;
+ TBAAAccessInfo TBAAInfo;
Address MemberAddr =
- EmitCXXMemberDataPointerAddress(E, BaseAddr, OffsetV, MPT, &BaseInfo);
+ EmitCXXMemberDataPointerAddress(E, BaseAddr, OffsetV, MPT, &BaseInfo,
+ &TBAAInfo);
- return MakeAddrLValue(MemberAddr, MPT->getPointeeType(), BaseInfo);
+ return MakeAddrLValue(MemberAddr, MPT->getPointeeType(), BaseInfo, TBAAInfo);
}
/// Given the address of a temporary variable, produce an r-value of
@@ -4524,8 +4647,7 @@ EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E) {
RValue CodeGenFunction::convertTempToRValue(Address addr,
QualType type,
SourceLocation loc) {
- LValue lvalue = MakeAddrLValue(addr, type,
- LValueBaseInfo(AlignmentSource::Decl, false));
+ LValue lvalue = MakeAddrLValue(addr, type, AlignmentSource::Decl);
switch (getEvaluationKind(type)) {
case TEK_Complex:
return RValue::getComplex(EmitLoadOfComplex(lvalue, loc));
@@ -4580,9 +4702,8 @@ static LValueOrRValue emitPseudoObjectExpr(CodeGenFunction &CGF,
if (ov == resultExpr && ov->isRValue() && !forLValue &&
CodeGenFunction::hasAggregateEvaluationKind(ov->getType())) {
CGF.EmitAggExpr(ov->getSourceExpr(), slot);
- LValueBaseInfo BaseInfo(AlignmentSource::Decl, false);
LValue LV = CGF.MakeAddrLValue(slot.getAddress(), ov->getType(),
- BaseInfo);
+ AlignmentSource::Decl);
opaqueData = OVMA::bind(CGF, ov, LV);
result.RV = slot.asRValue();
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp
index a05a088f09191..1ab8433864c4b 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp
@@ -124,24 +124,7 @@ public:
}
// l-values.
- void VisitDeclRefExpr(DeclRefExpr *E) {
- // For aggregates, we should always be able to emit the variable
- // as an l-value unless it's a reference. This is due to the fact
- // that we can't actually ever see a normal l2r conversion on an
- // aggregate in C++, and in C there's no language standard
- // actively preventing us from listing variables in the captures
- // list of a block.
- if (E->getDecl()->getType()->isReferenceType()) {
- if (CodeGenFunction::ConstantEmission result
- = CGF.tryEmitAsConstant(E)) {
- EmitFinalDestCopy(E->getType(), result.getReferenceLValue(CGF, E));
- return;
- }
- }
-
- EmitAggLoadOfLValue(E);
- }
-
+ void VisitDeclRefExpr(DeclRefExpr *E) { EmitAggLoadOfLValue(E); }
void VisitMemberExpr(MemberExpr *ME) { EmitAggLoadOfLValue(ME); }
void VisitUnaryDeref(UnaryOperator *E) { EmitAggLoadOfLValue(E); }
void VisitStringLiteral(StringLiteral *E) { EmitAggLoadOfLValue(E); }
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp
index ab170245284ce..41bb199ffde73 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp
@@ -16,6 +16,7 @@
#include "CGCXXABI.h"
#include "CGDebugInfo.h"
#include "CGObjCRuntime.h"
+#include "ConstantEmitter.h"
#include "clang/CodeGen/CGFunctionInfo.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/IR/CallSite.h"
@@ -367,9 +368,11 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
} else {
if (SanOpts.has(SanitizerKind::CFINVCall) &&
MD->getParent()->isDynamicClass()) {
- llvm::Value *VTable = GetVTablePtr(This, Int8PtrTy, MD->getParent());
- EmitVTablePtrCheckForCall(MD->getParent(), VTable, CFITCK_NVCall,
- CE->getLocStart());
+ llvm::Value *VTable;
+ const CXXRecordDecl *RD;
+ std::tie(VTable, RD) =
+ CGM.getCXXABI().LoadVTablePtr(*this, This, MD->getParent());
+ EmitVTablePtrCheckForCall(RD, VTable, CFITCK_NVCall, CE->getLocStart());
}
if (getLangOpts().AppleKext && MD->isVirtual() && HasQualifier)
@@ -681,8 +684,8 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
// Emit the array size expression.
// We multiply the size of all dimensions for NumElements.
// e.g for 'int[2][3]', ElemType is 'int' and NumElements is 6.
- numElements = CGF.CGM.EmitConstantExpr(e->getArraySize(),
- CGF.getContext().getSizeType(), &CGF);
+ numElements =
+ ConstantEmitter(CGF).tryEmitAbstract(e->getArraySize(), e->getType());
if (!numElements)
numElements = CGF.EmitScalarExpr(e->getArraySize());
assert(isa<llvm::IntegerType>(numElements->getType()));
@@ -1310,29 +1313,44 @@ RValue CodeGenFunction::EmitBuiltinNewDeleteCall(const FunctionProtoType *Type,
llvm_unreachable("predeclared global operator new/delete is missing");
}
-static std::pair<bool, bool>
-shouldPassSizeAndAlignToUsualDelete(const FunctionProtoType *FPT) {
+namespace {
+/// The parameters to pass to a usual operator delete.
+struct UsualDeleteParams {
+ bool DestroyingDelete = false;
+ bool Size = false;
+ bool Alignment = false;
+};
+}
+
+static UsualDeleteParams getUsualDeleteParams(const FunctionDecl *FD) {
+ UsualDeleteParams Params;
+
+ const FunctionProtoType *FPT = FD->getType()->castAs<FunctionProtoType>();
auto AI = FPT->param_type_begin(), AE = FPT->param_type_end();
// The first argument is always a void*.
++AI;
- // Figure out what other parameters we should be implicitly passing.
- bool PassSize = false;
- bool PassAlignment = false;
+ // The next parameter may be a std::destroying_delete_t.
+ if (FD->isDestroyingOperatorDelete()) {
+ Params.DestroyingDelete = true;
+ assert(AI != AE);
+ ++AI;
+ }
+ // Figure out what other parameters we should be implicitly passing.
if (AI != AE && (*AI)->isIntegerType()) {
- PassSize = true;
+ Params.Size = true;
++AI;
}
if (AI != AE && (*AI)->isAlignValT()) {
- PassAlignment = true;
+ Params.Alignment = true;
++AI;
}
assert(AI == AE && "unexpected usual deallocation function parameter");
- return {PassSize, PassAlignment};
+ return Params;
}
namespace {
@@ -1385,25 +1403,27 @@ namespace {
OperatorDelete->getType()->getAs<FunctionProtoType>();
CallArgList DeleteArgs;
- // The first argument is always a void*.
+ // The first argument is always a void* (or C* for a destroying operator
+ // delete for class type C).
DeleteArgs.add(Traits::get(CGF, Ptr), FPT->getParamType(0));
// Figure out what other parameters we should be implicitly passing.
- bool PassSize = false;
- bool PassAlignment = false;
+ UsualDeleteParams Params;
if (NumPlacementArgs) {
// A placement deallocation function is implicitly passed an alignment
// if the placement allocation function was, but is never passed a size.
- PassAlignment = PassAlignmentToPlacementDelete;
+ Params.Alignment = PassAlignmentToPlacementDelete;
} else {
// For a non-placement new-expression, 'operator delete' can take a
// size and/or an alignment if it has the right parameters.
- std::tie(PassSize, PassAlignment) =
- shouldPassSizeAndAlignToUsualDelete(FPT);
+ Params = getUsualDeleteParams(OperatorDelete);
}
+ assert(!Params.DestroyingDelete &&
+ "should not call destroying delete in a new-expression");
+
// The second argument can be a std::size_t (for non-placement delete).
- if (PassSize)
+ if (Params.Size)
DeleteArgs.add(Traits::get(CGF, AllocSize),
CGF.getContext().getSizeType());
@@ -1411,7 +1431,7 @@ namespace {
// is an enum whose underlying type is std::size_t.
// FIXME: Use the right type as the parameter type. Note that in a call
// to operator delete(size_t, ...), we may not have it available.
- if (PassAlignment)
+ if (Params.Alignment)
DeleteArgs.add(RValue::get(llvm::ConstantInt::get(
CGF.SizeTy, AllocAlign.getQuantity())),
CGF.getContext().getSizeType());
@@ -1714,9 +1734,7 @@ void CodeGenFunction::EmitDeleteCall(const FunctionDecl *DeleteFD,
CallArgList DeleteArgs;
- std::pair<bool, bool> PassSizeAndAlign =
- shouldPassSizeAndAlignToUsualDelete(DeleteFTy);
-
+ auto Params = getUsualDeleteParams(DeleteFD);
auto ParamTypeIt = DeleteFTy->param_type_begin();
// Pass the pointer itself.
@@ -1724,8 +1742,16 @@ void CodeGenFunction::EmitDeleteCall(const FunctionDecl *DeleteFD,
llvm::Value *DeletePtr = Builder.CreateBitCast(Ptr, ConvertType(ArgTy));
DeleteArgs.add(RValue::get(DeletePtr), ArgTy);
+ // Pass the std::destroying_delete tag if present.
+ if (Params.DestroyingDelete) {
+ QualType DDTag = *ParamTypeIt++;
+ // Just pass an 'undef'. We expect the tag type to be an empty struct.
+ auto *V = llvm::UndefValue::get(getTypes().ConvertType(DDTag));
+ DeleteArgs.add(RValue::get(V), DDTag);
+ }
+
// Pass the size if the delete function has a size_t parameter.
- if (PassSizeAndAlign.first) {
+ if (Params.Size) {
QualType SizeType = *ParamTypeIt++;
CharUnits DeleteTypeSize = getContext().getTypeSizeInChars(DeleteTy);
llvm::Value *Size = llvm::ConstantInt::get(ConvertType(SizeType),
@@ -1744,7 +1770,7 @@ void CodeGenFunction::EmitDeleteCall(const FunctionDecl *DeleteFD,
}
// Pass the alignment if the delete function has an align_val_t parameter.
- if (PassSizeAndAlign.second) {
+ if (Params.Alignment) {
QualType AlignValType = *ParamTypeIt++;
CharUnits DeleteTypeAlign = getContext().toCharUnitsFromBits(
getContext().getTypeAlignIfKnown(DeleteTy));
@@ -1786,6 +1812,21 @@ CodeGenFunction::pushCallObjectDeleteCleanup(const FunctionDecl *OperatorDelete,
OperatorDelete, ElementType);
}
+/// Emit the code for deleting a single object with a destroying operator
+/// delete. If the element type has a non-virtual destructor, Ptr has already
+/// been converted to the type of the parameter of 'operator delete'. Otherwise
+/// Ptr points to an object of the static type.
+static void EmitDestroyingObjectDelete(CodeGenFunction &CGF,
+ const CXXDeleteExpr *DE, Address Ptr,
+ QualType ElementType) {
+ auto *Dtor = ElementType->getAsCXXRecordDecl()->getDestructor();
+ if (Dtor && Dtor->isVirtual())
+ CGF.CGM.getCXXABI().emitVirtualObjectDelete(CGF, DE, Ptr, ElementType,
+ Dtor);
+ else
+ CGF.EmitDeleteCall(DE->getOperatorDelete(), Ptr.getPointer(), ElementType);
+}
+
/// Emit the code for deleting a single object.
static void EmitObjectDelete(CodeGenFunction &CGF,
const CXXDeleteExpr *DE,
@@ -1800,6 +1841,9 @@ static void EmitObjectDelete(CodeGenFunction &CGF,
DE->getExprLoc(), Ptr.getPointer(),
ElementType);
+ const FunctionDecl *OperatorDelete = DE->getOperatorDelete();
+ assert(!OperatorDelete->isDestroyingOperatorDelete());
+
// Find the destructor for the type, if applicable. If the
// destructor is virtual, we'll just emit the vcall and return.
const CXXDestructorDecl *Dtor = nullptr;
@@ -1819,7 +1863,6 @@ static void EmitObjectDelete(CodeGenFunction &CGF,
// Make sure that we call delete even if the dtor throws.
// This doesn't have to a conditional cleanup because we're going
// to pop it off in a second.
- const FunctionDecl *OperatorDelete = DE->getOperatorDelete();
CGF.EHStack.pushCleanup<CallObjectDelete>(NormalAndEHCleanup,
Ptr.getPointer(),
OperatorDelete, ElementType);
@@ -1931,10 +1974,19 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) {
Builder.CreateCondBr(IsNull, DeleteEnd, DeleteNotNull);
EmitBlock(DeleteNotNull);
+ QualType DeleteTy = E->getDestroyedType();
+
+ // A destroying operator delete overrides the entire operation of the
+ // delete expression.
+ if (E->getOperatorDelete()->isDestroyingOperatorDelete()) {
+ EmitDestroyingObjectDelete(*this, E, Ptr, DeleteTy);
+ EmitBlock(DeleteEnd);
+ return;
+ }
+
// We might be deleting a pointer to array. If so, GEP down to the
// first non-array element.
// (this assumes that A(*)[3][7] is converted to [3 x [7 x %A]]*)
- QualType DeleteTy = Arg->getType()->getAs<PointerType>()->getPointeeType();
if (DeleteTy->isConstantArrayType()) {
llvm::Value *Zero = Builder.getInt32(0);
SmallVector<llvm::Value*,8> GEP;
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp
index 980972370dc2b..e860b3045f0e1 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp
@@ -120,18 +120,22 @@ public:
return Visit(E->getSubExpr());
}
+ ComplexPairTy emitConstant(const CodeGenFunction::ConstantEmission &Constant,
+ Expr *E) {
+ assert(Constant && "not a constant");
+ if (Constant.isReference())
+ return EmitLoadOfLValue(Constant.getReferenceLValue(CGF, E),
+ E->getExprLoc());
+
+ llvm::Constant *pair = Constant.getValue();
+ return ComplexPairTy(pair->getAggregateElement(0U),
+ pair->getAggregateElement(1U));
+ }
// l-values.
ComplexPairTy VisitDeclRefExpr(DeclRefExpr *E) {
- if (CodeGenFunction::ConstantEmission result = CGF.tryEmitAsConstant(E)) {
- if (result.isReference())
- return EmitLoadOfLValue(result.getReferenceLValue(CGF, E),
- E->getExprLoc());
-
- llvm::Constant *pair = result.getValue();
- return ComplexPairTy(pair->getAggregateElement(0U),
- pair->getAggregateElement(1U));
- }
+ if (CodeGenFunction::ConstantEmission Constant = CGF.tryEmitAsConstant(E))
+ return emitConstant(Constant, E);
return EmitLoadOfLValue(E);
}
ComplexPairTy VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
@@ -141,7 +145,14 @@ public:
return CGF.EmitObjCMessageExpr(E).getComplexVal();
}
ComplexPairTy VisitArraySubscriptExpr(Expr *E) { return EmitLoadOfLValue(E); }
- ComplexPairTy VisitMemberExpr(const Expr *E) { return EmitLoadOfLValue(E); }
+ ComplexPairTy VisitMemberExpr(MemberExpr *ME) {
+ if (CodeGenFunction::ConstantEmission Constant =
+ CGF.tryEmitAsConstant(ME)) {
+ CGF.EmitIgnoredExpr(ME->getBase());
+ return emitConstant(Constant, ME);
+ }
+ return EmitLoadOfLValue(ME);
+ }
ComplexPairTy VisitOpaqueValueExpr(OpaqueValueExpr *E) {
if (E->isGLValue())
return EmitLoadOfLValue(CGF.getOpaqueLValueMapping(E), E->getExprLoc());
@@ -764,7 +775,6 @@ ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) {
if (!LHSi)
LibCallOp.LHS.second = llvm::Constant::getNullValue(LHSr->getType());
- StringRef LibCallName;
switch (LHSr->getType()->getTypeID()) {
default:
llvm_unreachable("Unsupported floating point type!");
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp
index 6b72774c10a59..d1b9e13a6f937 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp
@@ -16,6 +16,7 @@
#include "CGObjCRuntime.h"
#include "CGRecordLayout.h"
#include "CodeGenModule.h"
+#include "ConstantEmitter.h"
#include "TargetInfo.h"
#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
@@ -37,25 +38,26 @@ namespace {
class ConstExprEmitter;
class ConstStructBuilder {
CodeGenModule &CGM;
- CodeGenFunction *CGF;
+ ConstantEmitter &Emitter;
bool Packed;
CharUnits NextFieldOffsetInChars;
CharUnits LLVMStructAlignment;
SmallVector<llvm::Constant *, 32> Elements;
public:
- static llvm::Constant *BuildStruct(CodeGenModule &CGM, CodeGenFunction *CFG,
- ConstExprEmitter *Emitter,
+ static llvm::Constant *BuildStruct(ConstantEmitter &Emitter,
+ ConstExprEmitter *ExprEmitter,
llvm::ConstantStruct *Base,
- InitListExpr *Updater);
- static llvm::Constant *BuildStruct(CodeGenModule &CGM, CodeGenFunction *CGF,
- InitListExpr *ILE);
- static llvm::Constant *BuildStruct(CodeGenModule &CGM, CodeGenFunction *CGF,
+ InitListExpr *Updater,
+ QualType ValTy);
+ static llvm::Constant *BuildStruct(ConstantEmitter &Emitter,
+ InitListExpr *ILE, QualType StructTy);
+ static llvm::Constant *BuildStruct(ConstantEmitter &Emitter,
const APValue &Value, QualType ValTy);
private:
- ConstStructBuilder(CodeGenModule &CGM, CodeGenFunction *CGF)
- : CGM(CGM), CGF(CGF), Packed(false),
+ ConstStructBuilder(ConstantEmitter &emitter)
+ : CGM(emitter.CGM), Emitter(emitter), Packed(false),
NextFieldOffsetInChars(CharUnits::Zero()),
LLVMStructAlignment(CharUnits::One()) { }
@@ -76,7 +78,7 @@ private:
bool Build(InitListExpr *ILE);
bool Build(ConstExprEmitter *Emitter, llvm::ConstantStruct *Base,
InitListExpr *Updater);
- void Build(const APValue &Val, const RecordDecl *RD, bool IsPrimaryBase,
+ bool Build(const APValue &Val, const RecordDecl *RD, bool IsPrimaryBase,
const CXXRecordDecl *VTableClass, CharUnits BaseOffset);
llvm::Constant *Finalize(QualType Ty);
@@ -391,10 +393,10 @@ bool ConstStructBuilder::Build(InitListExpr *ILE) {
// we just use explicit null values for them.
llvm::Constant *EltInit;
if (ElementNo < ILE->getNumInits())
- EltInit = CGM.EmitConstantExpr(ILE->getInit(ElementNo++),
- Field->getType(), CGF);
+ EltInit = Emitter.tryEmitPrivateForMemory(ILE->getInit(ElementNo++),
+ Field->getType());
else
- EltInit = CGM.EmitNullConstant(Field->getType());
+ EltInit = Emitter.emitNullForMemory(Field->getType());
if (!EltInit)
return false;
@@ -431,7 +433,7 @@ struct BaseInfo {
};
}
-void ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,
+bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,
bool IsPrimaryBase,
const CXXRecordDecl *VTableClass,
CharUnits Offset) {
@@ -486,8 +488,9 @@ void ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,
const APValue &FieldValue =
RD->isUnion() ? Val.getUnionValue() : Val.getStructField(FieldNo);
llvm::Constant *EltInit =
- CGM.EmitConstantValueForMemory(FieldValue, Field->getType(), CGF);
- assert(EltInit && "EmitConstantValue can't fail");
+ Emitter.tryEmitPrivateForMemory(FieldValue, Field->getType());
+ if (!EltInit)
+ return false;
if (!Field->isBitField()) {
// Handle non-bitfield members.
@@ -498,6 +501,8 @@ void ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,
cast<llvm::ConstantInt>(EltInit));
}
}
+
+ return true;
}
llvm::Constant *ConstStructBuilder::Finalize(QualType Ty) {
@@ -559,37 +564,37 @@ llvm::Constant *ConstStructBuilder::Finalize(QualType Ty) {
return Result;
}
-llvm::Constant *ConstStructBuilder::BuildStruct(CodeGenModule &CGM,
- CodeGenFunction *CGF,
- ConstExprEmitter *Emitter,
+llvm::Constant *ConstStructBuilder::BuildStruct(ConstantEmitter &Emitter,
+ ConstExprEmitter *ExprEmitter,
llvm::ConstantStruct *Base,
- InitListExpr *Updater) {
- ConstStructBuilder Builder(CGM, CGF);
- if (!Builder.Build(Emitter, Base, Updater))
+ InitListExpr *Updater,
+ QualType ValTy) {
+ ConstStructBuilder Builder(Emitter);
+ if (!Builder.Build(ExprEmitter, Base, Updater))
return nullptr;
- return Builder.Finalize(Updater->getType());
+ return Builder.Finalize(ValTy);
}
-llvm::Constant *ConstStructBuilder::BuildStruct(CodeGenModule &CGM,
- CodeGenFunction *CGF,
- InitListExpr *ILE) {
- ConstStructBuilder Builder(CGM, CGF);
+llvm::Constant *ConstStructBuilder::BuildStruct(ConstantEmitter &Emitter,
+ InitListExpr *ILE,
+ QualType ValTy) {
+ ConstStructBuilder Builder(Emitter);
if (!Builder.Build(ILE))
return nullptr;
- return Builder.Finalize(ILE->getType());
+ return Builder.Finalize(ValTy);
}
-llvm::Constant *ConstStructBuilder::BuildStruct(CodeGenModule &CGM,
- CodeGenFunction *CGF,
+llvm::Constant *ConstStructBuilder::BuildStruct(ConstantEmitter &Emitter,
const APValue &Val,
QualType ValTy) {
- ConstStructBuilder Builder(CGM, CGF);
+ ConstStructBuilder Builder(Emitter);
const RecordDecl *RD = ValTy->castAs<RecordType>()->getDecl();
const CXXRecordDecl *CD = dyn_cast<CXXRecordDecl>(RD);
- Builder.Build(Val, RD, false, CD, CharUnits::Zero());
+ if (!Builder.Build(Val, RD, false, CD, CharUnits::Zero()))
+ return nullptr;
return Builder.Finalize(ValTy);
}
@@ -599,57 +604,86 @@ llvm::Constant *ConstStructBuilder::BuildStruct(CodeGenModule &CGM,
// ConstExprEmitter
//===----------------------------------------------------------------------===//
+static ConstantAddress tryEmitGlobalCompoundLiteral(CodeGenModule &CGM,
+ CodeGenFunction *CGF,
+ const CompoundLiteralExpr *E) {
+ CharUnits Align = CGM.getContext().getTypeAlignInChars(E->getType());
+ if (llvm::GlobalVariable *Addr =
+ CGM.getAddrOfConstantCompoundLiteralIfEmitted(E))
+ return ConstantAddress(Addr, Align);
+
+ LangAS addressSpace = E->getType().getAddressSpace();
+
+ ConstantEmitter emitter(CGM, CGF);
+ llvm::Constant *C = emitter.tryEmitForInitializer(E->getInitializer(),
+ addressSpace, E->getType());
+ if (!C) {
+ assert(!E->isFileScope() &&
+ "file-scope compound literal did not have constant initializer!");
+ return ConstantAddress::invalid();
+ }
+
+ auto GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(),
+ CGM.isTypeConstant(E->getType(), true),
+ llvm::GlobalValue::InternalLinkage,
+ C, ".compoundliteral", nullptr,
+ llvm::GlobalVariable::NotThreadLocal,
+ CGM.getContext().getTargetAddressSpace(addressSpace));
+ emitter.finalize(GV);
+ GV->setAlignment(Align.getQuantity());
+ CGM.setAddrOfConstantCompoundLiteral(E, GV);
+ return ConstantAddress(GV, Align);
+}
+
/// This class only needs to handle two cases:
/// 1) Literals (this is used by APValue emission to emit literals).
/// 2) Arrays, structs and unions (outside C++11 mode, we don't currently
/// constant fold these types).
class ConstExprEmitter :
- public StmtVisitor<ConstExprEmitter, llvm::Constant*> {
+ public StmtVisitor<ConstExprEmitter, llvm::Constant*, QualType> {
CodeGenModule &CGM;
- CodeGenFunction *CGF;
+ ConstantEmitter &Emitter;
llvm::LLVMContext &VMContext;
public:
- ConstExprEmitter(CodeGenModule &cgm, CodeGenFunction *cgf)
- : CGM(cgm), CGF(cgf), VMContext(cgm.getLLVMContext()) {
+ ConstExprEmitter(ConstantEmitter &emitter)
+ : CGM(emitter.CGM), Emitter(emitter), VMContext(CGM.getLLVMContext()) {
}
//===--------------------------------------------------------------------===//
// Visitor Methods
//===--------------------------------------------------------------------===//
- llvm::Constant *VisitStmt(Stmt *S) {
+ llvm::Constant *VisitStmt(Stmt *S, QualType T) {
return nullptr;
}
- llvm::Constant *VisitParenExpr(ParenExpr *PE) {
- return Visit(PE->getSubExpr());
+ llvm::Constant *VisitParenExpr(ParenExpr *PE, QualType T) {
+ return Visit(PE->getSubExpr(), T);
}
llvm::Constant *
- VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *PE) {
- return Visit(PE->getReplacement());
+ VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *PE,
+ QualType T) {
+ return Visit(PE->getReplacement(), T);
}
- llvm::Constant *VisitGenericSelectionExpr(GenericSelectionExpr *GE) {
- return Visit(GE->getResultExpr());
+ llvm::Constant *VisitGenericSelectionExpr(GenericSelectionExpr *GE,
+ QualType T) {
+ return Visit(GE->getResultExpr(), T);
}
- llvm::Constant *VisitChooseExpr(ChooseExpr *CE) {
- return Visit(CE->getChosenSubExpr());
+ llvm::Constant *VisitChooseExpr(ChooseExpr *CE, QualType T) {
+ return Visit(CE->getChosenSubExpr(), T);
}
- llvm::Constant *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
- return Visit(E->getInitializer());
+ llvm::Constant *VisitCompoundLiteralExpr(CompoundLiteralExpr *E, QualType T) {
+ return Visit(E->getInitializer(), T);
}
- llvm::Constant *VisitCastExpr(CastExpr* E) {
+ llvm::Constant *VisitCastExpr(CastExpr *E, QualType destType) {
if (const auto *ECE = dyn_cast<ExplicitCastExpr>(E))
- CGM.EmitExplicitCastExprType(ECE, CGF);
+ CGM.EmitExplicitCastExprType(ECE, Emitter.CGF);
Expr *subExpr = E->getSubExpr();
- llvm::Constant *C = CGM.EmitConstantExpr(subExpr, subExpr->getType(), CGF);
- if (!C) return nullptr;
-
- llvm::Type *destType = ConvertType(E->getType());
switch (E->getCastKind()) {
case CK_ToUnion: {
@@ -657,14 +691,22 @@ public:
assert(E->getType()->isUnionType() &&
"Destination type is not union type!");
+ auto field = E->getTargetUnionField();
+
+ auto C = Emitter.tryEmitPrivateForMemory(subExpr, field->getType());
+ if (!C) return nullptr;
+
+ auto destTy = ConvertType(destType);
+ if (C->getType() == destTy) return C;
+
// Build a struct with the union sub-element as the first member,
- // and padded to the appropriate size
+ // and padded to the appropriate size.
SmallVector<llvm::Constant*, 2> Elts;
SmallVector<llvm::Type*, 2> Types;
Elts.push_back(C);
Types.push_back(C->getType());
unsigned CurSize = CGM.getDataLayout().getTypeAllocSize(C->getType());
- unsigned TotalSize = CGM.getDataLayout().getTypeAllocSize(destType);
+ unsigned TotalSize = CGM.getDataLayout().getTypeAllocSize(destTy);
assert(CurSize <= TotalSize && "Union size mismatch!");
if (unsigned NumPadBytes = TotalSize - CurSize) {
@@ -676,20 +718,26 @@ public:
Types.push_back(Ty);
}
- llvm::StructType* STy =
- llvm::StructType::get(C->getType()->getContext(), Types, false);
+ llvm::StructType *STy = llvm::StructType::get(VMContext, Types, false);
return llvm::ConstantStruct::get(STy, Elts);
}
- case CK_AddressSpaceConversion:
- return llvm::ConstantExpr::getAddrSpaceCast(C, destType);
+ case CK_AddressSpaceConversion: {
+ auto C = Emitter.tryEmitPrivate(subExpr, subExpr->getType());
+ if (!C) return nullptr;
+ LangAS destAS = E->getType()->getPointeeType().getAddressSpace();
+ LangAS srcAS = subExpr->getType()->getPointeeType().getAddressSpace();
+ llvm::Type *destTy = ConvertType(E->getType());
+ return CGM.getTargetCodeGenInfo().performAddrSpaceCast(CGM, C, srcAS,
+ destAS, destTy);
+ }
case CK_LValueToRValue:
case CK_AtomicToNonAtomic:
case CK_NonAtomicToAtomic:
case CK_NoOp:
case CK_ConstructorConversion:
- return C;
+ return Visit(subExpr, destType);
case CK_IntToOCLSampler:
llvm_unreachable("global sampler variables are not generated");
@@ -701,8 +749,11 @@ public:
case CK_ReinterpretMemberPointer:
case CK_DerivedToBaseMemberPointer:
- case CK_BaseToDerivedMemberPointer:
+ case CK_BaseToDerivedMemberPointer: {
+ auto C = Emitter.tryEmitPrivate(subExpr, subExpr->getType());
+ if (!C) return nullptr;
return CGM.getCXXABI().EmitMemberPointerConversion(E, C);
+ }
// These will never be supported.
case CK_ObjCObjectLValueCast:
@@ -759,27 +810,28 @@ public:
llvm_unreachable("Invalid CastKind");
}
- llvm::Constant *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
- return Visit(DAE->getExpr());
+ llvm::Constant *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE, QualType T) {
+ return Visit(DAE->getExpr(), T);
}
- llvm::Constant *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE) {
+ llvm::Constant *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE, QualType T) {
// No need for a DefaultInitExprScope: we don't handle 'this' in a
// constant expression.
- return Visit(DIE->getExpr());
+ return Visit(DIE->getExpr(), T);
}
- llvm::Constant *VisitExprWithCleanups(ExprWithCleanups *E) {
+ llvm::Constant *VisitExprWithCleanups(ExprWithCleanups *E, QualType T) {
if (!E->cleanupsHaveSideEffects())
- return Visit(E->getSubExpr());
+ return Visit(E->getSubExpr(), T);
return nullptr;
}
- llvm::Constant *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
- return Visit(E->GetTemporaryExpr());
+ llvm::Constant *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E,
+ QualType T) {
+ return Visit(E->GetTemporaryExpr(), T);
}
- llvm::Constant *EmitArrayInitialization(InitListExpr *ILE) {
+ llvm::Constant *EmitArrayInitialization(InitListExpr *ILE, QualType T) {
llvm::ArrayType *AType =
cast<llvm::ArrayType>(ConvertType(ILE->getType()));
llvm::Type *ElemTy = AType->getElementType();
@@ -790,13 +842,14 @@ public:
// initialise any elements that have not been initialised explicitly
unsigned NumInitableElts = std::min(NumInitElements, NumElements);
+ QualType EltType = CGM.getContext().getAsArrayType(T)->getElementType();
+
// Initialize remaining array elements.
- // FIXME: This doesn't handle member pointers correctly!
llvm::Constant *fillC;
if (Expr *filler = ILE->getArrayFiller())
- fillC = CGM.EmitConstantExpr(filler, filler->getType(), CGF);
+ fillC = Emitter.tryEmitAbstractForMemory(filler, EltType);
else
- fillC = llvm::Constant::getNullValue(ElemTy);
+ fillC = Emitter.emitNullForMemory(EltType);
if (!fillC)
return nullptr;
@@ -805,13 +858,13 @@ public:
return llvm::ConstantAggregateZero::get(AType);
// Copy initializer elements.
- std::vector<llvm::Constant*> Elts;
+ SmallVector<llvm::Constant*, 16> Elts;
Elts.reserve(NumInitableElts + NumElements);
bool RewriteType = false;
for (unsigned i = 0; i < NumInitableElts; ++i) {
Expr *Init = ILE->getInit(i);
- llvm::Constant *C = CGM.EmitConstantExpr(Init, Init->getType(), CGF);
+ llvm::Constant *C = Emitter.tryEmitPrivateForMemory(Init, EltType);
if (!C)
return nullptr;
RewriteType |= (C->getType() != ElemTy);
@@ -835,33 +888,33 @@ public:
return llvm::ConstantArray::get(AType, Elts);
}
- llvm::Constant *EmitRecordInitialization(InitListExpr *ILE) {
- return ConstStructBuilder::BuildStruct(CGM, CGF, ILE);
+ llvm::Constant *EmitRecordInitialization(InitListExpr *ILE, QualType T) {
+ return ConstStructBuilder::BuildStruct(Emitter, ILE, T);
}
- llvm::Constant *VisitImplicitValueInitExpr(ImplicitValueInitExpr* E) {
- return CGM.EmitNullConstant(E->getType());
+ llvm::Constant *VisitImplicitValueInitExpr(ImplicitValueInitExpr* E,
+ QualType T) {
+ return CGM.EmitNullConstant(T);
}
- llvm::Constant *VisitInitListExpr(InitListExpr *ILE) {
+ llvm::Constant *VisitInitListExpr(InitListExpr *ILE, QualType T) {
if (ILE->isTransparent())
- return Visit(ILE->getInit(0));
+ return Visit(ILE->getInit(0), T);
if (ILE->getType()->isArrayType())
- return EmitArrayInitialization(ILE);
+ return EmitArrayInitialization(ILE, T);
if (ILE->getType()->isRecordType())
- return EmitRecordInitialization(ILE);
+ return EmitRecordInitialization(ILE, T);
return nullptr;
}
llvm::Constant *EmitDesignatedInitUpdater(llvm::Constant *Base,
- InitListExpr *Updater) {
- QualType ExprType = Updater->getType();
-
- if (ExprType->isArrayType()) {
- llvm::ArrayType *AType = cast<llvm::ArrayType>(ConvertType(ExprType));
+ InitListExpr *Updater,
+ QualType destType) {
+ if (auto destAT = CGM.getContext().getAsArrayType(destType)) {
+ llvm::ArrayType *AType = cast<llvm::ArrayType>(ConvertType(destType));
llvm::Type *ElemType = AType->getElementType();
unsigned NumInitElements = Updater->getNumInits();
@@ -870,12 +923,12 @@ public:
std::vector<llvm::Constant *> Elts;
Elts.reserve(NumElements);
- if (llvm::ConstantDataArray *DataArray =
- dyn_cast<llvm::ConstantDataArray>(Base))
+ QualType destElemType = destAT->getElementType();
+
+ if (auto DataArray = dyn_cast<llvm::ConstantDataArray>(Base))
for (unsigned i = 0; i != NumElements; ++i)
Elts.push_back(DataArray->getElementAsConstant(i));
- else if (llvm::ConstantArray *Array =
- dyn_cast<llvm::ConstantArray>(Base))
+ else if (auto Array = dyn_cast<llvm::ConstantArray>(Base))
for (unsigned i = 0; i != NumElements; ++i)
Elts.push_back(Array->getOperand(i));
else
@@ -884,7 +937,7 @@ public:
llvm::Constant *fillC = nullptr;
if (Expr *filler = Updater->getArrayFiller())
if (!isa<NoInitExpr>(filler))
- fillC = CGM.EmitConstantExpr(filler, filler->getType(), CGF);
+ fillC = Emitter.tryEmitAbstractForMemory(filler, destElemType);
bool RewriteType = (fillC && fillC->getType() != ElemType);
for (unsigned i = 0; i != NumElements; ++i) {
@@ -897,9 +950,9 @@ public:
else if (!Init || isa<NoInitExpr>(Init))
; // Do nothing.
else if (InitListExpr *ChildILE = dyn_cast<InitListExpr>(Init))
- Elts[i] = EmitDesignatedInitUpdater(Elts[i], ChildILE);
+ Elts[i] = EmitDesignatedInitUpdater(Elts[i], ChildILE, destElemType);
else
- Elts[i] = CGM.EmitConstantExpr(Init, Init->getType(), CGF);
+ Elts[i] = Emitter.tryEmitPrivateForMemory(Init, destElemType);
if (!Elts[i])
return nullptr;
@@ -919,25 +972,24 @@ public:
return llvm::ConstantArray::get(AType, Elts);
}
- if (ExprType->isRecordType())
- return ConstStructBuilder::BuildStruct(CGM, CGF, this,
- dyn_cast<llvm::ConstantStruct>(Base), Updater);
+ if (destType->isRecordType())
+ return ConstStructBuilder::BuildStruct(Emitter, this,
+ dyn_cast<llvm::ConstantStruct>(Base), Updater, destType);
return nullptr;
}
- llvm::Constant *VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *E) {
- return EmitDesignatedInitUpdater(
- CGM.EmitConstantExpr(E->getBase(), E->getType(), CGF),
- E->getUpdater());
+ llvm::Constant *VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *E,
+ QualType destType) {
+ auto C = Visit(E->getBase(), destType);
+ if (!C) return nullptr;
+ return EmitDesignatedInitUpdater(C, E->getUpdater(), destType);
}
- llvm::Constant *VisitCXXConstructExpr(CXXConstructExpr *E) {
+ llvm::Constant *VisitCXXConstructExpr(CXXConstructExpr *E, QualType Ty) {
if (!E->getConstructor()->isTrivial())
return nullptr;
- QualType Ty = E->getType();
-
// FIXME: We should not have to call getBaseElementType here.
const RecordType *RT =
CGM.getContext().getBaseElementType(Ty)->getAs<RecordType>();
@@ -960,26 +1012,23 @@ public:
assert(CGM.getContext().hasSameUnqualifiedType(Ty, Arg->getType()) &&
"argument to copy ctor is of wrong type");
- return Visit(Arg);
+ return Visit(Arg, Ty);
}
return CGM.EmitNullConstant(Ty);
}
- llvm::Constant *VisitStringLiteral(StringLiteral *E) {
+ llvm::Constant *VisitStringLiteral(StringLiteral *E, QualType T) {
return CGM.GetConstantArrayFromStringLiteral(E);
}
- llvm::Constant *VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
+ llvm::Constant *VisitObjCEncodeExpr(ObjCEncodeExpr *E, QualType T) {
// This must be an @encode initializing an array in a static initializer.
// Don't emit it as the address of the string, emit the string data itself
// as an inline array.
std::string Str;
CGM.getContext().getObjCEncodingForType(E->getEncodedType(), Str);
- QualType T = E->getType();
- if (T->getTypeClass() == Type::TypeOfExpr)
- T = cast<TypeOfExprType>(T)->getUnderlyingExpr()->getType();
- const ConstantArrayType *CAT = cast<ConstantArrayType>(T);
+ const ConstantArrayType *CAT = CGM.getContext().getAsConstantArrayType(T);
// Resize the string to the right size, adding zeros at the end, or
// truncating as needed.
@@ -987,151 +1036,19 @@ public:
return llvm::ConstantDataArray::getString(VMContext, Str, false);
}
- llvm::Constant *VisitUnaryExtension(const UnaryOperator *E) {
- return Visit(E->getSubExpr());
+ llvm::Constant *VisitUnaryExtension(const UnaryOperator *E, QualType T) {
+ return Visit(E->getSubExpr(), T);
}
// Utility methods
llvm::Type *ConvertType(QualType T) {
return CGM.getTypes().ConvertType(T);
}
-
-public:
- ConstantAddress EmitLValue(APValue::LValueBase LVBase) {
- if (const ValueDecl *Decl = LVBase.dyn_cast<const ValueDecl*>()) {
- if (Decl->hasAttr<WeakRefAttr>())
- return CGM.GetWeakRefReference(Decl);
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl))
- return ConstantAddress(CGM.GetAddrOfFunction(FD), CharUnits::One());
- if (const VarDecl* VD = dyn_cast<VarDecl>(Decl)) {
- // We can never refer to a variable with local storage.
- if (!VD->hasLocalStorage()) {
- CharUnits Align = CGM.getContext().getDeclAlign(VD);
- if (VD->isFileVarDecl() || VD->hasExternalStorage())
- return ConstantAddress(CGM.GetAddrOfGlobalVar(VD), Align);
- else if (VD->isLocalVarDecl()) {
- auto Ptr = CGM.getOrCreateStaticVarDecl(
- *VD, CGM.getLLVMLinkageVarDefinition(VD, /*isConstant=*/false));
- return ConstantAddress(Ptr, Align);
- }
- }
- }
- return ConstantAddress::invalid();
- }
-
- Expr *E = const_cast<Expr*>(LVBase.get<const Expr*>());
- switch (E->getStmtClass()) {
- default: break;
- case Expr::CompoundLiteralExprClass: {
- CompoundLiteralExpr *CLE = cast<CompoundLiteralExpr>(E);
- CharUnits Align = CGM.getContext().getTypeAlignInChars(E->getType());
- if (llvm::GlobalVariable *Addr =
- CGM.getAddrOfConstantCompoundLiteralIfEmitted(CLE))
- return ConstantAddress(Addr, Align);
-
- llvm::Constant* C = CGM.EmitConstantExpr(CLE->getInitializer(),
- CLE->getType(), CGF);
- // FIXME: "Leaked" on failure.
- if (!C) return ConstantAddress::invalid();
-
- auto GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(),
- E->getType().isConstant(CGM.getContext()),
- llvm::GlobalValue::InternalLinkage,
- C, ".compoundliteral", nullptr,
- llvm::GlobalVariable::NotThreadLocal,
- CGM.getContext().getTargetAddressSpace(E->getType()));
- GV->setAlignment(Align.getQuantity());
- CGM.setAddrOfConstantCompoundLiteral(CLE, GV);
- return ConstantAddress(GV, Align);
- }
- case Expr::StringLiteralClass:
- return CGM.GetAddrOfConstantStringFromLiteral(cast<StringLiteral>(E));
- case Expr::ObjCEncodeExprClass:
- return CGM.GetAddrOfConstantStringFromObjCEncode(cast<ObjCEncodeExpr>(E));
- case Expr::ObjCStringLiteralClass: {
- ObjCStringLiteral* SL = cast<ObjCStringLiteral>(E);
- ConstantAddress C =
- CGM.getObjCRuntime().GenerateConstantString(SL->getString());
- return C.getElementBitCast(ConvertType(E->getType()));
- }
- case Expr::PredefinedExprClass: {
- unsigned Type = cast<PredefinedExpr>(E)->getIdentType();
- if (CGF) {
- LValue Res = CGF->EmitPredefinedLValue(cast<PredefinedExpr>(E));
- return cast<ConstantAddress>(Res.getAddress());
- } else if (Type == PredefinedExpr::PrettyFunction) {
- return CGM.GetAddrOfConstantCString("top level", ".tmp");
- }
-
- return CGM.GetAddrOfConstantCString("", ".tmp");
- }
- case Expr::AddrLabelExprClass: {
- assert(CGF && "Invalid address of label expression outside function.");
- llvm::Constant *Ptr =
- CGF->GetAddrOfLabel(cast<AddrLabelExpr>(E)->getLabel());
- Ptr = llvm::ConstantExpr::getBitCast(Ptr, ConvertType(E->getType()));
- return ConstantAddress(Ptr, CharUnits::One());
- }
- case Expr::CallExprClass: {
- CallExpr* CE = cast<CallExpr>(E);
- unsigned builtin = CE->getBuiltinCallee();
- if (builtin !=
- Builtin::BI__builtin___CFStringMakeConstantString &&
- builtin !=
- Builtin::BI__builtin___NSStringMakeConstantString)
- break;
- const Expr *Arg = CE->getArg(0)->IgnoreParenCasts();
- const StringLiteral *Literal = cast<StringLiteral>(Arg);
- if (builtin ==
- Builtin::BI__builtin___NSStringMakeConstantString) {
- return CGM.getObjCRuntime().GenerateConstantString(Literal);
- }
- // FIXME: need to deal with UCN conversion issues.
- return CGM.GetAddrOfConstantCFString(Literal);
- }
- case Expr::BlockExprClass: {
- StringRef FunctionName;
- if (CGF)
- FunctionName = CGF->CurFn->getName();
- else
- FunctionName = "global";
-
- // This is not really an l-value.
- llvm::Constant *Ptr =
- CGM.GetAddrOfGlobalBlock(cast<BlockExpr>(E), FunctionName);
- return ConstantAddress(Ptr, CGM.getPointerAlign());
- }
- case Expr::CXXTypeidExprClass: {
- CXXTypeidExpr *Typeid = cast<CXXTypeidExpr>(E);
- QualType T;
- if (Typeid->isTypeOperand())
- T = Typeid->getTypeOperand(CGM.getContext());
- else
- T = Typeid->getExprOperand()->getType();
- return ConstantAddress(CGM.GetAddrOfRTTIDescriptor(T),
- CGM.getPointerAlign());
- }
- case Expr::CXXUuidofExprClass: {
- return CGM.GetAddrOfUuidDescriptor(cast<CXXUuidofExpr>(E));
- }
- case Expr::MaterializeTemporaryExprClass: {
- MaterializeTemporaryExpr *MTE = cast<MaterializeTemporaryExpr>(E);
- assert(MTE->getStorageDuration() == SD_Static);
- SmallVector<const Expr *, 2> CommaLHSs;
- SmallVector<SubobjectAdjustment, 2> Adjustments;
- const Expr *Inner = MTE->GetTemporaryExpr()
- ->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments);
- return CGM.GetAddrOfGlobalTemporary(MTE, Inner);
- }
- }
-
- return ConstantAddress::invalid();
- }
};
} // end anonymous namespace.
-bool ConstStructBuilder::Build(ConstExprEmitter *Emitter,
+bool ConstStructBuilder::Build(ConstExprEmitter *ExprEmitter,
llvm::ConstantStruct *Base,
InitListExpr *Updater) {
assert(Base && "base expression should not be empty");
@@ -1179,9 +1096,10 @@ bool ConstStructBuilder::Build(ConstExprEmitter *Emitter,
if (!Init || isa<NoInitExpr>(Init))
; // Do nothing.
else if (InitListExpr *ChildILE = dyn_cast<InitListExpr>(Init))
- EltInit = Emitter->EmitDesignatedInitUpdater(EltInit, ChildILE);
+ EltInit = ExprEmitter->EmitDesignatedInitUpdater(EltInit, ChildILE,
+ Field->getType());
else
- EltInit = CGM.EmitConstantExpr(Init, Field->getType(), CGF);
+ EltInit = Emitter.tryEmitPrivateForMemory(Init, Field->getType());
++ElementNo;
@@ -1200,26 +1118,294 @@ bool ConstStructBuilder::Build(ConstExprEmitter *Emitter,
return true;
}
-llvm::Constant *CodeGenModule::EmitConstantInit(const VarDecl &D,
- CodeGenFunction *CGF) {
+llvm::Constant *ConstantEmitter::validateAndPopAbstract(llvm::Constant *C,
+ AbstractState saved) {
+ Abstract = saved.OldValue;
+
+ assert(saved.OldPlaceholdersSize == PlaceholderAddresses.size() &&
+ "created a placeholder while doing an abstract emission?");
+
+ // No validation necessary for now.
+ // No cleanup to do for now.
+ return C;
+}
+
+llvm::Constant *
+ConstantEmitter::tryEmitAbstractForInitializer(const VarDecl &D) {
+ auto state = pushAbstract();
+ auto C = tryEmitPrivateForVarInit(D);
+ return validateAndPopAbstract(C, state);
+}
+
+llvm::Constant *
+ConstantEmitter::tryEmitAbstract(const Expr *E, QualType destType) {
+ auto state = pushAbstract();
+ auto C = tryEmitPrivate(E, destType);
+ return validateAndPopAbstract(C, state);
+}
+
+llvm::Constant *
+ConstantEmitter::tryEmitAbstract(const APValue &value, QualType destType) {
+ auto state = pushAbstract();
+ auto C = tryEmitPrivate(value, destType);
+ return validateAndPopAbstract(C, state);
+}
+
+llvm::Constant *
+ConstantEmitter::emitAbstract(const Expr *E, QualType destType) {
+ auto state = pushAbstract();
+ auto C = tryEmitPrivate(E, destType);
+ C = validateAndPopAbstract(C, state);
+ if (!C) {
+ CGM.Error(E->getExprLoc(),
+ "internal error: could not emit constant value \"abstractly\"");
+ C = CGM.EmitNullConstant(destType);
+ }
+ return C;
+}
+
+llvm::Constant *
+ConstantEmitter::emitAbstract(SourceLocation loc, const APValue &value,
+ QualType destType) {
+ auto state = pushAbstract();
+ auto C = tryEmitPrivate(value, destType);
+ C = validateAndPopAbstract(C, state);
+ if (!C) {
+ CGM.Error(loc,
+ "internal error: could not emit constant value \"abstractly\"");
+ C = CGM.EmitNullConstant(destType);
+ }
+ return C;
+}
+
+llvm::Constant *ConstantEmitter::tryEmitForInitializer(const VarDecl &D) {
+ initializeNonAbstract(D.getType().getAddressSpace());
+ return markIfFailed(tryEmitPrivateForVarInit(D));
+}
+
+llvm::Constant *ConstantEmitter::tryEmitForInitializer(const Expr *E,
+ LangAS destAddrSpace,
+ QualType destType) {
+ initializeNonAbstract(destAddrSpace);
+ return markIfFailed(tryEmitPrivateForMemory(E, destType));
+}
+
+llvm::Constant *ConstantEmitter::emitForInitializer(const APValue &value,
+ LangAS destAddrSpace,
+ QualType destType) {
+ initializeNonAbstract(destAddrSpace);
+ auto C = tryEmitPrivateForMemory(value, destType);
+ assert(C && "couldn't emit constant value non-abstractly?");
+ return C;
+}
+
+llvm::GlobalValue *ConstantEmitter::getCurrentAddrPrivate() {
+ assert(!Abstract && "cannot get current address for abstract constant");
+
+
+
+ // Make an obviously ill-formed global that should blow up compilation
+ // if it survives.
+ auto global = new llvm::GlobalVariable(CGM.getModule(), CGM.Int8Ty, true,
+ llvm::GlobalValue::PrivateLinkage,
+ /*init*/ nullptr,
+ /*name*/ "",
+ /*before*/ nullptr,
+ llvm::GlobalVariable::NotThreadLocal,
+ CGM.getContext().getTargetAddressSpace(DestAddressSpace));
+
+ PlaceholderAddresses.push_back(std::make_pair(nullptr, global));
+
+ return global;
+}
+
+void ConstantEmitter::registerCurrentAddrPrivate(llvm::Constant *signal,
+ llvm::GlobalValue *placeholder) {
+ assert(!PlaceholderAddresses.empty());
+ assert(PlaceholderAddresses.back().first == nullptr);
+ assert(PlaceholderAddresses.back().second == placeholder);
+ PlaceholderAddresses.back().first = signal;
+}
+
+namespace {
+ struct ReplacePlaceholders {
+ CodeGenModule &CGM;
+
+ /// The base address of the global.
+ llvm::Constant *Base;
+ llvm::Type *BaseValueTy = nullptr;
+
+ /// The placeholder addresses that were registered during emission.
+ llvm::DenseMap<llvm::Constant*, llvm::GlobalVariable*> PlaceholderAddresses;
+
+ /// The locations of the placeholder signals.
+ llvm::DenseMap<llvm::GlobalVariable*, llvm::Constant*> Locations;
+
+ /// The current index stack. We use a simple unsigned stack because
+ /// we assume that placeholders will be relatively sparse in the
+ /// initializer, but we cache the index values we find just in case.
+ llvm::SmallVector<unsigned, 8> Indices;
+ llvm::SmallVector<llvm::Constant*, 8> IndexValues;
+
+ ReplacePlaceholders(CodeGenModule &CGM, llvm::Constant *base,
+ ArrayRef<std::pair<llvm::Constant*,
+ llvm::GlobalVariable*>> addresses)
+ : CGM(CGM), Base(base),
+ PlaceholderAddresses(addresses.begin(), addresses.end()) {
+ }
+
+ void replaceInInitializer(llvm::Constant *init) {
+ // Remember the type of the top-most initializer.
+ BaseValueTy = init->getType();
+
+ // Initialize the stack.
+ Indices.push_back(0);
+ IndexValues.push_back(nullptr);
+
+ // Recurse into the initializer.
+ findLocations(init);
+
+ // Check invariants.
+ assert(IndexValues.size() == Indices.size() && "mismatch");
+ assert(Indices.size() == 1 && "didn't pop all indices");
+
+ // Do the replacement; this basically invalidates 'init'.
+ assert(Locations.size() == PlaceholderAddresses.size() &&
+ "missed a placeholder?");
+
+ // We're iterating over a hashtable, so this would be a source of
+ // non-determinism in compiler output *except* that we're just
+ // messing around with llvm::Constant structures, which never itself
+ // does anything that should be visible in compiler output.
+ for (auto &entry : Locations) {
+ assert(entry.first->getParent() == nullptr && "not a placeholder!");
+ entry.first->replaceAllUsesWith(entry.second);
+ entry.first->eraseFromParent();
+ }
+ }
+
+ private:
+ void findLocations(llvm::Constant *init) {
+ // Recurse into aggregates.
+ if (auto agg = dyn_cast<llvm::ConstantAggregate>(init)) {
+ for (unsigned i = 0, e = agg->getNumOperands(); i != e; ++i) {
+ Indices.push_back(i);
+ IndexValues.push_back(nullptr);
+
+ findLocations(agg->getOperand(i));
+
+ IndexValues.pop_back();
+ Indices.pop_back();
+ }
+ return;
+ }
+
+ // Otherwise, check for registered constants.
+ while (true) {
+ auto it = PlaceholderAddresses.find(init);
+ if (it != PlaceholderAddresses.end()) {
+ setLocation(it->second);
+ break;
+ }
+
+ // Look through bitcasts or other expressions.
+ if (auto expr = dyn_cast<llvm::ConstantExpr>(init)) {
+ init = expr->getOperand(0);
+ } else {
+ break;
+ }
+ }
+ }
+
+ void setLocation(llvm::GlobalVariable *placeholder) {
+ assert(Locations.find(placeholder) == Locations.end() &&
+ "already found location for placeholder!");
+
+ // Lazily fill in IndexValues with the values from Indices.
+ // We do this in reverse because we should always have a strict
+ // prefix of indices from the start.
+ assert(Indices.size() == IndexValues.size());
+ for (size_t i = Indices.size() - 1; i != size_t(-1); --i) {
+ if (IndexValues[i]) {
+#ifndef NDEBUG
+ for (size_t j = 0; j != i + 1; ++j) {
+ assert(IndexValues[j] &&
+ isa<llvm::ConstantInt>(IndexValues[j]) &&
+ cast<llvm::ConstantInt>(IndexValues[j])->getZExtValue()
+ == Indices[j]);
+ }
+#endif
+ break;
+ }
+
+ IndexValues[i] = llvm::ConstantInt::get(CGM.Int32Ty, Indices[i]);
+ }
+
+ // Form a GEP and then bitcast to the placeholder type so that the
+ // replacement will succeed.
+ llvm::Constant *location =
+ llvm::ConstantExpr::getInBoundsGetElementPtr(BaseValueTy,
+ Base, IndexValues);
+ location = llvm::ConstantExpr::getBitCast(location,
+ placeholder->getType());
+
+ Locations.insert({placeholder, location});
+ }
+ };
+}
+
+void ConstantEmitter::finalize(llvm::GlobalVariable *global) {
+ assert(InitializedNonAbstract &&
+ "finalizing emitter that was used for abstract emission?");
+ assert(!Finalized && "finalizing emitter multiple times");
+ assert(global->getInitializer());
+
+ // Note that we might also be Failed.
+ Finalized = true;
+
+ if (!PlaceholderAddresses.empty()) {
+ ReplacePlaceholders(CGM, global, PlaceholderAddresses)
+ .replaceInInitializer(global->getInitializer());
+ PlaceholderAddresses.clear(); // satisfy
+ }
+}
+
+ConstantEmitter::~ConstantEmitter() {
+ assert((!InitializedNonAbstract || Finalized || Failed) &&
+ "not finalized after being initialized for non-abstract emission");
+ assert(PlaceholderAddresses.empty() && "unhandled placeholders");
+}
+
+static QualType getNonMemoryType(CodeGenModule &CGM, QualType type) {
+ if (auto AT = type->getAs<AtomicType>()) {
+ return CGM.getContext().getQualifiedType(AT->getValueType(),
+ type.getQualifiers());
+ }
+ return type;
+}
+
+llvm::Constant *ConstantEmitter::tryEmitPrivateForVarInit(const VarDecl &D) {
// Make a quick check if variable can be default NULL initialized
// and avoid going through rest of code which may do, for c++11,
// initialization of memory to all NULLs.
if (!D.hasLocalStorage()) {
- QualType Ty = D.getType();
- if (Ty->isArrayType())
- Ty = Context.getBaseElementType(Ty);
+ QualType Ty = CGM.getContext().getBaseElementType(D.getType());
if (Ty->isRecordType())
if (const CXXConstructExpr *E =
dyn_cast_or_null<CXXConstructExpr>(D.getInit())) {
const CXXConstructorDecl *CD = E->getConstructor();
if (CD->isTrivial() && CD->isDefaultConstructor())
- return EmitNullConstant(D.getType());
+ return CGM.EmitNullConstant(D.getType());
}
}
-
- if (const APValue *Value = D.evaluateValue())
- return EmitConstantValueForMemory(*Value, D.getType(), CGF);
+
+ QualType destType = D.getType();
+
+ // Try to emit the initializer. Note that this can allow some things that
+ // are not allowed by tryEmitPrivateForMemory alone.
+ if (auto value = D.evaluateValue()) {
+ return tryEmitPrivateForMemory(*value, destType);
+ }
// FIXME: Implement C++11 [basic.start.init]p2: if the initializer of a
// reference is a constant expression, and the reference binds to a temporary,
@@ -1227,42 +1413,95 @@ llvm::Constant *CodeGenModule::EmitConstantInit(const VarDecl &D,
// incorrectly emit a prvalue constant in this case, and the calling code
// interprets that as the (pointer) value of the reference, rather than the
// desired value of the referee.
- if (D.getType()->isReferenceType())
+ if (destType->isReferenceType())
return nullptr;
const Expr *E = D.getInit();
assert(E && "No initializer to emit");
- llvm::Constant* C = ConstExprEmitter(*this, CGF).Visit(const_cast<Expr*>(E));
- if (C && C->getType()->isIntegerTy(1)) {
- llvm::Type *BoolTy = getTypes().ConvertTypeForMem(E->getType());
- C = llvm::ConstantExpr::getZExt(C, BoolTy);
+ auto nonMemoryDestType = getNonMemoryType(CGM, destType);
+ auto C =
+ ConstExprEmitter(*this).Visit(const_cast<Expr*>(E), nonMemoryDestType);
+ return (C ? emitForMemory(C, destType) : nullptr);
+}
+
+llvm::Constant *
+ConstantEmitter::tryEmitAbstractForMemory(const Expr *E, QualType destType) {
+ auto nonMemoryDestType = getNonMemoryType(CGM, destType);
+ auto C = tryEmitAbstract(E, nonMemoryDestType);
+ return (C ? emitForMemory(C, destType) : nullptr);
+}
+
+llvm::Constant *
+ConstantEmitter::tryEmitAbstractForMemory(const APValue &value,
+ QualType destType) {
+ auto nonMemoryDestType = getNonMemoryType(CGM, destType);
+ auto C = tryEmitAbstract(value, nonMemoryDestType);
+ return (C ? emitForMemory(C, destType) : nullptr);
+}
+
+llvm::Constant *ConstantEmitter::tryEmitPrivateForMemory(const Expr *E,
+ QualType destType) {
+ auto nonMemoryDestType = getNonMemoryType(CGM, destType);
+ llvm::Constant *C = tryEmitPrivate(E, nonMemoryDestType);
+ return (C ? emitForMemory(C, destType) : nullptr);
+}
+
+llvm::Constant *ConstantEmitter::tryEmitPrivateForMemory(const APValue &value,
+ QualType destType) {
+ auto nonMemoryDestType = getNonMemoryType(CGM, destType);
+ auto C = tryEmitPrivate(value, nonMemoryDestType);
+ return (C ? emitForMemory(C, destType) : nullptr);
+}
+
+llvm::Constant *ConstantEmitter::emitForMemory(CodeGenModule &CGM,
+ llvm::Constant *C,
+ QualType destType) {
+ // For an _Atomic-qualified constant, we may need to add tail padding.
+ if (auto AT = destType->getAs<AtomicType>()) {
+ QualType destValueType = AT->getValueType();
+ C = emitForMemory(CGM, C, destValueType);
+
+ uint64_t innerSize = CGM.getContext().getTypeSize(destValueType);
+ uint64_t outerSize = CGM.getContext().getTypeSize(destType);
+ if (innerSize == outerSize)
+ return C;
+
+ assert(innerSize < outerSize && "emitted over-large constant for atomic");
+ llvm::Constant *elts[] = {
+ C,
+ llvm::ConstantAggregateZero::get(
+ llvm::ArrayType::get(CGM.Int8Ty, (outerSize - innerSize) / 8))
+ };
+ return llvm::ConstantStruct::getAnon(elts);
+ }
+
+ // Zero-extend bool.
+ if (C->getType()->isIntegerTy(1)) {
+ llvm::Type *boolTy = CGM.getTypes().ConvertTypeForMem(destType);
+ return llvm::ConstantExpr::getZExt(C, boolTy);
}
+
return C;
}
-llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E,
- QualType DestType,
- CodeGenFunction *CGF) {
+llvm::Constant *ConstantEmitter::tryEmitPrivate(const Expr *E,
+ QualType destType) {
Expr::EvalResult Result;
bool Success = false;
- if (DestType->isReferenceType())
- Success = E->EvaluateAsLValue(Result, Context);
+ if (destType->isReferenceType())
+ Success = E->EvaluateAsLValue(Result, CGM.getContext());
else
- Success = E->EvaluateAsRValue(Result, Context);
+ Success = E->EvaluateAsRValue(Result, CGM.getContext());
- llvm::Constant *C = nullptr;
+ llvm::Constant *C;
if (Success && !Result.HasSideEffects)
- C = EmitConstantValue(Result.Val, DestType, CGF);
+ C = tryEmitPrivate(Result.Val, destType);
else
- C = ConstExprEmitter(*this, CGF).Visit(const_cast<Expr*>(E));
+ C = ConstExprEmitter(*this).Visit(const_cast<Expr*>(E), destType);
- if (C && C->getType()->isIntegerTy(1)) {
- llvm::Type *BoolTy = getTypes().ConvertTypeForMem(E->getType());
- C = llvm::ConstantExpr::getZExt(C, BoolTy);
- }
return C;
}
@@ -1270,94 +1509,311 @@ llvm::Constant *CodeGenModule::getNullPointer(llvm::PointerType *T, QualType QT)
return getTargetCodeGenInfo().getNullPointer(*this, T, QT);
}
-llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value,
- QualType DestType,
- CodeGenFunction *CGF) {
- // For an _Atomic-qualified constant, we may need to add tail padding.
- if (auto *AT = DestType->getAs<AtomicType>()) {
- QualType InnerType = AT->getValueType();
- auto *Inner = EmitConstantValue(Value, InnerType, CGF);
+namespace {
+/// A struct which can be used to peephole certain kinds of finalization
+/// that normally happen during l-value emission.
+struct ConstantLValue {
+ llvm::Constant *Value;
+ bool HasOffsetApplied;
- uint64_t InnerSize = Context.getTypeSize(InnerType);
- uint64_t OuterSize = Context.getTypeSize(DestType);
- if (InnerSize == OuterSize)
- return Inner;
+ /*implicit*/ ConstantLValue(llvm::Constant *value,
+ bool hasOffsetApplied = false)
+ : Value(value), HasOffsetApplied(false) {}
- assert(InnerSize < OuterSize && "emitted over-large constant for atomic");
- llvm::Constant *Elts[] = {
- Inner,
- llvm::ConstantAggregateZero::get(
- llvm::ArrayType::get(Int8Ty, (OuterSize - InnerSize) / 8))
- };
- return llvm::ConstantStruct::getAnon(Elts);
+ /*implicit*/ ConstantLValue(ConstantAddress address)
+ : ConstantLValue(address.getPointer()) {}
+};
+
+/// A helper class for emitting constant l-values.
+class ConstantLValueEmitter : public ConstStmtVisitor<ConstantLValueEmitter,
+ ConstantLValue> {
+ CodeGenModule &CGM;
+ ConstantEmitter &Emitter;
+ const APValue &Value;
+ QualType DestType;
+
+ // Befriend StmtVisitorBase so that we don't have to expose Visit*.
+ friend StmtVisitorBase;
+
+public:
+ ConstantLValueEmitter(ConstantEmitter &emitter, const APValue &value,
+ QualType destType)
+ : CGM(emitter.CGM), Emitter(emitter), Value(value), DestType(destType) {}
+
+ llvm::Constant *tryEmit();
+
+private:
+ llvm::Constant *tryEmitAbsolute(llvm::Type *destTy);
+ ConstantLValue tryEmitBase(const APValue::LValueBase &base);
+
+ ConstantLValue VisitStmt(const Stmt *S) { return nullptr; }
+ ConstantLValue VisitCompoundLiteralExpr(const CompoundLiteralExpr *E);
+ ConstantLValue VisitStringLiteral(const StringLiteral *E);
+ ConstantLValue VisitObjCEncodeExpr(const ObjCEncodeExpr *E);
+ ConstantLValue VisitObjCStringLiteral(const ObjCStringLiteral *E);
+ ConstantLValue VisitPredefinedExpr(const PredefinedExpr *E);
+ ConstantLValue VisitAddrLabelExpr(const AddrLabelExpr *E);
+ ConstantLValue VisitCallExpr(const CallExpr *E);
+ ConstantLValue VisitBlockExpr(const BlockExpr *E);
+ ConstantLValue VisitCXXTypeidExpr(const CXXTypeidExpr *E);
+ ConstantLValue VisitCXXUuidofExpr(const CXXUuidofExpr *E);
+ ConstantLValue VisitMaterializeTemporaryExpr(
+ const MaterializeTemporaryExpr *E);
+
+ bool hasNonZeroOffset() const {
+ return !Value.getLValueOffset().isZero();
}
- switch (Value.getKind()) {
- case APValue::Uninitialized:
- llvm_unreachable("Constant expressions should be initialized.");
- case APValue::LValue: {
- llvm::Type *DestTy = getTypes().ConvertTypeForMem(DestType);
- llvm::Constant *Offset =
- llvm::ConstantInt::get(Int64Ty, Value.getLValueOffset().getQuantity());
+ /// Return the value offset.
+ llvm::Constant *getOffset() {
+ return llvm::ConstantInt::get(CGM.Int64Ty,
+ Value.getLValueOffset().getQuantity());
+ }
- llvm::Constant *C = nullptr;
+ /// Apply the value offset to the given constant.
+ llvm::Constant *applyOffset(llvm::Constant *C) {
+ if (!hasNonZeroOffset())
+ return C;
- if (APValue::LValueBase LVBase = Value.getLValueBase()) {
- // An array can be represented as an lvalue referring to the base.
- if (isa<llvm::ArrayType>(DestTy)) {
- assert(Offset->isNullValue() && "offset on array initializer");
- return ConstExprEmitter(*this, CGF).Visit(
- const_cast<Expr*>(LVBase.get<const Expr*>()));
- }
+ llvm::Type *origPtrTy = C->getType();
+ unsigned AS = origPtrTy->getPointerAddressSpace();
+ llvm::Type *charPtrTy = CGM.Int8Ty->getPointerTo(AS);
+ C = llvm::ConstantExpr::getBitCast(C, charPtrTy);
+ C = llvm::ConstantExpr::getGetElementPtr(CGM.Int8Ty, C, getOffset());
+ C = llvm::ConstantExpr::getPointerCast(C, origPtrTy);
+ return C;
+ }
+};
- C = ConstExprEmitter(*this, CGF).EmitLValue(LVBase).getPointer();
+}
- // Apply offset if necessary.
- if (!Offset->isNullValue()) {
- unsigned AS = C->getType()->getPointerAddressSpace();
- llvm::Type *CharPtrTy = Int8Ty->getPointerTo(AS);
- llvm::Constant *Casted = llvm::ConstantExpr::getBitCast(C, CharPtrTy);
- Casted = llvm::ConstantExpr::getGetElementPtr(Int8Ty, Casted, Offset);
- C = llvm::ConstantExpr::getPointerCast(Casted, C->getType());
- }
+llvm::Constant *ConstantLValueEmitter::tryEmit() {
+ const APValue::LValueBase &base = Value.getLValueBase();
- // Convert to the appropriate type; this could be an lvalue for
- // an integer.
- if (isa<llvm::PointerType>(DestTy))
- return llvm::ConstantExpr::getPointerCast(C, DestTy);
+ // Certain special array initializers are represented in APValue
+ // as l-values referring to the base expression which generates the
+ // array. This happens with e.g. string literals. These should
+ // probably just get their own representation kind in APValue.
+ if (DestType->isArrayType()) {
+ assert(!hasNonZeroOffset() && "offset on array initializer");
+ auto expr = const_cast<Expr*>(base.get<const Expr*>());
+ return ConstExprEmitter(Emitter).Visit(expr, DestType);
+ }
- return llvm::ConstantExpr::getPtrToInt(C, DestTy);
- } else {
- C = Offset;
+ // Otherwise, the destination type should be a pointer or reference
+ // type, but it might also be a cast thereof.
+ //
+ // FIXME: the chain of casts required should be reflected in the APValue.
+ // We need this in order to correctly handle things like a ptrtoint of a
+ // non-zero null pointer and addrspace casts that aren't trivially
+ // represented in LLVM IR.
+ auto destTy = CGM.getTypes().ConvertTypeForMem(DestType);
+ assert(isa<llvm::IntegerType>(destTy) || isa<llvm::PointerType>(destTy));
- // Convert to the appropriate type; this could be an lvalue for
- // an integer.
- if (auto PT = dyn_cast<llvm::PointerType>(DestTy)) {
- if (Value.isNullPointer())
- return getNullPointer(PT, DestType);
- // Convert the integer to a pointer-sized integer before converting it
- // to a pointer.
- C = llvm::ConstantExpr::getIntegerCast(
- C, getDataLayout().getIntPtrType(DestTy),
- /*isSigned=*/false);
- return llvm::ConstantExpr::getIntToPtr(C, DestTy);
- }
+ // If there's no base at all, this is a null or absolute pointer,
+ // possibly cast back to an integer type.
+ if (!base) {
+ return tryEmitAbsolute(destTy);
+ }
- // If the types don't match this should only be a truncate.
- if (C->getType() != DestTy)
- return llvm::ConstantExpr::getTrunc(C, DestTy);
+ // Otherwise, try to emit the base.
+ ConstantLValue result = tryEmitBase(base);
- return C;
+ // If that failed, we're done.
+ llvm::Constant *value = result.Value;
+ if (!value) return nullptr;
+
+ // Apply the offset if necessary and not already done.
+ if (!result.HasOffsetApplied) {
+ value = applyOffset(value);
+ }
+
+ // Convert to the appropriate type; this could be an lvalue for
+ // an integer. FIXME: performAddrSpaceCast
+ if (isa<llvm::PointerType>(destTy))
+ return llvm::ConstantExpr::getPointerCast(value, destTy);
+
+ return llvm::ConstantExpr::getPtrToInt(value, destTy);
+}
+
+/// Try to emit an absolute l-value, such as a null pointer or an integer
+/// bitcast to pointer type.
+llvm::Constant *
+ConstantLValueEmitter::tryEmitAbsolute(llvm::Type *destTy) {
+ auto offset = getOffset();
+
+ // If we're producing a pointer, this is easy.
+ if (auto destPtrTy = cast<llvm::PointerType>(destTy)) {
+ if (Value.isNullPointer()) {
+ // FIXME: integer offsets from non-zero null pointers.
+ return CGM.getNullPointer(destPtrTy, DestType);
+ }
+
+ // Convert the integer to a pointer-sized integer before converting it
+ // to a pointer.
+ // FIXME: signedness depends on the original integer type.
+ auto intptrTy = CGM.getDataLayout().getIntPtrType(destPtrTy);
+ llvm::Constant *C = offset;
+ C = llvm::ConstantExpr::getIntegerCast(getOffset(), intptrTy,
+ /*isSigned*/ false);
+ C = llvm::ConstantExpr::getIntToPtr(C, destPtrTy);
+ return C;
+ }
+
+ // Otherwise, we're basically returning an integer constant.
+
+ // FIXME: this does the wrong thing with ptrtoint of a null pointer,
+ // but since we don't know the original pointer type, there's not much
+ // we can do about it.
+
+ auto C = getOffset();
+ C = llvm::ConstantExpr::getIntegerCast(C, destTy, /*isSigned*/ false);
+ return C;
+}
+
+ConstantLValue
+ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) {
+ // Handle values.
+ if (const ValueDecl *D = base.dyn_cast<const ValueDecl*>()) {
+ if (D->hasAttr<WeakRefAttr>())
+ return CGM.GetWeakRefReference(D).getPointer();
+
+ if (auto FD = dyn_cast<FunctionDecl>(D))
+ return CGM.GetAddrOfFunction(FD);
+
+ if (auto VD = dyn_cast<VarDecl>(D)) {
+ // We can never refer to a variable with local storage.
+ if (!VD->hasLocalStorage()) {
+ if (VD->isFileVarDecl() || VD->hasExternalStorage())
+ return CGM.GetAddrOfGlobalVar(VD);
+
+ if (VD->isLocalVarDecl()) {
+ return CGM.getOrCreateStaticVarDecl(
+ *VD, CGM.getLLVMLinkageVarDefinition(VD, /*isConstant=*/false));
+ }
+ }
}
+
+ return nullptr;
+ }
+
+ // Otherwise, it must be an expression.
+ return Visit(base.get<const Expr*>());
+}
+
+ConstantLValue
+ConstantLValueEmitter::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
+ return tryEmitGlobalCompoundLiteral(CGM, Emitter.CGF, E);
+}
+
+ConstantLValue
+ConstantLValueEmitter::VisitStringLiteral(const StringLiteral *E) {
+ return CGM.GetAddrOfConstantStringFromLiteral(E);
+}
+
+ConstantLValue
+ConstantLValueEmitter::VisitObjCEncodeExpr(const ObjCEncodeExpr *E) {
+ return CGM.GetAddrOfConstantStringFromObjCEncode(E);
+}
+
+ConstantLValue
+ConstantLValueEmitter::VisitObjCStringLiteral(const ObjCStringLiteral *E) {
+ auto C = CGM.getObjCRuntime().GenerateConstantString(E->getString());
+ return C.getElementBitCast(CGM.getTypes().ConvertTypeForMem(E->getType()));
+}
+
+ConstantLValue
+ConstantLValueEmitter::VisitPredefinedExpr(const PredefinedExpr *E) {
+ if (auto CGF = Emitter.CGF) {
+ LValue Res = CGF->EmitPredefinedLValue(E);
+ return cast<ConstantAddress>(Res.getAddress());
+ }
+
+ auto kind = E->getIdentType();
+ if (kind == PredefinedExpr::PrettyFunction) {
+ return CGM.GetAddrOfConstantCString("top level", ".tmp");
}
+
+ return CGM.GetAddrOfConstantCString("", ".tmp");
+}
+
+ConstantLValue
+ConstantLValueEmitter::VisitAddrLabelExpr(const AddrLabelExpr *E) {
+ assert(Emitter.CGF && "Invalid address of label expression outside function");
+ llvm::Constant *Ptr = Emitter.CGF->GetAddrOfLabel(E->getLabel());
+ Ptr = llvm::ConstantExpr::getBitCast(Ptr,
+ CGM.getTypes().ConvertType(E->getType()));
+ return Ptr;
+}
+
+ConstantLValue
+ConstantLValueEmitter::VisitCallExpr(const CallExpr *E) {
+ unsigned builtin = E->getBuiltinCallee();
+ if (builtin != Builtin::BI__builtin___CFStringMakeConstantString &&
+ builtin != Builtin::BI__builtin___NSStringMakeConstantString)
+ return nullptr;
+
+ auto literal = cast<StringLiteral>(E->getArg(0)->IgnoreParenCasts());
+ if (builtin == Builtin::BI__builtin___NSStringMakeConstantString) {
+ return CGM.getObjCRuntime().GenerateConstantString(literal);
+ } else {
+ // FIXME: need to deal with UCN conversion issues.
+ return CGM.GetAddrOfConstantCFString(literal);
+ }
+}
+
+ConstantLValue
+ConstantLValueEmitter::VisitBlockExpr(const BlockExpr *E) {
+ StringRef functionName;
+ if (auto CGF = Emitter.CGF)
+ functionName = CGF->CurFn->getName();
+ else
+ functionName = "global";
+
+ return CGM.GetAddrOfGlobalBlock(E, functionName);
+}
+
+ConstantLValue
+ConstantLValueEmitter::VisitCXXTypeidExpr(const CXXTypeidExpr *E) {
+ QualType T;
+ if (E->isTypeOperand())
+ T = E->getTypeOperand(CGM.getContext());
+ else
+ T = E->getExprOperand()->getType();
+ return CGM.GetAddrOfRTTIDescriptor(T);
+}
+
+ConstantLValue
+ConstantLValueEmitter::VisitCXXUuidofExpr(const CXXUuidofExpr *E) {
+ return CGM.GetAddrOfUuidDescriptor(E);
+}
+
+ConstantLValue
+ConstantLValueEmitter::VisitMaterializeTemporaryExpr(
+ const MaterializeTemporaryExpr *E) {
+ assert(E->getStorageDuration() == SD_Static);
+ SmallVector<const Expr *, 2> CommaLHSs;
+ SmallVector<SubobjectAdjustment, 2> Adjustments;
+ const Expr *Inner = E->GetTemporaryExpr()
+ ->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments);
+ return CGM.GetAddrOfGlobalTemporary(E, Inner);
+}
+
+llvm::Constant *ConstantEmitter::tryEmitPrivate(const APValue &Value,
+ QualType DestType) {
+ switch (Value.getKind()) {
+ case APValue::Uninitialized:
+ llvm_unreachable("Constant expressions should be initialized.");
+ case APValue::LValue:
+ return ConstantLValueEmitter(*this, Value, DestType).tryEmit();
case APValue::Int:
- return llvm::ConstantInt::get(VMContext, Value.getInt());
+ return llvm::ConstantInt::get(CGM.getLLVMContext(), Value.getInt());
case APValue::ComplexInt: {
llvm::Constant *Complex[2];
- Complex[0] = llvm::ConstantInt::get(VMContext,
+ Complex[0] = llvm::ConstantInt::get(CGM.getLLVMContext(),
Value.getComplexIntReal());
- Complex[1] = llvm::ConstantInt::get(VMContext,
+ Complex[1] = llvm::ConstantInt::get(CGM.getLLVMContext(),
Value.getComplexIntImag());
// FIXME: the target may want to specify that this is packed.
@@ -1368,18 +1824,19 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value,
case APValue::Float: {
const llvm::APFloat &Init = Value.getFloat();
if (&Init.getSemantics() == &llvm::APFloat::IEEEhalf() &&
- !Context.getLangOpts().NativeHalfType &&
- !Context.getLangOpts().HalfArgsAndReturns)
- return llvm::ConstantInt::get(VMContext, Init.bitcastToAPInt());
+ !CGM.getContext().getLangOpts().NativeHalfType &&
+ CGM.getContext().getTargetInfo().useFP16ConversionIntrinsics())
+ return llvm::ConstantInt::get(CGM.getLLVMContext(),
+ Init.bitcastToAPInt());
else
- return llvm::ConstantFP::get(VMContext, Init);
+ return llvm::ConstantFP::get(CGM.getLLVMContext(), Init);
}
case APValue::ComplexFloat: {
llvm::Constant *Complex[2];
- Complex[0] = llvm::ConstantFP::get(VMContext,
+ Complex[0] = llvm::ConstantFP::get(CGM.getLLVMContext(),
Value.getComplexFloatReal());
- Complex[1] = llvm::ConstantFP::get(VMContext,
+ Complex[1] = llvm::ConstantFP::get(CGM.getLLVMContext(),
Value.getComplexFloatImag());
// FIXME: the target may want to specify that this is packed.
@@ -1394,9 +1851,9 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value,
for (unsigned I = 0; I != NumElts; ++I) {
const APValue &Elt = Value.getVectorElt(I);
if (Elt.isInt())
- Inits[I] = llvm::ConstantInt::get(VMContext, Elt.getInt());
+ Inits[I] = llvm::ConstantInt::get(CGM.getLLVMContext(), Elt.getInt());
else if (Elt.isFloat())
- Inits[I] = llvm::ConstantFP::get(VMContext, Elt.getFloat());
+ Inits[I] = llvm::ConstantFP::get(CGM.getLLVMContext(), Elt.getFloat());
else
llvm_unreachable("unsupported vector element type");
}
@@ -1405,13 +1862,14 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value,
case APValue::AddrLabelDiff: {
const AddrLabelExpr *LHSExpr = Value.getAddrLabelDiffLHS();
const AddrLabelExpr *RHSExpr = Value.getAddrLabelDiffRHS();
- llvm::Constant *LHS = EmitConstantExpr(LHSExpr, LHSExpr->getType(), CGF);
- llvm::Constant *RHS = EmitConstantExpr(RHSExpr, RHSExpr->getType(), CGF);
+ llvm::Constant *LHS = tryEmitPrivate(LHSExpr, LHSExpr->getType());
+ llvm::Constant *RHS = tryEmitPrivate(RHSExpr, RHSExpr->getType());
+ if (!LHS || !RHS) return nullptr;
// Compute difference
- llvm::Type *ResultType = getTypes().ConvertType(DestType);
- LHS = llvm::ConstantExpr::getPtrToInt(LHS, IntPtrTy);
- RHS = llvm::ConstantExpr::getPtrToInt(RHS, IntPtrTy);
+ llvm::Type *ResultType = CGM.getTypes().ConvertType(DestType);
+ LHS = llvm::ConstantExpr::getPtrToInt(LHS, CGM.IntPtrTy);
+ RHS = llvm::ConstantExpr::getPtrToInt(RHS, CGM.IntPtrTy);
llvm::Constant *AddrLabelDiff = llvm::ConstantExpr::getSub(LHS, RHS);
// LLVM is a bit sensitive about the exact format of the
@@ -1421,21 +1879,21 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value,
}
case APValue::Struct:
case APValue::Union:
- return ConstStructBuilder::BuildStruct(*this, CGF, Value, DestType);
+ return ConstStructBuilder::BuildStruct(*this, Value, DestType);
case APValue::Array: {
- const ArrayType *CAT = Context.getAsArrayType(DestType);
+ const ArrayType *CAT = CGM.getContext().getAsArrayType(DestType);
unsigned NumElements = Value.getArraySize();
unsigned NumInitElts = Value.getArrayInitializedElts();
// Emit array filler, if there is one.
llvm::Constant *Filler = nullptr;
if (Value.hasArrayFiller())
- Filler = EmitConstantValueForMemory(Value.getArrayFiller(),
- CAT->getElementType(), CGF);
+ Filler = tryEmitAbstractForMemory(Value.getArrayFiller(),
+ CAT->getElementType());
// Emit initializer elements.
llvm::Type *CommonElementType =
- getTypes().ConvertType(CAT->getElementType());
+ CGM.getTypes().ConvertType(CAT->getElementType());
// Try to use a ConstantAggregateZero if we can.
if (Filler && Filler->isNullValue() && !NumInitElts) {
@@ -1444,15 +1902,21 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value,
return llvm::ConstantAggregateZero::get(AType);
}
- std::vector<llvm::Constant*> Elts;
+ SmallVector<llvm::Constant*, 16> Elts;
Elts.reserve(NumElements);
for (unsigned I = 0; I < NumElements; ++I) {
llvm::Constant *C = Filler;
- if (I < NumInitElts)
- C = EmitConstantValueForMemory(Value.getArrayInitializedElt(I),
- CAT->getElementType(), CGF);
- else
- assert(Filler && "Missing filler for implicit elements of initializer");
+ if (I < NumInitElts) {
+ C = tryEmitPrivateForMemory(Value.getArrayInitializedElt(I),
+ CAT->getElementType());
+ } else if (!Filler) {
+ assert(Value.hasArrayFiller() &&
+ "Missing filler for implicit elements of initializer");
+ C = tryEmitPrivateForMemory(Value.getArrayFiller(),
+ CAT->getElementType());
+ }
+ if (!C) return nullptr;
+
if (I == 0)
CommonElementType = C->getType();
else if (C->getType() != CommonElementType)
@@ -1466,7 +1930,8 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value,
Types.reserve(NumElements);
for (unsigned i = 0, e = Elts.size(); i < e; ++i)
Types.push_back(Elts[i]->getType());
- llvm::StructType *SType = llvm::StructType::get(VMContext, Types, true);
+ llvm::StructType *SType =
+ llvm::StructType::get(CGM.getLLVMContext(), Types, true);
return llvm::ConstantStruct::get(SType, Elts);
}
@@ -1475,23 +1940,11 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value,
return llvm::ConstantArray::get(AType, Elts);
}
case APValue::MemberPointer:
- return getCXXABI().EmitMemberPointer(Value, DestType);
+ return CGM.getCXXABI().EmitMemberPointer(Value, DestType);
}
llvm_unreachable("Unknown APValue kind");
}
-llvm::Constant *
-CodeGenModule::EmitConstantValueForMemory(const APValue &Value,
- QualType DestType,
- CodeGenFunction *CGF) {
- llvm::Constant *C = EmitConstantValue(Value, DestType, CGF);
- if (C->getType()->isIntegerTy(1)) {
- llvm::Type *BoolTy = getTypes().ConvertTypeForMem(DestType);
- C = llvm::ConstantExpr::getZExt(C, BoolTy);
- }
- return C;
-}
-
llvm::GlobalVariable *CodeGenModule::getAddrOfConstantCompoundLiteralIfEmitted(
const CompoundLiteralExpr *E) {
return EmittedCompoundLiterals.lookup(E);
@@ -1507,7 +1960,7 @@ void CodeGenModule::setAddrOfConstantCompoundLiteral(
ConstantAddress
CodeGenModule::GetAddrOfConstantCompoundLiteral(const CompoundLiteralExpr *E) {
assert(E->isFileScope() && "not a file-scope compound literal expr");
- return ConstExprEmitter(*this, nullptr).EmitLValue(E);
+ return tryEmitGlobalCompoundLiteral(*this, nullptr, E);
}
llvm::Constant *
@@ -1629,6 +2082,11 @@ static llvm::Constant *EmitNullConstantForBase(CodeGenModule &CGM,
return EmitNullConstant(CGM, base, /*asCompleteObject=*/false);
}
+llvm::Constant *ConstantEmitter::emitNullForMemory(CodeGenModule &CGM,
+ QualType T) {
+ return emitForMemory(CGM, CGM.EmitNullConstant(T), T);
+}
+
llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) {
if (T->getAs<PointerType>())
return getNullPointer(
@@ -1643,7 +2101,8 @@ llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) {
QualType ElementTy = CAT->getElementType();
- llvm::Constant *Element = EmitNullConstant(ElementTy);
+ llvm::Constant *Element =
+ ConstantEmitter::emitNullForMemory(*this, ElementTy);
unsigned NumElements = CAT->getSize().getZExtValue();
SmallVector<llvm::Constant *, 8> Array(NumElements, Element);
return llvm::ConstantArray::get(ATy, Array);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp
index 1170b014ec7f4..c46215067a68c 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp
@@ -428,14 +428,19 @@ public:
return CGF.getOpaqueRValueMapping(E).getScalarVal();
}
+ Value *emitConstant(const CodeGenFunction::ConstantEmission &Constant,
+ Expr *E) {
+ assert(Constant && "not a constant");
+ if (Constant.isReference())
+ return EmitLoadOfLValue(Constant.getReferenceLValue(CGF, E),
+ E->getExprLoc());
+ return Constant.getValue();
+ }
+
// l-values.
Value *VisitDeclRefExpr(DeclRefExpr *E) {
- if (CodeGenFunction::ConstantEmission result = CGF.tryEmitAsConstant(E)) {
- if (result.isReference())
- return EmitLoadOfLValue(result.getReferenceLValue(CGF, E),
- E->getExprLoc());
- return result.getValue();
- }
+ if (CodeGenFunction::ConstantEmission Constant = CGF.tryEmitAsConstant(E))
+ return emitConstant(Constant, E);
return EmitLoadOfLValue(E);
}
@@ -946,7 +951,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
if (SrcType->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType) {
// Cast to FP using the intrinsic if the half type itself isn't supported.
if (DstTy->isFloatingPointTy()) {
- if (!CGF.getContext().getLangOpts().HalfArgsAndReturns)
+ if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics())
return Builder.CreateCall(
CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_from_fp16, DstTy),
Src);
@@ -954,7 +959,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
// Cast to other types through float, using either the intrinsic or FPExt,
// depending on whether the half type itself is supported
// (as opposed to operations on half, available with NativeHalfType).
- if (!CGF.getContext().getLangOpts().HalfArgsAndReturns) {
+ if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
Src = Builder.CreateCall(
CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_from_fp16,
CGF.CGM.FloatTy),
@@ -1009,10 +1014,42 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
return Builder.CreateVectorSplat(NumElements, Src, "splat");
}
- // Allow bitcast from vector to integer/fp of the same size.
- if (isa<llvm::VectorType>(SrcTy) ||
- isa<llvm::VectorType>(DstTy))
- return Builder.CreateBitCast(Src, DstTy, "conv");
+ if (isa<llvm::VectorType>(SrcTy) || isa<llvm::VectorType>(DstTy)) {
+ // Allow bitcast from vector to integer/fp of the same size.
+ unsigned SrcSize = SrcTy->getPrimitiveSizeInBits();
+ unsigned DstSize = DstTy->getPrimitiveSizeInBits();
+ if (SrcSize == DstSize)
+ return Builder.CreateBitCast(Src, DstTy, "conv");
+
+ // Conversions between vectors of different sizes are not allowed except
+ // when vectors of half are involved. Operations on storage-only half
+ // vectors require promoting half vector operands to float vectors and
+ // truncating the result, which is either an int or float vector, to a
+ // short or half vector.
+
+ // Source and destination are both expected to be vectors.
+ llvm::Type *SrcElementTy = SrcTy->getVectorElementType();
+ llvm::Type *DstElementTy = DstTy->getVectorElementType();
+ (void)DstElementTy;
+
+ assert(((SrcElementTy->isIntegerTy() &&
+ DstElementTy->isIntegerTy()) ||
+ (SrcElementTy->isFloatingPointTy() &&
+ DstElementTy->isFloatingPointTy())) &&
+ "unexpected conversion between a floating-point vector and an "
+ "integer vector");
+
+ // Truncate an i32 vector to an i16 vector.
+ if (SrcElementTy->isIntegerTy())
+ return Builder.CreateIntCast(Src, DstTy, false, "conv");
+
+ // Truncate a float vector to a half vector.
+ if (SrcSize > DstSize)
+ return Builder.CreateFPTrunc(Src, DstTy, "conv");
+
+ // Promote a half vector to a float vector.
+ return Builder.CreateFPExt(Src, DstTy, "conv");
+ }
// Finally, we have the arithmetic types: real int/float.
Value *Res = nullptr;
@@ -1031,7 +1068,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
if (SrcTy->isFloatingPointTy()) {
// Use the intrinsic if the half type itself isn't supported
// (as opposed to operations on half, available with NativeHalfType).
- if (!CGF.getContext().getLangOpts().HalfArgsAndReturns)
+ if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics())
return Builder.CreateCall(
CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_to_fp16, SrcTy), Src);
// If the half type is supported, just use an fptrunc.
@@ -1067,7 +1104,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
}
if (DstTy != ResTy) {
- if (!CGF.getContext().getLangOpts().HalfArgsAndReturns) {
+ if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
assert(ResTy->isIntegerTy(16) && "Only half FP requires extra conversion");
Res = Builder.CreateCall(
CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_to_fp16, CGF.CGM.FloatTy),
@@ -1299,13 +1336,15 @@ Value *ScalarExprEmitter::VisitConvertVectorExpr(ConvertVectorExpr *E) {
}
Value *ScalarExprEmitter::VisitMemberExpr(MemberExpr *E) {
- llvm::APSInt Value;
- if (E->EvaluateAsInt(Value, CGF.getContext(), Expr::SE_AllowSideEffects)) {
- if (E->isArrow())
- CGF.EmitScalarExpr(E->getBase());
- else
- EmitLValue(E->getBase());
- return Builder.getInt(Value);
+ if (CodeGenFunction::ConstantEmission Constant = CGF.tryEmitAsConstant(E)) {
+ CGF.EmitIgnoredExpr(E->getBase());
+ return emitConstant(Constant, E);
+ } else {
+ llvm::APSInt Value;
+ if (E->EvaluateAsInt(Value, CGF.getContext(), Expr::SE_AllowSideEffects)) {
+ CGF.EmitIgnoredExpr(E->getBase());
+ return Builder.getInt(Value);
+ }
}
return EmitLoadOfLValue(E);
@@ -1778,7 +1817,7 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
}
case CK_IntToOCLSampler:
- return CGF.CGM.createOpenCLIntToSamplerConversion(E, CGF);
+ return CGF.CGM.createOpenCLIntToSamplerConversion(E, CGF);
} // end of switch
@@ -1989,7 +2028,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
if (type->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType) {
// Another special case: half FP increment should be done via float
- if (!CGF.getContext().getLangOpts().HalfArgsAndReturns) {
+ if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
value = Builder.CreateCall(
CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_from_fp16,
CGF.CGM.FloatTy),
@@ -2024,7 +2063,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
value = Builder.CreateFAdd(value, amt, isInc ? "inc" : "dec");
if (type->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType) {
- if (!CGF.getContext().getLangOpts().HalfArgsAndReturns) {
+ if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
value = Builder.CreateCall(
CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_to_fp16,
CGF.CGM.FloatTy),
@@ -2671,6 +2710,30 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF,
unsigned width = cast<llvm::IntegerType>(index->getType())->getBitWidth();
auto &DL = CGF.CGM.getDataLayout();
auto PtrTy = cast<llvm::PointerType>(pointer->getType());
+
+ // Some versions of glibc and gcc use idioms (particularly in their malloc
+ // routines) that add a pointer-sized integer (known to be a pointer value)
+ // to a null pointer in order to cast the value back to an integer or as
+ // part of a pointer alignment algorithm. This is undefined behavior, but
+ // we'd like to be able to compile programs that use it.
+ //
+ // Normally, we'd generate a GEP with a null-pointer base here in response
+ // to that code, but it's also UB to dereference a pointer created that
+ // way. Instead (as an acknowledged hack to tolerate the idiom) we will
+ // generate a direct cast of the integer value to a pointer.
+ //
+ // The idiom (p = nullptr + N) is not met if any of the following are true:
+ //
+ // The operation is subtraction.
+ // The index is not pointer-sized.
+ // The pointer type is not byte-sized.
+ //
+ if (BinaryOperator::isNullPointerArithmeticExtension(CGF.getContext(),
+ op.Opcode,
+ expr->getLHS(),
+ expr->getRHS()))
+ return CGF.Builder.CreateIntToPtr(index, pointer->getType());
+
if (width != DL.getTypeSizeInBits(PtrTy)) {
// Zero-extend or sign-extend the pointer value according to
// whether the index is signed or not.
@@ -3057,16 +3120,25 @@ static llvm::Intrinsic::ID GetIntrinsic(IntrinsicType IT,
return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_altivec_vcmpequh_p :
llvm::Intrinsic::ppc_altivec_vcmpgtsh_p;
case BuiltinType::UInt:
- case BuiltinType::ULong:
return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_altivec_vcmpequw_p :
llvm::Intrinsic::ppc_altivec_vcmpgtuw_p;
case BuiltinType::Int:
- case BuiltinType::Long:
return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_altivec_vcmpequw_p :
llvm::Intrinsic::ppc_altivec_vcmpgtsw_p;
+ case BuiltinType::ULong:
+ case BuiltinType::ULongLong:
+ return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_altivec_vcmpequd_p :
+ llvm::Intrinsic::ppc_altivec_vcmpgtud_p;
+ case BuiltinType::Long:
+ case BuiltinType::LongLong:
+ return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_altivec_vcmpequd_p :
+ llvm::Intrinsic::ppc_altivec_vcmpgtsd_p;
case BuiltinType::Float:
return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_altivec_vcmpeqfp_p :
llvm::Intrinsic::ppc_altivec_vcmpgtfp_p;
+ case BuiltinType::Double:
+ return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_vsx_xvcmpeqdp_p :
+ llvm::Intrinsic::ppc_vsx_xvcmpgtdp_p;
}
}
@@ -3151,6 +3223,16 @@ Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,
Value *CR6Param = Builder.getInt32(CR6);
llvm::Function *F = CGF.CGM.getIntrinsic(ID);
Result = Builder.CreateCall(F, {CR6Param, FirstVecArg, SecondVecArg});
+
+ // The result type of intrinsic may not be same as E->getType().
+ // If E->getType() is not BoolTy, EmitScalarConversion will do the
+ // conversion work. If E->getType() is BoolTy, EmitScalarConversion will
+ // do nothing, if ResultTy is not i1 at the same time, it will cause
+ // crash later.
+ llvm::IntegerType *ResultTy = cast<llvm::IntegerType>(Result->getType());
+ if (ResultTy->getBitWidth() > 1 &&
+ E->getType() == CGF.getContext().BoolTy)
+ Result = Builder.CreateTrunc(Result, Builder.getInt1Ty());
return EmitScalarConversion(Result, CGF.getContext().BoolTy, E->getType(),
E->getExprLoc());
}
@@ -3840,6 +3922,7 @@ LValue CodeGenFunction::EmitCompoundAssignmentLValue(
case BO_GE:
case BO_EQ:
case BO_NE:
+ case BO_Cmp:
case BO_And:
case BO_Xor:
case BO_Or:
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp
index 90fcad2614154..f26263d9472d3 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp
@@ -162,7 +162,7 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
const Expr *Rhs = ALE->getElement(i);
LValue LV = MakeAddrLValue(
Builder.CreateConstArrayGEP(Objects, i, getPointerSize()),
- ElementType, LValueBaseInfo(AlignmentSource::Decl, false));
+ ElementType, AlignmentSource::Decl);
llvm::Value *value = EmitScalarExpr(Rhs);
EmitStoreThroughLValue(RValue::get(value), LV, true);
@@ -174,7 +174,7 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
const Expr *Key = DLE->getKeyValueElement(i).Key;
LValue KeyLV = MakeAddrLValue(
Builder.CreateConstArrayGEP(Keys, i, getPointerSize()),
- ElementType, LValueBaseInfo(AlignmentSource::Decl, false));
+ ElementType, AlignmentSource::Decl);
llvm::Value *keyValue = EmitScalarExpr(Key);
EmitStoreThroughLValue(RValue::get(keyValue), KeyLV, /*isInit=*/true);
@@ -182,7 +182,7 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
const Expr *Value = DLE->getKeyValueElement(i).Value;
LValue ValueLV = MakeAddrLValue(
Builder.CreateConstArrayGEP(Objects, i, getPointerSize()),
- ElementType, LValueBaseInfo(AlignmentSource::Decl, false));
+ ElementType, AlignmentSource::Decl);
llvm::Value *valueValue = EmitScalarExpr(Value);
EmitStoreThroughLValue(RValue::get(valueValue), ValueLV, /*isInit=*/true);
if (TrackNeededObjects) {
@@ -1546,16 +1546,15 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
getContext().getPointerType(ItemsTy));
// The third argument is the capacity of that temporary array.
- llvm::Type *UnsignedLongLTy = ConvertType(getContext().UnsignedLongTy);
- llvm::Constant *Count = llvm::ConstantInt::get(UnsignedLongLTy, NumItems);
- Args.add(RValue::get(Count), getContext().UnsignedLongTy);
+ llvm::Type *NSUIntegerTy = ConvertType(getContext().getNSUIntegerType());
+ llvm::Constant *Count = llvm::ConstantInt::get(NSUIntegerTy, NumItems);
+ Args.add(RValue::get(Count), getContext().getNSUIntegerType());
// Start the enumeration.
RValue CountRV =
- CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(),
- getContext().UnsignedLongTy,
- FastEnumSel,
- Collection, Args);
+ CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(),
+ getContext().getNSUIntegerType(),
+ FastEnumSel, Collection, Args);
// The initial number of objects that were returned in the buffer.
llvm::Value *initialBufferLimit = CountRV.getScalarVal();
@@ -1563,7 +1562,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
llvm::BasicBlock *EmptyBB = createBasicBlock("forcoll.empty");
llvm::BasicBlock *LoopInitBB = createBasicBlock("forcoll.loopinit");
- llvm::Value *zero = llvm::Constant::getNullValue(UnsignedLongLTy);
+ llvm::Value *zero = llvm::Constant::getNullValue(NSUIntegerTy);
// If the limit pointer was zero to begin with, the collection is
// empty; skip all this. Set the branch weight assuming this has the same
@@ -1595,11 +1594,11 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
EmitBlock(LoopBodyBB);
// The current index into the buffer.
- llvm::PHINode *index = Builder.CreatePHI(UnsignedLongLTy, 3, "forcoll.index");
+ llvm::PHINode *index = Builder.CreatePHI(NSUIntegerTy, 3, "forcoll.index");
index->addIncoming(zero, LoopInitBB);
// The current buffer size.
- llvm::PHINode *count = Builder.CreatePHI(UnsignedLongLTy, 3, "forcoll.count");
+ llvm::PHINode *count = Builder.CreatePHI(NSUIntegerTy, 3, "forcoll.count");
count->addIncoming(initialBufferLimit, LoopInitBB);
incrementProfileCounter(&S);
@@ -1709,8 +1708,8 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
llvm::BasicBlock *FetchMoreBB = createBasicBlock("forcoll.refetch");
// First we check in the local buffer.
- llvm::Value *indexPlusOne
- = Builder.CreateAdd(index, llvm::ConstantInt::get(UnsignedLongLTy, 1));
+ llvm::Value *indexPlusOne =
+ Builder.CreateAdd(index, llvm::ConstantInt::get(NSUIntegerTy, 1));
// If we haven't overrun the buffer yet, we can continue.
// Set the branch weights based on the simplifying assumption that this is
@@ -1727,10 +1726,9 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
EmitBlock(FetchMoreBB);
CountRV =
- CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(),
- getContext().UnsignedLongTy,
- FastEnumSel,
- Collection, Args);
+ CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(),
+ getContext().getNSUIntegerType(),
+ FastEnumSel, Collection, Args);
// If we got a zero count, we're done.
llvm::Value *refetchCount = CountRV.getScalarVal();
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp
index 98435fefbd2ea..ef4e6cd4f01b3 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp
@@ -4885,10 +4885,7 @@ void CGObjCCommonMac::EmitImageInfo() {
}
// Indicate whether we're compiling this to run on a simulator.
- const llvm::Triple &Triple = CGM.getTarget().getTriple();
- if ((Triple.isiOS() || Triple.isWatchOS()) &&
- (Triple.getArch() == llvm::Triple::x86 ||
- Triple.getArch() == llvm::Triple::x86_64))
+ if (CGM.getTarget().getTriple().isSimulatorEnvironment())
Mod.addModuleFlag(llvm::Module::Error, "Objective-C Is Simulated",
eImageInfo_ImageIsSimulated);
@@ -5084,6 +5081,11 @@ void IvarLayoutBuilder::visitField(const FieldDecl *field,
// Drill down into arrays.
uint64_t numElts = 1;
+ if (auto arrayType = CGM.getContext().getAsIncompleteArrayType(fieldType)) {
+ numElts = 0;
+ fieldType = arrayType->getElementType();
+ }
+ // Unlike incomplete arrays, constant arrays can be nested.
while (auto arrayType = CGM.getContext().getAsConstantArrayType(fieldType)) {
numElts *= arrayType->getSize().getZExtValue();
fieldType = arrayType->getElementType();
@@ -6615,10 +6617,14 @@ CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
Ivar->getAccessControl() == ObjCIvarDecl::Private ||
Ivar->getAccessControl() == ObjCIvarDecl::Package;
- if (ID->hasAttr<DLLExportAttr>() && !IsPrivateOrPackage)
- IvarOffsetGV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
- else if (ID->hasAttr<DLLImportAttr>())
- IvarOffsetGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
+ const ObjCInterfaceDecl *ContainingID = Ivar->getContainingInterface();
+
+ if (ContainingID->hasAttr<DLLImportAttr>())
+ IvarOffsetGV
+ ->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
+ else if (ContainingID->hasAttr<DLLExportAttr>() && !IsPrivateOrPackage)
+ IvarOffsetGV
+ ->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
}
}
return IvarOffsetGV;
@@ -7549,8 +7555,9 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2);
ConstantInitBuilder builder(CGM);
auto values = builder.beginStruct(ObjCTypes.EHTypeTy);
- values.add(llvm::ConstantExpr::getGetElementPtr(VTableGV->getValueType(),
- VTableGV, VTableIdx));
+ values.add(
+ llvm::ConstantExpr::getInBoundsGetElementPtr(VTableGV->getValueType(),
+ VTableGV, VTableIdx));
values.add(GetClassName(ClassName));
values.add(GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition));
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.cpp
index 4cfddcb107cb3..2f886fd82caa7 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.cpp
@@ -110,7 +110,8 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
llvm::Type::getIntNTy(CGF.getLLVMContext(),
Info->StorageSize));
return LValue::MakeBitfield(Addr, *Info, IvarTy,
- LValueBaseInfo(AlignmentSource::Decl, false));
+ LValueBaseInfo(AlignmentSource::Decl),
+ TBAAAccessInfo());
}
namespace {
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.cpp
index db02c631c9e64..d140e7f09e9a6 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.cpp
@@ -16,6 +16,7 @@
#include "CGOpenCLRuntime.h"
#include "CodeGenFunction.h"
#include "TargetInfo.h"
+#include "clang/CodeGen/ConstantInitBuilder.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/GlobalValue.h"
#include <assert.h>
@@ -35,8 +36,8 @@ llvm::Type *CGOpenCLRuntime::convertOpenCLSpecificType(const Type *T) {
"Not an OpenCL specific type!");
llvm::LLVMContext& Ctx = CGM.getLLVMContext();
- uint32_t ImgAddrSpc = CGM.getContext().getTargetAddressSpace(
- CGM.getTarget().getOpenCLImageAddrSpace());
+ uint32_t AddrSpc = CGM.getContext().getTargetAddressSpace(
+ CGM.getContext().getOpenCLTypeAddrSpace(T));
switch (cast<BuiltinType>(T)->getKind()) {
default:
llvm_unreachable("Unexpected opencl builtin type!");
@@ -45,29 +46,29 @@ llvm::Type *CGOpenCLRuntime::convertOpenCLSpecificType(const Type *T) {
case BuiltinType::Id: \
return llvm::PointerType::get( \
llvm::StructType::create(Ctx, "opencl." #ImgType "_" #Suffix "_t"), \
- ImgAddrSpc);
+ AddrSpc);
#include "clang/Basic/OpenCLImageTypes.def"
case BuiltinType::OCLSampler:
- return getSamplerType();
+ return getSamplerType(T);
case BuiltinType::OCLEvent:
- return llvm::PointerType::get(llvm::StructType::create(
- Ctx, "opencl.event_t"), 0);
+ return llvm::PointerType::get(
+ llvm::StructType::create(Ctx, "opencl.event_t"), AddrSpc);
case BuiltinType::OCLClkEvent:
return llvm::PointerType::get(
- llvm::StructType::create(Ctx, "opencl.clk_event_t"), 0);
+ llvm::StructType::create(Ctx, "opencl.clk_event_t"), AddrSpc);
case BuiltinType::OCLQueue:
return llvm::PointerType::get(
- llvm::StructType::create(Ctx, "opencl.queue_t"), 0);
+ llvm::StructType::create(Ctx, "opencl.queue_t"), AddrSpc);
case BuiltinType::OCLReserveID:
return llvm::PointerType::get(
- llvm::StructType::create(Ctx, "opencl.reserve_id_t"), 0);
+ llvm::StructType::create(Ctx, "opencl.reserve_id_t"), AddrSpc);
}
}
-llvm::Type *CGOpenCLRuntime::getPipeType() {
+llvm::Type *CGOpenCLRuntime::getPipeType(const PipeType *T) {
if (!PipeTy){
- uint32_t PipeAddrSpc =
- CGM.getContext().getTargetAddressSpace(LangAS::opencl_global);
+ uint32_t PipeAddrSpc = CGM.getContext().getTargetAddressSpace(
+ CGM.getContext().getOpenCLTypeAddrSpace(T));
PipeTy = llvm::PointerType::get(llvm::StructType::create(
CGM.getLLVMContext(), "opencl.pipe_t"), PipeAddrSpc);
}
@@ -75,12 +76,12 @@ llvm::Type *CGOpenCLRuntime::getPipeType() {
return PipeTy;
}
-llvm::PointerType *CGOpenCLRuntime::getSamplerType() {
+llvm::PointerType *CGOpenCLRuntime::getSamplerType(const Type *T) {
if (!SamplerTy)
SamplerTy = llvm::PointerType::get(llvm::StructType::create(
CGM.getLLVMContext(), "opencl.sampler_t"),
CGM.getContext().getTargetAddressSpace(
- LangAS::opencl_constant));
+ CGM.getContext().getOpenCLTypeAddrSpace(T)));
return SamplerTy;
}
@@ -103,3 +104,45 @@ llvm::Value *CGOpenCLRuntime::getPipeElemAlign(const Expr *PipeArg) {
.getQuantity();
return llvm::ConstantInt::get(Int32Ty, TypeSize, false);
}
+
+llvm::PointerType *CGOpenCLRuntime::getGenericVoidPointerType() {
+ assert(CGM.getLangOpts().OpenCL);
+ return llvm::IntegerType::getInt8PtrTy(
+ CGM.getLLVMContext(),
+ CGM.getContext().getTargetAddressSpace(LangAS::opencl_generic));
+}
+
+CGOpenCLRuntime::EnqueuedBlockInfo
+CGOpenCLRuntime::emitOpenCLEnqueuedBlock(CodeGenFunction &CGF, const Expr *E) {
+ // The block literal may be assigned to a const variable. Chasing down
+ // to get the block literal.
+ if (auto DR = dyn_cast<DeclRefExpr>(E)) {
+ E = cast<VarDecl>(DR->getDecl())->getInit();
+ }
+ if (auto Cast = dyn_cast<CastExpr>(E)) {
+ E = Cast->getSubExpr();
+ }
+ auto *Block = cast<BlockExpr>(E);
+
+ // The same block literal may be enqueued multiple times. Cache it if
+ // possible.
+ auto Loc = EnqueuedBlockMap.find(Block);
+ if (Loc != EnqueuedBlockMap.end()) {
+ return Loc->second;
+ }
+
+ // Emit block literal as a common block expression and get the block invoke
+ // function.
+ llvm::Function *Invoke;
+ auto *V = CGF.EmitBlockLiteral(cast<BlockExpr>(Block), &Invoke);
+ auto *F = CGF.getTargetHooks().createEnqueuedBlockKernel(
+ CGF, Invoke, V->stripPointerCasts());
+
+ // The common part of the post-processing of the kernel goes here.
+ F->addFnAttr(llvm::Attribute::NoUnwind);
+ F->setCallingConv(
+ CGF.getTypes().ClangCallConvToLLVMCallConv(CallingConv::CC_OpenCLKernel));
+ EnqueuedBlockInfo Info{F, V};
+ EnqueuedBlockMap[Block] = Info;
+ return Info;
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.h b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.h
index ee3cb3dda0631..ead303d1d0d5e 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.h
@@ -17,11 +17,13 @@
#define LLVM_CLANG_LIB_CODEGEN_CGOPENCLRUNTIME_H
#include "clang/AST/Type.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
namespace clang {
+class Expr;
class VarDecl;
namespace CodeGen {
@@ -35,6 +37,14 @@ protected:
llvm::Type *PipeTy;
llvm::PointerType *SamplerTy;
+ /// Structure for enqueued block information.
+ struct EnqueuedBlockInfo {
+ llvm::Function *Kernel; /// Enqueued block kernel.
+ llvm::Value *BlockArg; /// The first argument to enqueued block kernel.
+ };
+ /// Maps block expression to block information.
+ llvm::DenseMap<const Expr *, EnqueuedBlockInfo> EnqueuedBlockMap;
+
public:
CGOpenCLRuntime(CodeGenModule &CGM) : CGM(CGM), PipeTy(nullptr),
SamplerTy(nullptr) {}
@@ -48,9 +58,9 @@ public:
virtual llvm::Type *convertOpenCLSpecificType(const Type *T);
- virtual llvm::Type *getPipeType();
+ virtual llvm::Type *getPipeType(const PipeType *T);
- llvm::PointerType *getSamplerType();
+ llvm::PointerType *getSamplerType(const Type *T);
// \brief Returnes a value which indicates the size in bytes of the pipe
// element.
@@ -59,6 +69,13 @@ public:
// \brief Returnes a value which indicates the alignment in bytes of the pipe
// element.
virtual llvm::Value *getPipeElemAlign(const Expr *PipeArg);
+
+ /// \return __generic void* type.
+ llvm::PointerType *getGenericVoidPointerType();
+
+ /// \return enqueued block information for enqueued block.
+ EnqueuedBlockInfo emitOpenCLEnqueuedBlock(CodeGenFunction &CGF,
+ const Expr *E);
};
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 9f8aa6c8d964c..5db29eb6004d7 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -19,6 +19,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/StmtOpenMP.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitmaskEnum.h"
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/DerivedTypes.h"
@@ -427,7 +428,7 @@ public:
/// \brief Values for bit flags used in the ident_t to describe the fields.
/// All enumeric elements are named and described in accordance with the code
/// from http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h
-enum OpenMPLocationFlags {
+enum OpenMPLocationFlags : unsigned {
/// \brief Use trampoline for internal microtask.
OMP_IDENT_IMD = 0x01,
/// \brief Use c-style ident structure.
@@ -443,7 +444,14 @@ enum OpenMPLocationFlags {
/// \brief Implicit barrier in 'sections' directive.
OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
/// \brief Implicit barrier in 'single' directive.
- OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140
+ OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140,
+ /// Call of __kmp_for_static_init for static loop.
+ OMP_IDENT_WORK_LOOP = 0x200,
+ /// Call of __kmp_for_static_init for sections.
+ OMP_IDENT_WORK_SECTIONS = 0x400,
+ /// Call of __kmp_for_static_init for distribute.
+ OMP_IDENT_WORK_DISTRIBUTE = 0x800,
+ LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE)
};
/// \brief Describes ident structure that describes a source location.
@@ -660,27 +668,47 @@ enum OpenMPRTLFunction {
//
// Offloading related calls
//
- // Call to int32_t __tgt_target(int32_t device_id, void *host_ptr, int32_t
- // arg_num, void** args_base, void **args, size_t *arg_sizes, int32_t
+ // Call to int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t
+ // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t
// *arg_types);
OMPRTL__tgt_target,
- // Call to int32_t __tgt_target_teams(int32_t device_id, void *host_ptr,
- // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes,
- // int32_t *arg_types, int32_t num_teams, int32_t thread_limit);
+ // Call to int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr,
+ // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t
+ // *arg_types);
+ OMPRTL__tgt_target_nowait,
+ // Call to int32_t __tgt_target_teams(int64_t device_id, void *host_ptr,
+ // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t
+ // *arg_types, int32_t num_teams, int32_t thread_limit);
OMPRTL__tgt_target_teams,
+ // Call to int32_t __tgt_target_teams_nowait(int64_t device_id, void
+ // *host_ptr, int32_t arg_num, void** args_base, void **args, size_t
+ // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit);
+ OMPRTL__tgt_target_teams_nowait,
// Call to void __tgt_register_lib(__tgt_bin_desc *desc);
OMPRTL__tgt_register_lib,
// Call to void __tgt_unregister_lib(__tgt_bin_desc *desc);
OMPRTL__tgt_unregister_lib,
- // Call to void __tgt_target_data_begin(int32_t device_id, int32_t arg_num,
- // void** args_base, void **args, size_t *arg_sizes, int32_t *arg_types);
+ // Call to void __tgt_target_data_begin(int64_t device_id, int32_t arg_num,
+ // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types);
OMPRTL__tgt_target_data_begin,
- // Call to void __tgt_target_data_end(int32_t device_id, int32_t arg_num,
- // void** args_base, void **args, size_t *arg_sizes, int32_t *arg_types);
+ // Call to void __tgt_target_data_begin_nowait(int64_t device_id, int32_t
+ // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t
+ // *arg_types);
+ OMPRTL__tgt_target_data_begin_nowait,
+ // Call to void __tgt_target_data_end(int64_t device_id, int32_t arg_num,
+ // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types);
OMPRTL__tgt_target_data_end,
- // Call to void __tgt_target_data_update(int32_t device_id, int32_t arg_num,
- // void** args_base, void **args, size_t *arg_sizes, int32_t *arg_types);
+ // Call to void __tgt_target_data_end_nowait(int64_t device_id, int32_t
+ // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t
+ // *arg_types);
+ OMPRTL__tgt_target_data_end_nowait,
+ // Call to void __tgt_target_data_update(int64_t device_id, int32_t arg_num,
+ // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types);
OMPRTL__tgt_target_data_update,
+ // Call to void __tgt_target_data_update_nowait(int64_t device_id, int32_t
+ // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t
+ // *arg_types);
+ OMPRTL__tgt_target_data_update_nowait,
};
/// A basic class for pre|post-action for advanced codegen sequence for OpenMP
@@ -862,18 +890,7 @@ static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr,
}
LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) {
- if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E))
- return CGF.EmitOMPArraySectionExpr(OASE);
- if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
- return CGF.EmitLValue(ASE);
- auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
- DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD),
- CGF.CapturedStmtInfo &&
- CGF.CapturedStmtInfo->lookup(OrigVD) != nullptr,
- E->getType(), VK_LValue, E->getExprLoc());
- // Store the address of the original variable associated with the LHS
- // implicit variable.
- return CGF.EmitLValue(&DRE);
+ return CGF.EmitOMPSharedLValue(E);
}
LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF,
@@ -919,8 +936,9 @@ ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds,
void ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, unsigned N) {
assert(SharedAddresses.size() == N &&
"Number of generated lvalues must be exactly N.");
- SharedAddresses.emplace_back(emitSharedLValue(CGF, ClausesData[N].Ref),
- emitSharedLValueUB(CGF, ClausesData[N].Ref));
+ LValue First = emitSharedLValue(CGF, ClausesData[N].Ref);
+ LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref);
+ SharedAddresses.emplace_back(First, Second);
}
void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) {
@@ -928,7 +946,7 @@ void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) {
cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
QualType PrivateType = PrivateVD->getType();
bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref);
- if (!AsArraySection && !PrivateType->isVariablyModifiedType()) {
+ if (!PrivateType->isVariablyModifiedType()) {
Sizes.emplace_back(
CGF.getTypeSize(
SharedAddresses[N].first.getType().getNonReferenceType()),
@@ -966,10 +984,9 @@ void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N,
auto *PrivateVD =
cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
QualType PrivateType = PrivateVD->getType();
- bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref);
- if (!AsArraySection && !PrivateType->isVariablyModifiedType()) {
+ if (!PrivateType->isVariablyModifiedType()) {
assert(!Size && !Sizes[N].second &&
- "Size should be nullptr for non-variably modified redution "
+ "Size should be nullptr for non-variably modified reduction "
"items.");
return;
}
@@ -995,9 +1012,9 @@ void ReductionCodeGen::emitInitialization(
SharedLVal = CGF.MakeAddrLValue(
CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(),
CGF.ConvertTypeForMem(SharedType)),
- SharedType, SharedAddresses[N].first.getBaseInfo());
- if (isa<OMPArraySectionExpr>(ClausesData[N].Ref) ||
- CGF.getContext().getAsArrayType(PrivateVD->getType())) {
+ SharedType, SharedAddresses[N].first.getBaseInfo(),
+ CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType));
+ if (CGF.getContext().getAsArrayType(PrivateVD->getType())) {
emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD);
} else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) {
emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp,
@@ -1040,15 +1057,16 @@ static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,
if (auto *PtrTy = BaseTy->getAs<PointerType>())
BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(), PtrTy);
else {
- BaseLV = CGF.EmitLoadOfReferenceLValue(BaseLV.getAddress(),
- BaseTy->castAs<ReferenceType>());
+ LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(), BaseTy);
+ BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal);
}
BaseTy = BaseTy->getPointeeType();
}
return CGF.MakeAddrLValue(
CGF.Builder.CreateElementBitCast(BaseLV.getAddress(),
CGF.ConvertTypeForMem(ElTy)),
- BaseLV.getType(), BaseLV.getBaseInfo());
+ BaseLV.getType(), BaseLV.getBaseInfo(),
+ CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType()));
}
static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,
@@ -1106,11 +1124,14 @@ Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N,
OriginalBaseLValue);
llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff(
BaseLValue.getPointer(), SharedAddresses[N].first.getPointer());
- llvm::Value *Ptr =
- CGF.Builder.CreateGEP(PrivateAddr.getPointer(), Adjustment);
+ llvm::Value *PrivatePointer =
+ CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ PrivateAddr.getPointer(),
+ SharedAddresses[N].first.getAddress().getType());
+ llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment);
return castToBase(CGF, OrigVD->getType(),
SharedAddresses[N].first.getType(),
- OriginalBaseLValue.getPointer()->getType(),
+ OriginalBaseLValue.getAddress().getType(),
OriginalBaseLValue.getAlignment(), Ptr);
}
BaseDecls.emplace_back(
@@ -1146,7 +1167,7 @@ LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
CodeGenFunction &CGF) {
return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()),
getThreadIDVariable()->getType(),
- LValueBaseInfo(AlignmentSource::Decl, false));
+ AlignmentSource::Decl);
}
CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)
@@ -1204,7 +1225,14 @@ emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty,
.getAddress();
});
(void)Scope.Privatize();
- CGF.EmitIgnoredExpr(CombinerInitializer);
+ if (!IsCombiner && Out->hasInit() &&
+ !CGF.isTrivialInitializer(Out->getInit())) {
+ CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out),
+ Out->getType().getQualifiers(),
+ /*IsInitializer=*/true);
+ }
+ if (CombinerInitializer)
+ CGF.EmitIgnoredExpr(CombinerInitializer);
Scope.ForceCleanup();
CGF.FinishFunction();
return Fn;
@@ -1230,7 +1258,10 @@ void CGOpenMPRuntime::emitUserDefinedReduction(
Orig = &C.Idents.get("omp_orig");
}
Initializer = emitCombinerOrInitializer(
- CGM, D->getType(), Init, cast<VarDecl>(D->lookup(Orig).front()),
+ CGM, D->getType(),
+ D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init
+ : nullptr,
+ cast<VarDecl>(D->lookup(Orig).front()),
cast<VarDecl>(D->lookup(Priv).front()),
/*IsCombiner=*/false);
}
@@ -1283,6 +1314,15 @@ static llvm::Value *emitParallelOrTeamsOutlinedFunction(
HasCancel = OPSD->hasCancel();
else if (auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
HasCancel = OPFD->hasCancel();
+ else if (auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D))
+ HasCancel = OPFD->hasCancel();
+ else if (auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D))
+ HasCancel = OPFD->hasCancel();
+ else if (auto *OPFD = dyn_cast<OMPTeamsDistributeParallelForDirective>(&D))
+ HasCancel = OPFD->hasCancel();
+ else if (auto *OPFD =
+ dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D))
+ HasCancel = OPFD->hasCancel();
CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind,
HasCancel, OutlinedHelperName);
CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
@@ -1442,19 +1482,24 @@ llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
if (ThreadID != nullptr)
return ThreadID;
}
- if (auto *OMPRegionInfo =
- dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
- if (OMPRegionInfo->getThreadIDVariable()) {
- // Check if this an outlined function with thread id passed as argument.
- auto LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
- ThreadID = CGF.EmitLoadOfLValue(LVal, Loc).getScalarVal();
- // If value loaded in entry block, cache it and use it everywhere in
- // function.
- if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) {
- auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
- Elem.second.ThreadID = ThreadID;
+ // If exceptions are enabled, do not use parameter to avoid possible crash.
+ if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions ||
+ !CGF.getLangOpts().CXXExceptions ||
+ CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) {
+ if (auto *OMPRegionInfo =
+ dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
+ if (OMPRegionInfo->getThreadIDVariable()) {
+ // Check if this an outlined function with thread id passed as argument.
+ auto LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
+ ThreadID = CGF.EmitLoadOfLValue(LVal, Loc).getScalarVal();
+ // If value loaded in entry block, cache it and use it everywhere in
+ // function.
+ if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) {
+ auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
+ Elem.second.ThreadID = ThreadID;
+ }
+ return ThreadID;
}
- return ThreadID;
}
}
@@ -1464,12 +1509,13 @@ llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
// function.
CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
- ThreadID =
- CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
- emitUpdateLocation(CGF, Loc));
+ auto *Call = CGF.Builder.CreateCall(
+ createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
+ emitUpdateLocation(CGF, Loc));
+ Call->setCallingConv(CGF.getRuntimeCC());
auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
- Elem.second.ThreadID = ThreadID;
- return ThreadID;
+ Elem.second.ThreadID = Call;
+ return Call;
}
void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
@@ -2001,32 +2047,48 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
break;
}
case OMPRTL__tgt_target: {
- // Build int32_t __tgt_target(int32_t device_id, void *host_ptr, int32_t
- // arg_num, void** args_base, void **args, size_t *arg_sizes, int32_t
+ // Build int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t
+ // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t
// *arg_types);
- llvm::Type *TypeParams[] = {CGM.Int32Ty,
+ llvm::Type *TypeParams[] = {CGM.Int64Ty,
CGM.VoidPtrTy,
CGM.Int32Ty,
CGM.VoidPtrPtrTy,
CGM.VoidPtrPtrTy,
CGM.SizeTy->getPointerTo(),
- CGM.Int32Ty->getPointerTo()};
+ CGM.Int64Ty->getPointerTo()};
llvm::FunctionType *FnTy =
llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target");
break;
}
+ case OMPRTL__tgt_target_nowait: {
+ // Build int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr,
+ // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes,
+ // int64_t *arg_types);
+ llvm::Type *TypeParams[] = {CGM.Int64Ty,
+ CGM.VoidPtrTy,
+ CGM.Int32Ty,
+ CGM.VoidPtrPtrTy,
+ CGM.VoidPtrPtrTy,
+ CGM.SizeTy->getPointerTo(),
+ CGM.Int64Ty->getPointerTo()};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_nowait");
+ break;
+ }
case OMPRTL__tgt_target_teams: {
- // Build int32_t __tgt_target_teams(int32_t device_id, void *host_ptr,
+ // Build int32_t __tgt_target_teams(int64_t device_id, void *host_ptr,
// int32_t arg_num, void** args_base, void **args, size_t *arg_sizes,
- // int32_t *arg_types, int32_t num_teams, int32_t thread_limit);
- llvm::Type *TypeParams[] = {CGM.Int32Ty,
+ // int64_t *arg_types, int32_t num_teams, int32_t thread_limit);
+ llvm::Type *TypeParams[] = {CGM.Int64Ty,
CGM.VoidPtrTy,
CGM.Int32Ty,
CGM.VoidPtrPtrTy,
CGM.VoidPtrPtrTy,
CGM.SizeTy->getPointerTo(),
- CGM.Int32Ty->getPointerTo(),
+ CGM.Int64Ty->getPointerTo(),
CGM.Int32Ty,
CGM.Int32Ty};
llvm::FunctionType *FnTy =
@@ -2034,6 +2096,24 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams");
break;
}
+ case OMPRTL__tgt_target_teams_nowait: {
+ // Build int32_t __tgt_target_teams_nowait(int64_t device_id, void
+ // *host_ptr, int32_t arg_num, void** args_base, void **args, size_t
+ // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit);
+ llvm::Type *TypeParams[] = {CGM.Int64Ty,
+ CGM.VoidPtrTy,
+ CGM.Int32Ty,
+ CGM.VoidPtrPtrTy,
+ CGM.VoidPtrPtrTy,
+ CGM.SizeTy->getPointerTo(),
+ CGM.Int64Ty->getPointerTo(),
+ CGM.Int32Ty,
+ CGM.Int32Ty};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams_nowait");
+ break;
+ }
case OMPRTL__tgt_register_lib: {
// Build void __tgt_register_lib(__tgt_bin_desc *desc);
QualType ParamTy =
@@ -2055,47 +2135,92 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
break;
}
case OMPRTL__tgt_target_data_begin: {
- // Build void __tgt_target_data_begin(int32_t device_id, int32_t arg_num,
- // void** args_base, void **args, size_t *arg_sizes, int32_t *arg_types);
- llvm::Type *TypeParams[] = {CGM.Int32Ty,
+ // Build void __tgt_target_data_begin(int64_t device_id, int32_t arg_num,
+ // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types);
+ llvm::Type *TypeParams[] = {CGM.Int64Ty,
CGM.Int32Ty,
CGM.VoidPtrPtrTy,
CGM.VoidPtrPtrTy,
CGM.SizeTy->getPointerTo(),
- CGM.Int32Ty->getPointerTo()};
+ CGM.Int64Ty->getPointerTo()};
llvm::FunctionType *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin");
break;
}
+ case OMPRTL__tgt_target_data_begin_nowait: {
+ // Build void __tgt_target_data_begin_nowait(int64_t device_id, int32_t
+ // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t
+ // *arg_types);
+ llvm::Type *TypeParams[] = {CGM.Int64Ty,
+ CGM.Int32Ty,
+ CGM.VoidPtrPtrTy,
+ CGM.VoidPtrPtrTy,
+ CGM.SizeTy->getPointerTo(),
+ CGM.Int64Ty->getPointerTo()};
+ auto *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin_nowait");
+ break;
+ }
case OMPRTL__tgt_target_data_end: {
- // Build void __tgt_target_data_end(int32_t device_id, int32_t arg_num,
- // void** args_base, void **args, size_t *arg_sizes, int32_t *arg_types);
- llvm::Type *TypeParams[] = {CGM.Int32Ty,
+ // Build void __tgt_target_data_end(int64_t device_id, int32_t arg_num,
+ // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types);
+ llvm::Type *TypeParams[] = {CGM.Int64Ty,
CGM.Int32Ty,
CGM.VoidPtrPtrTy,
CGM.VoidPtrPtrTy,
CGM.SizeTy->getPointerTo(),
- CGM.Int32Ty->getPointerTo()};
+ CGM.Int64Ty->getPointerTo()};
llvm::FunctionType *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end");
break;
}
+ case OMPRTL__tgt_target_data_end_nowait: {
+ // Build void __tgt_target_data_end_nowait(int64_t device_id, int32_t
+ // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t
+ // *arg_types);
+ llvm::Type *TypeParams[] = {CGM.Int64Ty,
+ CGM.Int32Ty,
+ CGM.VoidPtrPtrTy,
+ CGM.VoidPtrPtrTy,
+ CGM.SizeTy->getPointerTo(),
+ CGM.Int64Ty->getPointerTo()};
+ auto *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end_nowait");
+ break;
+ }
case OMPRTL__tgt_target_data_update: {
- // Build void __tgt_target_data_update(int32_t device_id, int32_t arg_num,
- // void** args_base, void **args, size_t *arg_sizes, int32_t *arg_types);
- llvm::Type *TypeParams[] = {CGM.Int32Ty,
+ // Build void __tgt_target_data_update(int64_t device_id, int32_t arg_num,
+ // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types);
+ llvm::Type *TypeParams[] = {CGM.Int64Ty,
CGM.Int32Ty,
CGM.VoidPtrPtrTy,
CGM.VoidPtrPtrTy,
CGM.SizeTy->getPointerTo(),
- CGM.Int32Ty->getPointerTo()};
+ CGM.Int64Ty->getPointerTo()};
llvm::FunctionType *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update");
break;
}
+ case OMPRTL__tgt_target_data_update_nowait: {
+ // Build void __tgt_target_data_update_nowait(int64_t device_id, int32_t
+ // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t
+ // *arg_types);
+ llvm::Type *TypeParams[] = {CGM.Int64Ty,
+ CGM.Int32Ty,
+ CGM.VoidPtrPtrTy,
+ CGM.VoidPtrPtrTy,
+ CGM.SizeTy->getPointerTo(),
+ CGM.Int64Ty->getPointerTo()};
+ auto *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update_nowait");
+ break;
+ }
}
assert(RTLFn && "Unable to find OpenMP runtime function");
return RTLFn;
@@ -2459,7 +2584,7 @@ void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
OutlinedFnArgs.push_back(ThreadIDAddr.getPointer());
OutlinedFnArgs.push_back(ZeroAddr.getPointer());
OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
- CGF.EmitCallOrInvoke(OutlinedFn, OutlinedFnArgs);
+ RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs);
// __kmpc_end_serialized_parallel(&Loc, GTid);
llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID};
@@ -2968,87 +3093,101 @@ static void emitForStaticInitCall(
CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
llvm::Constant *ForStaticInitFunction, OpenMPSchedType Schedule,
OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
- unsigned IVSize, bool Ordered, Address IL, Address LB, Address UB,
- Address ST, llvm::Value *Chunk) {
+ const CGOpenMPRuntime::StaticRTInput &Values) {
if (!CGF.HaveInsertPoint())
- return;
+ return;
- assert(!Ordered);
- assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
- Schedule == OMP_sch_static_balanced_chunked ||
- Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
- Schedule == OMP_dist_sch_static ||
- Schedule == OMP_dist_sch_static_chunked);
+ assert(!Values.Ordered);
+ assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
+ Schedule == OMP_sch_static_balanced_chunked ||
+ Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
+ Schedule == OMP_dist_sch_static ||
+ Schedule == OMP_dist_sch_static_chunked);
- // Call __kmpc_for_static_init(
- // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
- // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
- // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
- // kmp_int[32|64] incr, kmp_int[32|64] chunk);
- if (Chunk == nullptr) {
- assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
- Schedule == OMP_dist_sch_static) &&
- "expected static non-chunked schedule");
- // If the Chunk was not specified in the clause - use default value 1.
- Chunk = CGF.Builder.getIntN(IVSize, 1);
- } else {
- assert((Schedule == OMP_sch_static_chunked ||
- Schedule == OMP_sch_static_balanced_chunked ||
- Schedule == OMP_ord_static_chunked ||
- Schedule == OMP_dist_sch_static_chunked) &&
- "expected static chunked schedule");
- }
- llvm::Value *Args[] = {
- UpdateLocation, ThreadId, CGF.Builder.getInt32(addMonoNonMonoModifier(
- Schedule, M1, M2)), // Schedule type
- IL.getPointer(), // &isLastIter
- LB.getPointer(), // &LB
- UB.getPointer(), // &UB
- ST.getPointer(), // &Stride
- CGF.Builder.getIntN(IVSize, 1), // Incr
- Chunk // Chunk
- };
- CGF.EmitRuntimeCall(ForStaticInitFunction, Args);
+ // Call __kmpc_for_static_init(
+ // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
+ // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
+ // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
+ // kmp_int[32|64] incr, kmp_int[32|64] chunk);
+ llvm::Value *Chunk = Values.Chunk;
+ if (Chunk == nullptr) {
+ assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
+ Schedule == OMP_dist_sch_static) &&
+ "expected static non-chunked schedule");
+ // If the Chunk was not specified in the clause - use default value 1.
+ Chunk = CGF.Builder.getIntN(Values.IVSize, 1);
+ } else {
+ assert((Schedule == OMP_sch_static_chunked ||
+ Schedule == OMP_sch_static_balanced_chunked ||
+ Schedule == OMP_ord_static_chunked ||
+ Schedule == OMP_dist_sch_static_chunked) &&
+ "expected static chunked schedule");
+ }
+ llvm::Value *Args[] = {
+ UpdateLocation,
+ ThreadId,
+ CGF.Builder.getInt32(addMonoNonMonoModifier(Schedule, M1,
+ M2)), // Schedule type
+ Values.IL.getPointer(), // &isLastIter
+ Values.LB.getPointer(), // &LB
+ Values.UB.getPointer(), // &UB
+ Values.ST.getPointer(), // &Stride
+ CGF.Builder.getIntN(Values.IVSize, 1), // Incr
+ Chunk // Chunk
+ };
+ CGF.EmitRuntimeCall(ForStaticInitFunction, Args);
}
void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF,
SourceLocation Loc,
+ OpenMPDirectiveKind DKind,
const OpenMPScheduleTy &ScheduleKind,
- unsigned IVSize, bool IVSigned,
- bool Ordered, Address IL, Address LB,
- Address UB, Address ST,
- llvm::Value *Chunk) {
- OpenMPSchedType ScheduleNum =
- getRuntimeSchedule(ScheduleKind.Schedule, Chunk != nullptr, Ordered);
- auto *UpdatedLocation = emitUpdateLocation(CGF, Loc);
+ const StaticRTInput &Values) {
+ OpenMPSchedType ScheduleNum = getRuntimeSchedule(
+ ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered);
+ assert(isOpenMPWorksharingDirective(DKind) &&
+ "Expected loop-based or sections-based directive.");
+ auto *UpdatedLocation = emitUpdateLocation(CGF, Loc,
+ isOpenMPLoopDirective(DKind)
+ ? OMP_IDENT_WORK_LOOP
+ : OMP_IDENT_WORK_SECTIONS);
auto *ThreadId = getThreadID(CGF, Loc);
- auto *StaticInitFunction = createForStaticInitFunction(IVSize, IVSigned);
+ auto *StaticInitFunction =
+ createForStaticInitFunction(Values.IVSize, Values.IVSigned);
emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
- ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, IVSize,
- Ordered, IL, LB, UB, ST, Chunk);
+ ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values);
}
void CGOpenMPRuntime::emitDistributeStaticInit(
CodeGenFunction &CGF, SourceLocation Loc,
- OpenMPDistScheduleClauseKind SchedKind, unsigned IVSize, bool IVSigned,
- bool Ordered, Address IL, Address LB, Address UB, Address ST,
- llvm::Value *Chunk) {
- OpenMPSchedType ScheduleNum = getRuntimeSchedule(SchedKind, Chunk != nullptr);
- auto *UpdatedLocation = emitUpdateLocation(CGF, Loc);
+ OpenMPDistScheduleClauseKind SchedKind,
+ const CGOpenMPRuntime::StaticRTInput &Values) {
+ OpenMPSchedType ScheduleNum =
+ getRuntimeSchedule(SchedKind, Values.Chunk != nullptr);
+ auto *UpdatedLocation =
+ emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE);
auto *ThreadId = getThreadID(CGF, Loc);
- auto *StaticInitFunction = createForStaticInitFunction(IVSize, IVSigned);
+ auto *StaticInitFunction =
+ createForStaticInitFunction(Values.IVSize, Values.IVSigned);
emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown,
- OMPC_SCHEDULE_MODIFIER_unknown, IVSize, Ordered, IL, LB,
- UB, ST, Chunk);
+ OMPC_SCHEDULE_MODIFIER_unknown, Values);
}
void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
- SourceLocation Loc) {
+ SourceLocation Loc,
+ OpenMPDirectiveKind DKind) {
if (!CGF.HaveInsertPoint())
return;
// Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
- llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
+ llvm::Value *Args[] = {
+ emitUpdateLocation(CGF, Loc,
+ isOpenMPDistributeDirective(DKind)
+ ? OMP_IDENT_WORK_DISTRIBUTE
+ : isOpenMPLoopDirective(DKind)
+ ? OMP_IDENT_WORK_LOOP
+ : OMP_IDENT_WORK_SECTIONS),
+ getThreadID(CGF, Loc)};
CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini),
Args);
}
@@ -3360,14 +3499,14 @@ CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() {
auto *UnRegFn = createOffloadingBinaryDescriptorFunction(
CGM, ".omp_offloading.descriptor_unreg",
[&](CodeGenFunction &CGF, PrePostActionTy &) {
- CGF.EmitCallOrInvoke(createRuntimeFunction(OMPRTL__tgt_unregister_lib),
- Desc);
+ CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_unregister_lib),
+ Desc);
});
auto *RegFn = createOffloadingBinaryDescriptorFunction(
CGM, ".omp_offloading.descriptor_reg",
[&](CodeGenFunction &CGF, PrePostActionTy &) {
- CGF.EmitCallOrInvoke(createRuntimeFunction(OMPRTL__tgt_register_lib),
- Desc);
+ CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_lib),
+ Desc);
CGM.getCXXABI().registerGlobalDtor(CGF, RegUnregVar, UnRegFn, Desc);
});
if (CGM.supportsCOMDAT()) {
@@ -3802,7 +3941,6 @@ emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
".omp_task_entry.", &CGM.getModule());
CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskEntry, TaskEntryFnInfo);
CodeGenFunction CGF(CGM);
- CGF.disableDebugInfo();
CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args);
// TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map,
@@ -3871,7 +4009,8 @@ emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
}
CallArgs.push_back(SharedsParam);
- CGF.EmitCallOrInvoke(TaskFunction, CallArgs);
+ CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction,
+ CallArgs);
CGF.EmitStoreThroughLValue(
RValue::get(CGF.Builder.getInt32(/*C=*/0)),
CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty));
@@ -3893,7 +4032,6 @@ static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
ImplicitParamDecl::Other);
Args.push_back(&GtidArg);
Args.push_back(&TaskTypeArg);
- FunctionType::ExtInfo Info;
auto &DestructorFnInfo =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
auto *DestructorFnTy = CGM.getTypes().GetFunctionType(DestructorFnInfo);
@@ -4020,9 +4158,9 @@ emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
return TaskPrivatesMap;
}
-static int array_pod_sort_comparator(const PrivateDataTy *P1,
- const PrivateDataTy *P2) {
- return P1->first < P2->first ? 1 : (P2->first < P1->first ? -1 : 0);
+static bool stable_sort_comparator(const PrivateDataTy P1,
+ const PrivateDataTy P2) {
+ return P1.first > P2.first;
}
/// Emit initialization for private variables in task-based directives.
@@ -4059,8 +4197,8 @@ static void emitPrivatesInit(CodeGenFunction &CGF,
SharedRefLValue = CGF.MakeAddrLValue(
Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)),
SharedRefLValue.getType(),
- LValueBaseInfo(AlignmentSource::Decl,
- SharedRefLValue.getBaseInfo().getMayAlias()));
+ LValueBaseInfo(AlignmentSource::Decl),
+ SharedRefLValue.getTBAAInfo());
QualType Type = OriginalVD->getType();
if (Type->isArrayType()) {
// Initialize firstprivate array.
@@ -4250,8 +4388,7 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
/*PrivateElemInit=*/nullptr)));
++I;
}
- llvm::array_pod_sort(Privates.begin(), Privates.end(),
- array_pod_sort_comparator);
+ std::stable_sort(Privates.begin(), Privates.end(), stable_sort_comparator);
auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
// Build type kmp_routine_entry_t (if not built yet).
emitKmpRoutineEntryT(KmpInt32Ty);
@@ -4262,7 +4399,7 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
}
KmpTaskTQTy = SavedKmpTaskloopTQTy;
- } else if (D.getDirectiveKind() == OMPD_task) {
+ } else {
assert(D.getDirectiveKind() == OMPD_task &&
"Expected taskloop or task directive");
if (SavedKmpTaskTQTy.isNull()) {
@@ -4557,8 +4694,8 @@ void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
}
auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry,
- NumDependencies, &DepWaitTaskArgs](CodeGenFunction &CGF,
- PrePostActionTy &) {
+ NumDependencies, &DepWaitTaskArgs,
+ Loc](CodeGenFunction &CGF, PrePostActionTy &) {
auto &RT = CGF.CGM.getOpenMPRuntime();
CodeGenFunction::RunCleanupsScope LocalScope(CGF);
// Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
@@ -4569,11 +4706,12 @@ void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps),
DepWaitTaskArgs);
// Call proxy_task_entry(gtid, new_task);
- auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy](
- CodeGenFunction &CGF, PrePostActionTy &Action) {
+ auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
+ Loc](CodeGenFunction &CGF, PrePostActionTy &Action) {
Action.Enter(CGF);
llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
- CGF.EmitCallOrInvoke(TaskEntry, OutlinedFnArgs);
+ CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
+ OutlinedFnArgs);
};
// Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
@@ -5805,21 +5943,21 @@ emitNumTeamsForTargetDirective(CGOpenMPRuntime &OMPRuntime,
const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
- // FIXME: Accommodate other combined directives with teams when they become
- // available.
- if (auto *TeamsDir = dyn_cast_or_null<OMPTeamsDirective>(
+ if (auto *TeamsDir = dyn_cast_or_null<OMPExecutableDirective>(
ignoreCompoundStmts(CS.getCapturedStmt()))) {
- if (auto *NTE = TeamsDir->getSingleClause<OMPNumTeamsClause>()) {
- CGOpenMPInnerExprInfo CGInfo(CGF, CS);
- CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
- llvm::Value *NumTeams = CGF.EmitScalarExpr(NTE->getNumTeams());
- return Bld.CreateIntCast(NumTeams, CGF.Int32Ty,
- /*IsSigned=*/true);
- }
+ if (isOpenMPTeamsDirective(TeamsDir->getDirectiveKind())) {
+ if (auto *NTE = TeamsDir->getSingleClause<OMPNumTeamsClause>()) {
+ CGOpenMPInnerExprInfo CGInfo(CGF, CS);
+ CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
+ llvm::Value *NumTeams = CGF.EmitScalarExpr(NTE->getNumTeams());
+ return Bld.CreateIntCast(NumTeams, CGF.Int32Ty,
+ /*IsSigned=*/true);
+ }
- // If we have an enclosed teams directive but no num_teams clause we use
- // the default value 0.
- return Bld.getInt32(0);
+ // If we have an enclosed teams directive but no num_teams clause we use
+ // the default value 0.
+ return Bld.getInt32(0);
+ }
}
// No teams associated with the directive.
@@ -5908,21 +6046,21 @@ emitNumThreadsForTargetDirective(CGOpenMPRuntime &OMPRuntime,
const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
- // FIXME: Accommodate other combined directives with teams when they become
- // available.
- if (auto *TeamsDir = dyn_cast_or_null<OMPTeamsDirective>(
+ if (auto *TeamsDir = dyn_cast_or_null<OMPExecutableDirective>(
ignoreCompoundStmts(CS.getCapturedStmt()))) {
- if (auto *TLE = TeamsDir->getSingleClause<OMPThreadLimitClause>()) {
- CGOpenMPInnerExprInfo CGInfo(CGF, CS);
- CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
- llvm::Value *ThreadLimit = CGF.EmitScalarExpr(TLE->getThreadLimit());
- return CGF.Builder.CreateIntCast(ThreadLimit, CGF.Int32Ty,
- /*IsSigned=*/true);
- }
+ if (isOpenMPTeamsDirective(TeamsDir->getDirectiveKind())) {
+ if (auto *TLE = TeamsDir->getSingleClause<OMPThreadLimitClause>()) {
+ CGOpenMPInnerExprInfo CGInfo(CGF, CS);
+ CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
+ llvm::Value *ThreadLimit = CGF.EmitScalarExpr(TLE->getThreadLimit());
+ return CGF.Builder.CreateIntCast(ThreadLimit, CGF.Int32Ty,
+ /*IsSigned=*/true);
+ }
- // If we have an enclosed teams directive but no thread_limit clause we use
- // the default value 0.
- return CGF.Builder.getInt32(0);
+ // If we have an enclosed teams directive but no thread_limit clause we
+ // use the default value 0.
+ return CGF.Builder.getInt32(0);
+ }
}
// No teams associated with the directive.
@@ -5949,22 +6087,23 @@ public:
/// \brief Delete the element from the device environment, ignoring the
/// current reference count associated with the element.
OMP_MAP_DELETE = 0x08,
- /// \brief The element being mapped is a pointer, therefore the pointee
- /// should be mapped as well.
- OMP_MAP_IS_PTR = 0x10,
- /// \brief This flags signals that an argument is the first one relating to
- /// a map/private clause expression. For some cases a single
- /// map/privatization results in multiple arguments passed to the runtime
- /// library.
- OMP_MAP_FIRST_REF = 0x20,
+ /// \brief The element being mapped is a pointer-pointee pair; both the
+ /// pointer and the pointee should be mapped.
+ OMP_MAP_PTR_AND_OBJ = 0x10,
+ /// \brief This flags signals that the base address of an entry should be
+ /// passed to the target kernel as an argument.
+ OMP_MAP_TARGET_PARAM = 0x20,
/// \brief Signal that the runtime library has to return the device pointer
- /// in the current position for the data being mapped.
- OMP_MAP_RETURN_PTR = 0x40,
+ /// in the current position for the data being mapped. Used when we have the
+ /// use_device_ptr clause.
+ OMP_MAP_RETURN_PARAM = 0x40,
/// \brief This flag signals that the reference being passed is a pointer to
/// private data.
- OMP_MAP_PRIVATE_PTR = 0x80,
+ OMP_MAP_PRIVATE = 0x80,
/// \brief Pass the element to the device by value.
- OMP_MAP_PRIVATE_VAL = 0x100,
+ OMP_MAP_LITERAL = 0x100,
+ /// Implicit map
+ OMP_MAP_IMPLICIT = 0x200,
};
/// Class that associates information with a base pointer to be passed to the
@@ -5986,7 +6125,7 @@ public:
typedef SmallVector<BasePointerInfo, 16> MapBaseValuesArrayTy;
typedef SmallVector<llvm::Value *, 16> MapValuesArrayTy;
- typedef SmallVector<unsigned, 16> MapFlagsArrayTy;
+ typedef SmallVector<uint64_t, 16> MapFlagsArrayTy;
private:
/// \brief Directive from where the map clauses were extracted.
@@ -5997,6 +6136,8 @@ private:
/// \brief Set of all first private variables in the current directive.
llvm::SmallPtrSet<const VarDecl *, 8> FirstPrivateDecls;
+ /// Set of all reduction variables in the current directive.
+ llvm::SmallPtrSet<const VarDecl *, 8> ReductionDecls;
/// Map between device pointer declarations and their expression components.
/// The key value for declarations in 'this' is null.
@@ -6051,10 +6192,10 @@ private:
/// a flag marking the map as a pointer if requested. Add a flag marking the
/// map as the first one of a series of maps that relate to the same map
/// expression.
- unsigned getMapTypeBits(OpenMPMapClauseKind MapType,
+ uint64_t getMapTypeBits(OpenMPMapClauseKind MapType,
OpenMPMapClauseKind MapTypeModifier, bool AddPtrFlag,
- bool AddIsFirstFlag) const {
- unsigned Bits = 0u;
+ bool AddIsTargetParamFlag) const {
+ uint64_t Bits = 0u;
switch (MapType) {
case OMPC_MAP_alloc:
case OMPC_MAP_release:
@@ -6080,9 +6221,9 @@ private:
break;
}
if (AddPtrFlag)
- Bits |= OMP_MAP_IS_PTR;
- if (AddIsFirstFlag)
- Bits |= OMP_MAP_FIRST_REF;
+ Bits |= OMP_MAP_PTR_AND_OBJ;
+ if (AddIsTargetParamFlag)
+ Bits |= OMP_MAP_TARGET_PARAM;
if (MapTypeModifier == OMPC_MAP_always)
Bits |= OMP_MAP_ALWAYS;
return Bits;
@@ -6135,7 +6276,7 @@ private:
OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
- bool IsFirstComponentList) const {
+ bool IsFirstComponentList, bool IsImplicit) const {
// The following summarizes what has to be generated for each map and the
// types bellow. The generated information is expressed in this order:
@@ -6189,28 +6330,28 @@ private:
//
// map(s.p[:22], s.a s.b)
// &s, &(s.p), sizeof(double*), noflags
- // &(s.p), &(s.p[0]), 22*sizeof(double), ptr_flag + extra_flag
+ // &(s.p), &(s.p[0]), 22*sizeof(double), ptr_flag
//
// map(s.ps)
// &s, &(s.ps), sizeof(S2*), noflags
//
// map(s.ps->s.i)
// &s, &(s.ps), sizeof(S2*), noflags
- // &(s.ps), &(s.ps->s.i), sizeof(int), ptr_flag + extra_flag
+ // &(s.ps), &(s.ps->s.i), sizeof(int), ptr_flag
//
// map(s.ps->ps)
// &s, &(s.ps), sizeof(S2*), noflags
- // &(s.ps), &(s.ps->ps), sizeof(S2*), ptr_flag + extra_flag
+ // &(s.ps), &(s.ps->ps), sizeof(S2*), ptr_flag
//
// map(s.ps->ps->ps)
// &s, &(s.ps), sizeof(S2*), noflags
- // &(s.ps), &(s.ps->ps), sizeof(S2*), ptr_flag + extra_flag
- // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), ptr_flag + extra_flag
+ // &(s.ps), &(s.ps->ps), sizeof(S2*), ptr_flag
+ // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), ptr_flag
//
// map(s.ps->ps->s.f[:22])
// &s, &(s.ps), sizeof(S2*), noflags
- // &(s.ps), &(s.ps->ps), sizeof(S2*), ptr_flag + extra_flag
- // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), ptr_flag + extra_flag
+ // &(s.ps), &(s.ps->ps), sizeof(S2*), ptr_flag
+ // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), ptr_flag
//
// map(ps)
// &ps, &ps, sizeof(S2*), noflags
@@ -6226,29 +6367,28 @@ private:
//
// map(ps->p[:22])
// ps, &(ps->p), sizeof(double*), noflags
- // &(ps->p), &(ps->p[0]), 22*sizeof(double), ptr_flag + extra_flag
+ // &(ps->p), &(ps->p[0]), 22*sizeof(double), ptr_flag
//
// map(ps->ps)
// ps, &(ps->ps), sizeof(S2*), noflags
//
// map(ps->ps->s.i)
// ps, &(ps->ps), sizeof(S2*), noflags
- // &(ps->ps), &(ps->ps->s.i), sizeof(int), ptr_flag + extra_flag
+ // &(ps->ps), &(ps->ps->s.i), sizeof(int), ptr_flag
//
// map(ps->ps->ps)
// ps, &(ps->ps), sizeof(S2*), noflags
- // &(ps->ps), &(ps->ps->ps), sizeof(S2*), ptr_flag + extra_flag
+ // &(ps->ps), &(ps->ps->ps), sizeof(S2*), ptr_flag
//
// map(ps->ps->ps->ps)
// ps, &(ps->ps), sizeof(S2*), noflags
- // &(ps->ps), &(ps->ps->ps), sizeof(S2*), ptr_flag + extra_flag
- // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), ptr_flag + extra_flag
+ // &(ps->ps), &(ps->ps->ps), sizeof(S2*), ptr_flag
+ // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), ptr_flag
//
// map(ps->ps->ps->s.f[:22])
// ps, &(ps->ps), sizeof(S2*), noflags
- // &(ps->ps), &(ps->ps->ps), sizeof(S2*), ptr_flag + extra_flag
- // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), ptr_flag +
- // extra_flag
+ // &(ps->ps), &(ps->ps->ps), sizeof(S2*), ptr_flag
+ // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), ptr_flag
// Track if the map information being generated is the first for a capture.
bool IsCaptureFirstInfo = IsFirstComponentList;
@@ -6270,8 +6410,7 @@ private:
} else {
// The base is the reference to the variable.
// BP = &Var.
- BP = CGF.EmitLValue(cast<DeclRefExpr>(I->getAssociatedExpression()))
- .getPointer();
+ BP = CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getPointer();
// If the variable is a pointer and is being dereferenced (i.e. is not
// the last component), the base has to be the pointer itself, not its
@@ -6290,6 +6429,7 @@ private:
}
}
+ uint64_t DefaultFlags = IsImplicit ? OMP_MAP_IMPLICIT : 0;
for (; I != CE; ++I) {
auto Next = std::next(I);
@@ -6324,7 +6464,8 @@ private:
isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) &&
"Unexpected expression");
- auto *LB = CGF.EmitLValue(I->getAssociatedExpression()).getPointer();
+ llvm::Value *LB =
+ CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getPointer();
auto *Size = getExprTypeSize(I->getAssociatedExpression());
// If we have a member expression and the current component is a
@@ -6339,9 +6480,11 @@ private:
BasePointers.push_back(BP);
Pointers.push_back(RefAddr);
Sizes.push_back(CGF.getTypeSize(CGF.getContext().VoidPtrTy));
- Types.push_back(getMapTypeBits(
- /*MapType*/ OMPC_MAP_alloc, /*MapTypeModifier=*/OMPC_MAP_unknown,
- !IsExpressionFirstInfo, IsCaptureFirstInfo));
+ Types.push_back(DefaultFlags |
+ getMapTypeBits(
+ /*MapType*/ OMPC_MAP_alloc,
+ /*MapTypeModifier=*/OMPC_MAP_unknown,
+ !IsExpressionFirstInfo, IsCaptureFirstInfo));
IsExpressionFirstInfo = false;
IsCaptureFirstInfo = false;
// The reference will be the next base address.
@@ -6356,9 +6499,9 @@ private:
// same expression except for the first one. We also need to signal
// this map is the first one that relates with the current capture
// (there is a set of entries for each capture).
- Types.push_back(getMapTypeBits(MapType, MapTypeModifier,
- !IsExpressionFirstInfo,
- IsCaptureFirstInfo));
+ Types.push_back(DefaultFlags | getMapTypeBits(MapType, MapTypeModifier,
+ !IsExpressionFirstInfo,
+ IsCaptureFirstInfo));
// If we have a final array section, we are done with this expression.
if (IsFinalArraySection)
@@ -6370,7 +6513,6 @@ private:
IsExpressionFirstInfo = false;
IsCaptureFirstInfo = false;
- continue;
}
}
}
@@ -6386,8 +6528,14 @@ private:
// 'private ptr' and 'map to' flag. Return the right flags if the captured
// declaration is known as first-private in this handler.
if (FirstPrivateDecls.count(Cap.getCapturedVar()))
- return MappableExprsHandler::OMP_MAP_PRIVATE_PTR |
+ return MappableExprsHandler::OMP_MAP_PRIVATE |
MappableExprsHandler::OMP_MAP_TO;
+ // Reduction variable will use only the 'private ptr' and 'map to_from'
+ // flag.
+ if (ReductionDecls.count(Cap.getCapturedVar())) {
+ return MappableExprsHandler::OMP_MAP_TO |
+ MappableExprsHandler::OMP_MAP_FROM;
+ }
// We didn't modify anything.
return CurrentModifiers;
@@ -6401,6 +6549,12 @@ public:
for (const auto *D : C->varlists())
FirstPrivateDecls.insert(
cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl())->getCanonicalDecl());
+ for (const auto *C : Dir.getClausesOfKind<OMPReductionClause>()) {
+ for (const auto *D : C->varlists()) {
+ ReductionDecls.insert(
+ cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl())->getCanonicalDecl());
+ }
+ }
// Extract device pointer clause information.
for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
for (auto L : C->component_lists())
@@ -6432,20 +6586,19 @@ public:
RPK_MemberReference,
};
OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
- OpenMPMapClauseKind MapType;
- OpenMPMapClauseKind MapTypeModifier;
- ReturnPointerKind ReturnDevicePointer;
+ OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
+ OpenMPMapClauseKind MapTypeModifier = OMPC_MAP_unknown;
+ ReturnPointerKind ReturnDevicePointer = RPK_None;
+ bool IsImplicit = false;
- MapInfo()
- : MapType(OMPC_MAP_unknown), MapTypeModifier(OMPC_MAP_unknown),
- ReturnDevicePointer(RPK_None) {}
+ MapInfo() = default;
MapInfo(
OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
OpenMPMapClauseKind MapType, OpenMPMapClauseKind MapTypeModifier,
- ReturnPointerKind ReturnDevicePointer)
+ ReturnPointerKind ReturnDevicePointer, bool IsImplicit)
: Components(Components), MapType(MapType),
MapTypeModifier(MapTypeModifier),
- ReturnDevicePointer(ReturnDevicePointer) {}
+ ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {}
};
// We have to process the component lists that relate with the same
@@ -6459,25 +6612,29 @@ public:
const ValueDecl *D,
OMPClauseMappableExprCommon::MappableExprComponentListRef L,
OpenMPMapClauseKind MapType, OpenMPMapClauseKind MapModifier,
- MapInfo::ReturnPointerKind ReturnDevicePointer) {
+ MapInfo::ReturnPointerKind ReturnDevicePointer, bool IsImplicit) {
const ValueDecl *VD =
D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
- Info[VD].push_back({L, MapType, MapModifier, ReturnDevicePointer});
+ Info[VD].emplace_back(L, MapType, MapModifier, ReturnDevicePointer,
+ IsImplicit);
};
// FIXME: MSVC 2013 seems to require this-> to find member CurDir.
for (auto *C : this->CurDir.getClausesOfKind<OMPMapClause>())
- for (auto L : C->component_lists())
+ for (auto L : C->component_lists()) {
InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifier(),
- MapInfo::RPK_None);
+ MapInfo::RPK_None, C->isImplicit());
+ }
for (auto *C : this->CurDir.getClausesOfKind<OMPToClause>())
- for (auto L : C->component_lists())
+ for (auto L : C->component_lists()) {
InfoGen(L.first, L.second, OMPC_MAP_to, OMPC_MAP_unknown,
- MapInfo::RPK_None);
+ MapInfo::RPK_None, C->isImplicit());
+ }
for (auto *C : this->CurDir.getClausesOfKind<OMPFromClause>())
- for (auto L : C->component_lists())
+ for (auto L : C->component_lists()) {
InfoGen(L.first, L.second, OMPC_MAP_from, OMPC_MAP_unknown,
- MapInfo::RPK_None);
+ MapInfo::RPK_None, C->isImplicit());
+ }
// Look at the use_device_ptr clause information and mark the existing map
// entries as such. If there is no map information for an entry in the
@@ -6524,7 +6681,7 @@ public:
BasePointers.push_back({Ptr, VD});
Pointers.push_back(Ptr);
Sizes.push_back(llvm::Constant::getNullValue(this->CGF.SizeTy));
- Types.push_back(OMP_MAP_RETURN_PTR | OMP_MAP_FIRST_REF);
+ Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM);
}
for (auto &M : Info) {
@@ -6538,9 +6695,9 @@ public:
// Remember the current base pointer index.
unsigned CurrentBasePointersIdx = BasePointers.size();
// FIXME: MSVC 2013 seems to require this-> to find the member method.
- this->generateInfoForComponentList(L.MapType, L.MapTypeModifier,
- L.Components, BasePointers, Pointers,
- Sizes, Types, IsFirstComponentList);
+ this->generateInfoForComponentList(
+ L.MapType, L.MapTypeModifier, L.Components, BasePointers, Pointers,
+ Sizes, Types, IsFirstComponentList, L.IsImplicit);
// If this entry relates with a device pointer, set the relevant
// declaration and add the 'return pointer' flag.
@@ -6562,7 +6719,7 @@ public:
"No relevant declaration related with device pointer??");
BasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD);
- Types[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PTR;
+ Types[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM;
}
IsFirstComponentList = false;
}
@@ -6604,7 +6761,8 @@ public:
for (auto L : It->second) {
generateInfoForComponentList(
/*MapType=*/OMPC_MAP_to, /*MapTypeModifier=*/OMPC_MAP_unknown, L,
- BasePointers, Pointers, Sizes, Types, IsFirstComponentList);
+ BasePointers, Pointers, Sizes, Types, IsFirstComponentList,
+ /*IsImplicit=*/false);
IsFirstComponentList = false;
}
return;
@@ -6613,7 +6771,7 @@ public:
BasePointers.push_back({Arg, VD});
Pointers.push_back(Arg);
Sizes.push_back(CGF.getTypeSize(CGF.getContext().VoidPtrTy));
- Types.push_back(OMP_MAP_PRIVATE_VAL | OMP_MAP_FIRST_REF);
+ Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM);
return;
}
@@ -6624,9 +6782,9 @@ public:
"We got information for the wrong declaration??");
assert(!L.second.empty() &&
"Not expecting declaration with no component lists.");
- generateInfoForComponentList(C->getMapType(), C->getMapTypeModifier(),
- L.second, BasePointers, Pointers, Sizes,
- Types, IsFirstComponentList);
+ generateInfoForComponentList(
+ C->getMapType(), C->getMapTypeModifier(), L.second, BasePointers,
+ Pointers, Sizes, Types, IsFirstComponentList, C->isImplicit());
IsFirstComponentList = false;
}
@@ -6656,7 +6814,7 @@ public:
if (!RI.getType()->isAnyPointerType()) {
// We have to signal to the runtime captures passed by value that are
// not pointers.
- CurMapTypes.push_back(OMP_MAP_PRIVATE_VAL);
+ CurMapTypes.push_back(OMP_MAP_LITERAL);
CurSizes.push_back(CGF.getTypeSize(RI.getType()));
} else {
// Pointers are implicitly mapped with a zero size and no flags
@@ -6676,19 +6834,12 @@ public:
// The default map type for a scalar/complex type is 'to' because by
// default the value doesn't have to be retrieved. For an aggregate
// type, the default is 'tofrom'.
- CurMapTypes.push_back(ElementType->isAggregateType()
- ? (OMP_MAP_TO | OMP_MAP_FROM)
- : OMP_MAP_TO);
-
- // If we have a capture by reference we may need to add the private
- // pointer flag if the base declaration shows in some first-private
- // clause.
- CurMapTypes.back() =
- adjustMapModifiersForPrivateClauses(CI, CurMapTypes.back());
+ CurMapTypes.emplace_back(adjustMapModifiersForPrivateClauses(
+ CI, ElementType->isAggregateType() ? (OMP_MAP_TO | OMP_MAP_FROM)
+ : OMP_MAP_TO));
}
- // Every default map produces a single argument, so, it is always the
- // first one.
- CurMapTypes.back() |= OMP_MAP_FIRST_REF;
+ // Every default map produces a single argument which is a target parameter.
+ CurMapTypes.back() |= OMP_MAP_TARGET_PARAM;
}
};
@@ -6831,7 +6982,7 @@ static void emitOffloadingArraysArgument(
llvm::ArrayType::get(CGM.SizeTy, Info.NumberOfPtrs), Info.SizesArray,
/*Idx0=*/0, /*Idx1=*/0);
MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
- llvm::ArrayType::get(CGM.Int32Ty, Info.NumberOfPtrs),
+ llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
Info.MapTypesArray,
/*Idx0=*/0,
/*Idx1=*/0);
@@ -6840,7 +6991,7 @@ static void emitOffloadingArraysArgument(
PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
SizesArrayArg = llvm::ConstantPointerNull::get(CGM.SizeTy->getPointerTo());
MapTypesArrayArg =
- llvm::ConstantPointerNull::get(CGM.Int32Ty->getPointerTo());
+ llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
}
}
@@ -6855,8 +7006,6 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
assert(OutlinedFn && "Invalid outlined function!");
- auto &Ctx = CGF.getContext();
-
// Fill up the arrays with all the captured variables.
MappableExprsHandler::MapValuesArrayTy KernelArgs;
MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
@@ -6878,9 +7027,6 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
CE = CS.capture_end();
CI != CE; ++CI, ++RI, ++CV) {
- StringRef Name;
- QualType Ty;
-
CurBasePointers.clear();
CurPointers.clear();
CurSizes.clear();
@@ -6893,8 +7039,8 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
CurPointers.push_back(*CV);
CurSizes.push_back(CGF.getTypeSize(RI->getType()));
// Copy to the device as an argument. No need to retrieve it.
- CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_PRIVATE_VAL |
- MappableExprsHandler::OMP_MAP_FIRST_REF);
+ CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL |
+ MappableExprsHandler::OMP_MAP_TARGET_PARAM);
} else {
// If we have any information in the map clause, we use it, otherwise we
// just do a default mapping.
@@ -6921,19 +7067,10 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
MapTypes.append(CurMapTypes.begin(), CurMapTypes.end());
}
- // Keep track on whether the host function has to be executed.
- auto OffloadErrorQType =
- Ctx.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true);
- auto OffloadError = CGF.MakeAddrLValue(
- CGF.CreateMemTemp(OffloadErrorQType, ".run_host_version"),
- OffloadErrorQType);
- CGF.EmitStoreOfScalar(llvm::Constant::getNullValue(CGM.Int32Ty),
- OffloadError);
-
// Fill up the pointer arrays and transfer execution to the device.
- auto &&ThenGen = [&BasePointers, &Pointers, &Sizes, &MapTypes, Device,
- OutlinedFnID, OffloadError,
- &D](CodeGenFunction &CGF, PrePostActionTy &) {
+ auto &&ThenGen = [this, &BasePointers, &Pointers, &Sizes, &MapTypes, Device,
+ OutlinedFn, OutlinedFnID, &D,
+ &KernelArgs](CodeGenFunction &CGF, PrePostActionTy &) {
auto &RT = CGF.CGM.getOpenMPRuntime();
// Emit the offloading arrays.
TargetDataInfo Info;
@@ -6956,11 +7093,12 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
// Emit device ID if any.
llvm::Value *DeviceID;
- if (Device)
+ if (Device) {
DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
- CGF.Int32Ty, /*isSigned=*/true);
- else
- DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF);
+ CGF.Int64Ty, /*isSigned=*/true);
+ } else {
+ DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
+ }
// Emit the number of elements in the offloading arrays.
llvm::Value *PointerNum = CGF.Builder.getInt32(BasePointers.size());
@@ -6971,6 +7109,7 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
auto *NumTeams = emitNumTeamsForTargetDirective(RT, CGF, D);
auto *NumThreads = emitNumThreadsForTargetDirective(RT, CGF, D);
+ bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
// The target region is an outlined function launched by the runtime
// via calls __tgt_target() or __tgt_target_teams().
//
@@ -7013,24 +7152,41 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
Info.MapTypesArray, NumTeams,
NumThreads};
Return = CGF.EmitRuntimeCall(
- RT.createRuntimeFunction(OMPRTL__tgt_target_teams), OffloadingArgs);
+ RT.createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait
+ : OMPRTL__tgt_target_teams),
+ OffloadingArgs);
} else {
llvm::Value *OffloadingArgs[] = {
DeviceID, OutlinedFnID,
PointerNum, Info.BasePointersArray,
Info.PointersArray, Info.SizesArray,
Info.MapTypesArray};
- Return = CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__tgt_target),
- OffloadingArgs);
+ Return = CGF.EmitRuntimeCall(
+ RT.createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait
+ : OMPRTL__tgt_target),
+ OffloadingArgs);
}
- CGF.EmitStoreOfScalar(Return, OffloadError);
+ // Check the error code and execute the host version if required.
+ llvm::BasicBlock *OffloadFailedBlock =
+ CGF.createBasicBlock("omp_offload.failed");
+ llvm::BasicBlock *OffloadContBlock =
+ CGF.createBasicBlock("omp_offload.cont");
+ llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return);
+ CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
+
+ CGF.EmitBlock(OffloadFailedBlock);
+ emitOutlinedFunctionCall(CGF, D.getLocStart(), OutlinedFn, KernelArgs);
+ CGF.EmitBranch(OffloadContBlock);
+
+ CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
};
// Notify that the host version must be executed.
- auto &&ElseGen = [OffloadError](CodeGenFunction &CGF, PrePostActionTy &) {
- CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.Int32Ty, /*V=*/-1u),
- OffloadError);
+ auto &&ElseGen = [this, &D, OutlinedFn, &KernelArgs](CodeGenFunction &CGF,
+ PrePostActionTy &) {
+ emitOutlinedFunctionCall(CGF, D.getLocStart(), OutlinedFn,
+ KernelArgs);
};
// If we have a target function ID it means that we need to support
@@ -7048,19 +7204,6 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
RegionCodeGenTy ElseRCG(ElseGen);
ElseRCG(CGF);
}
-
- // Check the error code and execute the host version if required.
- auto OffloadFailedBlock = CGF.createBasicBlock("omp_offload.failed");
- auto OffloadContBlock = CGF.createBasicBlock("omp_offload.cont");
- auto OffloadErrorVal = CGF.EmitLoadOfScalar(OffloadError, SourceLocation());
- auto Failed = CGF.Builder.CreateIsNotNull(OffloadErrorVal);
- CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
-
- CGF.EmitBlock(OffloadFailedBlock);
- CGF.Builder.CreateCall(OutlinedFn, KernelArgs);
- CGF.EmitBranch(OffloadContBlock);
-
- CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
}
void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
@@ -7101,6 +7244,26 @@ void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
CodeGenFunction::EmitOMPTargetTeamsDeviceFunction(
CGM, ParentName, cast<OMPTargetTeamsDirective>(*S));
break;
+ case Stmt::OMPTargetTeamsDistributeDirectiveClass:
+ CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction(
+ CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(*S));
+ break;
+ case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
+ CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction(
+ CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(*S));
+ break;
+ case Stmt::OMPTargetParallelForDirectiveClass:
+ CodeGenFunction::EmitOMPTargetParallelForDeviceFunction(
+ CGM, ParentName, cast<OMPTargetParallelForDirective>(*S));
+ break;
+ case Stmt::OMPTargetParallelForSimdDirectiveClass:
+ CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction(
+ CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(*S));
+ break;
+ case Stmt::OMPTargetSimdDirectiveClass:
+ CodeGenFunction::EmitOMPTargetSimdDeviceFunction(
+ CGM, ParentName, cast<OMPTargetSimdDirective>(*S));
+ break;
default:
llvm_unreachable("Unknown target directive for OpenMP device codegen.");
}
@@ -7278,11 +7441,12 @@ void CGOpenMPRuntime::emitTargetDataCalls(
// Emit device ID if any.
llvm::Value *DeviceID = nullptr;
- if (Device)
+ if (Device) {
DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
- CGF.Int32Ty, /*isSigned=*/true);
- else
- DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF);
+ CGF.Int64Ty, /*isSigned=*/true);
+ } else {
+ DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
+ }
// Emit the number of elements in the offloading arrays.
auto *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
@@ -7313,11 +7477,12 @@ void CGOpenMPRuntime::emitTargetDataCalls(
// Emit device ID if any.
llvm::Value *DeviceID = nullptr;
- if (Device)
+ if (Device) {
DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
- CGF.Int32Ty, /*isSigned=*/true);
- else
- DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF);
+ CGF.Int64Ty, /*isSigned=*/true);
+ } else {
+ DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
+ }
// Emit the number of elements in the offloading arrays.
auto *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
@@ -7399,11 +7564,12 @@ void CGOpenMPRuntime::emitTargetDataStandAloneCall(
// Emit device ID if any.
llvm::Value *DeviceID = nullptr;
- if (Device)
+ if (Device) {
DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
- CGF.Int32Ty, /*isSigned=*/true);
- else
- DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF);
+ CGF.Int64Ty, /*isSigned=*/true);
+ } else {
+ DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
+ }
// Emit the number of elements in the offloading arrays.
auto *PointerNum = CGF.Builder.getInt32(BasePointers.size());
@@ -7415,19 +7581,23 @@ void CGOpenMPRuntime::emitTargetDataStandAloneCall(
auto &RT = CGF.CGM.getOpenMPRuntime();
// Select the right runtime function call for each expected standalone
// directive.
+ const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
OpenMPRTLFunction RTLFn;
switch (D.getDirectiveKind()) {
default:
llvm_unreachable("Unexpected standalone target data directive.");
break;
case OMPD_target_enter_data:
- RTLFn = OMPRTL__tgt_target_data_begin;
+ RTLFn = HasNowait ? OMPRTL__tgt_target_data_begin_nowait
+ : OMPRTL__tgt_target_data_begin;
break;
case OMPD_target_exit_data:
- RTLFn = OMPRTL__tgt_target_data_end;
+ RTLFn = HasNowait ? OMPRTL__tgt_target_data_end_nowait
+ : OMPRTL__tgt_target_data_end;
break;
case OMPD_target_update:
- RTLFn = OMPRTL__tgt_target_data_update;
+ RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait
+ : OMPRTL__tgt_target_data_update;
break;
}
CGF.EmitRuntimeCall(RT.createRuntimeFunction(RTLFn), OffloadingArgs);
@@ -7777,3 +7947,29 @@ void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
CGF.EmitRuntimeCall(RTLFn, Args);
}
+void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, llvm::Value *Callee,
+ ArrayRef<llvm::Value *> Args,
+ SourceLocation Loc) const {
+ auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc);
+
+ if (auto *Fn = dyn_cast<llvm::Function>(Callee)) {
+ if (Fn->doesNotThrow()) {
+ CGF.EmitNounwindRuntimeCall(Fn, Args);
+ return;
+ }
+ }
+ CGF.EmitRuntimeCall(Callee, Args);
+}
+
+void CGOpenMPRuntime::emitOutlinedFunctionCall(
+ CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *OutlinedFn,
+ ArrayRef<llvm::Value *> Args) const {
+ assert(Loc.isValid() && "Outlined function call location must be valid.");
+ emitCall(CGF, OutlinedFn, Args, Loc);
+}
+
+Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF,
+ const VarDecl *NativeParam,
+ const VarDecl *TargetParam) const {
+ return CGF.GetAddrOfLocalVar(NativeParam);
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h
index 185c01d5e5402..94a143841373a 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h
@@ -250,6 +250,11 @@ protected:
//
virtual StringRef getOutlinedHelperName() const { return ".omp_outlined."; }
+ /// Emits \p Callee function call with arguments \p Args with location \p Loc.
+ void emitCall(CodeGenFunction &CGF, llvm::Value *Callee,
+ ArrayRef<llvm::Value *> Args = llvm::None,
+ SourceLocation Loc = SourceLocation()) const;
+
private:
/// \brief Default const ident_t object used for initialization of all other
/// ident_t objects.
@@ -805,6 +810,35 @@ public:
unsigned IVSize, bool IVSigned, bool Ordered,
const DispatchRTInput &DispatchValues);
+ /// Struct with the values to be passed to the static runtime function
+ struct StaticRTInput {
+ /// Size of the iteration variable in bits.
+ unsigned IVSize = 0;
+ /// Sign of the iteration variable.
+ bool IVSigned = false;
+ /// true if loop is ordered, false otherwise.
+ bool Ordered = false;
+ /// Address of the output variable in which the flag of the last iteration
+ /// is returned.
+ Address IL = Address::invalid();
+ /// Address of the output variable in which the lower iteration number is
+ /// returned.
+ Address LB = Address::invalid();
+ /// Address of the output variable in which the upper iteration number is
+ /// returned.
+ Address UB = Address::invalid();
+ /// Address of the output variable in which the stride value is returned
+ /// necessary to generated the static_chunked scheduled loop.
+ Address ST = Address::invalid();
+ /// Value of the chunk for the static_chunked scheduled loop. For the
+ /// default (nullptr) value, the chunk 1 will be used.
+ llvm::Value *Chunk = nullptr;
+ StaticRTInput(unsigned IVSize, bool IVSigned, bool Ordered, Address IL,
+ Address LB, Address UB, Address ST,
+ llvm::Value *Chunk = nullptr)
+ : IVSize(IVSize), IVSigned(IVSigned), Ordered(Ordered), IL(IL), LB(LB),
+ UB(UB), ST(ST), Chunk(Chunk) {}
+ };
/// \brief Call the appropriate runtime routine to initialize it before start
/// of loop.
///
@@ -812,55 +846,29 @@ public:
/// specify a ordered clause on the loop construct.
/// Depending on the loop schedule, it is necessary to call some runtime
/// routine before start of the OpenMP loop to get the loop upper / lower
- /// bounds \a LB and \a UB and stride \a ST.
+ /// bounds LB and UB and stride ST.
///
/// \param CGF Reference to current CodeGenFunction.
/// \param Loc Clang source location.
+ /// \param DKind Kind of the directive.
/// \param ScheduleKind Schedule kind, specified by the 'schedule' clause.
- /// \param IVSize Size of the iteration variable in bits.
- /// \param IVSigned Sign of the iteration variable.
- /// \param Ordered true if loop is ordered, false otherwise.
- /// \param IL Address of the output variable in which the flag of the
- /// last iteration is returned.
- /// \param LB Address of the output variable in which the lower iteration
- /// number is returned.
- /// \param UB Address of the output variable in which the upper iteration
- /// number is returned.
- /// \param ST Address of the output variable in which the stride value is
- /// returned necessary to generated the static_chunked scheduled loop.
- /// \param Chunk Value of the chunk for the static_chunked scheduled loop.
- /// For the default (nullptr) value, the chunk 1 will be used.
+ /// \param Values Input arguments for the construct.
///
virtual void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc,
+ OpenMPDirectiveKind DKind,
const OpenMPScheduleTy &ScheduleKind,
- unsigned IVSize, bool IVSigned, bool Ordered,
- Address IL, Address LB, Address UB, Address ST,
- llvm::Value *Chunk = nullptr);
+ const StaticRTInput &Values);
///
/// \param CGF Reference to current CodeGenFunction.
/// \param Loc Clang source location.
/// \param SchedKind Schedule kind, specified by the 'dist_schedule' clause.
- /// \param IVSize Size of the iteration variable in bits.
- /// \param IVSigned Sign of the iteration variable.
- /// \param Ordered true if loop is ordered, false otherwise.
- /// \param IL Address of the output variable in which the flag of the
- /// last iteration is returned.
- /// \param LB Address of the output variable in which the lower iteration
- /// number is returned.
- /// \param UB Address of the output variable in which the upper iteration
- /// number is returned.
- /// \param ST Address of the output variable in which the stride value is
- /// returned necessary to generated the static_chunked scheduled loop.
- /// \param Chunk Value of the chunk for the static_chunked scheduled loop.
- /// For the default (nullptr) value, the chunk 1 will be used.
+ /// \param Values Input arguments for the construct.
///
- virtual void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc,
+ virtual void emitDistributeStaticInit(CodeGenFunction &CGF,
+ SourceLocation Loc,
OpenMPDistScheduleClauseKind SchedKind,
- unsigned IVSize, bool IVSigned,
- bool Ordered, Address IL, Address LB,
- Address UB, Address ST,
- llvm::Value *Chunk = nullptr);
+ const StaticRTInput &Values);
/// \brief Call the appropriate runtime routine to notify that we finished
/// iteration of the ordered loop with the dynamic scheduling.
@@ -879,8 +887,10 @@ public:
///
/// \param CGF Reference to current CodeGenFunction.
/// \param Loc Clang source location.
+ /// \param DKind Kind of the directive for which the static finish is emitted.
///
- virtual void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc);
+ virtual void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc,
+ OpenMPDirectiveKind DKind);
/// Call __kmpc_dispatch_next(
/// ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
@@ -1328,6 +1338,30 @@ public:
/// \param C 'depend' clause with 'sink|source' dependency kind.
virtual void emitDoacrossOrdered(CodeGenFunction &CGF,
const OMPDependClause *C);
+
+ /// Translates the native parameter of outlined function if this is required
+ /// for target.
+ /// \param FD Field decl from captured record for the paramater.
+ /// \param NativeParam Parameter itself.
+ virtual const VarDecl *translateParameter(const FieldDecl *FD,
+ const VarDecl *NativeParam) const {
+ return NativeParam;
+ }
+
+ /// Gets the address of the native argument basing on the address of the
+ /// target-specific parameter.
+ /// \param NativeParam Parameter itself.
+ /// \param TargetParam Corresponding target-specific parameter.
+ virtual Address getParameterAddress(CodeGenFunction &CGF,
+ const VarDecl *NativeParam,
+ const VarDecl *TargetParam) const;
+
+ /// Emits call of the outlined function with the provided arguments,
+ /// translating these arguments to correct target-specific arguments.
+ virtual void
+ emitOutlinedFunctionCall(CodeGenFunction &CGF, SourceLocation Loc,
+ llvm::Value *OutlinedFn,
+ ArrayRef<llvm::Value *> Args = llvm::None) const;
};
} // namespace CodeGen
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
index 3ced05d08a47c..b5fc8d308067e 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
@@ -22,19 +22,21 @@ using namespace CodeGen;
namespace {
enum OpenMPRTLFunctionNVPTX {
- /// \brief Call to void __kmpc_kernel_init(kmp_int32 thread_limit);
+ /// \brief Call to void __kmpc_kernel_init(kmp_int32 thread_limit,
+ /// int16_t RequiresOMPRuntime);
OMPRTL_NVPTX__kmpc_kernel_init,
- /// \brief Call to void __kmpc_kernel_deinit();
+ /// \brief Call to void __kmpc_kernel_deinit(int16_t IsOMPRuntimeInitialized);
OMPRTL_NVPTX__kmpc_kernel_deinit,
/// \brief Call to void __kmpc_spmd_kernel_init(kmp_int32 thread_limit,
- /// short RequiresOMPRuntime, short RequiresDataSharing);
+ /// int16_t RequiresOMPRuntime, int16_t RequiresDataSharing);
OMPRTL_NVPTX__kmpc_spmd_kernel_init,
/// \brief Call to void __kmpc_spmd_kernel_deinit();
OMPRTL_NVPTX__kmpc_spmd_kernel_deinit,
/// \brief Call to void __kmpc_kernel_prepare_parallel(void
- /// *outlined_function);
+ /// *outlined_function, void ***args, kmp_int32 nArgs);
OMPRTL_NVPTX__kmpc_kernel_prepare_parallel,
- /// \brief Call to bool __kmpc_kernel_parallel(void **outlined_function);
+ /// \brief Call to bool __kmpc_kernel_parallel(void **outlined_function, void
+ /// ***args);
OMPRTL_NVPTX__kmpc_kernel_parallel,
/// \brief Call to void __kmpc_kernel_end_parallel();
OMPRTL_NVPTX__kmpc_kernel_end_parallel,
@@ -150,20 +152,18 @@ enum NamedBarrier : unsigned {
/// Get the GPU warp size.
static llvm::Value *getNVPTXWarpSize(CodeGenFunction &CGF) {
- CGBuilderTy &Bld = CGF.Builder;
- return Bld.CreateCall(
+ return CGF.EmitRuntimeCall(
llvm::Intrinsic::getDeclaration(
&CGF.CGM.getModule(), llvm::Intrinsic::nvvm_read_ptx_sreg_warpsize),
- llvm::None, "nvptx_warp_size");
+ "nvptx_warp_size");
}
/// Get the id of the current thread on the GPU.
static llvm::Value *getNVPTXThreadID(CodeGenFunction &CGF) {
- CGBuilderTy &Bld = CGF.Builder;
- return Bld.CreateCall(
+ return CGF.EmitRuntimeCall(
llvm::Intrinsic::getDeclaration(
&CGF.CGM.getModule(), llvm::Intrinsic::nvvm_read_ptx_sreg_tid_x),
- llvm::None, "nvptx_tid");
+ "nvptx_tid");
}
/// Get the id of the warp in the block.
@@ -185,17 +185,15 @@ static llvm::Value *getNVPTXLaneID(CodeGenFunction &CGF) {
/// Get the maximum number of threads in a block of the GPU.
static llvm::Value *getNVPTXNumThreads(CodeGenFunction &CGF) {
- CGBuilderTy &Bld = CGF.Builder;
- return Bld.CreateCall(
+ return CGF.EmitRuntimeCall(
llvm::Intrinsic::getDeclaration(
&CGF.CGM.getModule(), llvm::Intrinsic::nvvm_read_ptx_sreg_ntid_x),
- llvm::None, "nvptx_num_threads");
+ "nvptx_num_threads");
}
/// Get barrier to synchronize all threads in a block.
static void getNVPTXCTABarrier(CodeGenFunction &CGF) {
- CGBuilderTy &Bld = CGF.Builder;
- Bld.CreateCall(llvm::Intrinsic::getDeclaration(
+ CGF.EmitRuntimeCall(llvm::Intrinsic::getDeclaration(
&CGF.CGM.getModule(), llvm::Intrinsic::nvvm_barrier0));
}
@@ -205,9 +203,9 @@ static void getNVPTXBarrier(CodeGenFunction &CGF, int ID,
llvm::Value *NumThreads) {
CGBuilderTy &Bld = CGF.Builder;
llvm::Value *Args[] = {Bld.getInt32(ID), NumThreads};
- Bld.CreateCall(llvm::Intrinsic::getDeclaration(&CGF.CGM.getModule(),
- llvm::Intrinsic::nvvm_barrier),
- Args);
+ CGF.EmitRuntimeCall(llvm::Intrinsic::getDeclaration(
+ &CGF.CGM.getModule(), llvm::Intrinsic::nvvm_barrier),
+ Args);
}
/// Synchronize all GPU threads in a block.
@@ -280,6 +278,8 @@ getExecutionModeForDirective(CodeGenModule &CGM,
case OMPD_target_teams:
return CGOpenMPRuntimeNVPTX::ExecutionMode::Generic;
case OMPD_target_parallel:
+ case OMPD_target_parallel_for:
+ case OMPD_target_parallel_for_simd:
return CGOpenMPRuntimeNVPTX::ExecutionMode::Spmd;
default:
llvm_unreachable("Unsupported directive on NVPTX device.");
@@ -298,6 +298,7 @@ void CGOpenMPRuntimeNVPTX::emitGenericKernel(const OMPExecutableDirective &D,
EntryFunctionState EST;
WorkerFunctionState WST(CGM);
Work.clear();
+ WrapperFunctionsMap.clear();
// Emit target region as a standalone region.
class NVPTXPrePostActionTy : public PrePostActionTy {
@@ -345,7 +346,7 @@ void CGOpenMPRuntimeNVPTX::emitGenericEntryHeader(CodeGenFunction &CGF,
Bld.CreateCondBr(IsWorker, WorkerBB, MasterCheckBB);
CGF.EmitBlock(WorkerBB);
- CGF.EmitCallOrInvoke(WST.WorkerFn, llvm::None);
+ emitCall(CGF, WST.WorkerFn);
CGF.EmitBranch(EST.ExitBB);
CGF.EmitBlock(MasterCheckBB);
@@ -356,7 +357,9 @@ void CGOpenMPRuntimeNVPTX::emitGenericEntryHeader(CodeGenFunction &CGF,
CGF.EmitBlock(MasterBB);
// First action in sequential region:
// Initialize the state of the OpenMP runtime library on the GPU.
- llvm::Value *Args[] = {getThreadLimit(CGF)};
+ // TODO: Optimize runtime initialization and pass in correct value.
+ llvm::Value *Args[] = {getThreadLimit(CGF),
+ Bld.getInt16(/*RequiresOMPRuntime=*/1)};
CGF.EmitRuntimeCall(
createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_kernel_init), Args);
}
@@ -371,8 +374,10 @@ void CGOpenMPRuntimeNVPTX::emitGenericEntryFooter(CodeGenFunction &CGF,
CGF.EmitBlock(TerminateBB);
// Signal termination condition.
+ // TODO: Optimize runtime initialization and pass in correct value.
+ llvm::Value *Args[] = {CGF.Builder.getInt16(/*IsOMPRuntimeInitialized=*/1)};
CGF.EmitRuntimeCall(
- createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_kernel_deinit), None);
+ createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_kernel_deinit), Args);
// Barrier to terminate worker threads.
syncCTAThreads(CGF);
// Master thread jumps to exit point.
@@ -413,7 +418,6 @@ void CGOpenMPRuntimeNVPTX::emitSpmdKernel(const OMPExecutableDirective &D,
CodeGen.setAction(Action);
emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID,
IsOffloadEntry, CodeGen);
- return;
}
void CGOpenMPRuntimeNVPTX::emitSpmdEntryHeader(
@@ -471,7 +475,7 @@ static void setPropertyExecutionMode(CodeGenModule &CGM, StringRef Name,
}
void CGOpenMPRuntimeNVPTX::emitWorkerFunction(WorkerFunctionState &WST) {
- auto &Ctx = CGM.getContext();
+ ASTContext &Ctx = CGM.getContext();
CodeGenFunction CGF(CGM, /*suppressNewContext=*/true);
CGF.disableDebugInfo();
@@ -514,7 +518,10 @@ void CGOpenMPRuntimeNVPTX::emitWorkerLoop(CodeGenFunction &CGF,
CGF.InitTempAlloca(ExecStatus, Bld.getInt8(/*C=*/0));
CGF.InitTempAlloca(WorkFn, llvm::Constant::getNullValue(CGF.Int8PtrTy));
- llvm::Value *Args[] = {WorkFn.getPointer()};
+ // Set up shared arguments
+ Address SharedArgs =
+ CGF.CreateDefaultAlignTempAlloca(CGF.Int8PtrPtrTy, "shared_args");
+ llvm::Value *Args[] = {WorkFn.getPointer(), SharedArgs.getPointer()};
llvm::Value *Ret = CGF.EmitRuntimeCall(
createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_kernel_parallel), Args);
Bld.CreateStore(Bld.CreateZExt(Ret, CGF.Int8Ty), ExecStatus);
@@ -533,6 +540,9 @@ void CGOpenMPRuntimeNVPTX::emitWorkerLoop(CodeGenFunction &CGF,
// Signal start of parallel region.
CGF.EmitBlock(ExecuteBB);
+ // Current context
+ ASTContext &Ctx = CGF.getContext();
+
// Process work items: outlined parallel functions.
for (auto *W : Work) {
// Try to match this outlined function.
@@ -548,14 +558,18 @@ void CGOpenMPRuntimeNVPTX::emitWorkerLoop(CodeGenFunction &CGF,
// Execute this outlined function.
CGF.EmitBlock(ExecuteFNBB);
- // Insert call to work function.
- // FIXME: Pass arguments to outlined function from master thread.
- auto *Fn = cast<llvm::Function>(W);
- Address ZeroAddr =
- CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, /*Name=*/".zero.addr");
- CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C=*/0));
- llvm::Value *FnArgs[] = {ZeroAddr.getPointer(), ZeroAddr.getPointer()};
- CGF.EmitCallOrInvoke(Fn, FnArgs);
+ // Insert call to work function via shared wrapper. The shared
+ // wrapper takes exactly three arguments:
+ // - the parallelism level;
+ // - the master thread ID;
+ // - the list of references to shared arguments.
+ //
+ // TODO: Assert that the function is a wrapper function.s
+ Address Capture = CGF.EmitLoadOfPointer(SharedArgs,
+ Ctx.getPointerType(
+ Ctx.getPointerType(Ctx.VoidPtrTy)).castAs<PointerType>());
+ emitCall(CGF, W, {Bld.getInt16(/*ParallelLevel=*/0),
+ getMasterThreadID(CGF), Capture.getPointer()});
// Go to end of parallel region.
CGF.EmitBranch(TerminateBB);
@@ -589,23 +603,25 @@ CGOpenMPRuntimeNVPTX::createNVPTXRuntimeFunction(unsigned Function) {
llvm::Constant *RTLFn = nullptr;
switch (static_cast<OpenMPRTLFunctionNVPTX>(Function)) {
case OMPRTL_NVPTX__kmpc_kernel_init: {
- // Build void __kmpc_kernel_init(kmp_int32 thread_limit);
- llvm::Type *TypeParams[] = {CGM.Int32Ty};
+ // Build void __kmpc_kernel_init(kmp_int32 thread_limit, int16_t
+ // RequiresOMPRuntime);
+ llvm::Type *TypeParams[] = {CGM.Int32Ty, CGM.Int16Ty};
llvm::FunctionType *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_kernel_init");
break;
}
case OMPRTL_NVPTX__kmpc_kernel_deinit: {
- // Build void __kmpc_kernel_deinit();
+ // Build void __kmpc_kernel_deinit(int16_t IsOMPRuntimeInitialized);
+ llvm::Type *TypeParams[] = {CGM.Int16Ty};
llvm::FunctionType *FnTy =
- llvm::FunctionType::get(CGM.VoidTy, llvm::None, /*isVarArg*/ false);
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_kernel_deinit");
break;
}
case OMPRTL_NVPTX__kmpc_spmd_kernel_init: {
// Build void __kmpc_spmd_kernel_init(kmp_int32 thread_limit,
- // short RequiresOMPRuntime, short RequiresDataSharing);
+ // int16_t RequiresOMPRuntime, int16_t RequiresDataSharing);
llvm::Type *TypeParams[] = {CGM.Int32Ty, CGM.Int16Ty, CGM.Int16Ty};
llvm::FunctionType *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
@@ -621,16 +637,18 @@ CGOpenMPRuntimeNVPTX::createNVPTXRuntimeFunction(unsigned Function) {
}
case OMPRTL_NVPTX__kmpc_kernel_prepare_parallel: {
/// Build void __kmpc_kernel_prepare_parallel(
- /// void *outlined_function);
- llvm::Type *TypeParams[] = {CGM.Int8PtrTy};
+ /// void *outlined_function, void ***args, kmp_int32 nArgs);
+ llvm::Type *TypeParams[] = {CGM.Int8PtrTy,
+ CGM.Int8PtrPtrTy->getPointerTo(0), CGM.Int32Ty};
llvm::FunctionType *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_kernel_prepare_parallel");
break;
}
case OMPRTL_NVPTX__kmpc_kernel_parallel: {
- /// Build bool __kmpc_kernel_parallel(void **outlined_function);
- llvm::Type *TypeParams[] = {CGM.Int8PtrPtrTy};
+ /// Build bool __kmpc_kernel_parallel(void **outlined_function, void ***args);
+ llvm::Type *TypeParams[] = {CGM.Int8PtrPtrTy,
+ CGM.Int8PtrPtrTy->getPointerTo(0)};
llvm::Type *RetTy = CGM.getTypes().ConvertType(CGM.getContext().BoolTy);
llvm::FunctionType *FnTy =
llvm::FunctionType::get(RetTy, TypeParams, /*isVarArg*/ false);
@@ -849,8 +867,17 @@ void CGOpenMPRuntimeNVPTX::emitNumTeamsClause(CodeGenFunction &CGF,
llvm::Value *CGOpenMPRuntimeNVPTX::emitParallelOutlinedFunction(
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
- return CGOpenMPRuntime::emitParallelOutlinedFunction(D, ThreadIDVar,
- InnermostKind, CodeGen);
+
+ auto *OutlinedFun = cast<llvm::Function>(
+ CGOpenMPRuntime::emitParallelOutlinedFunction(
+ D, ThreadIDVar, InnermostKind, CodeGen));
+ if (!isInSpmdExecutionMode()) {
+ llvm::Function *WrapperFun =
+ createDataSharingWrapper(OutlinedFun, D);
+ WrapperFunctionsMap[OutlinedFun] = WrapperFun;
+ }
+
+ return OutlinedFun;
}
llvm::Value *CGOpenMPRuntimeNVPTX::emitTeamsOutlinedFunction(
@@ -883,7 +910,7 @@ void CGOpenMPRuntimeNVPTX::emitTeamsCall(CodeGenFunction &CGF,
OutlinedFnArgs.push_back(ZeroAddr.getPointer());
OutlinedFnArgs.push_back(ZeroAddr.getPointer());
OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
- CGF.EmitCallOrInvoke(OutlinedFn, OutlinedFnArgs);
+ emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs);
}
void CGOpenMPRuntimeNVPTX::emitParallelCall(
@@ -902,15 +929,54 @@ void CGOpenMPRuntimeNVPTX::emitGenericParallelCall(
CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *OutlinedFn,
ArrayRef<llvm::Value *> CapturedVars, const Expr *IfCond) {
llvm::Function *Fn = cast<llvm::Function>(OutlinedFn);
+ llvm::Function *WFn = WrapperFunctionsMap[Fn];
+ assert(WFn && "Wrapper function does not exist!");
+
+ // Force inline this outlined function at its call site.
+ Fn->setLinkage(llvm::GlobalValue::InternalLinkage);
- auto &&L0ParallelGen = [this, Fn](CodeGenFunction &CGF, PrePostActionTy &) {
+ auto &&L0ParallelGen = [this, WFn, &CapturedVars](CodeGenFunction &CGF,
+ PrePostActionTy &) {
CGBuilderTy &Bld = CGF.Builder;
- // Prepare for parallel region. Indicate the outlined function.
- llvm::Value *Args[] = {Bld.CreateBitOrPointerCast(Fn, CGM.Int8PtrTy)};
- CGF.EmitRuntimeCall(
- createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_kernel_prepare_parallel),
- Args);
+ llvm::Value *ID = Bld.CreateBitOrPointerCast(WFn, CGM.Int8PtrTy);
+
+ if (!CapturedVars.empty()) {
+ // There's somehting to share, add the attribute
+ CGF.CurFn->addFnAttr("has-nvptx-shared-depot");
+ // Prepare for parallel region. Indicate the outlined function.
+ Address SharedArgs =
+ CGF.CreateDefaultAlignTempAlloca(CGF.VoidPtrPtrTy,
+ "shared_args");
+ llvm::Value *SharedArgsPtr = SharedArgs.getPointer();
+ llvm::Value *Args[] = {ID, SharedArgsPtr,
+ Bld.getInt32(CapturedVars.size())};
+
+ CGF.EmitRuntimeCall(
+ createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_kernel_prepare_parallel),
+ Args);
+
+ unsigned Idx = 0;
+ ASTContext &Ctx = CGF.getContext();
+ for (llvm::Value *V : CapturedVars) {
+ Address Dst = Bld.CreateConstInBoundsGEP(
+ CGF.EmitLoadOfPointer(SharedArgs,
+ Ctx.getPointerType(
+ Ctx.getPointerType(Ctx.VoidPtrTy)).castAs<PointerType>()),
+ Idx, CGF.getPointerSize());
+ llvm::Value *PtrV = Bld.CreateBitCast(V, CGF.VoidPtrTy);
+ CGF.EmitStoreOfScalar(PtrV, Dst, /*Volatile=*/false,
+ Ctx.getPointerType(Ctx.VoidPtrTy));
+ Idx++;
+ }
+ } else {
+ llvm::Value *Args[] = {ID,
+ llvm::ConstantPointerNull::get(CGF.VoidPtrPtrTy->getPointerTo(0)),
+ /*nArgs=*/Bld.getInt32(0)};
+ CGF.EmitRuntimeCall(
+ createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_kernel_prepare_parallel),
+ Args);
+ }
// Activate workers. This barrier is used by the master to signal
// work for the workers.
@@ -925,17 +991,17 @@ void CGOpenMPRuntimeNVPTX::emitGenericParallelCall(
syncCTAThreads(CGF);
// Remember for post-processing in worker loop.
- Work.push_back(Fn);
+ Work.emplace_back(WFn);
};
auto *RTLoc = emitUpdateLocation(CGF, Loc);
auto *ThreadID = getThreadID(CGF, Loc);
llvm::Value *Args[] = {RTLoc, ThreadID};
- auto &&SeqGen = [this, Fn, &CapturedVars, &Args](CodeGenFunction &CGF,
- PrePostActionTy &) {
- auto &&CodeGen = [this, Fn, &CapturedVars](CodeGenFunction &CGF,
- PrePostActionTy &Action) {
+ auto &&SeqGen = [this, Fn, &CapturedVars, &Args, Loc](CodeGenFunction &CGF,
+ PrePostActionTy &) {
+ auto &&CodeGen = [this, Fn, &CapturedVars, Loc](CodeGenFunction &CGF,
+ PrePostActionTy &Action) {
Action.Enter(CGF);
llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
@@ -944,7 +1010,7 @@ void CGOpenMPRuntimeNVPTX::emitGenericParallelCall(
OutlinedFnArgs.push_back(
llvm::ConstantPointerNull::get(CGM.Int32Ty->getPointerTo()));
OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
- CGF.EmitCallOrInvoke(Fn, OutlinedFnArgs);
+ emitOutlinedFunctionCall(CGF, Loc, Fn, OutlinedFnArgs);
};
RegionCodeGenTy RCG(CodeGen);
@@ -980,7 +1046,7 @@ void CGOpenMPRuntimeNVPTX::emitSpmdParallelCall(
OutlinedFnArgs.push_back(
llvm::ConstantPointerNull::get(CGM.Int32Ty->getPointerTo()));
OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
- CGF.EmitCallOrInvoke(OutlinedFn, OutlinedFnArgs);
+ emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs);
}
/// This function creates calls to one of two shuffle functions to copy
@@ -2238,3 +2304,183 @@ void CGOpenMPRuntimeNVPTX::emitReduction(
CGF.EmitBranch(DefaultBB);
CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
}
+
+const VarDecl *
+CGOpenMPRuntimeNVPTX::translateParameter(const FieldDecl *FD,
+ const VarDecl *NativeParam) const {
+ if (!NativeParam->getType()->isReferenceType())
+ return NativeParam;
+ QualType ArgType = NativeParam->getType();
+ QualifierCollector QC;
+ const Type *NonQualTy = QC.strip(ArgType);
+ QualType PointeeTy = cast<ReferenceType>(NonQualTy)->getPointeeType();
+ if (const auto *Attr = FD->getAttr<OMPCaptureKindAttr>()) {
+ if (Attr->getCaptureKind() == OMPC_map) {
+ PointeeTy = CGM.getContext().getAddrSpaceQualType(PointeeTy,
+ LangAS::opencl_global);
+ }
+ }
+ ArgType = CGM.getContext().getPointerType(PointeeTy);
+ QC.addRestrict();
+ enum { NVPTX_local_addr = 5 };
+ QC.addAddressSpace(getLangASFromTargetAS(NVPTX_local_addr));
+ ArgType = QC.apply(CGM.getContext(), ArgType);
+ if (isa<ImplicitParamDecl>(NativeParam)) {
+ return ImplicitParamDecl::Create(
+ CGM.getContext(), /*DC=*/nullptr, NativeParam->getLocation(),
+ NativeParam->getIdentifier(), ArgType, ImplicitParamDecl::Other);
+ }
+ return ParmVarDecl::Create(
+ CGM.getContext(),
+ const_cast<DeclContext *>(NativeParam->getDeclContext()),
+ NativeParam->getLocStart(), NativeParam->getLocation(),
+ NativeParam->getIdentifier(), ArgType,
+ /*TInfo=*/nullptr, SC_None, /*DefArg=*/nullptr);
+}
+
+Address
+CGOpenMPRuntimeNVPTX::getParameterAddress(CodeGenFunction &CGF,
+ const VarDecl *NativeParam,
+ const VarDecl *TargetParam) const {
+ assert(NativeParam != TargetParam &&
+ NativeParam->getType()->isReferenceType() &&
+ "Native arg must not be the same as target arg.");
+ Address LocalAddr = CGF.GetAddrOfLocalVar(TargetParam);
+ QualType NativeParamType = NativeParam->getType();
+ QualifierCollector QC;
+ const Type *NonQualTy = QC.strip(NativeParamType);
+ QualType NativePointeeTy = cast<ReferenceType>(NonQualTy)->getPointeeType();
+ unsigned NativePointeeAddrSpace =
+ CGF.getContext().getTargetAddressSpace(NativePointeeTy);
+ QualType TargetTy = TargetParam->getType();
+ llvm::Value *TargetAddr = CGF.EmitLoadOfScalar(
+ LocalAddr, /*Volatile=*/false, TargetTy, SourceLocation());
+ // First cast to generic.
+ TargetAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ TargetAddr, TargetAddr->getType()->getPointerElementType()->getPointerTo(
+ /*AddrSpace=*/0));
+ // Cast from generic to native address space.
+ TargetAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ TargetAddr, TargetAddr->getType()->getPointerElementType()->getPointerTo(
+ NativePointeeAddrSpace));
+ Address NativeParamAddr = CGF.CreateMemTemp(NativeParamType);
+ CGF.EmitStoreOfScalar(TargetAddr, NativeParamAddr, /*Volatile=*/false,
+ NativeParamType);
+ return NativeParamAddr;
+}
+
+void CGOpenMPRuntimeNVPTX::emitOutlinedFunctionCall(
+ CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *OutlinedFn,
+ ArrayRef<llvm::Value *> Args) const {
+ SmallVector<llvm::Value *, 4> TargetArgs;
+ TargetArgs.reserve(Args.size());
+ auto *FnType =
+ cast<llvm::FunctionType>(OutlinedFn->getType()->getPointerElementType());
+ for (unsigned I = 0, E = Args.size(); I < E; ++I) {
+ if (FnType->isVarArg() && FnType->getNumParams() <= I) {
+ TargetArgs.append(std::next(Args.begin(), I), Args.end());
+ break;
+ }
+ llvm::Type *TargetType = FnType->getParamType(I);
+ llvm::Value *NativeArg = Args[I];
+ if (!TargetType->isPointerTy()) {
+ TargetArgs.emplace_back(NativeArg);
+ continue;
+ }
+ llvm::Value *TargetArg = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ NativeArg, NativeArg->getType()->getPointerElementType()->getPointerTo(
+ /*AddrSpace=*/0));
+ TargetArgs.emplace_back(
+ CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TargetArg, TargetType));
+ }
+ CGOpenMPRuntime::emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, TargetArgs);
+}
+
+/// Emit function which wraps the outline parallel region
+/// and controls the arguments which are passed to this function.
+/// The wrapper ensures that the outlined function is called
+/// with the correct arguments when data is shared.
+llvm::Function *CGOpenMPRuntimeNVPTX::createDataSharingWrapper(
+ llvm::Function *OutlinedParallelFn, const OMPExecutableDirective &D) {
+ ASTContext &Ctx = CGM.getContext();
+ const auto &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
+
+ // Create a function that takes as argument the source thread.
+ FunctionArgList WrapperArgs;
+ QualType Int16QTy =
+ Ctx.getIntTypeForBitwidth(/*DestWidth=*/16, /*Signed=*/false);
+ QualType Int32QTy =
+ Ctx.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false);
+ QualType Int32PtrQTy = Ctx.getPointerType(Int32QTy);
+ QualType VoidPtrPtrQTy = Ctx.getPointerType(Ctx.VoidPtrTy);
+ ImplicitParamDecl ParallelLevelArg(Ctx, Int16QTy, ImplicitParamDecl::Other);
+ ImplicitParamDecl WrapperArg(Ctx, Int32QTy, ImplicitParamDecl::Other);
+ ImplicitParamDecl SharedArgsList(Ctx, VoidPtrPtrQTy,
+ ImplicitParamDecl::Other);
+ WrapperArgs.emplace_back(&ParallelLevelArg);
+ WrapperArgs.emplace_back(&WrapperArg);
+ WrapperArgs.emplace_back(&SharedArgsList);
+
+ auto &CGFI =
+ CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, WrapperArgs);
+
+ auto *Fn = llvm::Function::Create(
+ CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
+ OutlinedParallelFn->getName() + "_wrapper", &CGM.getModule());
+ CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI);
+ Fn->setLinkage(llvm::GlobalValue::InternalLinkage);
+
+ CodeGenFunction CGF(CGM, /*suppressNewContext=*/true);
+ CGF.StartFunction(GlobalDecl(), Ctx.VoidTy, Fn, CGFI, WrapperArgs);
+
+ const auto *RD = CS.getCapturedRecordDecl();
+ auto CurField = RD->field_begin();
+
+ // Get the array of arguments.
+ SmallVector<llvm::Value *, 8> Args;
+
+ // TODO: suppport SIMD and pass actual values
+ Args.emplace_back(llvm::ConstantPointerNull::get(
+ CGM.Int32Ty->getPointerTo()));
+ Args.emplace_back(llvm::ConstantPointerNull::get(
+ CGM.Int32Ty->getPointerTo()));
+
+ CGBuilderTy &Bld = CGF.Builder;
+ auto CI = CS.capture_begin();
+
+ // Load the start of the array
+ auto SharedArgs =
+ CGF.EmitLoadOfPointer(CGF.GetAddrOfLocalVar(&SharedArgsList),
+ VoidPtrPtrQTy->castAs<PointerType>());
+
+ // For each captured variable
+ for (unsigned I = 0; I < CS.capture_size(); ++I, ++CI, ++CurField) {
+ // Name of captured variable
+ StringRef Name;
+ if (CI->capturesThis())
+ Name = "this";
+ else
+ Name = CI->getCapturedVar()->getName();
+
+ // We retrieve the CLANG type of the argument. We use it to create
+ // an alloca which will give us the LLVM type.
+ QualType ElemTy = CurField->getType();
+ // If this is a capture by copy the element type has to be the pointer to
+ // the data.
+ if (CI->capturesVariableByCopy())
+ ElemTy = Ctx.getPointerType(ElemTy);
+
+ // Get shared address of the captured variable.
+ Address ArgAddress = Bld.CreateConstInBoundsGEP(
+ SharedArgs, I, CGF.getPointerSize());
+ Address TypedArgAddress = Bld.CreateBitCast(
+ ArgAddress, CGF.ConvertTypeForMem(Ctx.getPointerType(ElemTy)));
+ llvm::Value *Arg = CGF.EmitLoadOfScalar(TypedArgAddress,
+ /*Volatile=*/false, Int32PtrQTy, SourceLocation());
+ Args.emplace_back(Arg);
+ }
+
+ emitCall(CGF, OutlinedParallelFn, Args);
+ CGF.FinishFunction();
+ return Fn;
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.h b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.h
index ae25e94759e6a..5d13408318a55 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.h
@@ -268,6 +268,26 @@ public:
/// \return Specified function.
llvm::Constant *createNVPTXRuntimeFunction(unsigned Function);
+ /// Translates the native parameter of outlined function if this is required
+ /// for target.
+ /// \param FD Field decl from captured record for the paramater.
+ /// \param NativeParam Parameter itself.
+ const VarDecl *translateParameter(const FieldDecl *FD,
+ const VarDecl *NativeParam) const override;
+
+ /// Gets the address of the native argument basing on the address of the
+ /// target-specific parameter.
+ /// \param NativeParam Parameter itself.
+ /// \param TargetParam Corresponding target-specific parameter.
+ Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam,
+ const VarDecl *TargetParam) const override;
+
+ /// Emits call of the outlined function with the provided arguments,
+ /// translating these arguments to correct target-specific arguments.
+ void emitOutlinedFunctionCall(
+ CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *OutlinedFn,
+ ArrayRef<llvm::Value *> Args = llvm::None) const override;
+
/// Target codegen is specialized based on two programming models: the
/// 'generic' fork-join model of OpenMP, and a more GPU efficient 'spmd'
/// model for constructs like 'target parallel' that support it.
@@ -285,6 +305,17 @@ private:
// target region and used by containing directives such as 'parallel'
// to emit optimized code.
ExecutionMode CurrentExecutionMode;
+
+ /// Map between an outlined function and its wrapper.
+ llvm::DenseMap<llvm::Function *, llvm::Function *> WrapperFunctionsMap;
+
+ /// Emit function which wraps the outline parallel region
+ /// and controls the parameters which are passed to this function.
+ /// The wrapper ensures that the outlined function is called
+ /// with the correct arguments when data is shared.
+ llvm::Function *
+ createDataSharingWrapper(llvm::Function *OutlinedParallelFn,
+ const OMPExecutableDirective &D);
};
} // CodeGen namespace.
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
index 7d530a278fbf0..1644ab4c07255 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -403,6 +403,27 @@ CGRecordLowering::accumulateBitFields(RecordDecl::field_iterator Field,
}
return;
}
+
+ // Check if current Field is better as a single field run. When current field
+ // has legal integer width, and its bitfield offset is naturally aligned, it
+ // is better to make the bitfield a separate storage component so as it can be
+ // accessed directly with lower cost.
+ auto IsBetterAsSingleFieldRun = [&](RecordDecl::field_iterator Field) {
+ if (!Types.getCodeGenOpts().FineGrainedBitfieldAccesses)
+ return false;
+ unsigned Width = Field->getBitWidthValue(Context);
+ if (!DataLayout.isLegalInteger(Width))
+ return false;
+ // Make sure Field is natually aligned if it is treated as an IType integer.
+ if (getFieldBitOffset(*Field) %
+ Context.toBits(getAlignment(getIntNType(Width))) !=
+ 0)
+ return false;
+ return true;
+ };
+
+ // The start field is better as a single field run.
+ bool StartFieldAsSingleRun = false;
for (;;) {
// Check to see if we need to start a new run.
if (Run == FieldEnd) {
@@ -414,17 +435,28 @@ CGRecordLowering::accumulateBitFields(RecordDecl::field_iterator Field,
Run = Field;
StartBitOffset = getFieldBitOffset(*Field);
Tail = StartBitOffset + Field->getBitWidthValue(Context);
+ StartFieldAsSingleRun = IsBetterAsSingleFieldRun(Run);
}
++Field;
continue;
}
- // Add bitfields to the run as long as they qualify.
- if (Field != FieldEnd && Field->getBitWidthValue(Context) != 0 &&
+
+ // If the start field of a new run is better as a single run, or
+ // if current field is better as a single run, or
+ // if current field has zero width bitfield, or
+ // if the offset of current field is inconsistent with the offset of
+ // previous field plus its offset,
+ // skip the block below and go ahead to emit the storage.
+ // Otherwise, try to add bitfields to the run.
+ if (!StartFieldAsSingleRun && Field != FieldEnd &&
+ !IsBetterAsSingleFieldRun(Field) &&
+ Field->getBitWidthValue(Context) != 0 &&
Tail == getFieldBitOffset(*Field)) {
Tail += Field->getBitWidthValue(Context);
++Field;
continue;
}
+
// We've hit a break-point in the run and need to emit a storage field.
llvm::Type *Type = getIntNType(Tail - StartBitOffset);
// Add the storage member to the record and set the bitfield info for all of
@@ -435,6 +467,7 @@ CGRecordLowering::accumulateBitFields(RecordDecl::field_iterator Field,
Members.push_back(MemberInfo(bitsToCharUnits(StartBitOffset),
MemberInfo::Field, nullptr, *Run));
Run = FieldEnd;
+ StartFieldAsSingleRun = false;
}
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp
index a13c386461647..91fa49a46ef1e 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp
@@ -45,7 +45,7 @@ void CodeGenFunction::EmitStopPoint(const Stmt *S) {
}
}
-void CodeGenFunction::EmitStmt(const Stmt *S) {
+void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) {
assert(S && "Null statement?");
PGO.setCurrentStmt(S);
@@ -131,16 +131,16 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
case Stmt::IndirectGotoStmtClass:
EmitIndirectGotoStmt(cast<IndirectGotoStmt>(*S)); break;
- case Stmt::IfStmtClass: EmitIfStmt(cast<IfStmt>(*S)); break;
- case Stmt::WhileStmtClass: EmitWhileStmt(cast<WhileStmt>(*S)); break;
- case Stmt::DoStmtClass: EmitDoStmt(cast<DoStmt>(*S)); break;
- case Stmt::ForStmtClass: EmitForStmt(cast<ForStmt>(*S)); break;
+ case Stmt::IfStmtClass: EmitIfStmt(cast<IfStmt>(*S)); break;
+ case Stmt::WhileStmtClass: EmitWhileStmt(cast<WhileStmt>(*S), Attrs); break;
+ case Stmt::DoStmtClass: EmitDoStmt(cast<DoStmt>(*S), Attrs); break;
+ case Stmt::ForStmtClass: EmitForStmt(cast<ForStmt>(*S), Attrs); break;
- case Stmt::ReturnStmtClass: EmitReturnStmt(cast<ReturnStmt>(*S)); break;
+ case Stmt::ReturnStmtClass: EmitReturnStmt(cast<ReturnStmt>(*S)); break;
- case Stmt::SwitchStmtClass: EmitSwitchStmt(cast<SwitchStmt>(*S)); break;
- case Stmt::GCCAsmStmtClass: // Intentional fall-through.
- case Stmt::MSAsmStmtClass: EmitAsmStmt(cast<AsmStmt>(*S)); break;
+ case Stmt::SwitchStmtClass: EmitSwitchStmt(cast<SwitchStmt>(*S)); break;
+ case Stmt::GCCAsmStmtClass: // Intentional fall-through.
+ case Stmt::MSAsmStmtClass: EmitAsmStmt(cast<AsmStmt>(*S)); break;
case Stmt::CoroutineBodyStmtClass:
EmitCoroutineBody(cast<CoroutineBodyStmt>(*S));
break;
@@ -178,7 +178,7 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
EmitCXXTryStmt(cast<CXXTryStmt>(*S));
break;
case Stmt::CXXForRangeStmtClass:
- EmitCXXForRangeStmt(cast<CXXForRangeStmt>(*S));
+ EmitCXXForRangeStmt(cast<CXXForRangeStmt>(*S), Attrs);
break;
case Stmt::SEHTryStmtClass:
EmitSEHTryStmt(cast<SEHTryStmt>(*S));
@@ -555,23 +555,7 @@ void CodeGenFunction::EmitLabelStmt(const LabelStmt &S) {
}
void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) {
- const Stmt *SubStmt = S.getSubStmt();
- switch (SubStmt->getStmtClass()) {
- case Stmt::DoStmtClass:
- EmitDoStmt(cast<DoStmt>(*SubStmt), S.getAttrs());
- break;
- case Stmt::ForStmtClass:
- EmitForStmt(cast<ForStmt>(*SubStmt), S.getAttrs());
- break;
- case Stmt::WhileStmtClass:
- EmitWhileStmt(cast<WhileStmt>(*SubStmt), S.getAttrs());
- break;
- case Stmt::CXXForRangeStmtClass:
- EmitCXXForRangeStmt(cast<CXXForRangeStmt>(*SubStmt), S.getAttrs());
- break;
- default:
- EmitStmt(SubStmt);
- }
+ EmitStmt(S.getSubStmt(), S.getAttrs());
}
void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) {
@@ -2165,10 +2149,11 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
llvm::ConstantAsMetadata::get(Loc)));
}
- if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice) {
- // Conservatively, mark all inline asm blocks in CUDA as convergent
- // (meaning, they may call an intrinsically convergent op, such as bar.sync,
- // and so can't have certain optimizations applied around them).
+ if (getLangOpts().assumeFunctionsAreConvergent()) {
+ // Conservatively, mark all inline asm blocks in CUDA or OpenCL as
+ // convergent (meaning, they may call an intrinsically convergent op, such
+ // as bar.sync, and so can't have certain optimizations applied around
+ // them).
Result->addAttribute(llvm::AttributeList::FunctionIndex,
llvm::Attribute::Convergent);
}
@@ -2210,7 +2195,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
llvm::IntegerType::get(getLLVMContext(), (unsigned)TmpSize));
Tmp = Builder.CreateTrunc(Tmp, TruncTy);
} else if (TruncTy->isIntegerTy()) {
- Tmp = Builder.CreateTrunc(Tmp, TruncTy);
+ Tmp = Builder.CreateZExtOrTrunc(Tmp, TruncTy);
} else if (TruncTy->isVectorTy()) {
Tmp = Builder.CreateBitCast(Tmp, TruncTy);
}
@@ -2283,7 +2268,6 @@ CodeGenFunction::GenerateCapturedStmtFunction(const CapturedStmt &S) {
Args.append(CD->param_begin(), CD->param_end());
// Create the function declaration.
- FunctionType::ExtInfo ExtInfo;
const CGFunctionInfo &FuncInfo =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Args);
llvm::FunctionType *FuncLLVMTy = CGM.getTypes().GetFunctionType(FuncInfo);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp
index cf430f860fd8a..f04d28ed0d4a9 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -65,6 +65,8 @@ public:
for (auto &C : CS->captures()) {
if (C.capturesVariable() || C.capturesVariableByCopy()) {
auto *VD = C.getCapturedVar();
+ assert(VD == VD->getCanonicalDecl() &&
+ "Canonical decl must be captured.");
DeclRefExpr DRE(const_cast<VarDecl *>(VD),
isCapturedVar(CGF, VD) ||
(CGF.CapturedStmtInfo &&
@@ -119,6 +121,14 @@ public:
/// of used expression from loop statement.
class OMPLoopScope : public CodeGenFunction::RunCleanupsScope {
void emitPreInitStmt(CodeGenFunction &CGF, const OMPLoopDirective &S) {
+ CodeGenFunction::OMPPrivateScope PreCondScope(CGF);
+ for (auto *E : S.counters()) {
+ const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
+ (void)PreCondScope.addPrivate(VD, [&CGF, VD]() {
+ return CGF.CreateMemTemp(VD->getType().getNonReferenceType());
+ });
+ }
+ (void)PreCondScope.Privatize();
if (auto *LD = dyn_cast<OMPLoopDirective>(&S)) {
if (auto *PreInits = cast_or_null<DeclStmt>(LD->getPreInits())) {
for (const auto *I : PreInits->decls())
@@ -136,6 +146,26 @@ public:
} // namespace
+static void emitCommonOMPTargetDirective(CodeGenFunction &CGF,
+ const OMPExecutableDirective &S,
+ const RegionCodeGenTy &CodeGen);
+
+LValue CodeGenFunction::EmitOMPSharedLValue(const Expr *E) {
+ if (auto *OrigDRE = dyn_cast<DeclRefExpr>(E)) {
+ if (auto *OrigVD = dyn_cast<VarDecl>(OrigDRE->getDecl())) {
+ OrigVD = OrigVD->getCanonicalDecl();
+ bool IsCaptured =
+ LambdaCaptureFields.lookup(OrigVD) ||
+ (CapturedStmtInfo && CapturedStmtInfo->lookup(OrigVD)) ||
+ (CurCodeDecl && isa<BlockDecl>(CurCodeDecl));
+ DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD), IsCaptured,
+ OrigDRE->getType(), VK_LValue, OrigDRE->getExprLoc());
+ return EmitLValue(&DRE);
+ }
+ }
+ return EmitLValue(E);
+}
+
llvm::Value *CodeGenFunction::getTypeSize(QualType Ty) {
auto &C = getContext();
llvm::Value *Size = nullptr;
@@ -236,6 +266,12 @@ static QualType getCanonicalParamType(ASTContext &C, QualType T) {
}
if (T->isPointerType())
return C.getPointerType(getCanonicalParamType(C, T->getPointeeType()));
+ if (auto *A = T->getAsArrayTypeUnsafe()) {
+ if (auto *VLA = dyn_cast<VariableArrayType>(A))
+ return getCanonicalParamType(C, VLA->getElementType());
+ else if (!A->isVariablyModifiedType())
+ return C.getCanonicalType(T);
+ }
return C.getCanonicalParamType(T);
}
@@ -246,12 +282,12 @@ namespace {
const CapturedStmt *S = nullptr;
/// true if cast to/from UIntPtr is required for variables captured by
/// value.
- bool UIntPtrCastRequired = true;
- /// true if only casted argumefnts must be registered as local args or VLA
+ const bool UIntPtrCastRequired = true;
+ /// true if only casted arguments must be registered as local args or VLA
/// sizes.
- bool RegisterCastedArgsOnly = false;
+ const bool RegisterCastedArgsOnly = false;
/// Name of the generated function.
- StringRef FunctionName;
+ const StringRef FunctionName;
explicit FunctionOptions(const CapturedStmt *S, bool UIntPtrCastRequired,
bool RegisterCastedArgsOnly,
StringRef FunctionName)
@@ -261,9 +297,9 @@ namespace {
};
}
-static std::pair<llvm::Function *, bool> emitOutlinedFunctionPrologue(
+static llvm::Function *emitOutlinedFunctionPrologue(
CodeGenFunction &CGF, FunctionArgList &Args,
- llvm::DenseMap<const Decl *, std::pair<const VarDecl *, Address>>
+ llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>>
&LocalAddrs,
llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>>
&VLASizes,
@@ -276,10 +312,23 @@ static std::pair<llvm::Function *, bool> emitOutlinedFunctionPrologue(
// Build the argument list.
CodeGenModule &CGM = CGF.CGM;
ASTContext &Ctx = CGM.getContext();
- bool HasUIntPtrArgs = false;
+ FunctionArgList TargetArgs;
Args.append(CD->param_begin(),
std::next(CD->param_begin(), CD->getContextParamPosition()));
+ TargetArgs.append(
+ CD->param_begin(),
+ std::next(CD->param_begin(), CD->getContextParamPosition()));
auto I = FO.S->captures().begin();
+ FunctionDecl *DebugFunctionDecl = nullptr;
+ if (!FO.UIntPtrCastRequired) {
+ FunctionProtoType::ExtProtoInfo EPI;
+ DebugFunctionDecl = FunctionDecl::Create(
+ Ctx, Ctx.getTranslationUnitDecl(), FO.S->getLocStart(),
+ SourceLocation(), DeclarationName(), Ctx.VoidTy,
+ Ctx.getTrivialTypeSourceInfo(
+ Ctx.getFunctionType(Ctx.VoidTy, llvm::None, EPI)),
+ SC_Static, /*isInlineSpecified=*/false, /*hasWrittenPrototype=*/false);
+ }
for (auto *FD : RD->fields()) {
QualType ArgType = FD->getType();
IdentifierInfo *II = nullptr;
@@ -292,7 +341,6 @@ static std::pair<llvm::Function *, bool> emitOutlinedFunctionPrologue(
// outlined function.
if ((I->capturesVariableByCopy() && !ArgType->isAnyPointerType()) ||
I->capturesVariableArrayType()) {
- HasUIntPtrArgs = true;
if (FO.UIntPtrCastRequired)
ArgType = Ctx.getUIntPtrType();
}
@@ -307,20 +355,36 @@ static std::pair<llvm::Function *, bool> emitOutlinedFunctionPrologue(
II = &Ctx.Idents.get("vla");
}
if (ArgType->isVariablyModifiedType())
- ArgType = getCanonicalParamType(Ctx, ArgType.getNonReferenceType());
- Args.push_back(ImplicitParamDecl::Create(Ctx, /*DC=*/nullptr,
- FD->getLocation(), II, ArgType,
- ImplicitParamDecl::Other));
+ ArgType = getCanonicalParamType(Ctx, ArgType);
+ VarDecl *Arg;
+ if (DebugFunctionDecl && (CapVar || I->capturesThis())) {
+ Arg = ParmVarDecl::Create(
+ Ctx, DebugFunctionDecl,
+ CapVar ? CapVar->getLocStart() : FD->getLocStart(),
+ CapVar ? CapVar->getLocation() : FD->getLocation(), II, ArgType,
+ /*TInfo=*/nullptr, SC_None, /*DefArg=*/nullptr);
+ } else {
+ Arg = ImplicitParamDecl::Create(Ctx, /*DC=*/nullptr, FD->getLocation(),
+ II, ArgType, ImplicitParamDecl::Other);
+ }
+ Args.emplace_back(Arg);
+ // Do not cast arguments if we emit function with non-original types.
+ TargetArgs.emplace_back(
+ FO.UIntPtrCastRequired
+ ? Arg
+ : CGM.getOpenMPRuntime().translateParameter(FD, Arg));
++I;
}
Args.append(
std::next(CD->param_begin(), CD->getContextParamPosition() + 1),
CD->param_end());
+ TargetArgs.append(
+ std::next(CD->param_begin(), CD->getContextParamPosition() + 1),
+ CD->param_end());
// Create the function declaration.
- FunctionType::ExtInfo ExtInfo;
const CGFunctionInfo &FuncInfo =
- CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Args);
+ CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, TargetArgs);
llvm::FunctionType *FuncLLVMTy = CGM.getTypes().GetFunctionType(FuncInfo);
llvm::Function *F =
@@ -328,19 +392,26 @@ static std::pair<llvm::Function *, bool> emitOutlinedFunctionPrologue(
FO.FunctionName, &CGM.getModule());
CGM.SetInternalFunctionAttributes(CD, F, FuncInfo);
if (CD->isNothrow())
- F->addFnAttr(llvm::Attribute::NoUnwind);
+ F->setDoesNotThrow();
// Generate the function.
- CGF.StartFunction(CD, Ctx.VoidTy, F, FuncInfo, Args, CD->getLocation(),
- CD->getBody()->getLocStart());
+ CGF.StartFunction(CD, Ctx.VoidTy, F, FuncInfo, TargetArgs,
+ FO.S->getLocStart(), CD->getBody()->getLocStart());
unsigned Cnt = CD->getContextParamPosition();
I = FO.S->captures().begin();
for (auto *FD : RD->fields()) {
+ // Do not map arguments if we emit function with non-original types.
+ Address LocalAddr(Address::invalid());
+ if (!FO.UIntPtrCastRequired && Args[Cnt] != TargetArgs[Cnt]) {
+ LocalAddr = CGM.getOpenMPRuntime().getParameterAddress(CGF, Args[Cnt],
+ TargetArgs[Cnt]);
+ } else {
+ LocalAddr = CGF.GetAddrOfLocalVar(Args[Cnt]);
+ }
// If we are capturing a pointer by copy we don't need to do anything, just
// use the value that we get from the arguments.
if (I->capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
const VarDecl *CurVD = I->getCapturedVar();
- Address LocalAddr = CGF.GetAddrOfLocalVar(Args[Cnt]);
// If the variable is a reference we need to materialize it here.
if (CurVD->getType()->isReferenceType()) {
Address RefAddr = CGF.CreateMemTemp(
@@ -356,15 +427,14 @@ static std::pair<llvm::Function *, bool> emitOutlinedFunctionPrologue(
continue;
}
- LValueBaseInfo BaseInfo(AlignmentSource::Decl, false);
- LValue ArgLVal = CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(Args[Cnt]),
- Args[Cnt]->getType(), BaseInfo);
+ LValue ArgLVal = CGF.MakeAddrLValue(LocalAddr, Args[Cnt]->getType(),
+ AlignmentSource::Decl);
if (FD->hasCapturedVLAType()) {
if (FO.UIntPtrCastRequired) {
ArgLVal = CGF.MakeAddrLValue(castValueFromUintptr(CGF, FD->getType(),
Args[Cnt]->getName(),
ArgLVal),
- FD->getType(), BaseInfo);
+ FD->getType(), AlignmentSource::Decl);
}
auto *ExprArg =
CGF.EmitLoadOfLValue(ArgLVal, SourceLocation()).getScalarVal();
@@ -376,8 +446,7 @@ static std::pair<llvm::Function *, bool> emitOutlinedFunctionPrologue(
Address ArgAddr = ArgLVal.getAddress();
if (!VarTy->isReferenceType()) {
if (ArgLVal.getType()->isLValueReferenceType()) {
- ArgAddr = CGF.EmitLoadOfReference(
- ArgAddr, ArgLVal.getType()->castAs<ReferenceType>());
+ ArgAddr = CGF.EmitLoadOfReference(ArgLVal);
} else if (!VarTy->isVariablyModifiedType() || !VarTy->isPointerType()) {
assert(ArgLVal.getType()->isPointerType());
ArgAddr = CGF.EmitLoadOfPointer(
@@ -412,7 +481,7 @@ static std::pair<llvm::Function *, bool> emitOutlinedFunctionPrologue(
++I;
}
- return {F, HasUIntPtrArgs};
+ return F;
}
llvm::Function *
@@ -426,14 +495,17 @@ CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) {
getDebugInfo() &&
CGM.getCodeGenOpts().getDebugInfo() >= codegenoptions::LimitedDebugInfo;
FunctionArgList Args;
- llvm::DenseMap<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs;
+ llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs;
llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes;
+ SmallString<256> Buffer;
+ llvm::raw_svector_ostream Out(Buffer);
+ Out << CapturedStmtInfo->getHelperName();
+ if (NeedWrapperFunction)
+ Out << "_debug__";
FunctionOptions FO(&S, !NeedWrapperFunction, /*RegisterCastedArgsOnly=*/false,
- CapturedStmtInfo->getHelperName());
- llvm::Function *F;
- bool HasUIntPtrArgs;
- std::tie(F, HasUIntPtrArgs) = emitOutlinedFunctionPrologue(
- *this, Args, LocalAddrs, VLASizes, CXXThisValue, FO);
+ Out.str());
+ llvm::Function *F = emitOutlinedFunctionPrologue(*this, Args, LocalAddrs,
+ VLASizes, CXXThisValue, FO);
for (const auto &LocalAddrPair : LocalAddrs) {
if (LocalAddrPair.second.first) {
setAddrOfLocalVar(LocalAddrPair.second.first,
@@ -445,28 +517,28 @@ CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) {
PGO.assignRegionCounters(GlobalDecl(CD), F);
CapturedStmtInfo->EmitBody(*this, CD->getBody());
FinishFunction(CD->getBodyRBrace());
- if (!NeedWrapperFunction || !HasUIntPtrArgs)
+ if (!NeedWrapperFunction)
return F;
FunctionOptions WrapperFO(&S, /*UIntPtrCastRequired=*/true,
/*RegisterCastedArgsOnly=*/true,
- ".nondebug_wrapper.");
+ CapturedStmtInfo->getHelperName());
CodeGenFunction WrapperCGF(CGM, /*suppressNewContext=*/true);
- WrapperCGF.disableDebugInfo();
Args.clear();
LocalAddrs.clear();
VLASizes.clear();
llvm::Function *WrapperF =
emitOutlinedFunctionPrologue(WrapperCGF, Args, LocalAddrs, VLASizes,
- WrapperCGF.CXXThisValue, WrapperFO).first;
- LValueBaseInfo BaseInfo(AlignmentSource::Decl, false);
+ WrapperCGF.CXXThisValue, WrapperFO);
llvm::SmallVector<llvm::Value *, 4> CallArgs;
for (const auto *Arg : Args) {
llvm::Value *CallArg;
auto I = LocalAddrs.find(Arg);
if (I != LocalAddrs.end()) {
- LValue LV =
- WrapperCGF.MakeAddrLValue(I->second.second, Arg->getType(), BaseInfo);
+ LValue LV = WrapperCGF.MakeAddrLValue(
+ I->second.second,
+ I->second.first ? I->second.first->getType() : Arg->getType(),
+ AlignmentSource::Decl);
CallArg = WrapperCGF.EmitLoadOfScalar(LV, SourceLocation());
} else {
auto EI = VLASizes.find(Arg);
@@ -474,13 +546,15 @@ CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) {
CallArg = EI->second.second;
else {
LValue LV = WrapperCGF.MakeAddrLValue(WrapperCGF.GetAddrOfLocalVar(Arg),
- Arg->getType(), BaseInfo);
+ Arg->getType(),
+ AlignmentSource::Decl);
CallArg = WrapperCGF.EmitLoadOfScalar(LV, SourceLocation());
}
}
- CallArgs.emplace_back(CallArg);
+ CallArgs.emplace_back(WrapperCGF.EmitFromMemory(CallArg, Arg->getType()));
}
- WrapperCGF.Builder.CreateCall(F, CallArgs);
+ CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, S.getLocStart(),
+ F, CallArgs);
WrapperCGF.FinishFunction();
return WrapperF;
}
@@ -956,7 +1030,9 @@ void CodeGenFunction::EmitOMPReductionClauseInit(
auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
- if (isa<OMPArraySectionExpr>(IRef)) {
+ QualType Type = PrivateVD->getType();
+ bool isaOMPArraySectionExpr = isa<OMPArraySectionExpr>(IRef);
+ if (isaOMPArraySectionExpr && Type->isVariablyModifiedType()) {
// Store the address of the original variable associated with the LHS
// implicit variable.
PrivateScope.addPrivate(LHSVD, [&RedCG, Count]() -> Address {
@@ -965,7 +1041,8 @@ void CodeGenFunction::EmitOMPReductionClauseInit(
PrivateScope.addPrivate(RHSVD, [this, PrivateVD]() -> Address {
return GetAddrOfLocalVar(PrivateVD);
});
- } else if (isa<ArraySubscriptExpr>(IRef)) {
+ } else if ((isaOMPArraySectionExpr && Type->isScalarType()) ||
+ isa<ArraySubscriptExpr>(IRef)) {
// Store the address of the original variable associated with the LHS
// implicit variable.
PrivateScope.addPrivate(LHSVD, [&RedCG, Count]() -> Address {
@@ -1024,7 +1101,8 @@ void CodeGenFunction::EmitOMPReductionClauseFinal(
bool WithNowait = D.getSingleClause<OMPNowaitClause>() ||
isOpenMPParallelDirective(D.getDirectiveKind()) ||
D.getDirectiveKind() == OMPD_simd;
- bool SimpleReduction = D.getDirectiveKind() == OMPD_simd;
+ bool SimpleReduction = D.getDirectiveKind() == OMPD_simd ||
+ D.getDirectiveKind() == OMPD_distribute_simd;
// Emit nowait reduction if nowait clause is present or directive is a
// parallel directive (it always has implicit barrier).
CGM.getOpenMPRuntime().emitReduction(
@@ -1146,9 +1224,13 @@ void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &D,
EmitIgnoredExpr(I);
}
// Update the linear variables.
- for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
- for (auto *U : C->updates())
- EmitIgnoredExpr(U);
+ // In distribute directives only loop counters may be marked as linear, no
+ // need to generate the code for them.
+ if (!isOpenMPDistributeDirective(D.getDirectiveKind())) {
+ for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
+ for (auto *U : C->updates())
+ EmitIgnoredExpr(U);
+ }
}
// On a continue in the body, jump to the end.
@@ -1488,83 +1570,90 @@ static void emitOMPLoopBodyWithStopPoint(CodeGenFunction &CGF,
CGF.EmitStopPoint(&S);
}
-void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
- auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
- OMPLoopScope PreInitScope(CGF, S);
- // if (PreCond) {
- // for (IV in 0..LastIteration) BODY;
- // <Final counter/linear vars updates>;
- // }
- //
+static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S,
+ PrePostActionTy &Action) {
+ Action.Enter(CGF);
+ assert(isOpenMPSimdDirective(S.getDirectiveKind()) &&
+ "Expected simd directive");
+ OMPLoopScope PreInitScope(CGF, S);
+ // if (PreCond) {
+ // for (IV in 0..LastIteration) BODY;
+ // <Final counter/linear vars updates>;
+ // }
+ //
- // Emit: if (PreCond) - begin.
- // If the condition constant folds and can be elided, avoid emitting the
- // whole loop.
- bool CondConstant;
- llvm::BasicBlock *ContBlock = nullptr;
- if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
- if (!CondConstant)
- return;
- } else {
- auto *ThenBlock = CGF.createBasicBlock("simd.if.then");
- ContBlock = CGF.createBasicBlock("simd.if.end");
- emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
- CGF.getProfileCount(&S));
- CGF.EmitBlock(ThenBlock);
- CGF.incrementProfileCounter(&S);
- }
+ // Emit: if (PreCond) - begin.
+ // If the condition constant folds and can be elided, avoid emitting the
+ // whole loop.
+ bool CondConstant;
+ llvm::BasicBlock *ContBlock = nullptr;
+ if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
+ if (!CondConstant)
+ return;
+ } else {
+ auto *ThenBlock = CGF.createBasicBlock("simd.if.then");
+ ContBlock = CGF.createBasicBlock("simd.if.end");
+ emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
+ CGF.getProfileCount(&S));
+ CGF.EmitBlock(ThenBlock);
+ CGF.incrementProfileCounter(&S);
+ }
- // Emit the loop iteration variable.
- const Expr *IVExpr = S.getIterationVariable();
- const VarDecl *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl());
- CGF.EmitVarDecl(*IVDecl);
- CGF.EmitIgnoredExpr(S.getInit());
+ // Emit the loop iteration variable.
+ const Expr *IVExpr = S.getIterationVariable();
+ const VarDecl *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl());
+ CGF.EmitVarDecl(*IVDecl);
+ CGF.EmitIgnoredExpr(S.getInit());
- // Emit the iterations count variable.
- // If it is not a variable, Sema decided to calculate iterations count on
- // each iteration (e.g., it is foldable into a constant).
- if (auto LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
- CGF.EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
- // Emit calculation of the iterations count.
- CGF.EmitIgnoredExpr(S.getCalcLastIteration());
- }
+ // Emit the iterations count variable.
+ // If it is not a variable, Sema decided to calculate iterations count on
+ // each iteration (e.g., it is foldable into a constant).
+ if (auto LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
+ CGF.EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
+ // Emit calculation of the iterations count.
+ CGF.EmitIgnoredExpr(S.getCalcLastIteration());
+ }
- CGF.EmitOMPSimdInit(S);
+ CGF.EmitOMPSimdInit(S);
- emitAlignedClause(CGF, S);
- (void)CGF.EmitOMPLinearClauseInit(S);
- {
- OMPPrivateScope LoopScope(CGF);
- CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
- CGF.EmitOMPLinearClause(S, LoopScope);
- CGF.EmitOMPPrivateClause(S, LoopScope);
- CGF.EmitOMPReductionClauseInit(S, LoopScope);
- bool HasLastprivateClause =
- CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
- (void)LoopScope.Privatize();
- CGF.EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), S.getCond(),
- S.getInc(),
- [&S](CodeGenFunction &CGF) {
- CGF.EmitOMPLoopBody(S, JumpDest());
- CGF.EmitStopPoint(&S);
- },
- [](CodeGenFunction &) {});
- CGF.EmitOMPSimdFinal(
- S, [](CodeGenFunction &) -> llvm::Value * { return nullptr; });
- // Emit final copy of the lastprivate variables at the end of loops.
- if (HasLastprivateClause)
- CGF.EmitOMPLastprivateClauseFinal(S, /*NoFinals=*/true);
- CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_simd);
- emitPostUpdateForReductionClause(
- CGF, S, [](CodeGenFunction &) -> llvm::Value * { return nullptr; });
- }
- CGF.EmitOMPLinearClauseFinal(
+ emitAlignedClause(CGF, S);
+ (void)CGF.EmitOMPLinearClauseInit(S);
+ {
+ CodeGenFunction::OMPPrivateScope LoopScope(CGF);
+ CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
+ CGF.EmitOMPLinearClause(S, LoopScope);
+ CGF.EmitOMPPrivateClause(S, LoopScope);
+ CGF.EmitOMPReductionClauseInit(S, LoopScope);
+ bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
+ (void)LoopScope.Privatize();
+ CGF.EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), S.getCond(),
+ S.getInc(),
+ [&S](CodeGenFunction &CGF) {
+ CGF.EmitOMPLoopBody(S, CodeGenFunction::JumpDest());
+ CGF.EmitStopPoint(&S);
+ },
+ [](CodeGenFunction &) {});
+ CGF.EmitOMPSimdFinal(
S, [](CodeGenFunction &) -> llvm::Value * { return nullptr; });
- // Emit: if (PreCond) - end.
- if (ContBlock) {
- CGF.EmitBranch(ContBlock);
- CGF.EmitBlock(ContBlock, true);
- }
+ // Emit final copy of the lastprivate variables at the end of loops.
+ if (HasLastprivateClause)
+ CGF.EmitOMPLastprivateClauseFinal(S, /*NoFinals=*/true);
+ CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_simd);
+ emitPostUpdateForReductionClause(
+ CGF, S, [](CodeGenFunction &) -> llvm::Value * { return nullptr; });
+ }
+ CGF.EmitOMPLinearClauseFinal(
+ S, [](CodeGenFunction &) -> llvm::Value * { return nullptr; });
+ // Emit: if (PreCond) - end.
+ if (ContBlock) {
+ CGF.EmitBranch(ContBlock);
+ CGF.EmitBlock(ContBlock, true);
+ }
+}
+
+void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ emitOMPSimdRegion(CGF, S, Action);
};
OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
@@ -1669,7 +1758,8 @@ void CodeGenFunction::EmitOMPOuterLoop(
// Tell the runtime we are done.
auto &&CodeGen = [DynamicOrOrdered, &S](CodeGenFunction &CGF) {
if (!DynamicOrOrdered)
- CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getLocEnd());
+ CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getLocEnd(),
+ S.getDirectiveKind());
};
OMPCancelStack.emitExit(*this, S.getDirectiveKind(), CodeGen);
}
@@ -1753,9 +1843,11 @@ void CodeGenFunction::EmitOMPForOuterLoop(
RT.emitForDispatchInit(*this, S.getLocStart(), ScheduleKind, IVSize,
IVSigned, Ordered, DipatchRTInputValues);
} else {
- RT.emitForStaticInit(*this, S.getLocStart(), ScheduleKind, IVSize, IVSigned,
- Ordered, LoopArgs.IL, LoopArgs.LB, LoopArgs.UB,
- LoopArgs.ST, LoopArgs.Chunk);
+ CGOpenMPRuntime::StaticRTInput StaticInit(
+ IVSize, IVSigned, Ordered, LoopArgs.IL, LoopArgs.LB, LoopArgs.UB,
+ LoopArgs.ST, LoopArgs.Chunk);
+ RT.emitForStaticInit(*this, S.getLocStart(), S.getDirectiveKind(),
+ ScheduleKind, StaticInit);
}
auto &&CodeGenOrdered = [Ordered](CodeGenFunction &CGF, SourceLocation Loc,
@@ -1797,10 +1889,10 @@ void CodeGenFunction::EmitOMPDistributeOuterLoop(
const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
- RT.emitDistributeStaticInit(*this, S.getLocStart(), ScheduleKind, IVSize,
- IVSigned, /* Ordered = */ false, LoopArgs.IL,
- LoopArgs.LB, LoopArgs.UB, LoopArgs.ST,
- LoopArgs.Chunk);
+ CGOpenMPRuntime::StaticRTInput StaticInit(
+ IVSize, IVSigned, /* Ordered = */ false, LoopArgs.IL, LoopArgs.LB,
+ LoopArgs.UB, LoopArgs.ST, LoopArgs.Chunk);
+ RT.emitDistributeStaticInit(*this, S.getLocStart(), ScheduleKind, StaticInit);
// for combined 'distribute' and 'for' the increment expression of distribute
// is store in DistInc. For 'distribute' alone, it is in Inc.
@@ -1929,13 +2021,27 @@ emitInnerParallelForWhenCombined(CodeGenFunction &CGF,
CodeGenFunction::JumpDest LoopExit) {
auto &&CGInlinedWorksharingLoop = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
+ bool HasCancel = false;
+ if (!isOpenMPSimdDirective(S.getDirectiveKind())) {
+ if (const auto *D = dyn_cast<OMPTeamsDistributeParallelForDirective>(&S))
+ HasCancel = D->hasCancel();
+ else if (const auto *D = dyn_cast<OMPDistributeParallelForDirective>(&S))
+ HasCancel = D->hasCancel();
+ else if (const auto *D =
+ dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&S))
+ HasCancel = D->hasCancel();
+ }
+ CodeGenFunction::OMPCancelStackRAII CancelRegion(CGF, S.getDirectiveKind(),
+ HasCancel);
CGF.EmitOMPWorksharingLoop(S, S.getPrevEnsureUpperBound(),
emitDistributeParallelForInnerBounds,
emitDistributeParallelForDispatchBounds);
};
emitCommonOMPParallelDirective(
- CGF, S, OMPD_for, CGInlinedWorksharingLoop,
+ CGF, S,
+ isOpenMPSimdDirective(S.getDirectiveKind()) ? OMPD_for_simd : OMPD_for,
+ CGInlinedWorksharingLoop,
emitDistributeParallelForDistributeInnerBoundParams);
}
@@ -1946,119 +2052,53 @@ void CodeGenFunction::EmitOMPDistributeParallelForDirective(
S.getDistInc());
};
OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
- OMPCancelStackRAII CancelRegion(*this, OMPD_distribute_parallel_for,
- /*HasCancel=*/false);
- CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen,
- /*HasCancel=*/false);
+ CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen);
}
void CodeGenFunction::EmitOMPDistributeParallelForSimdDirective(
const OMPDistributeParallelForSimdDirective &S) {
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined,
+ S.getDistInc());
+ };
OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
- CGM.getOpenMPRuntime().emitInlinedDirective(
- *this, OMPD_distribute_parallel_for_simd,
- [&S](CodeGenFunction &CGF, PrePostActionTy &) {
- OMPLoopScope PreInitScope(CGF, S);
- CGF.EmitStmt(
- cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
- });
+ CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen);
}
void CodeGenFunction::EmitOMPDistributeSimdDirective(
const OMPDistributeSimdDirective &S) {
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc());
+ };
OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
- CGM.getOpenMPRuntime().emitInlinedDirective(
- *this, OMPD_distribute_simd,
- [&S](CodeGenFunction &CGF, PrePostActionTy &) {
- OMPLoopScope PreInitScope(CGF, S);
- CGF.EmitStmt(
- cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
- });
+ CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
}
-void CodeGenFunction::EmitOMPTargetParallelForSimdDirective(
- const OMPTargetParallelForSimdDirective &S) {
- OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
- CGM.getOpenMPRuntime().emitInlinedDirective(
- *this, OMPD_target_parallel_for_simd,
- [&S](CodeGenFunction &CGF, PrePostActionTy &) {
- OMPLoopScope PreInitScope(CGF, S);
- CGF.EmitStmt(
- cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
- });
+void CodeGenFunction::EmitOMPTargetSimdDeviceFunction(
+ CodeGenModule &CGM, StringRef ParentName, const OMPTargetSimdDirective &S) {
+ // Emit SPMD target parallel for region as a standalone region.
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ emitOMPSimdRegion(CGF, S, Action);
+ };
+ llvm::Function *Fn;
+ llvm::Constant *Addr;
+ // Emit target region as a standalone region.
+ CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
+ S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
+ assert(Fn && Addr && "Target device function emission failed.");
}
void CodeGenFunction::EmitOMPTargetSimdDirective(
const OMPTargetSimdDirective &S) {
- OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
- CGM.getOpenMPRuntime().emitInlinedDirective(
- *this, OMPD_target_simd, [&S](CodeGenFunction &CGF, PrePostActionTy &) {
- OMPLoopScope PreInitScope(CGF, S);
- CGF.EmitStmt(
- cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
- });
-}
-
-void CodeGenFunction::EmitOMPTeamsDistributeDirective(
- const OMPTeamsDistributeDirective &S) {
- OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
- CGM.getOpenMPRuntime().emitInlinedDirective(
- *this, OMPD_teams_distribute,
- [&S](CodeGenFunction &CGF, PrePostActionTy &) {
- OMPLoopScope PreInitScope(CGF, S);
- CGF.EmitStmt(
- cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
- });
-}
-
-void CodeGenFunction::EmitOMPTeamsDistributeSimdDirective(
- const OMPTeamsDistributeSimdDirective &S) {
- OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
- CGM.getOpenMPRuntime().emitInlinedDirective(
- *this, OMPD_teams_distribute_simd,
- [&S](CodeGenFunction &CGF, PrePostActionTy &) {
- OMPLoopScope PreInitScope(CGF, S);
- CGF.EmitStmt(
- cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
- });
-}
-
-void CodeGenFunction::EmitOMPTeamsDistributeParallelForSimdDirective(
- const OMPTeamsDistributeParallelForSimdDirective &S) {
- OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
- CGM.getOpenMPRuntime().emitInlinedDirective(
- *this, OMPD_teams_distribute_parallel_for_simd,
- [&S](CodeGenFunction &CGF, PrePostActionTy &) {
- OMPLoopScope PreInitScope(CGF, S);
- CGF.EmitStmt(
- cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
- });
-}
-
-void CodeGenFunction::EmitOMPTeamsDistributeParallelForDirective(
- const OMPTeamsDistributeParallelForDirective &S) {
- OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
- CGM.getOpenMPRuntime().emitInlinedDirective(
- *this, OMPD_teams_distribute_parallel_for,
- [&S](CodeGenFunction &CGF, PrePostActionTy &) {
- OMPLoopScope PreInitScope(CGF, S);
- CGF.EmitStmt(
- cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
- });
-}
-
-void CodeGenFunction::EmitOMPTargetTeamsDistributeDirective(
- const OMPTargetTeamsDistributeDirective &S) {
- CGM.getOpenMPRuntime().emitInlinedDirective(
- *this, OMPD_target_teams_distribute,
- [&S](CodeGenFunction &CGF, PrePostActionTy &) {
- CGF.EmitStmt(
- cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
- });
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ emitOMPSimdRegion(CGF, S, Action);
+ };
+ emitCommonOMPTargetDirective(*this, S, CodeGen);
}
void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDirective(
const OMPTargetTeamsDistributeParallelForDirective &S) {
+ OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
CGM.getOpenMPRuntime().emitInlinedDirective(
*this, OMPD_target_teams_distribute_parallel_for,
[&S](CodeGenFunction &CGF, PrePostActionTy &) {
@@ -2069,6 +2109,7 @@ void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDirective(
void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForSimdDirective(
const OMPTargetTeamsDistributeParallelForSimdDirective &S) {
+ OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
CGM.getOpenMPRuntime().emitInlinedDirective(
*this, OMPD_target_teams_distribute_parallel_for_simd,
[&S](CodeGenFunction &CGF, PrePostActionTy &) {
@@ -2077,16 +2118,6 @@ void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForSimdDirective(
});
}
-void CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDirective(
- const OMPTargetTeamsDistributeSimdDirective &S) {
- CGM.getOpenMPRuntime().emitInlinedDirective(
- *this, OMPD_target_teams_distribute_simd,
- [&S](CodeGenFunction &CGF, PrePostActionTy &) {
- CGF.EmitStmt(
- cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
- });
-}
-
namespace {
struct ScheduleKindModifiersTy {
OpenMPScheduleClauseKind Kind;
@@ -2209,10 +2240,11 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(
// chunks that are approximately equal in size, and at most one chunk is
// distributed to each thread. Note that the size of the chunks is
// unspecified in this case.
- RT.emitForStaticInit(*this, S.getLocStart(), ScheduleKind,
- IVSize, IVSigned, Ordered,
- IL.getAddress(), LB.getAddress(),
- UB.getAddress(), ST.getAddress());
+ CGOpenMPRuntime::StaticRTInput StaticInit(
+ IVSize, IVSigned, Ordered, IL.getAddress(), LB.getAddress(),
+ UB.getAddress(), ST.getAddress());
+ RT.emitForStaticInit(*this, S.getLocStart(), S.getDirectiveKind(),
+ ScheduleKind, StaticInit);
auto LoopExit =
getJumpDestInCurrentScope(createBasicBlock("omp.loop.exit"));
// UB = min(UB, GlobalUB);
@@ -2230,7 +2262,8 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(
EmitBlock(LoopExit.getBlock());
// Tell the runtime we are done.
auto &&CodeGen = [&S](CodeGenFunction &CGF) {
- CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getLocEnd());
+ CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getLocEnd(),
+ S.getDirectiveKind());
};
OMPCancelStack.emitExit(*this, S.getDirectiveKind(), CodeGen);
} else {
@@ -2444,10 +2477,11 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
// Emit static non-chunked loop.
OpenMPScheduleTy ScheduleKind;
ScheduleKind.Schedule = OMPC_SCHEDULE_static;
+ CGOpenMPRuntime::StaticRTInput StaticInit(
+ /*IVSize=*/32, /*IVSigned=*/true, /*Ordered=*/false, IL.getAddress(),
+ LB.getAddress(), UB.getAddress(), ST.getAddress());
CGF.CGM.getOpenMPRuntime().emitForStaticInit(
- CGF, S.getLocStart(), ScheduleKind, /*IVSize=*/32,
- /*IVSigned=*/true, /*Ordered=*/false, IL.getAddress(), LB.getAddress(),
- UB.getAddress(), ST.getAddress());
+ CGF, S.getLocStart(), S.getDirectiveKind(), ScheduleKind, StaticInit);
// UB = min(UB, GlobalUB);
auto *UBVal = CGF.EmitLoadOfScalar(UB, S.getLocStart());
auto *MinUBGlobalUB = CGF.Builder.CreateSelect(
@@ -2460,7 +2494,8 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
[](CodeGenFunction &) {});
// Tell the runtime we are done.
auto &&CodeGen = [&S](CodeGenFunction &CGF) {
- CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getLocEnd());
+ CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getLocEnd(),
+ S.getDirectiveKind());
};
CGF.OMPCancelStack.emitExit(CGF, S.getDirectiveKind(), CodeGen);
CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
@@ -2731,6 +2766,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective(const OMPExecutableDirective &S,
OMPPrivateScope Scope(CGF);
if (!Data.PrivateVars.empty() || !Data.FirstprivateVars.empty() ||
!Data.LastprivateVars.empty()) {
+ enum { PrivatesParam = 2, CopyFnParam = 3 };
auto *CopyFn = CGF.Builder.CreateLoad(
CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(3)));
auto *PrivatesPtr = CGF.Builder.CreateLoad(
@@ -2762,7 +2798,8 @@ void CodeGenFunction::EmitOMPTaskBasedDirective(const OMPExecutableDirective &S,
PrivatePtrs.push_back(std::make_pair(VD, PrivatePtr));
CallArgs.push_back(PrivatePtr.getPointer());
}
- CGF.EmitRuntimeCall(CopyFn, CallArgs);
+ CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getLocStart(),
+ CopyFn, CallArgs);
for (auto &&Pair : LastprivateDstsOrigs) {
auto *OrigVD = cast<VarDecl>(Pair.second->getDecl());
DeclRefExpr DRE(
@@ -2808,7 +2845,57 @@ void CodeGenFunction::EmitOMPTaskBasedDirective(const OMPExecutableDirective &S,
RedCG, Cnt);
}
}
+ // Privatize all private variables except for in_reduction items.
(void)Scope.Privatize();
+ SmallVector<const Expr *, 4> InRedVars;
+ SmallVector<const Expr *, 4> InRedPrivs;
+ SmallVector<const Expr *, 4> InRedOps;
+ SmallVector<const Expr *, 4> TaskgroupDescriptors;
+ for (const auto *C : S.getClausesOfKind<OMPInReductionClause>()) {
+ auto IPriv = C->privates().begin();
+ auto IRed = C->reduction_ops().begin();
+ auto ITD = C->taskgroup_descriptors().begin();
+ for (const auto *Ref : C->varlists()) {
+ InRedVars.emplace_back(Ref);
+ InRedPrivs.emplace_back(*IPriv);
+ InRedOps.emplace_back(*IRed);
+ TaskgroupDescriptors.emplace_back(*ITD);
+ std::advance(IPriv, 1);
+ std::advance(IRed, 1);
+ std::advance(ITD, 1);
+ }
+ }
+ // Privatize in_reduction items here, because taskgroup descriptors must be
+ // privatized earlier.
+ OMPPrivateScope InRedScope(CGF);
+ if (!InRedVars.empty()) {
+ ReductionCodeGen RedCG(InRedVars, InRedPrivs, InRedOps);
+ for (unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
+ RedCG.emitSharedLValue(CGF, Cnt);
+ RedCG.emitAggregateType(CGF, Cnt);
+ // The taskgroup descriptor variable is always implicit firstprivate and
+ // privatized already during procoessing of the firstprivates.
+ llvm::Value *ReductionsPtr = CGF.EmitLoadOfScalar(
+ CGF.EmitLValue(TaskgroupDescriptors[Cnt]), SourceLocation());
+ Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
+ CGF, S.getLocStart(), ReductionsPtr, RedCG.getSharedLValue(Cnt));
+ Replacement = Address(
+ CGF.EmitScalarConversion(
+ Replacement.getPointer(), CGF.getContext().VoidPtrTy,
+ CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()),
+ SourceLocation()),
+ Replacement.getAlignment());
+ Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement);
+ InRedScope.addPrivate(RedCG.getBaseDecl(Cnt),
+ [Replacement]() { return Replacement; });
+ // FIXME: This must removed once the runtime library is fixed.
+ // Emit required threadprivate variables for
+ // initilizer/combiner/finalizer.
+ CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getLocStart(),
+ RedCG, Cnt);
+ }
+ }
+ (void)InRedScope.Privatize();
Action.Enter(CGF);
BodyGen(CGF);
@@ -2867,6 +2954,35 @@ void CodeGenFunction::EmitOMPTaskgroupDirective(
const OMPTaskgroupDirective &S) {
auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
Action.Enter(CGF);
+ if (const Expr *E = S.getReductionRef()) {
+ SmallVector<const Expr *, 4> LHSs;
+ SmallVector<const Expr *, 4> RHSs;
+ OMPTaskDataTy Data;
+ for (const auto *C : S.getClausesOfKind<OMPTaskReductionClause>()) {
+ auto IPriv = C->privates().begin();
+ auto IRed = C->reduction_ops().begin();
+ auto ILHS = C->lhs_exprs().begin();
+ auto IRHS = C->rhs_exprs().begin();
+ for (const auto *Ref : C->varlists()) {
+ Data.ReductionVars.emplace_back(Ref);
+ Data.ReductionCopies.emplace_back(*IPriv);
+ Data.ReductionOps.emplace_back(*IRed);
+ LHSs.emplace_back(*ILHS);
+ RHSs.emplace_back(*IRHS);
+ std::advance(IPriv, 1);
+ std::advance(IRed, 1);
+ std::advance(ILHS, 1);
+ std::advance(IRHS, 1);
+ }
+ }
+ llvm::Value *ReductionDesc =
+ CGF.CGM.getOpenMPRuntime().emitTaskReductionInit(CGF, S.getLocStart(),
+ LHSs, RHSs, Data);
+ const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
+ CGF.EmitVarDecl(*VD);
+ CGF.EmitStoreOfScalar(ReductionDesc, CGF.GetAddrOfLocalVar(VD),
+ /*Volatile=*/false, E->getType());
+ }
CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
};
OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
@@ -2923,6 +3039,7 @@ void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S,
incrementProfileCounter(&S);
}
+ emitAlignedClause(*this, S);
// Emit 'then' code.
{
// Emit helper vars inits.
@@ -2944,14 +3061,18 @@ void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S,
OMPPrivateScope LoopScope(*this);
if (EmitOMPFirstprivateClause(S, LoopScope)) {
- // Emit implicit barrier to synchronize threads and avoid data races on
- // initialization of firstprivate variables and post-update of
+ // Emit implicit barrier to synchronize threads and avoid data races
+ // on initialization of firstprivate variables and post-update of
// lastprivate variables.
CGM.getOpenMPRuntime().emitBarrierCall(
- *this, S.getLocStart(), OMPD_unknown, /*EmitChecks=*/false,
- /*ForceSimpleCall=*/true);
+ *this, S.getLocStart(), OMPD_unknown, /*EmitChecks=*/false,
+ /*ForceSimpleCall=*/true);
}
EmitOMPPrivateClause(S, LoopScope);
+ if (isOpenMPSimdDirective(S.getDirectiveKind()) &&
+ !isOpenMPParallelDirective(S.getDirectiveKind()) &&
+ !isOpenMPTeamsDirective(S.getDirectiveKind()))
+ EmitOMPReductionClauseInit(S, LoopScope);
HasLastprivateClause = EmitOMPLastprivateClauseInit(S, LoopScope);
EmitOMPPrivateLoopCounters(S, LoopScope);
(void)LoopScope.Privatize();
@@ -2964,8 +3085,8 @@ void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S,
if (const auto *Ch = C->getChunkSize()) {
Chunk = EmitScalarExpr(Ch);
Chunk = EmitScalarConversion(Chunk, Ch->getType(),
- S.getIterationVariable()->getType(),
- S.getLocStart());
+ S.getIterationVariable()->getType(),
+ S.getLocStart());
}
}
const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
@@ -2981,10 +3102,13 @@ void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S,
// league. The size of the chunks is unspecified in this case.
if (RT.isStaticNonchunked(ScheduleKind,
/* Chunked */ Chunk != nullptr)) {
+ if (isOpenMPSimdDirective(S.getDirectiveKind()))
+ EmitOMPSimdInit(S, /*IsMonotonic=*/true);
+ CGOpenMPRuntime::StaticRTInput StaticInit(
+ IVSize, IVSigned, /* Ordered = */ false, IL.getAddress(),
+ LB.getAddress(), UB.getAddress(), ST.getAddress());
RT.emitDistributeStaticInit(*this, S.getLocStart(), ScheduleKind,
- IVSize, IVSigned, /* Ordered = */ false,
- IL.getAddress(), LB.getAddress(),
- UB.getAddress(), ST.getAddress());
+ StaticInit);
auto LoopExit =
getJumpDestInCurrentScope(createBasicBlock("omp.loop.exit"));
// UB = min(UB, GlobalUB);
@@ -3011,7 +3135,7 @@ void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S,
[](CodeGenFunction &) {});
EmitBlock(LoopExit.getBlock());
// Tell the runtime we are done.
- RT.emitForStaticFinish(*this, S.getLocStart());
+ RT.emitForStaticFinish(*this, S.getLocStart(), S.getDirectiveKind());
} else {
// Emit the outer loop, which requests its work chunk [LB..UB] from
// runtime and runs the inner loop to process it.
@@ -3021,13 +3145,38 @@ void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S,
EmitOMPDistributeOuterLoop(ScheduleKind, S, LoopScope, LoopArguments,
CodeGenLoop);
}
-
+ if (isOpenMPSimdDirective(S.getDirectiveKind())) {
+ EmitOMPSimdFinal(S, [&](CodeGenFunction &CGF) -> llvm::Value * {
+ return CGF.Builder.CreateIsNotNull(
+ CGF.EmitLoadOfScalar(IL, S.getLocStart()));
+ });
+ }
+ OpenMPDirectiveKind ReductionKind = OMPD_unknown;
+ if (isOpenMPParallelDirective(S.getDirectiveKind()) &&
+ isOpenMPSimdDirective(S.getDirectiveKind())) {
+ ReductionKind = OMPD_parallel_for_simd;
+ } else if (isOpenMPParallelDirective(S.getDirectiveKind())) {
+ ReductionKind = OMPD_parallel_for;
+ } else if (isOpenMPSimdDirective(S.getDirectiveKind())) {
+ ReductionKind = OMPD_simd;
+ } else if (!isOpenMPTeamsDirective(S.getDirectiveKind()) &&
+ S.hasClausesOfKind<OMPReductionClause>()) {
+ llvm_unreachable(
+ "No reduction clauses is allowed in distribute directive.");
+ }
+ EmitOMPReductionClauseFinal(S, ReductionKind);
+ // Emit post-update of the reduction variables if IsLastIter != 0.
+ emitPostUpdateForReductionClause(
+ *this, S, [&](CodeGenFunction &CGF) -> llvm::Value * {
+ return CGF.Builder.CreateIsNotNull(
+ CGF.EmitLoadOfScalar(IL, S.getLocStart()));
+ });
// Emit final copy of the lastprivate variables if IsLastIter != 0.
- if (HasLastprivateClause)
+ if (HasLastprivateClause) {
EmitOMPLastprivateClauseFinal(
S, /*NoFinals=*/false,
- Builder.CreateIsNotNull(
- EmitLoadOfScalar(IL, S.getLocStart())));
+ Builder.CreateIsNotNull(EmitLoadOfScalar(IL, S.getLocStart())));
+ }
}
// We're now done with the loop, so jump to the continuation block.
@@ -3045,8 +3194,7 @@ void CodeGenFunction::EmitOMPDistributeDirective(
CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc());
};
OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
- CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen,
- false);
+ CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen);
}
static llvm::Function *emitOutlinedOrderedFunction(CodeGenModule &CGM,
@@ -3073,7 +3221,8 @@ void CodeGenFunction::EmitOMPOrderedDirective(const OMPOrderedDirective &S) {
llvm::SmallVector<llvm::Value *, 16> CapturedVars;
CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
auto *OutlinedFn = emitOutlinedOrderedFunction(CGM, CS);
- CGF.EmitNounwindRuntimeCall(OutlinedFn, CapturedVars);
+ CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getLocStart(),
+ OutlinedFn, CapturedVars);
} else {
Action.Enter(CGF);
CGF.EmitStmt(
@@ -3259,6 +3408,7 @@ static std::pair<bool, RValue> emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X,
case BO_GE:
case BO_EQ:
case BO_NE:
+ case BO_Cmp:
case BO_AddAssign:
case BO_SubAssign:
case BO_AndAssign:
@@ -3470,6 +3620,7 @@ static void EmitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
case OMPC_lastprivate:
case OMPC_reduction:
case OMPC_task_reduction:
+ case OMPC_in_reduction:
case OMPC_safelen:
case OMPC_simdlen:
case OMPC_collapse:
@@ -3552,7 +3703,7 @@ static void emitCommonOMPTargetDirective(CodeGenFunction &CGF,
const RegionCodeGenTy &CodeGen) {
assert(isOpenMPTargetExecutionDirective(S.getDirectiveKind()));
CodeGenModule &CGM = CGF.CGM;
- const CapturedStmt &CS = *cast<CapturedStmt>(S.getAssociatedStmt());
+ const CapturedStmt &CS = *S.getCapturedStmt(OMPD_target);
llvm::Function *Fn = nullptr;
llvm::Constant *FnID = nullptr;
@@ -3675,7 +3826,7 @@ void CodeGenFunction::EmitOMPTeamsDirective(const OMPTeamsDirective &S) {
CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
};
- emitCommonOMPTeamsDirective(*this, S, OMPD_teams, CodeGen);
+ emitCommonOMPTeamsDirective(*this, S, OMPD_distribute, CodeGen);
emitPostUpdateForReductionClause(
*this, S, [](CodeGenFunction &) -> llvm::Value * { return nullptr; });
}
@@ -3684,11 +3835,20 @@ static void emitTargetTeamsRegion(CodeGenFunction &CGF, PrePostActionTy &Action,
const OMPTargetTeamsDirective &S) {
auto *CS = S.getCapturedStmt(OMPD_teams);
Action.Enter(CGF);
- auto &&CodeGen = [CS](CodeGenFunction &CGF, PrePostActionTy &) {
- // TODO: Add support for clauses.
+ // Emit teams region as a standalone region.
+ auto &&CodeGen = [&S, CS](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
+ (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
+ CGF.EmitOMPPrivateClause(S, PrivateScope);
+ CGF.EmitOMPReductionClauseInit(S, PrivateScope);
+ (void)PrivateScope.Privatize();
+ Action.Enter(CGF);
CGF.EmitStmt(CS->getCapturedStmt());
+ CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
};
emitCommonOMPTeamsDirective(CGF, S, OMPD_teams, CodeGen);
+ emitPostUpdateForReductionClause(
+ CGF, S, [](CodeGenFunction &) -> llvm::Value * { return nullptr; });
}
void CodeGenFunction::EmitOMPTargetTeamsDeviceFunction(
@@ -3713,6 +3873,183 @@ void CodeGenFunction::EmitOMPTargetTeamsDirective(
emitCommonOMPTargetDirective(*this, S, CodeGen);
}
+static void
+emitTargetTeamsDistributeRegion(CodeGenFunction &CGF, PrePostActionTy &Action,
+ const OMPTargetTeamsDistributeDirective &S) {
+ Action.Enter(CGF);
+ auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc());
+ };
+
+ // Emit teams region as a standalone region.
+ auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
+ PrePostActionTy &) {
+ CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
+ CGF.EmitOMPReductionClauseInit(S, PrivateScope);
+ (void)PrivateScope.Privatize();
+ CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
+ CodeGenDistribute);
+ CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
+ };
+ emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute, CodeGen);
+ emitPostUpdateForReductionClause(CGF, S,
+ [](CodeGenFunction &) { return nullptr; });
+}
+
+void CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction(
+ CodeGenModule &CGM, StringRef ParentName,
+ const OMPTargetTeamsDistributeDirective &S) {
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ emitTargetTeamsDistributeRegion(CGF, Action, S);
+ };
+ llvm::Function *Fn;
+ llvm::Constant *Addr;
+ // Emit target region as a standalone region.
+ CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
+ S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
+ assert(Fn && Addr && "Target device function emission failed.");
+}
+
+void CodeGenFunction::EmitOMPTargetTeamsDistributeDirective(
+ const OMPTargetTeamsDistributeDirective &S) {
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ emitTargetTeamsDistributeRegion(CGF, Action, S);
+ };
+ emitCommonOMPTargetDirective(*this, S, CodeGen);
+}
+
+static void emitTargetTeamsDistributeSimdRegion(
+ CodeGenFunction &CGF, PrePostActionTy &Action,
+ const OMPTargetTeamsDistributeSimdDirective &S) {
+ Action.Enter(CGF);
+ auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc());
+ };
+
+ // Emit teams region as a standalone region.
+ auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
+ PrePostActionTy &) {
+ CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
+ CGF.EmitOMPReductionClauseInit(S, PrivateScope);
+ (void)PrivateScope.Privatize();
+ CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
+ CodeGenDistribute);
+ CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
+ };
+ emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute_simd, CodeGen);
+ emitPostUpdateForReductionClause(CGF, S,
+ [](CodeGenFunction &) { return nullptr; });
+}
+
+void CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction(
+ CodeGenModule &CGM, StringRef ParentName,
+ const OMPTargetTeamsDistributeSimdDirective &S) {
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ emitTargetTeamsDistributeSimdRegion(CGF, Action, S);
+ };
+ llvm::Function *Fn;
+ llvm::Constant *Addr;
+ // Emit target region as a standalone region.
+ CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
+ S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
+ assert(Fn && Addr && "Target device function emission failed.");
+}
+
+void CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDirective(
+ const OMPTargetTeamsDistributeSimdDirective &S) {
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ emitTargetTeamsDistributeSimdRegion(CGF, Action, S);
+ };
+ emitCommonOMPTargetDirective(*this, S, CodeGen);
+}
+
+void CodeGenFunction::EmitOMPTeamsDistributeDirective(
+ const OMPTeamsDistributeDirective &S) {
+
+ auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc());
+ };
+
+ // Emit teams region as a standalone region.
+ auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
+ PrePostActionTy &) {
+ OMPPrivateScope PrivateScope(CGF);
+ CGF.EmitOMPReductionClauseInit(S, PrivateScope);
+ (void)PrivateScope.Privatize();
+ CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
+ CodeGenDistribute);
+ CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
+ };
+ emitCommonOMPTeamsDirective(*this, S, OMPD_distribute, CodeGen);
+ emitPostUpdateForReductionClause(*this, S,
+ [](CodeGenFunction &) { return nullptr; });
+}
+
+void CodeGenFunction::EmitOMPTeamsDistributeSimdDirective(
+ const OMPTeamsDistributeSimdDirective &S) {
+ auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc());
+ };
+
+ // Emit teams region as a standalone region.
+ auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
+ PrePostActionTy &) {
+ OMPPrivateScope PrivateScope(CGF);
+ CGF.EmitOMPReductionClauseInit(S, PrivateScope);
+ (void)PrivateScope.Privatize();
+ CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_simd,
+ CodeGenDistribute);
+ CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
+ };
+ emitCommonOMPTeamsDirective(*this, S, OMPD_distribute_simd, CodeGen);
+ emitPostUpdateForReductionClause(*this, S,
+ [](CodeGenFunction &) { return nullptr; });
+}
+
+void CodeGenFunction::EmitOMPTeamsDistributeParallelForDirective(
+ const OMPTeamsDistributeParallelForDirective &S) {
+ auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined,
+ S.getDistInc());
+ };
+
+ // Emit teams region as a standalone region.
+ auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
+ PrePostActionTy &) {
+ OMPPrivateScope PrivateScope(CGF);
+ CGF.EmitOMPReductionClauseInit(S, PrivateScope);
+ (void)PrivateScope.Privatize();
+ CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
+ CodeGenDistribute);
+ CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
+ };
+ emitCommonOMPTeamsDirective(*this, S, OMPD_distribute_parallel_for, CodeGen);
+ emitPostUpdateForReductionClause(*this, S,
+ [](CodeGenFunction &) { return nullptr; });
+}
+
+void CodeGenFunction::EmitOMPTeamsDistributeParallelForSimdDirective(
+ const OMPTeamsDistributeParallelForSimdDirective &S) {
+ auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined,
+ S.getDistInc());
+ };
+
+ // Emit teams region as a standalone region.
+ auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
+ PrePostActionTy &) {
+ OMPPrivateScope PrivateScope(CGF);
+ CGF.EmitOMPReductionClauseInit(S, PrivateScope);
+ (void)PrivateScope.Privatize();
+ CGF.CGM.getOpenMPRuntime().emitInlinedDirective(
+ CGF, OMPD_distribute, CodeGenDistribute, /*HasCancel=*/false);
+ CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
+ };
+ emitCommonOMPTeamsDirective(*this, S, OMPD_distribute_parallel_for, CodeGen);
+ emitPostUpdateForReductionClause(*this, S,
+ [](CodeGenFunction &) { return nullptr; });
+}
+
void CodeGenFunction::EmitOMPCancellationPointDirective(
const OMPCancellationPointDirective &S) {
CGM.getOpenMPRuntime().emitCancellationPointCall(*this, S.getLocStart(),
@@ -3740,7 +4077,9 @@ CodeGenFunction::getOMPCancelDestination(OpenMPDirectiveKind Kind) {
assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections ||
Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for ||
Kind == OMPD_distribute_parallel_for ||
- Kind == OMPD_target_parallel_for);
+ Kind == OMPD_target_parallel_for ||
+ Kind == OMPD_teams_distribute_parallel_for ||
+ Kind == OMPD_target_teams_distribute_parallel_for);
return OMPCancelStack.getExitBlock();
}
@@ -3913,7 +4252,14 @@ void CodeGenFunction::EmitOMPTargetEnterDataDirective(
if (auto *C = S.getSingleClause<OMPDeviceClause>())
Device = C->getDevice();
- CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device);
+ auto &&CodeGen = [&S, IfCond, Device](CodeGenFunction &CGF,
+ PrePostActionTy &) {
+ CGF.CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(CGF, S, IfCond,
+ Device);
+ };
+ OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
+ CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_target_enter_data,
+ CodeGen);
}
void CodeGenFunction::EmitOMPTargetExitDataDirective(
@@ -3933,7 +4279,14 @@ void CodeGenFunction::EmitOMPTargetExitDataDirective(
if (auto *C = S.getSingleClause<OMPDeviceClause>())
Device = C->getDevice();
- CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device);
+ auto &&CodeGen = [&S, IfCond, Device](CodeGenFunction &CGF,
+ PrePostActionTy &) {
+ CGF.CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(CGF, S, IfCond,
+ Device);
+ };
+ OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
+ CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_target_exit_data,
+ CodeGen);
}
static void emitTargetParallelRegion(CodeGenFunction &CGF,
@@ -3980,9 +4333,81 @@ void CodeGenFunction::EmitOMPTargetParallelDirective(
emitCommonOMPTargetDirective(*this, S, CodeGen);
}
+static void emitTargetParallelForRegion(CodeGenFunction &CGF,
+ const OMPTargetParallelForDirective &S,
+ PrePostActionTy &Action) {
+ Action.Enter(CGF);
+ // Emit directive as a combined directive that consists of two implicit
+ // directives: 'parallel' with 'for' directive.
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ CodeGenFunction::OMPCancelStackRAII CancelRegion(
+ CGF, OMPD_target_parallel_for, S.hasCancel());
+ CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds,
+ emitDispatchForLoopBounds);
+ };
+ emitCommonOMPParallelDirective(CGF, S, OMPD_for, CodeGen,
+ emitEmptyBoundParameters);
+}
+
+void CodeGenFunction::EmitOMPTargetParallelForDeviceFunction(
+ CodeGenModule &CGM, StringRef ParentName,
+ const OMPTargetParallelForDirective &S) {
+ // Emit SPMD target parallel for region as a standalone region.
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ emitTargetParallelForRegion(CGF, S, Action);
+ };
+ llvm::Function *Fn;
+ llvm::Constant *Addr;
+ // Emit target region as a standalone region.
+ CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
+ S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
+ assert(Fn && Addr && "Target device function emission failed.");
+}
+
void CodeGenFunction::EmitOMPTargetParallelForDirective(
const OMPTargetParallelForDirective &S) {
- // TODO: codegen for target parallel for.
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ emitTargetParallelForRegion(CGF, S, Action);
+ };
+ emitCommonOMPTargetDirective(*this, S, CodeGen);
+}
+
+static void
+emitTargetParallelForSimdRegion(CodeGenFunction &CGF,
+ const OMPTargetParallelForSimdDirective &S,
+ PrePostActionTy &Action) {
+ Action.Enter(CGF);
+ // Emit directive as a combined directive that consists of two implicit
+ // directives: 'parallel' with 'for' directive.
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds,
+ emitDispatchForLoopBounds);
+ };
+ emitCommonOMPParallelDirective(CGF, S, OMPD_simd, CodeGen,
+ emitEmptyBoundParameters);
+}
+
+void CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction(
+ CodeGenModule &CGM, StringRef ParentName,
+ const OMPTargetParallelForSimdDirective &S) {
+ // Emit SPMD target parallel for region as a standalone region.
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ emitTargetParallelForSimdRegion(CGF, S, Action);
+ };
+ llvm::Function *Fn;
+ llvm::Constant *Addr;
+ // Emit target region as a standalone region.
+ CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
+ S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
+ assert(Fn && Addr && "Target device function emission failed.");
+}
+
+void CodeGenFunction::EmitOMPTargetParallelForSimdDirective(
+ const OMPTargetParallelForSimdDirective &S) {
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ emitTargetParallelForSimdRegion(CGF, S, Action);
+ };
+ emitCommonOMPTargetDirective(*this, S, CodeGen);
}
/// Emit a helper variable and return corresponding lvalue.
@@ -4160,5 +4585,12 @@ void CodeGenFunction::EmitOMPTargetUpdateDirective(
if (auto *C = S.getSingleClause<OMPDeviceClause>())
Device = C->getDevice();
- CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device);
+ auto &&CodeGen = [&S, IfCond, Device](CodeGenFunction &CGF,
+ PrePostActionTy &) {
+ CGF.CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(CGF, S, IfCond,
+ Device);
+ };
+ OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
+ CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_target_update,
+ CodeGen);
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp
index 92fd93b5ca387..78928d04220d3 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp
@@ -100,7 +100,7 @@ CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT,
VTT->setComdat(CGM.getModule().getOrInsertComdat(VTT->getName()));
// Set the right visibility.
- CGM.setGlobalVisibility(VTT, RD);
+ CGM.setGlobalVisibility(VTT, RD, ForDefinition);
}
llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTT(const CXXRecordDecl *RD) {
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp
index 64b6d0d3fe9f5..2d9bf3bce926a 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp
@@ -14,11 +14,12 @@
#include "CGCXXABI.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
-#include "clang/CodeGen/ConstantInitBuilder.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/RecordLayout.h"
#include "clang/CodeGen/CGFunctionInfo.h"
+#include "clang/CodeGen/ConstantInitBuilder.h"
#include "clang/Frontend/CodeGenOptions.h"
+#include "llvm/IR/IntrinsicInst.h"
#include "llvm/Support/Format.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include <algorithm>
@@ -50,7 +51,7 @@ llvm::Constant *CodeGenModule::GetAddrOfThunk(GlobalDecl GD,
static void setThunkVisibility(CodeGenModule &CGM, const CXXMethodDecl *MD,
const ThunkInfo &Thunk, llvm::Function *Fn) {
- CGM.setGlobalVisibility(Fn, MD);
+ CGM.setGlobalVisibility(Fn, MD, ForDefinition);
}
static void setThunkProperties(CodeGenModule &CGM, const ThunkInfo &Thunk,
@@ -122,6 +123,33 @@ static RValue PerformReturnAdjustment(CodeGenFunction &CGF,
return RValue::get(ReturnValue);
}
+/// This function clones a function's DISubprogram node and enters it into
+/// a value map with the intent that the map can be utilized by the cloner
+/// to short-circuit Metadata node mapping.
+/// Furthermore, the function resolves any DILocalVariable nodes referenced
+/// by dbg.value intrinsics so they can be properly mapped during cloning.
+static void resolveTopLevelMetadata(llvm::Function *Fn,
+ llvm::ValueToValueMapTy &VMap) {
+ // Clone the DISubprogram node and put it into the Value map.
+ auto *DIS = Fn->getSubprogram();
+ if (!DIS)
+ return;
+ auto *NewDIS = DIS->replaceWithDistinct(DIS->clone());
+ VMap.MD()[DIS].reset(NewDIS);
+
+ // Find all llvm.dbg.declare intrinsics and resolve the DILocalVariable nodes
+ // they are referencing.
+ for (auto &BB : Fn->getBasicBlockList()) {
+ for (auto &I : BB) {
+ if (auto *DII = dyn_cast<llvm::DbgInfoIntrinsic>(&I)) {
+ auto *DILocal = DII->getVariable();
+ if (!DILocal->isResolved())
+ DILocal->resolve();
+ }
+ }
+ }
+}
+
// This function does roughly the same thing as GenerateThunk, but in a
// very different way, so that va_start and va_end work correctly.
// FIXME: This function assumes "this" is the first non-sret LLVM argument of
@@ -154,6 +182,10 @@ CodeGenFunction::GenerateVarArgsThunk(llvm::Function *Fn,
// Clone to thunk.
llvm::ValueToValueMapTy VMap;
+
+ // We are cloning a function while some Metadata nodes are still unresolved.
+ // Ensure that the value mapper does not encounter any of them.
+ resolveTopLevelMetadata(BaseFn, VMap);
llvm::Function *NewFn = llvm::CloneFunction(BaseFn, VMap);
Fn->replaceAllUsesWith(NewFn);
NewFn->takeName(Fn);
@@ -698,7 +730,7 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
// Create the variable that will hold the construction vtable.
llvm::GlobalVariable *VTable =
CGM.CreateOrReplaceCXXRuntimeVariable(Name, VTType, Linkage);
- CGM.setGlobalVisibility(VTable, RD);
+ CGM.setGlobalVisibility(VTable, RD, ForDefinition);
// V-tables are always unnamed_addr.
VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGValue.h b/contrib/llvm/tools/clang/lib/CodeGen/CGValue.h
index b768eb86367be..7d07ea4516c92 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGValue.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGValue.h
@@ -20,6 +20,7 @@
#include "llvm/IR/Value.h"
#include "llvm/IR/Type.h"
#include "Address.h"
+#include "CodeGenTBAA.h"
namespace llvm {
class Constant;
@@ -148,20 +149,15 @@ static inline AlignmentSource getFieldAlignmentSource(AlignmentSource Source) {
class LValueBaseInfo {
AlignmentSource AlignSource;
- bool MayAlias;
public:
- explicit LValueBaseInfo(AlignmentSource Source = AlignmentSource::Type,
- bool Alias = false)
- : AlignSource(Source), MayAlias(Alias) {}
+ explicit LValueBaseInfo(AlignmentSource Source = AlignmentSource::Type)
+ : AlignSource(Source) {}
AlignmentSource getAlignmentSource() const { return AlignSource; }
void setAlignmentSource(AlignmentSource Source) { AlignSource = Source; }
- bool getMayAlias() const { return MayAlias; }
- void setMayAlias(bool Alias) { MayAlias = Alias; }
void mergeForCast(const LValueBaseInfo &Info) {
setAlignmentSource(Info.getAlignmentSource());
- setMayAlias(getMayAlias() || Info.getMayAlias());
}
};
@@ -220,6 +216,7 @@ class LValue {
bool ImpreciseLifetime : 1;
LValueBaseInfo BaseInfo;
+ TBAAAccessInfo TBAAInfo;
// This flag shows if a nontemporal load/stores should be used when accessing
// this lvalue.
@@ -227,18 +224,9 @@ class LValue {
Expr *BaseIvarExp;
- /// Used by struct-path-aware TBAA.
- QualType TBAABaseType;
- /// Offset relative to the base type.
- uint64_t TBAAOffset;
-
- /// TBAAInfo - TBAA information to attach to dereferences of this LValue.
- llvm::MDNode *TBAAInfo;
-
private:
- void Initialize(QualType Type, Qualifiers Quals,
- CharUnits Alignment, LValueBaseInfo BaseInfo,
- llvm::MDNode *TBAAInfo = nullptr) {
+ void Initialize(QualType Type, Qualifiers Quals, CharUnits Alignment,
+ LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo) {
assert((!Alignment.isZero() || Type->isIncompleteType()) &&
"initializing l-value with zero alignment!");
this->Type = Type;
@@ -247,6 +235,7 @@ private:
assert(this->Alignment == Alignment.getQuantity() &&
"Alignment exceeds allowed max!");
this->BaseInfo = BaseInfo;
+ this->TBAAInfo = TBAAInfo;
// Initialize Objective-C flags.
this->Ivar = this->ObjIsArray = this->NonGC = this->GlobalObjCRef = false;
@@ -254,11 +243,6 @@ private:
this->Nontemporal = false;
this->ThreadLocalRef = false;
this->BaseIvarExp = nullptr;
-
- // Initialize fields for TBAA.
- this->TBAABaseType = Type;
- this->TBAAOffset = 0;
- this->TBAAInfo = TBAAInfo;
}
public:
@@ -318,19 +302,13 @@ public:
Expr *getBaseIvarExp() const { return BaseIvarExp; }
void setBaseIvarExp(Expr *V) { BaseIvarExp = V; }
- QualType getTBAABaseType() const { return TBAABaseType; }
- void setTBAABaseType(QualType T) { TBAABaseType = T; }
-
- uint64_t getTBAAOffset() const { return TBAAOffset; }
- void setTBAAOffset(uint64_t O) { TBAAOffset = O; }
-
- llvm::MDNode *getTBAAInfo() const { return TBAAInfo; }
- void setTBAAInfo(llvm::MDNode *N) { TBAAInfo = N; }
+ TBAAAccessInfo getTBAAInfo() const { return TBAAInfo; }
+ void setTBAAInfo(TBAAAccessInfo Info) { TBAAInfo = Info; }
const Qualifiers &getQuals() const { return Quals; }
Qualifiers &getQuals() { return Quals; }
- unsigned getAddressSpace() const { return Quals.getAddressSpace(); }
+ LangAS getAddressSpace() const { return Quals.getAddressSpace(); }
CharUnits getAlignment() const { return CharUnits::fromQuantity(Alignment); }
void setAlignment(CharUnits A) { Alignment = A.getQuantity(); }
@@ -383,10 +361,8 @@ public:
// global register lvalue
llvm::Value *getGlobalReg() const { assert(isGlobalReg()); return V; }
- static LValue MakeAddr(Address address, QualType type,
- ASTContext &Context,
- LValueBaseInfo BaseInfo,
- llvm::MDNode *TBAAInfo = nullptr) {
+ static LValue MakeAddr(Address address, QualType type, ASTContext &Context,
+ LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo) {
Qualifiers qs = type.getQualifiers();
qs.setObjCGCAttr(Context.getObjCGCAttrKind(type));
@@ -399,24 +375,26 @@ public:
}
static LValue MakeVectorElt(Address vecAddress, llvm::Value *Idx,
- QualType type, LValueBaseInfo BaseInfo) {
+ QualType type, LValueBaseInfo BaseInfo,
+ TBAAAccessInfo TBAAInfo) {
LValue R;
R.LVType = VectorElt;
R.V = vecAddress.getPointer();
R.VectorIdx = Idx;
R.Initialize(type, type.getQualifiers(), vecAddress.getAlignment(),
- BaseInfo);
+ BaseInfo, TBAAInfo);
return R;
}
static LValue MakeExtVectorElt(Address vecAddress, llvm::Constant *Elts,
- QualType type, LValueBaseInfo BaseInfo) {
+ QualType type, LValueBaseInfo BaseInfo,
+ TBAAAccessInfo TBAAInfo) {
LValue R;
R.LVType = ExtVectorElt;
R.V = vecAddress.getPointer();
R.VectorElts = Elts;
R.Initialize(type, type.getQualifiers(), vecAddress.getAlignment(),
- BaseInfo);
+ BaseInfo, TBAAInfo);
return R;
}
@@ -426,15 +404,15 @@ public:
/// bit-field refers to.
/// \param Info - The information describing how to perform the bit-field
/// access.
- static LValue MakeBitfield(Address Addr,
- const CGBitFieldInfo &Info,
- QualType type,
- LValueBaseInfo BaseInfo) {
+ static LValue MakeBitfield(Address Addr, const CGBitFieldInfo &Info,
+ QualType type, LValueBaseInfo BaseInfo,
+ TBAAAccessInfo TBAAInfo) {
LValue R;
R.LVType = BitField;
R.V = Addr.getPointer();
R.BitFieldInfo = &Info;
- R.Initialize(type, type.getQualifiers(), Addr.getAlignment(), BaseInfo);
+ R.Initialize(type, type.getQualifiers(), Addr.getAlignment(), BaseInfo,
+ TBAAInfo);
return R;
}
@@ -443,7 +421,7 @@ public:
R.LVType = GlobalReg;
R.V = Reg.getPointer();
R.Initialize(type, type.getQualifiers(), Reg.getAlignment(),
- LValueBaseInfo(AlignmentSource::Decl, false));
+ LValueBaseInfo(AlignmentSource::Decl), TBAAAccessInfo());
return R;
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenABITypes.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenABITypes.cpp
index 0735a9c3dfbc1..c152291b15b93 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenABITypes.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenABITypes.cpp
@@ -17,6 +17,7 @@
//===----------------------------------------------------------------------===//
#include "clang/CodeGen/CodeGenABITypes.h"
+#include "CGRecordLayout.h"
#include "CodeGenModule.h"
#include "clang/CodeGen/CGFunctionInfo.h"
#include "clang/Frontend/CodeGenOptions.h"
@@ -80,3 +81,9 @@ llvm::Type *
CodeGen::convertTypeForMemory(CodeGenModule &CGM, QualType T) {
return CGM.getTypes().ConvertTypeForMem(T);
}
+
+unsigned CodeGen::getLLVMFieldNumber(CodeGenModule &CGM,
+ const RecordDecl *RD,
+ const FieldDecl *FD) {
+ return CGM.getTypes().getCGRecordLayout(RD).getLLVMFieldNo(FD);
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp
index 4f03de55149b8..6ca69d63cdce7 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp
@@ -46,6 +46,38 @@ using namespace clang;
using namespace llvm;
namespace clang {
+ class BackendConsumer;
+ class ClangDiagnosticHandler final : public DiagnosticHandler {
+ public:
+ ClangDiagnosticHandler(const CodeGenOptions &CGOpts, BackendConsumer *BCon)
+ : CodeGenOpts(CGOpts), BackendCon(BCon) {}
+
+ bool handleDiagnostics(const DiagnosticInfo &DI) override;
+
+ bool isAnalysisRemarkEnabled(StringRef PassName) const override {
+ return (CodeGenOpts.OptimizationRemarkAnalysisPattern &&
+ CodeGenOpts.OptimizationRemarkAnalysisPattern->match(PassName));
+ }
+ bool isMissedOptRemarkEnabled(StringRef PassName) const override {
+ return (CodeGenOpts.OptimizationRemarkMissedPattern &&
+ CodeGenOpts.OptimizationRemarkMissedPattern->match(PassName));
+ }
+ bool isPassedOptRemarkEnabled(StringRef PassName) const override {
+ return (CodeGenOpts.OptimizationRemarkPattern &&
+ CodeGenOpts.OptimizationRemarkPattern->match(PassName));
+ }
+
+ bool isAnyRemarkEnabled() const override {
+ return (CodeGenOpts.OptimizationRemarkAnalysisPattern ||
+ CodeGenOpts.OptimizationRemarkMissedPattern ||
+ CodeGenOpts.OptimizationRemarkPattern);
+ }
+
+ private:
+ const CodeGenOptions &CodeGenOpts;
+ BackendConsumer *BackendCon;
+ };
+
class BackendConsumer : public ASTConsumer {
using LinkModule = CodeGenAction::LinkModule;
@@ -224,21 +256,20 @@ namespace clang {
void *OldContext = Ctx.getInlineAsmDiagnosticContext();
Ctx.setInlineAsmDiagnosticHandler(InlineAsmDiagHandler, this);
- LLVMContext::DiagnosticHandlerTy OldDiagnosticHandler =
+ std::unique_ptr<DiagnosticHandler> OldDiagnosticHandler =
Ctx.getDiagnosticHandler();
- void *OldDiagnosticContext = Ctx.getDiagnosticContext();
- Ctx.setDiagnosticHandler(DiagnosticHandler, this);
+ Ctx.setDiagnosticHandler(llvm::make_unique<ClangDiagnosticHandler>(
+ CodeGenOpts, this));
Ctx.setDiagnosticsHotnessRequested(CodeGenOpts.DiagnosticsWithHotness);
if (CodeGenOpts.DiagnosticsHotnessThreshold != 0)
Ctx.setDiagnosticsHotnessThreshold(
CodeGenOpts.DiagnosticsHotnessThreshold);
- std::unique_ptr<llvm::tool_output_file> OptRecordFile;
+ std::unique_ptr<llvm::ToolOutputFile> OptRecordFile;
if (!CodeGenOpts.OptRecordFile.empty()) {
std::error_code EC;
- OptRecordFile =
- llvm::make_unique<llvm::tool_output_file>(CodeGenOpts.OptRecordFile,
- EC, sys::fs::F_None);
+ OptRecordFile = llvm::make_unique<llvm::ToolOutputFile>(
+ CodeGenOpts.OptRecordFile, EC, sys::fs::F_None);
if (EC) {
Diags.Report(diag::err_cannot_open_file) <<
CodeGenOpts.OptRecordFile << EC.message();
@@ -264,7 +295,7 @@ namespace clang {
Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext);
- Ctx.setDiagnosticHandler(OldDiagnosticHandler, OldDiagnosticContext);
+ Ctx.setDiagnosticHandler(std::move(OldDiagnosticHandler));
if (OptRecordFile)
OptRecordFile->keep();
@@ -299,11 +330,6 @@ namespace clang {
((BackendConsumer*)Context)->InlineAsmDiagHandler2(SM, Loc);
}
- static void DiagnosticHandler(const llvm::DiagnosticInfo &DI,
- void *Context) {
- ((BackendConsumer *)Context)->DiagnosticHandlerImpl(DI);
- }
-
/// Get the best possible source location to represent a diagnostic that
/// may have associated debug info.
const FullSourceLoc
@@ -343,6 +369,11 @@ namespace clang {
void BackendConsumer::anchor() {}
}
+bool ClangDiagnosticHandler::handleDiagnostics(const DiagnosticInfo &DI) {
+ BackendCon->DiagnosticHandlerImpl(DI);
+ return true;
+}
+
/// ConvertBackendLocation - Convert a location in a temporary llvm::SourceMgr
/// buffer to be a valid FullSourceLoc.
static FullSourceLoc ConvertBackendLocation(const llvm::SMDiagnostic &D,
@@ -402,6 +433,8 @@ void BackendConsumer::InlineAsmDiagHandler2(const llvm::SMDiagnostic &D,
case llvm::SourceMgr::DK_Note:
DiagID = diag::note_fe_inline_asm;
break;
+ case llvm::SourceMgr::DK_Remark:
+ llvm_unreachable("remarks unexpected");
}
// If this problem has clang-level source location information, report the
// issue in the source with a note showing the instantiated
@@ -600,6 +633,10 @@ void BackendConsumer::EmitOptimizationMessage(
void BackendConsumer::OptimizationRemarkHandler(
const llvm::DiagnosticInfoOptimizationBase &D) {
+ // Without hotness information, don't show noisy remarks.
+ if (D.isVerbose() && !D.getHotness())
+ return;
+
if (D.isPassed()) {
// Optimization remarks are active only if the -Rpass flag has a regular
// expression that matches the name of the pass name in \p D.
@@ -884,6 +921,8 @@ static void BitcodeInlineAsmDiagHandler(const llvm::SMDiagnostic &SM,
case llvm::SourceMgr::DK_Note:
DiagID = diag::note_fe_inline_asm;
break;
+ case llvm::SourceMgr::DK_Remark:
+ llvm_unreachable("remarks unexpected");
}
Diags->Report(DiagID).AddString("cannot compile inline asm");
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp
index c23b25ea461fe..9dbd7cc3fcbfb 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -33,9 +33,11 @@
#include "clang/Frontend/CodeGenOptions.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Dominators.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Operator.h"
+#include "llvm/Transforms/Utils/PromoteMemToReg.h"
using namespace clang;
using namespace CodeGen;
@@ -87,7 +89,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
llvm::FastMathFlags FMF;
if (CGM.getLangOpts().FastMath)
- FMF.setUnsafeAlgebra();
+ FMF.setFast();
if (CGM.getLangOpts().FiniteMathOnly) {
FMF.setNoNaNs();
FMF.setNoInfs();
@@ -101,6 +103,9 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
if (CGM.getCodeGenOpts().ReciprocalMath) {
FMF.setAllowReciprocal();
}
+ if (CGM.getCodeGenOpts().Reassociate) {
+ FMF.setAllowReassoc();
+ }
Builder.setFastMathFlags(FMF);
}
@@ -118,27 +123,32 @@ CodeGenFunction::~CodeGenFunction() {
}
CharUnits CodeGenFunction::getNaturalPointeeTypeAlignment(QualType T,
- LValueBaseInfo *BaseInfo) {
- return getNaturalTypeAlignment(T->getPointeeType(), BaseInfo,
- /*forPointee*/ true);
+ LValueBaseInfo *BaseInfo,
+ TBAAAccessInfo *TBAAInfo) {
+ return getNaturalTypeAlignment(T->getPointeeType(), BaseInfo, TBAAInfo,
+ /* forPointeeType= */ true);
}
CharUnits CodeGenFunction::getNaturalTypeAlignment(QualType T,
LValueBaseInfo *BaseInfo,
+ TBAAAccessInfo *TBAAInfo,
bool forPointeeType) {
+ if (TBAAInfo)
+ *TBAAInfo = CGM.getTBAAAccessInfo(T);
+
// Honor alignment typedef attributes even on incomplete types.
// We also honor them straight for C++ class types, even as pointees;
// there's an expressivity gap here.
if (auto TT = T->getAs<TypedefType>()) {
if (auto Align = TT->getDecl()->getMaxAlignment()) {
if (BaseInfo)
- *BaseInfo = LValueBaseInfo(AlignmentSource::AttributedType, false);
+ *BaseInfo = LValueBaseInfo(AlignmentSource::AttributedType);
return getContext().toCharUnitsFromBits(Align);
}
}
if (BaseInfo)
- *BaseInfo = LValueBaseInfo(AlignmentSource::Type, false);
+ *BaseInfo = LValueBaseInfo(AlignmentSource::Type);
CharUnits Alignment;
if (T->isIncompleteType()) {
@@ -169,9 +179,10 @@ CharUnits CodeGenFunction::getNaturalTypeAlignment(QualType T,
LValue CodeGenFunction::MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T) {
LValueBaseInfo BaseInfo;
- CharUnits Alignment = getNaturalTypeAlignment(T, &BaseInfo);
+ TBAAAccessInfo TBAAInfo;
+ CharUnits Alignment = getNaturalTypeAlignment(T, &BaseInfo, &TBAAInfo);
return LValue::MakeAddr(Address(V, Alignment), T, getContext(), BaseInfo,
- CGM.getTBAAInfo(T));
+ TBAAInfo);
}
/// Given a value of type T* that may not be to a complete object,
@@ -179,8 +190,10 @@ LValue CodeGenFunction::MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T) {
LValue
CodeGenFunction::MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T) {
LValueBaseInfo BaseInfo;
- CharUnits Align = getNaturalTypeAlignment(T, &BaseInfo, /*pointee*/ true);
- return MakeAddrLValue(Address(V, Align), T, BaseInfo);
+ TBAAAccessInfo TBAAInfo;
+ CharUnits Align = getNaturalTypeAlignment(T, &BaseInfo, &TBAAInfo,
+ /* forPointeeType= */ true);
+ return MakeAddrLValue(Address(V, Align), T, BaseInfo, TBAAInfo);
}
@@ -344,8 +357,13 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
// Emit function epilog (to return).
llvm::DebugLoc Loc = EmitReturnBlock();
- if (ShouldInstrumentFunction())
- EmitFunctionInstrumentation("__cyg_profile_func_exit");
+ if (ShouldInstrumentFunction()) {
+ if (CGM.getCodeGenOpts().InstrumentFunctions)
+ CurFn->addFnAttr("instrument-function-exit", "__cyg_profile_func_exit");
+ if (CGM.getCodeGenOpts().InstrumentFunctionsAfterInlining)
+ CurFn->addFnAttr("instrument-function-exit-inlined",
+ "__cyg_profile_func_exit");
+ }
// Emit debug descriptor for function end.
if (CGDebugInfo *DI = getDebugInfo())
@@ -411,12 +429,26 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
I->first->replaceAllUsesWith(I->second);
I->first->eraseFromParent();
}
+
+ // Eliminate CleanupDestSlot alloca by replacing it with SSA values and
+ // PHIs if the current function is a coroutine. We don't do it for all
+ // functions as it may result in slight increase in numbers of instructions
+ // if compiled with no optimizations. We do it for coroutine as the lifetime
+ // of CleanupDestSlot alloca make correct coroutine frame building very
+ // difficult.
+ if (NormalCleanupDest && isCoroutine()) {
+ llvm::DominatorTree DT(*CurFn);
+ llvm::PromoteMemToReg(NormalCleanupDest, DT);
+ NormalCleanupDest = nullptr;
+ }
}
/// ShouldInstrumentFunction - Return true if the current function should be
/// instrumented with __cyg_profile_func_* calls
bool CodeGenFunction::ShouldInstrumentFunction() {
- if (!CGM.getCodeGenOpts().InstrumentFunctions)
+ if (!CGM.getCodeGenOpts().InstrumentFunctions &&
+ !CGM.getCodeGenOpts().InstrumentFunctionsAfterInlining &&
+ !CGM.getCodeGenOpts().InstrumentFunctionEntryBare)
return false;
if (!CurFuncDecl || CurFuncDecl->hasAttr<NoInstrumentFunctionAttr>())
return false;
@@ -429,29 +461,47 @@ bool CodeGenFunction::ShouldXRayInstrumentFunction() const {
return CGM.getCodeGenOpts().XRayInstrumentFunctions;
}
-/// EmitFunctionInstrumentation - Emit LLVM code to call the specified
-/// instrumentation function with the current function and the call site, if
-/// function instrumentation is enabled.
-void CodeGenFunction::EmitFunctionInstrumentation(const char *Fn) {
- auto NL = ApplyDebugLocation::CreateArtificial(*this);
- // void __cyg_profile_func_{enter,exit} (void *this_fn, void *call_site);
- llvm::PointerType *PointerTy = Int8PtrTy;
- llvm::Type *ProfileFuncArgs[] = { PointerTy, PointerTy };
- llvm::FunctionType *FunctionTy =
- llvm::FunctionType::get(VoidTy, ProfileFuncArgs, false);
+/// AlwaysEmitXRayCustomEvents - Return true if we should emit IR for calls to
+/// the __xray_customevent(...) builin calls, when doing XRay instrumentation.
+bool CodeGenFunction::AlwaysEmitXRayCustomEvents() const {
+ return CGM.getCodeGenOpts().XRayAlwaysEmitCustomEvents;
+}
- llvm::Constant *F = CGM.CreateRuntimeFunction(FunctionTy, Fn);
- llvm::CallInst *CallSite = Builder.CreateCall(
- CGM.getIntrinsic(llvm::Intrinsic::returnaddress),
- llvm::ConstantInt::get(Int32Ty, 0),
- "callsite");
+llvm::Constant *
+CodeGenFunction::EncodeAddrForUseInPrologue(llvm::Function *F,
+ llvm::Constant *Addr) {
+ // Addresses stored in prologue data can't require run-time fixups and must
+ // be PC-relative. Run-time fixups are undesirable because they necessitate
+ // writable text segments, which are unsafe. And absolute addresses are
+ // undesirable because they break PIE mode.
- llvm::Value *args[] = {
- llvm::ConstantExpr::getBitCast(CurFn, PointerTy),
- CallSite
- };
+ // Add a layer of indirection through a private global. Taking its address
+ // won't result in a run-time fixup, even if Addr has linkonce_odr linkage.
+ auto *GV = new llvm::GlobalVariable(CGM.getModule(), Addr->getType(),
+ /*isConstant=*/true,
+ llvm::GlobalValue::PrivateLinkage, Addr);
- EmitNounwindRuntimeCall(F, args);
+ // Create a PC-relative address.
+ auto *GOTAsInt = llvm::ConstantExpr::getPtrToInt(GV, IntPtrTy);
+ auto *FuncAsInt = llvm::ConstantExpr::getPtrToInt(F, IntPtrTy);
+ auto *PCRelAsInt = llvm::ConstantExpr::getSub(GOTAsInt, FuncAsInt);
+ return (IntPtrTy == Int32Ty)
+ ? PCRelAsInt
+ : llvm::ConstantExpr::getTrunc(PCRelAsInt, Int32Ty);
+}
+
+llvm::Value *
+CodeGenFunction::DecodeAddrUsedInPrologue(llvm::Value *F,
+ llvm::Value *EncodedAddr) {
+ // Reconstruct the address of the global.
+ auto *PCRelAsInt = Builder.CreateSExt(EncodedAddr, IntPtrTy);
+ auto *FuncAsInt = Builder.CreatePtrToInt(F, IntPtrTy, "func_addr.int");
+ auto *GOTAsInt = Builder.CreateAdd(PCRelAsInt, FuncAsInt, "global_addr.int");
+ auto *GOTAddr = Builder.CreateIntToPtr(GOTAsInt, Int8PtrPtrTy, "global_addr");
+
+ // Load the original pointer through the global.
+ return Builder.CreateLoad(Address(GOTAddr, getPointerAlign()),
+ "decoded_addr");
}
static void removeImageAccessQualifier(std::string& TyName) {
@@ -480,8 +530,8 @@ static void removeImageAccessQualifier(std::string& TyName) {
// for example in clGetKernelArgInfo() implementation between the address
// spaces with targets without unique mapping to the OpenCL address spaces
// (basically all single AS CPUs).
-static unsigned ArgInfoAddressSpace(unsigned LangAS) {
- switch (LangAS) {
+static unsigned ArgInfoAddressSpace(LangAS AS) {
+ switch (AS) {
case LangAS::opencl_global: return 1;
case LangAS::opencl_constant: return 2;
case LangAS::opencl_local: return 3;
@@ -621,7 +671,10 @@ static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn,
// Get image and pipe access qualifier:
if (ty->isImageType()|| ty->isPipeType()) {
- const OpenCLAccessAttr *A = parm->getAttr<OpenCLAccessAttr>();
+ const Decl *PDecl = parm;
+ if (auto *TD = dyn_cast<TypedefType>(ty))
+ PDecl = TD->getDecl();
+ const OpenCLAccessAttr *A = PDecl->getAttr<OpenCLAccessAttr>();
if (A && A->isWriteOnly())
accessQuals.push_back(llvm::MDString::get(Context, "write_only"));
else if (A && A->isReadWrite())
@@ -721,6 +774,35 @@ static void markAsIgnoreThreadCheckingAtRuntime(llvm::Function *Fn) {
Fn->removeFnAttr(llvm::Attribute::SanitizeThread);
}
+static bool matchesStlAllocatorFn(const Decl *D, const ASTContext &Ctx) {
+ auto *MD = dyn_cast_or_null<CXXMethodDecl>(D);
+ if (!MD || !MD->getDeclName().getAsIdentifierInfo() ||
+ !MD->getDeclName().getAsIdentifierInfo()->isStr("allocate") ||
+ (MD->getNumParams() != 1 && MD->getNumParams() != 2))
+ return false;
+
+ if (MD->parameters()[0]->getType().getCanonicalType() != Ctx.getSizeType())
+ return false;
+
+ if (MD->getNumParams() == 2) {
+ auto *PT = MD->parameters()[1]->getType()->getAs<PointerType>();
+ if (!PT || !PT->isVoidPointerType() ||
+ !PT->getPointeeType().isConstQualified())
+ return false;
+ }
+
+ return true;
+}
+
+/// Return the UBSan prologue signature for \p FD if one is available.
+static llvm::Constant *getPrologueSignature(CodeGenModule &CGM,
+ const FunctionDecl *FD) {
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(FD))
+ if (!MD->isStatic())
+ return nullptr;
+ return CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM);
+}
+
void CodeGenFunction::StartFunction(GlobalDecl GD,
QualType RetTy,
llvm::Function *Fn,
@@ -744,8 +826,19 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
CurFnInfo = &FnInfo;
assert(CurFn->isDeclaration() && "Function already has body?");
- if (CGM.isInSanitizerBlacklist(Fn, Loc))
- SanOpts.clear();
+ // If this function has been blacklisted for any of the enabled sanitizers,
+ // disable the sanitizer for the function.
+ do {
+#define SANITIZER(NAME, ID) \
+ if (SanOpts.empty()) \
+ break; \
+ if (SanOpts.has(SanitizerKind::ID)) \
+ if (CGM.isInSanitizerBlacklist(SanitizerKind::ID, Fn, Loc)) \
+ SanOpts.set(SanitizerKind::ID, false);
+
+#include "clang/Basic/Sanitizers.def"
+#undef SANITIZER
+ } while (0);
if (D) {
// Apply the no_sanitize* attributes to SanOpts.
@@ -756,6 +849,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
// Apply sanitizer attributes to the function.
if (SanOpts.hasOneOf(SanitizerKind::Address | SanitizerKind::KernelAddress))
Fn->addFnAttr(llvm::Attribute::SanitizeAddress);
+ if (SanOpts.hasOneOf(SanitizerKind::HWAddress))
+ Fn->addFnAttr(llvm::Attribute::SanitizeHWAddress);
if (SanOpts.has(SanitizerKind::Thread))
Fn->addFnAttr(llvm::Attribute::SanitizeThread);
if (SanOpts.has(SanitizerKind::Memory))
@@ -780,6 +875,14 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
}
}
+ // Ignore unrelated casts in STL allocate() since the allocator must cast
+ // from void* to T* before object initialization completes. Don't match on the
+ // namespace because not all allocators are in std::
+ if (D && SanOpts.has(SanitizerKind::CFIUnrelatedCast)) {
+ if (matchesStlAllocatorFn(D, getContext()))
+ SanOpts.Mask &= ~SanitizerKind::CFIUnrelatedCast;
+ }
+
// Apply xray attributes to the function (as a string, for now)
if (D && ShouldXRayInstrumentFunction()) {
if (const auto *XRayAttr = D->getAttr<XRayInstrumentAttr>()) {
@@ -799,14 +902,14 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
}
}
- if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
- if (CGM.getLangOpts().OpenMP && FD->hasAttr<OMPDeclareSimdDeclAttr>())
- CGM.getOpenMPRuntime().emitDeclareSimdFunction(FD, Fn);
-
// Add no-jump-tables value.
Fn->addFnAttr("no-jump-tables",
llvm::toStringRef(CGM.getCodeGenOpts().NoUseJumpTables));
+ // Add profile-sample-accurate value.
+ if (CGM.getCodeGenOpts().ProfileSampleAccurate)
+ Fn->addFnAttr("profile-sample-accurate");
+
if (getLangOpts().OpenCL) {
// Add metadata for a kernel function.
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
@@ -817,11 +920,13 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
// prologue data.
if (getLangOpts().CPlusPlus && SanOpts.has(SanitizerKind::Function)) {
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
- if (llvm::Constant *PrologueSig =
- CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM)) {
+ if (llvm::Constant *PrologueSig = getPrologueSignature(CGM, FD)) {
llvm::Constant *FTRTTIConst =
CGM.GetAddrOfRTTIDescriptor(FD->getType(), /*ForEH=*/true);
- llvm::Constant *PrologueStructElems[] = { PrologueSig, FTRTTIConst };
+ llvm::Constant *FTRTTIConstEncoded =
+ EncodeAddrForUseInPrologue(Fn, FTRTTIConst);
+ llvm::Constant *PrologueStructElems[] = {PrologueSig,
+ FTRTTIConstEncoded};
llvm::Constant *PrologueStructConst =
llvm::ConstantStruct::getAnon(PrologueStructElems, /*Packed=*/true);
Fn->setPrologueData(PrologueStructConst);
@@ -885,8 +990,16 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
DI->EmitFunctionStart(GD, Loc, StartLoc, FnType, CurFn, Builder);
}
- if (ShouldInstrumentFunction())
- EmitFunctionInstrumentation("__cyg_profile_func_enter");
+ if (ShouldInstrumentFunction()) {
+ if (CGM.getCodeGenOpts().InstrumentFunctions)
+ CurFn->addFnAttr("instrument-function-entry", "__cyg_profile_func_enter");
+ if (CGM.getCodeGenOpts().InstrumentFunctionsAfterInlining)
+ CurFn->addFnAttr("instrument-function-entry-inlined",
+ "__cyg_profile_func_enter");
+ if (CGM.getCodeGenOpts().InstrumentFunctionEntryBare)
+ CurFn->addFnAttr("instrument-function-entry-inlined",
+ "__cyg_profile_func_enter_bare");
+ }
// Since emitting the mcount call here impacts optimizations such as function
// inlining, we just add an attribute to insert a mcount call in backend.
@@ -896,8 +1009,10 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
if (CGM.getCodeGenOpts().CallFEntry)
Fn->addFnAttr("fentry-call", "true");
else {
- if (!CurFuncDecl || !CurFuncDecl->hasAttr<NoInstrumentFunctionAttr>())
- Fn->addFnAttr("counting-function", getTarget().getMCountName());
+ if (!CurFuncDecl || !CurFuncDecl->hasAttr<NoInstrumentFunctionAttr>()) {
+ Fn->addFnAttr("instrument-function-entry-inlined",
+ getTarget().getMCountName());
+ }
}
}
@@ -1185,16 +1300,11 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
!getLangOpts().CUDAIsDevice &&
FD->hasAttr<CUDAGlobalAttr>())
CGM.getCUDARuntime().emitDeviceStub(*this, Args);
- else if (isa<CXXConversionDecl>(FD) &&
- cast<CXXConversionDecl>(FD)->isLambdaToBlockPointerConversion()) {
- // The lambda conversion to block pointer is special; the semantics can't be
- // expressed in the AST, so IRGen needs to special-case it.
- EmitLambdaToBlockPointerBody(Args);
- } else if (isa<CXXMethodDecl>(FD) &&
- cast<CXXMethodDecl>(FD)->isLambdaStaticInvoker()) {
+ else if (isa<CXXMethodDecl>(FD) &&
+ cast<CXXMethodDecl>(FD)->isLambdaStaticInvoker()) {
// The lambda static invoker function is special, because it forwards or
// clones the body of the function call operator (but is actually static).
- EmitLambdaStaticInvokeFunction(cast<CXXMethodDecl>(FD));
+ EmitLambdaStaticInvokeBody(cast<CXXMethodDecl>(FD));
} else if (FD->isDefaulted() && isa<CXXMethodDecl>(FD) &&
(cast<CXXMethodDecl>(FD)->isCopyAssignmentOperator() ||
cast<CXXMethodDecl>(FD)->isMoveAssignmentOperator())) {
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h
index 6a1fa487ed14f..ab5bbc03db955 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h
@@ -76,6 +76,10 @@ class ObjCAtThrowStmt;
class ObjCAtSynchronizedStmt;
class ObjCAutoreleasePoolStmt;
+namespace analyze_os_log {
+class OSLogBufferLayout;
+}
+
namespace CodeGen {
class CodeGenTypes;
class CGCallee;
@@ -111,6 +115,7 @@ enum TypeEvaluationKind {
SANITIZER_CHECK(DynamicTypeCacheMiss, dynamic_type_cache_miss, 0) \
SANITIZER_CHECK(FloatCastOverflow, float_cast_overflow, 0) \
SANITIZER_CHECK(FunctionTypeMismatch, function_type_mismatch, 0) \
+ SANITIZER_CHECK(InvalidBuiltin, invalid_builtin, 0) \
SANITIZER_CHECK(LoadInvalidValue, load_invalid_value, 0) \
SANITIZER_CHECK(MissingReturn, missing_return, 0) \
SANITIZER_CHECK(MulOverflow, mul_overflow, 0) \
@@ -220,6 +225,10 @@ public:
};
CGCoroInfo CurCoro;
+ bool isCoroutine() const {
+ return CurCoro.Data != nullptr;
+ }
+
/// CurGD - The GlobalDecl for the current function being compiled.
GlobalDecl CurGD;
@@ -262,9 +271,9 @@ public:
if (I->capturesThis())
CXXThisFieldDecl = *Field;
else if (I->capturesVariable())
- CaptureFields[I->getCapturedVar()] = *Field;
+ CaptureFields[I->getCapturedVar()->getCanonicalDecl()] = *Field;
else if (I->capturesVariableByCopy())
- CaptureFields[I->getCapturedVar()] = *Field;
+ CaptureFields[I->getCapturedVar()->getCanonicalDecl()] = *Field;
}
}
@@ -278,7 +287,7 @@ public:
/// \brief Lookup the captured field decl for a variable.
virtual const FieldDecl *lookup(const VarDecl *VD) const {
- return CaptureFields.lookup(VD);
+ return CaptureFields.lookup(VD->getCanonicalDecl());
}
bool isCXXThisExprCaptured() const { return getThisFieldDecl() != nullptr; }
@@ -708,6 +717,7 @@ public:
llvm::function_ref<Address()> PrivateGen) {
assert(PerformCleanup && "adding private to dead scope");
+ LocalVD = LocalVD->getCanonicalDecl();
// Only save it once.
if (SavedLocals.count(LocalVD)) return false;
@@ -758,8 +768,9 @@ public:
ForceCleanup();
}
- /// Checks if the global variable is captured in current function.
+ /// Checks if the global variable is captured in current function.
bool isGlobalVarCaptured(const VarDecl *VD) const {
+ VD = VD->getCanonicalDecl();
return !VD->isLocalVarDeclOrParm() && CGF.LocalDeclMap.count(VD) > 0;
}
@@ -819,7 +830,7 @@ public:
/// block through the normal cleanup handling code (if any) and then
/// on to \arg Dest.
void EmitBranchThroughCleanup(JumpDest Dest);
-
+
/// isObviouslyBranchWithoutCleanups - Return true if a branch to the
/// specified destination obviously has no cleanups to run. 'false' is always
/// a conservatively correct answer for this method.
@@ -1038,7 +1049,7 @@ public:
if (Data.isValid()) Data.unbind(CGF);
}
};
-
+
private:
CGDebugInfo *DebugInfo;
bool DisableDebugInfo;
@@ -1156,19 +1167,6 @@ private:
};
OpenMPCancelExitStack OMPCancelStack;
- /// Controls insertion of cancellation exit blocks in worksharing constructs.
- class OMPCancelStackRAII {
- CodeGenFunction &CGF;
-
- public:
- OMPCancelStackRAII(CodeGenFunction &CGF, OpenMPDirectiveKind Kind,
- bool HasCancel)
- : CGF(CGF) {
- CGF.OMPCancelStack.enter(CGF, Kind, HasCancel);
- }
- ~OMPCancelStackRAII() { CGF.OMPCancelStack.exit(CGF); }
- };
-
CodeGenPGO PGO;
/// Calculate branch weights appropriate for PGO data
@@ -1427,7 +1425,7 @@ private:
/// Add OpenCL kernel arg metadata and the kernel attribute meatadata to
/// the function metadata.
- void EmitOpenCLKernelMetadata(const FunctionDecl *FD,
+ void EmitOpenCLKernelMetadata(const FunctionDecl *FD,
llvm::Function *Fn);
public:
@@ -1436,10 +1434,10 @@ public:
CodeGenTypes &getTypes() const { return CGM.getTypes(); }
ASTContext &getContext() const { return CGM.getContext(); }
- CGDebugInfo *getDebugInfo() {
- if (DisableDebugInfo)
+ CGDebugInfo *getDebugInfo() {
+ if (DisableDebugInfo)
return nullptr;
- return DebugInfo;
+ return DebugInfo;
}
void disableDebugInfo() { DisableDebugInfo = true; }
void enableDebugInfo() { DisableDebugInfo = false; }
@@ -1577,13 +1575,21 @@ public:
// Block Bits
//===--------------------------------------------------------------------===//
- llvm::Value *EmitBlockLiteral(const BlockExpr *);
+ /// Emit block literal.
+ /// \return an LLVM value which is a pointer to a struct which contains
+ /// information about the block, including the block invoke function, the
+ /// captured variables, etc.
+ /// \param InvokeF will contain the block invoke function if it is not
+ /// nullptr.
+ llvm::Value *EmitBlockLiteral(const BlockExpr *,
+ llvm::Function **InvokeF = nullptr);
static void destroyBlockInfos(CGBlockInfo *info);
llvm::Function *GenerateBlockFunction(GlobalDecl GD,
const CGBlockInfo &Info,
const DeclMapTy &ldm,
- bool IsLambdaConversionToBlock);
+ bool IsLambdaConversionToBlock,
+ bool BuildGlobalBlock);
llvm::Constant *GenerateCopyHelperFunction(const CGBlockInfo &blockInfo);
llvm::Constant *GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo);
@@ -1642,10 +1648,9 @@ public:
void EmitForwardingCallToLambda(const CXXMethodDecl *LambdaCallOperator,
CallArgList &CallArgs);
- void EmitLambdaToBlockPointerBody(FunctionArgList &Args);
void EmitLambdaBlockInvokeBody();
void EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD);
- void EmitLambdaStaticInvokeFunction(const CXXMethodDecl *MD);
+ void EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD);
void EmitAsanPrologueOrEpilogue(bool Prologue);
/// \brief Emit the unified return block, trying to avoid its emission when
@@ -1766,13 +1771,18 @@ public:
/// instrumented with XRay nop sleds.
bool ShouldXRayInstrumentFunction() const;
- /// EmitFunctionInstrumentation - Emit LLVM code to call the specified
- /// instrumentation function with the current function and the call site, if
- /// function instrumentation is enabled.
- void EmitFunctionInstrumentation(const char *Fn);
+ /// AlwaysEmitXRayCustomEvents - Return true if we must unconditionally emit
+ /// XRay custom event handling calls.
+ bool AlwaysEmitXRayCustomEvents() const;
+
+ /// Encode an address into a form suitable for use in a function prologue.
+ llvm::Constant *EncodeAddrForUseInPrologue(llvm::Function *F,
+ llvm::Constant *Addr);
- /// EmitMCountInstrumentation - Emit call to .mcount.
- void EmitMCountInstrumentation();
+ /// Decode an address used in a function prologue, encoded by \c
+ /// EncodeAddrForUseInPrologue.
+ llvm::Value *DecodeAddrUsedInPrologue(llvm::Value *F,
+ llvm::Value *EncodedAddr);
/// EmitFunctionProlog - Emit the target specific LLVM code to load the
/// arguments for the given function. This is also responsible for naming the
@@ -1816,8 +1826,7 @@ public:
/// TypeOfSelfObject - Return type of object that this self represents.
QualType TypeOfSelfObject();
- /// hasAggregateLLVMType - Return true if the specified AST type will map into
- /// an aggregate LLVM type or is void.
+ /// getEvaluationKind - Return the TypeEvaluationKind of QualType \c T.
static TypeEvaluationKind getEvaluationKind(QualType T);
static bool hasScalarEvaluationKind(QualType T) {
@@ -1896,33 +1905,53 @@ public:
//===--------------------------------------------------------------------===//
LValue MakeAddrLValue(Address Addr, QualType T,
- LValueBaseInfo BaseInfo =
- LValueBaseInfo(AlignmentSource::Type)) {
- return LValue::MakeAddr(Addr, T, getContext(), BaseInfo,
- CGM.getTBAAInfo(T));
+ AlignmentSource Source = AlignmentSource::Type) {
+ return LValue::MakeAddr(Addr, T, getContext(), LValueBaseInfo(Source),
+ CGM.getTBAAAccessInfo(T));
+ }
+
+ LValue MakeAddrLValue(Address Addr, QualType T, LValueBaseInfo BaseInfo,
+ TBAAAccessInfo TBAAInfo) {
+ return LValue::MakeAddr(Addr, T, getContext(), BaseInfo, TBAAInfo);
}
LValue MakeAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment,
- LValueBaseInfo BaseInfo =
- LValueBaseInfo(AlignmentSource::Type)) {
+ AlignmentSource Source = AlignmentSource::Type) {
return LValue::MakeAddr(Address(V, Alignment), T, getContext(),
- BaseInfo, CGM.getTBAAInfo(T));
+ LValueBaseInfo(Source), CGM.getTBAAAccessInfo(T));
+ }
+
+ LValue MakeAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment,
+ LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo) {
+ return LValue::MakeAddr(Address(V, Alignment), T, getContext(),
+ BaseInfo, TBAAInfo);
}
LValue MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T);
LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T);
CharUnits getNaturalTypeAlignment(QualType T,
LValueBaseInfo *BaseInfo = nullptr,
+ TBAAAccessInfo *TBAAInfo = nullptr,
bool forPointeeType = false);
CharUnits getNaturalPointeeTypeAlignment(QualType T,
- LValueBaseInfo *BaseInfo = nullptr);
+ LValueBaseInfo *BaseInfo = nullptr,
+ TBAAAccessInfo *TBAAInfo = nullptr);
- Address EmitLoadOfReference(Address Ref, const ReferenceType *RefTy,
- LValueBaseInfo *BaseInfo = nullptr);
- LValue EmitLoadOfReferenceLValue(Address Ref, const ReferenceType *RefTy);
+ Address EmitLoadOfReference(LValue RefLVal,
+ LValueBaseInfo *PointeeBaseInfo = nullptr,
+ TBAAAccessInfo *PointeeTBAAInfo = nullptr);
+ LValue EmitLoadOfReferenceLValue(LValue RefLVal);
+ LValue EmitLoadOfReferenceLValue(Address RefAddr, QualType RefTy,
+ AlignmentSource Source =
+ AlignmentSource::Type) {
+ LValue RefLVal = MakeAddrLValue(RefAddr, RefTy, LValueBaseInfo(Source),
+ CGM.getTBAAAccessInfo(RefTy));
+ return EmitLoadOfReferenceLValue(RefLVal);
+ }
Address EmitLoadOfPointer(Address Ptr, const PointerType *PtrTy,
- LValueBaseInfo *BaseInfo = nullptr);
+ LValueBaseInfo *BaseInfo = nullptr,
+ TBAAAccessInfo *TBAAInfo = nullptr);
LValue EmitLoadOfPointerLValue(Address Ptr, const PointerType *PtrTy);
/// CreateTempAlloca - This creates an alloca and inserts it into the entry
@@ -2345,6 +2374,12 @@ public:
TCK_NonnullAssign
};
+ /// Determine whether the pointer type check \p TCK permits null pointers.
+ static bool isNullPointerAllowed(TypeCheckKind TCK);
+
+ /// Determine whether the pointer type check \p TCK requires a vptr check.
+ static bool isVptrCheckRequired(TypeCheckKind TCK, QualType Ty);
+
/// \brief Whether any type-checking sanitizers are enabled. If \c false,
/// calls to EmitTypeCheck can be skipped.
bool sanitizePerformTypeCheck() const;
@@ -2464,7 +2499,7 @@ public:
};
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var);
void EmitAutoVarInit(const AutoVarEmission &emission);
- void EmitAutoVarCleanups(const AutoVarEmission &emission);
+ void EmitAutoVarCleanups(const AutoVarEmission &emission);
void emitAutoVarTypeCleanup(const AutoVarEmission &emission,
QualType::DestructionKind dtorKind);
@@ -2486,7 +2521,7 @@ public:
bool isIndirect() const { return Alignment != 0; }
llvm::Value *getAnyValue() const { return Value; }
-
+
llvm::Value *getDirectValue() const {
assert(!isIndirect());
return Value;
@@ -2532,7 +2567,7 @@ public:
/// This function may clear the current insertion point; callers should use
/// EnsureInsertPoint if they wish to subsequently generate code without first
/// calling EmitBlock, EmitBranch, or EmitStmt.
- void EmitStmt(const Stmt *S);
+ void EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs = None);
/// EmitSimpleStmt - Try to emit a "simple" statement which does not
/// necessarily require an insertion point or debug information; typically
@@ -2635,6 +2670,19 @@ public:
void EmitCXXForRangeStmt(const CXXForRangeStmt &S,
ArrayRef<const Attr *> Attrs = None);
+ /// Controls insertion of cancellation exit blocks in worksharing constructs.
+ class OMPCancelStackRAII {
+ CodeGenFunction &CGF;
+
+ public:
+ OMPCancelStackRAII(CodeGenFunction &CGF, OpenMPDirectiveKind Kind,
+ bool HasCancel)
+ : CGF(CGF) {
+ CGF.OMPCancelStack.enter(CGF, Kind, HasCancel);
+ }
+ ~OMPCancelStackRAII() { CGF.OMPCancelStack.exit(CGF); }
+ };
+
/// Returns calculated size of the specified type.
llvm::Value *getTypeSize(QualType Ty);
LValue InitCapturedStruct(const CapturedStmt &S);
@@ -2841,9 +2889,30 @@ public:
static void
EmitOMPTargetParallelDeviceFunction(CodeGenModule &CGM, StringRef ParentName,
const OMPTargetParallelDirective &S);
+ /// Emit device code for the target parallel for directive.
+ static void EmitOMPTargetParallelForDeviceFunction(
+ CodeGenModule &CGM, StringRef ParentName,
+ const OMPTargetParallelForDirective &S);
+ /// Emit device code for the target parallel for simd directive.
+ static void EmitOMPTargetParallelForSimdDeviceFunction(
+ CodeGenModule &CGM, StringRef ParentName,
+ const OMPTargetParallelForSimdDirective &S);
+ /// Emit device code for the target teams directive.
static void
EmitOMPTargetTeamsDeviceFunction(CodeGenModule &CGM, StringRef ParentName,
const OMPTargetTeamsDirective &S);
+ /// Emit device code for the target teams distribute directive.
+ static void EmitOMPTargetTeamsDistributeDeviceFunction(
+ CodeGenModule &CGM, StringRef ParentName,
+ const OMPTargetTeamsDistributeDirective &S);
+ /// Emit device code for the target teams distribute simd directive.
+ static void EmitOMPTargetTeamsDistributeSimdDeviceFunction(
+ CodeGenModule &CGM, StringRef ParentName,
+ const OMPTargetTeamsDistributeSimdDirective &S);
+ /// Emit device code for the target simd directive.
+ static void EmitOMPTargetSimdDeviceFunction(CodeGenModule &CGM,
+ StringRef ParentName,
+ const OMPTargetSimdDirective &S);
/// \brief Emit inner loop of the worksharing/simd construct.
///
/// \param S Directive, for which the inner loop must be emitted.
@@ -2875,9 +2944,9 @@ public:
const CodeGenLoopBoundsTy &CodeGenLoopBounds,
const CodeGenDispatchBoundsTy &CGDispatchBounds);
-private:
- /// Helpers for blocks
- llvm::Value *EmitBlockLiteral(const CGBlockInfo &Info);
+ /// Emit code for the distribute loop-based directive.
+ void EmitOMPDistributeLoop(const OMPLoopDirective &S,
+ const CodeGenLoopTy &CodeGenLoop, Expr *IncExpr);
/// Helpers for the OpenMP loop directives.
void EmitOMPSimdInit(const OMPLoopDirective &D, bool IsMonotonic = false);
@@ -2885,8 +2954,15 @@ private:
const OMPLoopDirective &D,
const llvm::function_ref<llvm::Value *(CodeGenFunction &)> &CondGen);
- void EmitOMPDistributeLoop(const OMPLoopDirective &S,
- const CodeGenLoopTy &CodeGenLoop, Expr *IncExpr);
+ /// Emits the lvalue for the expression with possibly captured variable.
+ LValue EmitOMPSharedLValue(const Expr *E);
+
+private:
+ /// Helpers for blocks. Returns invoke function by \p InvokeF if it is not
+ /// nullptr. It should be called without \p InvokeF if the caller does not
+ /// need invoke function to be returned.
+ llvm::Value *EmitBlockLiteral(const CGBlockInfo &Info,
+ llvm::Function **InvokeF = nullptr);
/// struct with the values to be passed to the OpenMP loop-related functions
struct OMPLoopArguments {
@@ -3034,11 +3110,15 @@ public:
/// the LLVM value representation.
llvm::Value *EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty,
SourceLocation Loc,
- LValueBaseInfo BaseInfo =
- LValueBaseInfo(AlignmentSource::Type),
- llvm::MDNode *TBAAInfo = nullptr,
- QualType TBAABaseTy = QualType(),
- uint64_t TBAAOffset = 0,
+ AlignmentSource Source = AlignmentSource::Type,
+ bool isNontemporal = false) {
+ return EmitLoadOfScalar(Addr, Volatile, Ty, Loc, LValueBaseInfo(Source),
+ CGM.getTBAAAccessInfo(Ty), isNontemporal);
+ }
+
+ llvm::Value *EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty,
+ SourceLocation Loc, LValueBaseInfo BaseInfo,
+ TBAAAccessInfo TBAAInfo,
bool isNontemporal = false);
/// EmitLoadOfScalar - Load a scalar value from an address, taking
@@ -3052,11 +3132,16 @@ public:
/// the LLVM value representation.
void EmitStoreOfScalar(llvm::Value *Value, Address Addr,
bool Volatile, QualType Ty,
- LValueBaseInfo BaseInfo =
- LValueBaseInfo(AlignmentSource::Type),
- llvm::MDNode *TBAAInfo = nullptr, bool isInit = false,
- QualType TBAABaseTy = QualType(),
- uint64_t TBAAOffset = 0, bool isNontemporal = false);
+ AlignmentSource Source = AlignmentSource::Type,
+ bool isInit = false, bool isNontemporal = false) {
+ EmitStoreOfScalar(Value, Addr, Volatile, Ty, LValueBaseInfo(Source),
+ CGM.getTBAAAccessInfo(Ty), isInit, isNontemporal);
+ }
+
+ void EmitStoreOfScalar(llvm::Value *Value, Address Addr,
+ bool Volatile, QualType Ty,
+ LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo,
+ bool isInit = false, bool isNontemporal = false);
/// EmitStoreOfScalar - Store a scalar value to an address, taking
/// care to appropriately convert from the memory representation to
@@ -3120,13 +3205,14 @@ public:
LValue EmitCastLValue(const CastExpr *E);
LValue EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E);
LValue EmitOpaqueValueLValue(const OpaqueValueExpr *e);
-
+
Address EmitExtVectorElementLValue(LValue V);
RValue EmitRValueForField(LValue LV, const FieldDecl *FD, SourceLocation Loc);
Address EmitArrayToPointerDecay(const Expr *Array,
- LValueBaseInfo *BaseInfo = nullptr);
+ LValueBaseInfo *BaseInfo = nullptr,
+ TBAAAccessInfo *TBAAInfo = nullptr);
class ConstantEmission {
llvm::PointerIntPair<llvm::Constant*, 1, bool> ValueAndIsReference;
@@ -3159,6 +3245,7 @@ public:
};
ConstantEmission tryEmitAsConstant(DeclRefExpr *refExpr);
+ ConstantEmission tryEmitAsConstant(const MemberExpr *ME);
RValue EmitPseudoObjectRValue(const PseudoObjectExpr *e,
AggValueSlot slot = AggValueSlot::ignored());
@@ -3235,12 +3322,12 @@ public:
void EmitNoreturnRuntimeCallOrInvoke(llvm::Value *callee,
ArrayRef<llvm::Value*> args);
- CGCallee BuildAppleKextVirtualCall(const CXXMethodDecl *MD,
+ CGCallee BuildAppleKextVirtualCall(const CXXMethodDecl *MD,
NestedNameSpecifier *Qual,
llvm::Type *Ty);
-
+
CGCallee BuildAppleKextVirtualDestructorCall(const CXXDestructorDecl *DD,
- CXXDtorType Type,
+ CXXDtorType Type,
const CXXRecordDecl *RD);
RValue
@@ -3267,7 +3354,8 @@ public:
Address EmitCXXMemberDataPointerAddress(const Expr *E, Address base,
llvm::Value *memberPtr,
const MemberPointerType *memberPtrType,
- LValueBaseInfo *BaseInfo = nullptr);
+ LValueBaseInfo *BaseInfo = nullptr,
+ TBAAAccessInfo *TBAAInfo = nullptr);
RValue EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E,
ReturnValueSlot ReturnValue);
@@ -3286,6 +3374,13 @@ public:
unsigned BuiltinID, const CallExpr *E,
ReturnValueSlot ReturnValue);
+ /// Emit IR for __builtin_os_log_format.
+ RValue emitBuiltinOSLogFormat(const CallExpr &E);
+
+ llvm::Function *generateBuiltinOSLogHelperFunction(
+ const analyze_os_log::OSLogBufferLayout &Layout,
+ CharUnits BufferAlignment);
+
RValue EmitBlockCallExpr(const CallExpr *E, ReturnValueSlot ReturnValue);
/// EmitTargetBuiltinExpr - Emit the given builtin call. Returns 0 if the call
@@ -3329,6 +3424,7 @@ public:
llvm::Value *EmitNVPTXBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
llvm::Value *EmitWebAssemblyBuiltinExpr(unsigned BuiltinID,
const CallExpr *E);
+ llvm::Value *EmitHexagonBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
private:
enum class MSVCIntrin;
@@ -3406,11 +3502,11 @@ public:
static Destroyer destroyARCWeak;
static Destroyer emitARCIntrinsicUse;
- void EmitObjCAutoreleasePoolPop(llvm::Value *Ptr);
+ void EmitObjCAutoreleasePoolPop(llvm::Value *Ptr);
llvm::Value *EmitObjCAutoreleasePoolPush();
llvm::Value *EmitObjCMRRAutoreleasePoolPush();
void EmitObjCAutoreleasePoolCleanup(llvm::Value *Ptr);
- void EmitObjCMRRAutoreleasePoolPop(llvm::Value *Ptr);
+ void EmitObjCMRRAutoreleasePoolPop(llvm::Value *Ptr);
/// \brief Emits a reference binding to the passed in expression.
RValue EmitReferenceBindingToExpr(const Expr *E);
@@ -3498,6 +3594,14 @@ public:
void EmitCXXGuardedInit(const VarDecl &D, llvm::GlobalVariable *DeclPtr,
bool PerformInit);
+ enum class GuardKind { VariableGuard, TlsGuard };
+
+ /// Emit a branch to select whether or not to perform guarded initialization.
+ void EmitCXXGuardedInitBranch(llvm::Value *NeedsInit,
+ llvm::BasicBlock *InitBlock,
+ llvm::BasicBlock *NoInitBlock,
+ GuardKind Kind, const VarDecl *D);
+
/// GenerateCXXGlobalInitFunc - Generates code for initializing global
/// variables.
void GenerateCXXGlobalInitFunc(llvm::Function *Fn,
@@ -3517,7 +3621,7 @@ public:
bool PerformInit);
void EmitCXXConstructExpr(const CXXConstructExpr *E, AggValueSlot Dest);
-
+
void EmitSynthesizedCXXCopyCtor(Address Dest, Address Src, const Expr *Exp);
void enterFullExpression(const ExprWithCleanups *E) {
@@ -3566,7 +3670,7 @@ public:
/// Determine if the given statement might introduce a declaration into the
/// current scope, by being a (possibly-labelled) DeclStmt.
static bool mightAddDeclToScope(const Stmt *S);
-
+
/// ConstantFoldsToSimpleInteger - If the specified expression does not fold
/// to a constant, or if it does but contains a label, return false. If it
/// constant folds return true and set the boolean result in Result.
@@ -3607,6 +3711,17 @@ public:
SourceLocation Loc,
const Twine &Name = "");
+ /// Specifies which type of sanitizer check to apply when handling a
+ /// particular builtin.
+ enum BuiltinCheckKind {
+ BCK_CTZPassedZero,
+ BCK_CLZPassedZero,
+ };
+
+ /// Emits an argument for a call to a builtin. If the builtin sanitizer is
+ /// enabled, a runtime check specified by \p Kind is also emitted.
+ llvm::Value *EmitCheckedArgForBuiltin(const Expr *E, BuiltinCheckKind Kind);
+
/// \brief Emit a description of a type in a format suitable for passing to
/// a runtime sanitizer handler.
llvm::Constant *EmitCheckTypeDescriptor(QualType T);
@@ -3820,7 +3935,13 @@ public:
/// reasonable to just ignore the returned alignment when it isn't from an
/// explicit source.
Address EmitPointerWithAlignment(const Expr *Addr,
- LValueBaseInfo *BaseInfo = nullptr);
+ LValueBaseInfo *BaseInfo = nullptr,
+ TBAAAccessInfo *TBAAInfo = nullptr);
+
+ /// If \p E references a parameter with pass_object_size info or a constant
+ /// array size modifier, emit the object size divided by the size of \p EltTy.
+ /// Otherwise return null.
+ llvm::Value *LoadPassedObjectSize(const Expr *E, QualType EltTy);
void EmitSanitizerStatReport(llvm::SanitizerStatKind SSK);
@@ -3835,6 +3956,11 @@ private:
void AddObjCARCExceptionMetadata(llvm::Instruction *Inst);
llvm::Value *GetValueForARMHint(unsigned BuiltinID);
+ llvm::Value *EmitX86CpuIs(const CallExpr *E);
+ llvm::Value *EmitX86CpuIs(StringRef CPUStr);
+ llvm::Value *EmitX86CpuSupports(const CallExpr *E);
+ llvm::Value *EmitX86CpuSupports(ArrayRef<StringRef> FeatureStrs);
+ llvm::Value *EmitX86CpuInit();
};
/// Helper class with most of the code for saving a value for a
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp
index 5561d4520cc85..c59dc71da5960 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp
@@ -23,7 +23,7 @@
#include "CGOpenMPRuntimeNVPTX.h"
#include "CodeGenFunction.h"
#include "CodeGenPGO.h"
-#include "CodeGenTBAA.h"
+#include "ConstantEmitter.h"
#include "CoverageMappingGen.h"
#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
@@ -60,6 +60,11 @@
using namespace clang;
using namespace CodeGen;
+static llvm::cl::opt<bool> LimitedCoverage(
+ "limited-coverage-experimental", llvm::cl::ZeroOrMore, llvm::cl::Hidden,
+ llvm::cl::desc("Emit limited coverage mapping information (experimental)"),
+ llvm::cl::init(false));
+
static const char AnnotationSection[] = "llvm.metadata";
static CGCXXABI *createCXXABI(CodeGenModule &CGM) {
@@ -131,7 +136,7 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO,
// Enable TBAA unless it's suppressed. ThreadSanitizer needs TBAA even at O0.
if (LangOpts.Sanitize.has(SanitizerKind::Thread) ||
(!CodeGenOpts.RelaxedAliasing && CodeGenOpts.OptimizationLevel > 0))
- TBAA.reset(new CodeGenTBAA(Context, VMContext, CodeGenOpts, getLangOpts(),
+ TBAA.reset(new CodeGenTBAA(Context, TheModule, CodeGenOpts, getLangOpts(),
getCXXABI().getMangleContext()));
// If debug info or coverage generation is enabled, create the CGDebugInfo
@@ -436,7 +441,7 @@ void CodeGenModule::Release() {
if (Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86)
getModule().addModuleFlag(llvm::Module::Error, "NumRegisterParameters",
CodeGenOpts.NumRegisterParameters);
-
+
if (CodeGenOpts.DwarfVersion) {
// We actually want the latest version when there are conflicts.
// We can change from Warning to Latest if such mode is supported.
@@ -470,17 +475,11 @@ void CodeGenModule::Release() {
getModule().addModuleFlag(llvm::Module::Warning, "Debug Info Version",
llvm::DEBUG_METADATA_VERSION);
- // Width of wchar_t in bytes
- uint64_t WCharWidth =
- Context.getTypeSizeInChars(Context.getWideCharType()).getQuantity();
- assert((LangOpts.ShortWChar ||
- llvm::TargetLibraryInfoImpl::getTargetWCharSize(Target.getTriple()) ==
- Target.getWCharWidth() / 8) &&
- "LLVM wchar_t size out of sync");
-
// We need to record the widths of enums and wchar_t, so that we can generate
// the correct build attributes in the ARM backend. wchar_size is also used by
// TargetLibraryInfo.
+ uint64_t WCharWidth =
+ Context.getTypeSizeInChars(Context.getWideCharType()).getQuantity();
getModule().addModuleFlag(llvm::Module::Error, "wchar_size", WCharWidth);
llvm::Triple::ArchType Arch = Context.getTargetInfo().getTriple().getArch();
@@ -573,16 +572,27 @@ void CodeGenModule::RefreshTypeCacheForClass(const CXXRecordDecl *RD) {
Types.RefreshTypeCacheForClass(RD);
}
-llvm::MDNode *CodeGenModule::getTBAAInfo(QualType QTy) {
+llvm::MDNode *CodeGenModule::getTBAATypeInfo(QualType QTy) {
if (!TBAA)
return nullptr;
- return TBAA->getTBAAInfo(QTy);
+ return TBAA->getTypeInfo(QTy);
}
-llvm::MDNode *CodeGenModule::getTBAAInfoForVTablePtr() {
+TBAAAccessInfo CodeGenModule::getTBAAAccessInfo(QualType AccessType) {
+ // Pointee values may have incomplete types, but they shall never be
+ // dereferenced.
+ if (AccessType->isIncompleteType())
+ return TBAAAccessInfo::getIncompleteInfo();
+
+ uint64_t Size = Context.getTypeSizeInChars(AccessType).getQuantity();
+ return TBAAAccessInfo(getTBAATypeInfo(AccessType), Size);
+}
+
+TBAAAccessInfo
+CodeGenModule::getTBAAVTablePtrAccessInfo(llvm::Type *VTablePtrType) {
if (!TBAA)
- return nullptr;
- return TBAA->getTBAAInfoForVTablePtr();
+ return TBAAAccessInfo();
+ return TBAA->getVTablePtrAccessInfo(VTablePtrType);
}
llvm::MDNode *CodeGenModule::getTBAAStructInfo(QualType QTy) {
@@ -591,26 +601,37 @@ llvm::MDNode *CodeGenModule::getTBAAStructInfo(QualType QTy) {
return TBAA->getTBAAStructInfo(QTy);
}
-llvm::MDNode *CodeGenModule::getTBAAStructTagInfo(QualType BaseTy,
- llvm::MDNode *AccessN,
- uint64_t O) {
+llvm::MDNode *CodeGenModule::getTBAABaseTypeInfo(QualType QTy) {
+ if (!TBAA)
+ return nullptr;
+ return TBAA->getBaseTypeInfo(QTy);
+}
+
+llvm::MDNode *CodeGenModule::getTBAAAccessTagInfo(TBAAAccessInfo Info) {
if (!TBAA)
return nullptr;
- return TBAA->getTBAAStructTagInfo(BaseTy, AccessN, O);
+ return TBAA->getAccessTagInfo(Info);
+}
+
+TBAAAccessInfo CodeGenModule::mergeTBAAInfoForCast(TBAAAccessInfo SourceInfo,
+ TBAAAccessInfo TargetInfo) {
+ if (!TBAA)
+ return TBAAAccessInfo();
+ return TBAA->mergeTBAAInfoForCast(SourceInfo, TargetInfo);
+}
+
+TBAAAccessInfo
+CodeGenModule::mergeTBAAInfoForConditionalOperator(TBAAAccessInfo InfoA,
+ TBAAAccessInfo InfoB) {
+ if (!TBAA)
+ return TBAAAccessInfo();
+ return TBAA->mergeTBAAInfoForConditionalOperator(InfoA, InfoB);
}
-/// Decorate the instruction with a TBAA tag. For both scalar TBAA
-/// and struct-path aware TBAA, the tag has the same format:
-/// base type, access type and offset.
-/// When ConvertTypeToTag is true, we create a tag based on the scalar type.
void CodeGenModule::DecorateInstructionWithTBAA(llvm::Instruction *Inst,
- llvm::MDNode *TBAAInfo,
- bool ConvertTypeToTag) {
- if (ConvertTypeToTag && TBAA)
- Inst->setMetadata(llvm::LLVMContext::MD_tbaa,
- TBAA->getTBAAScalarTagInfo(TBAAInfo));
- else
- Inst->setMetadata(llvm::LLVMContext::MD_tbaa, TBAAInfo);
+ TBAAAccessInfo TBAAInfo) {
+ if (llvm::MDNode *Tag = getTBAAAccessTagInfo(TBAAInfo))
+ Inst->setMetadata(llvm::LLVMContext::MD_tbaa, Tag);
}
void CodeGenModule::DecorateInstructionWithInvariantGroup(
@@ -648,7 +669,8 @@ llvm::ConstantInt *CodeGenModule::getSize(CharUnits size) {
}
void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV,
- const NamedDecl *D) const {
+ const NamedDecl *D,
+ ForDefinition_t IsForDefinition) const {
// Internal definitions always have default visibility.
if (GV->hasLocalLinkage()) {
GV->setVisibility(llvm::GlobalValue::DefaultVisibility);
@@ -657,7 +679,8 @@ void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV,
// Set visibility for definitions.
LinkageInfo LV = D->getLinkageAndVisibility();
- if (LV.isVisibilityExplicit() || !GV->hasAvailableExternallyLinkage())
+ if (LV.isVisibilityExplicit() ||
+ (IsForDefinition && !GV->hasAvailableExternallyLinkage()))
GV->setVisibility(GetLLVMVisibility(LV.getVisibility()));
}
@@ -712,9 +735,9 @@ StringRef CodeGenModule::getMangledName(GlobalDecl GD) {
}
}
- StringRef &FoundStr = MangledDeclNames[CanonicalGD];
- if (!FoundStr.empty())
- return FoundStr;
+ auto FoundName = MangledDeclNames.find(CanonicalGD);
+ if (FoundName != MangledDeclNames.end())
+ return FoundName->second;
const auto *ND = cast<NamedDecl>(GD.getDecl());
SmallString<256> Buffer;
@@ -745,7 +768,7 @@ StringRef CodeGenModule::getMangledName(GlobalDecl GD) {
// Keep the first result in the case of a mangling collision.
auto Result = Manglings.insert(std::make_pair(Str, GD));
- return FoundStr = Result.first->first();
+ return MangledDeclNames[CanonicalGD] = Result.first->first();
}
StringRef CodeGenModule::getBlockMangledName(GlobalDecl GD,
@@ -756,7 +779,7 @@ StringRef CodeGenModule::getBlockMangledName(GlobalDecl GD,
SmallString<256> Buffer;
llvm::raw_svector_ostream Out(Buffer);
if (!D)
- MangleCtx.mangleGlobalBlock(BD,
+ MangleCtx.mangleGlobalBlock(BD,
dyn_cast_or_null<VarDecl>(initializedGlobalDecl.getDecl()), Out);
else if (const auto *CD = dyn_cast<CXXConstructorDecl>(D))
MangleCtx.mangleCtorBlock(CD, GD.getCtorType(), BD, Out);
@@ -1038,7 +1061,7 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
void CodeGenModule::SetCommonAttributes(const Decl *D,
llvm::GlobalValue *GV) {
if (const auto *ND = dyn_cast_or_null<NamedDecl>(D))
- setGlobalVisibility(GV, ND);
+ setGlobalVisibility(GV, ND, ForDefinition);
else
GV->setVisibility(llvm::GlobalValue::DefaultVisibility);
@@ -1080,7 +1103,7 @@ void CodeGenModule::setNonAliasAttributes(const Decl *D,
GO->setSection(SA->getName());
}
- getTargetCodeGenInfo().setTargetAttributes(D, GO, *this);
+ getTargetCodeGenInfo().setTargetAttributes(D, GO, *this, ForDefinition);
}
void CodeGenModule::SetInternalFunctionAttributes(const Decl *D,
@@ -1094,8 +1117,8 @@ void CodeGenModule::SetInternalFunctionAttributes(const Decl *D,
setNonAliasAttributes(D, F);
}
-static void setLinkageAndVisibilityForGV(llvm::GlobalValue *GV,
- const NamedDecl *ND) {
+static void setLinkageForGV(llvm::GlobalValue *GV,
+ const NamedDecl *ND) {
// Set linkage and visibility in case we never see a definition.
LinkageInfo LV = ND->getLinkageAndVisibility();
if (!isExternallyVisible(LV.getLinkage())) {
@@ -1111,10 +1134,6 @@ static void setLinkageAndVisibilityForGV(llvm::GlobalValue *GV,
// separate linkage types for this.
GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
}
-
- // Set visibility on a declaration only if it's explicit.
- if (LV.isVisibilityExplicit())
- GV->setVisibility(CodeGenModule::GetLLVMVisibility(LV.getVisibility()));
}
}
@@ -1138,6 +1157,7 @@ void CodeGenModule::CreateFunctionTypeMetadata(const FunctionDecl *FD,
llvm::Metadata *MD = CreateMetadataIdentifierForType(FD->getType());
F->addTypeMetadata(0, MD);
+ F->addTypeMetadata(0, CreateMetadataIdentifierGeneralized(FD->getType()));
// Emit a hash-based bit set entry for cross-DSO calls.
if (CodeGenOpts.SanitizeCfiCrossDso)
@@ -1147,7 +1167,9 @@ void CodeGenModule::CreateFunctionTypeMetadata(const FunctionDecl *FD,
void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
bool IsIncompleteFunction,
- bool IsThunk) {
+ bool IsThunk,
+ ForDefinition_t IsForDefinition) {
+
if (llvm::Intrinsic::ID IID = F->getIntrinsicID()) {
// If this is an intrinsic function, set the function's attributes
// to the intrinsic's attributes.
@@ -1157,8 +1179,13 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
const auto *FD = cast<FunctionDecl>(GD.getDecl());
- if (!IsIncompleteFunction)
+ if (!IsIncompleteFunction) {
SetLLVMFunctionAttributes(FD, getTypes().arrangeGlobalDeclaration(GD), F);
+ // Setup target-specific attributes.
+ if (!IsForDefinition)
+ getTargetCodeGenInfo().setTargetAttributes(FD, F, *this,
+ NotForDefinition);
+ }
// Add the Returned attribute for "this", except for iOS 5 and earlier
// where substantial code, including the libstdc++ dylib, was compiled with
@@ -1175,7 +1202,8 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
// Only a few attributes are set on declarations; these may later be
// overridden by a definition.
- setLinkageAndVisibilityForGV(F, FD);
+ setLinkageForGV(F, FD);
+ setGlobalVisibility(F, FD, NotForDefinition);
if (FD->getAttr<PragmaClangTextSectionAttr>()) {
F->addFnAttr("implicit-section-name");
@@ -1210,6 +1238,9 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
// is handled with better precision by the receiving DSO.
if (!CodeGenOpts.SanitizeCfiCrossDso)
CreateFunctionTypeMetadata(FD, F);
+
+ if (getLangOpts().OpenMP && FD->hasAttr<OMPDeclareSimdDeclAttr>())
+ getOpenMPRuntime().emitDeclareSimdFunction(FD, F);
}
void CodeGenModule::addUsedGlobal(llvm::GlobalValue *GV) {
@@ -1530,20 +1561,21 @@ void CodeGenModule::AddGlobalAnnotations(const ValueDecl *D,
Annotations.push_back(EmitAnnotateAttr(GV, I, D->getLocation()));
}
-bool CodeGenModule::isInSanitizerBlacklist(llvm::Function *Fn,
+bool CodeGenModule::isInSanitizerBlacklist(SanitizerMask Kind,
+ llvm::Function *Fn,
SourceLocation Loc) const {
const auto &SanitizerBL = getContext().getSanitizerBlacklist();
// Blacklist by function name.
- if (SanitizerBL.isBlacklistedFunction(Fn->getName()))
+ if (SanitizerBL.isBlacklistedFunction(Kind, Fn->getName()))
return true;
// Blacklist by location.
if (Loc.isValid())
- return SanitizerBL.isBlacklistedLocation(Loc);
+ return SanitizerBL.isBlacklistedLocation(Kind, Loc);
// If location is unknown, this may be a compiler-generated function. Assume
// it's located in the main file.
auto &SM = Context.getSourceManager();
if (const auto *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
- return SanitizerBL.isBlacklistedFile(MainFile->getName());
+ return SanitizerBL.isBlacklistedFile(Kind, MainFile->getName());
}
return false;
}
@@ -1552,13 +1584,14 @@ bool CodeGenModule::isInSanitizerBlacklist(llvm::GlobalVariable *GV,
SourceLocation Loc, QualType Ty,
StringRef Category) const {
// For now globals can be blacklisted only in ASan and KASan.
- if (!LangOpts.Sanitize.hasOneOf(
- SanitizerKind::Address | SanitizerKind::KernelAddress))
+ const SanitizerMask EnabledAsanMask = LangOpts.Sanitize.Mask &
+ (SanitizerKind::Address | SanitizerKind::KernelAddress | SanitizerKind::HWAddress);
+ if (!EnabledAsanMask)
return false;
const auto &SanitizerBL = getContext().getSanitizerBlacklist();
- if (SanitizerBL.isBlacklistedGlobal(GV->getName(), Category))
+ if (SanitizerBL.isBlacklistedGlobal(EnabledAsanMask, GV->getName(), Category))
return true;
- if (SanitizerBL.isBlacklistedLocation(Loc, Category))
+ if (SanitizerBL.isBlacklistedLocation(EnabledAsanMask, Loc, Category))
return true;
// Check global type.
if (!Ty.isNull()) {
@@ -1570,7 +1603,7 @@ bool CodeGenModule::isInSanitizerBlacklist(llvm::GlobalVariable *GV,
// We allow to blacklist only record types (classes, structs etc.)
if (Ty->isRecordType()) {
std::string TypeStr = Ty.getAsString(getContext().getPrintingPolicy());
- if (SanitizerBL.isBlacklistedType(TypeStr, Category))
+ if (SanitizerBL.isBlacklistedType(EnabledAsanMask, TypeStr, Category))
return true;
}
}
@@ -1986,12 +2019,12 @@ bool CodeGenModule::shouldOpportunisticallyEmitVTables() {
void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {
const auto *D = cast<ValueDecl>(GD.getDecl());
- PrettyStackTraceDecl CrashInfo(const_cast<ValueDecl *>(D), D->getLocation(),
+ PrettyStackTraceDecl CrashInfo(const_cast<ValueDecl *>(D), D->getLocation(),
Context.getSourceManager(),
"Generating code for declaration");
-
+
if (isa<FunctionDecl>(D)) {
- // At -O0, don't generate IR for functions with available_externally
+ // At -O0, don't generate IR for functions with available_externally
// linkage.
if (!shouldEmitFunction(GD))
return;
@@ -2017,7 +2050,7 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {
if (const auto *VD = dyn_cast<VarDecl>(D))
return EmitGlobalVarDefinition(VD, !VD->hasDefinition());
-
+
llvm_unreachable("Invalid argument to EmitGlobalDefinition()");
}
@@ -2123,7 +2156,8 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
assert(F->getName() == MangledName && "name was uniqued!");
if (D)
- SetFunctionAttributes(GD, F, IsIncompleteFunction, IsThunk);
+ SetFunctionAttributes(GD, F, IsIncompleteFunction, IsThunk,
+ IsForDefinition);
if (ExtraAttrs.hasAttributes(llvm::AttributeList::FunctionIndex)) {
llvm::AttrBuilder B(ExtraAttrs, llvm::AttributeList::FunctionIndex);
F->addAttributes(llvm::AttributeList::FunctionIndex, B);
@@ -2259,7 +2293,8 @@ CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy, StringRef Name,
F->setCallingConv(getRuntimeCC());
if (!Local && getTriple().isOSBinFormatCOFF() &&
- !getCodeGenOpts().LTOVisibilityPublicStd) {
+ !getCodeGenOpts().LTOVisibilityPublicStd &&
+ !getTriple().isWindowsGNUEnvironment()) {
const FunctionDecl *FD = GetRuntimeFunctionDecl(Context, Name);
if (!FD || FD->hasAttr<DLLImportAttr>()) {
F->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
@@ -2408,7 +2443,8 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
GV->setAlignment(getContext().getDeclAlign(D).getQuantity());
- setLinkageAndVisibilityForGV(GV, D);
+ setLinkageForGV(GV, D);
+ setGlobalVisibility(GV, D, NotForDefinition);
if (D->getTLSKind()) {
if (D->getTLSKind() == VarDecl::TLS_Dynamic)
@@ -2422,18 +2458,65 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
EmitGlobalVarDefinition(D);
}
+ // Emit section information for extern variables.
+ if (D->hasExternalStorage()) {
+ if (const SectionAttr *SA = D->getAttr<SectionAttr>())
+ GV->setSection(SA->getName());
+ }
+
// Handle XCore specific ABI requirements.
if (getTriple().getArch() == llvm::Triple::xcore &&
D->getLanguageLinkage() == CLanguageLinkage &&
D->getType().isConstant(Context) &&
isExternallyVisible(D->getLinkageAndVisibility().getLinkage()))
GV->setSection(".cp.rodata");
+
+ // Check if we a have a const declaration with an initializer, we may be
+ // able to emit it as available_externally to expose it's value to the
+ // optimizer.
+ if (Context.getLangOpts().CPlusPlus && GV->hasExternalLinkage() &&
+ D->getType().isConstQualified() && !GV->hasInitializer() &&
+ !D->hasDefinition() && D->hasInit() && !D->hasAttr<DLLImportAttr>()) {
+ const auto *Record =
+ Context.getBaseElementType(D->getType())->getAsCXXRecordDecl();
+ bool HasMutableFields = Record && Record->hasMutableFields();
+ if (!HasMutableFields) {
+ const VarDecl *InitDecl;
+ const Expr *InitExpr = D->getAnyInitializer(InitDecl);
+ if (InitExpr) {
+ ConstantEmitter emitter(*this);
+ llvm::Constant *Init = emitter.tryEmitForInitializer(*InitDecl);
+ if (Init) {
+ auto *InitType = Init->getType();
+ if (GV->getType()->getElementType() != InitType) {
+ // The type of the initializer does not match the definition.
+ // This happens when an initializer has a different type from
+ // the type of the global (because of padding at the end of a
+ // structure for instance).
+ GV->setName(StringRef());
+ // Make a new global with the correct type, this is now guaranteed
+ // to work.
+ auto *NewGV = cast<llvm::GlobalVariable>(
+ GetAddrOfGlobalVar(D, InitType, IsForDefinition));
+
+ // Erase the old global, since it is no longer used.
+ cast<llvm::GlobalValue>(GV)->eraseFromParent();
+ GV = NewGV;
+ } else {
+ GV->setInitializer(Init);
+ GV->setConstant(true);
+ GV->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
+ }
+ emitter.finalize(GV);
+ }
+ }
+ }
+ }
}
- auto ExpectedAS =
+ LangAS ExpectedAS =
D ? D->getType().getAddressSpace()
- : static_cast<unsigned>(LangOpts.OpenCL ? LangAS::opencl_global
- : LangAS::Default);
+ : (LangOpts.OpenCL ? LangAS::opencl_global : LangAS::Default);
assert(getContext().getTargetAddressSpace(ExpectedAS) ==
Ty->getPointerAddressSpace());
if (AddrSpace != ExpectedAS)
@@ -2474,7 +2557,7 @@ CodeGenModule::GetAddrOfGlobal(GlobalDecl GD,
}
llvm::GlobalVariable *
-CodeGenModule::CreateOrReplaceCXXRuntimeVariable(StringRef Name,
+CodeGenModule::CreateOrReplaceCXXRuntimeVariable(StringRef Name,
llvm::Type *Ty,
llvm::GlobalValue::LinkageTypes Linkage) {
llvm::GlobalVariable *GV = getModule().getNamedGlobal(Name);
@@ -2490,7 +2573,7 @@ CodeGenModule::CreateOrReplaceCXXRuntimeVariable(StringRef Name,
assert(GV->isDeclaration() && "Declaration has wrong type!");
OldGV = GV;
}
-
+
// Create a new variable.
GV = new llvm::GlobalVariable(getModule(), Ty, /*isConstant=*/true,
Linkage, nullptr, Name);
@@ -2498,13 +2581,13 @@ CodeGenModule::CreateOrReplaceCXXRuntimeVariable(StringRef Name,
if (OldGV) {
// Replace occurrences of the old variable if needed.
GV->takeName(OldGV);
-
+
if (!OldGV->use_empty()) {
llvm::Constant *NewPtrForOldDecl =
llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
OldGV->replaceAllUsesWith(NewPtrForOldDecl);
}
-
+
OldGV->eraseFromParent();
}
@@ -2572,11 +2655,10 @@ CharUnits CodeGenModule::GetTargetTypeStoreSize(llvm::Type *Ty) const {
getDataLayout().getTypeStoreSizeInBits(Ty));
}
-unsigned CodeGenModule::GetGlobalVarAddressSpace(const VarDecl *D) {
- unsigned AddrSpace;
+LangAS CodeGenModule::GetGlobalVarAddressSpace(const VarDecl *D) {
+ LangAS AddrSpace = LangAS::Default;
if (LangOpts.OpenCL) {
- AddrSpace = D ? D->getType().getAddressSpace()
- : static_cast<unsigned>(LangAS::opencl_global);
+ AddrSpace = D ? D->getType().getAddressSpace() : LangAS::opencl_global;
assert(AddrSpace == LangAS::opencl_global ||
AddrSpace == LangAS::opencl_constant ||
AddrSpace == LangAS::opencl_local ||
@@ -2678,6 +2760,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
const VarDecl *InitDecl;
const Expr *InitExpr = D->getAnyInitializer(InitDecl);
+ Optional<ConstantEmitter> emitter;
+
// CUDA E.2.4.1 "__shared__ variables cannot have an initialization
// as part of their declaration." Sema has already checked for
// error cases, so we just need to set Init to UndefValue.
@@ -2698,7 +2782,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
Init = EmitNullConstant(D->getType());
} else {
initializedGlobalDecl = GlobalDecl(D);
- Init = EmitConstantInit(*InitDecl);
+ emitter.emplace(*this);
+ Init = emitter->tryEmitForInitializer(*InitDecl);
if (!Init) {
QualType T = InitExpr->getType();
@@ -2811,7 +2896,9 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
Linkage = llvm::GlobalValue::InternalLinkage;
}
}
+
GV->setInitializer(Init);
+ if (emitter) emitter->finalize(GV);
// If it is safe to mark the global 'constant', do so now.
GV->setConstant(!NeedsGlobalCtor && !NeedsGlobalDtor &&
@@ -3176,7 +3263,7 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD,
setFunctionDLLStorageClass(GD, Fn);
// FIXME: this is redundant with part of setFunctionDefinitionAttributes
- setGlobalVisibility(Fn, D);
+ setGlobalVisibility(Fn, D, ForDefinition);
MaybeHandleStaticInExternC(D, Fn);
@@ -3497,11 +3584,15 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
return ConstantAddress(GV, Alignment);
}
+bool CodeGenModule::getExpressionLocationsEnabled() const {
+ return !CodeGenOpts.EmitCodeView || CodeGenOpts.DebugColumnInfo;
+}
+
QualType CodeGenModule::getObjCFastEnumerationStateType() {
if (ObjCFastEnumerationStateType.isNull()) {
RecordDecl *D = Context.buildImplicitRecord("__objcFastEnumerationState");
D->startDefinition();
-
+
QualType FieldTypes[] = {
Context.UnsignedLongTy,
Context.getPointerType(Context.getObjCIdType()),
@@ -3509,7 +3600,7 @@ QualType CodeGenModule::getObjCFastEnumerationStateType() {
Context.getConstantArrayType(Context.UnsignedLongTy,
llvm::APInt(32, 5), ArrayType::Normal, 0)
};
-
+
for (size_t i = 0; i < 4; ++i) {
FieldDecl *Field = FieldDecl::Create(Context,
D,
@@ -3522,18 +3613,18 @@ QualType CodeGenModule::getObjCFastEnumerationStateType() {
Field->setAccess(AS_public);
D->addDecl(Field);
}
-
+
D->completeDefinition();
ObjCFastEnumerationStateType = Context.getTagDeclType(D);
}
-
+
return ObjCFastEnumerationStateType;
}
llvm::Constant *
CodeGenModule::GetConstantArrayFromStringLiteral(const StringLiteral *E) {
assert(!E->getType()->isPointerType() && "Strings are always arrays");
-
+
// Don't emit it as the address of the string, emit the string data itself
// as an inline array.
if (E->getCharByteWidth() == 1) {
@@ -3559,11 +3650,11 @@ CodeGenModule::GetConstantArrayFromStringLiteral(const StringLiteral *E) {
Elements.resize(NumElements);
return llvm::ConstantDataArray::get(VMContext, Elements);
}
-
+
assert(ElemTy->getPrimitiveSizeInBits() == 32);
SmallVector<uint32_t, 32> Elements;
Elements.reserve(NumElements);
-
+
for(unsigned i = 0, e = E->getLength(); i != e; ++i)
Elements.push_back(E->getCodeUnit(i));
Elements.resize(NumElements);
@@ -3727,12 +3818,18 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary(
!EvalResult.hasSideEffects())
Value = &EvalResult.Val;
+ LangAS AddrSpace =
+ VD ? GetGlobalVarAddressSpace(VD) : MaterializedType.getAddressSpace();
+
+ Optional<ConstantEmitter> emitter;
llvm::Constant *InitialValue = nullptr;
bool Constant = false;
llvm::Type *Type;
if (Value) {
// The temporary has a constant initializer, use it.
- InitialValue = EmitConstantValue(*Value, MaterializedType, nullptr);
+ emitter.emplace(*this);
+ InitialValue = emitter->emitForInitializer(*Value, AddrSpace,
+ MaterializedType);
Constant = isTypeConstant(MaterializedType, /*ExcludeCtor*/Value);
Type = InitialValue->getType();
} else {
@@ -3757,13 +3854,12 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary(
Linkage = llvm::GlobalVariable::InternalLinkage;
}
}
- unsigned AddrSpace =
- VD ? GetGlobalVarAddressSpace(VD) : MaterializedType.getAddressSpace();
auto TargetAS = getContext().getTargetAddressSpace(AddrSpace);
auto *GV = new llvm::GlobalVariable(
getModule(), Type, Constant, Linkage, InitialValue, Name.c_str(),
/*InsertBefore=*/nullptr, llvm::GlobalVariable::NotThreadLocal, TargetAS);
- setGlobalVisibility(GV, VD);
+ if (emitter) emitter->finalize(GV);
+ setGlobalVisibility(GV, VD, ForDefinition);
GV->setAlignment(Align.getQuantity());
if (supportsCOMDAT() && GV->isWeakForLinker())
GV->setComdat(TheModule.getOrInsertComdat(GV->getName()));
@@ -3850,11 +3946,11 @@ void CodeGenModule::EmitObjCIvarInitializations(ObjCImplementationDecl *D) {
if (D->getNumIvarInitializers() == 0 ||
AllTrivialInitializers(*this, D))
return;
-
+
IdentifierInfo *II = &getContext().Idents.get(".cxx_construct");
Selector cxxSelector = getContext().Selectors.getSelector(0, &II);
// The constructor returns 'self'.
- ObjCMethodDecl *CTORMethod = ObjCMethodDecl::Create(getContext(),
+ ObjCMethodDecl *CTORMethod = ObjCMethodDecl::Create(getContext(),
D->getLocation(),
D->getLocation(),
cxxSelector,
@@ -3945,6 +4041,13 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
case Decl::Namespace:
EmitDeclContext(cast<NamespaceDecl>(D));
break;
+ case Decl::ClassTemplateSpecialization: {
+ const auto *Spec = cast<ClassTemplateSpecializationDecl>(D);
+ if (DebugInfo &&
+ Spec->getSpecializationKind() == TSK_ExplicitInstantiationDefinition &&
+ Spec->hasDefinition())
+ DebugInfo->completeTemplateDefinition(*Spec);
+ } LLVM_FALLTHROUGH;
case Decl::CXXRecord:
if (DebugInfo) {
if (auto *ES = D->getASTContext().getExternalSource())
@@ -3983,7 +4086,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
if (cast<FunctionDecl>(D)->getDescribedFunctionTemplate() ||
cast<FunctionDecl>(D)->isLateTemplateParsed())
return;
-
+
getCXXABI().EmitCXXConstructors(cast<CXXConstructorDecl>(D));
break;
case Decl::CXXDestructor:
@@ -4009,7 +4112,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
ObjCRuntime->GenerateProtocol(Proto);
break;
}
-
+
case Decl::ObjCCategoryImpl:
// Categories have properties but don't support synthesize so we
// can ignore them here.
@@ -4131,15 +4234,6 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
EmitOMPThreadPrivateDecl(cast<OMPThreadPrivateDecl>(D));
break;
- case Decl::ClassTemplateSpecialization: {
- const auto *Spec = cast<ClassTemplateSpecializationDecl>(D);
- if (DebugInfo &&
- Spec->getSpecializationKind() == TSK_ExplicitInstantiationDefinition &&
- Spec->hasDefinition())
- DebugInfo->completeTemplateDefinition(*Spec);
- break;
- }
-
case Decl::OMPDeclareReduction:
EmitOMPDeclareReduction(cast<OMPDeclareReductionDecl>(D));
break;
@@ -4166,6 +4260,9 @@ void CodeGenModule::AddDeferredUnusedCoverageMapping(Decl *D) {
case Decl::CXXDestructor: {
if (!cast<FunctionDecl>(D)->doesThisDeclarationHaveABody())
return;
+ SourceManager &SM = getContext().getSourceManager();
+ if (LimitedCoverage && SM.getMainFileID() != SM.getFileID(D->getLocStart()))
+ return;
auto I = DeferredEmptyCoverageMappingDecls.find(D);
if (I == DeferredEmptyCoverageMappingDecls.end())
DeferredEmptyCoverageMappingDecls[D] = true;
@@ -4192,20 +4289,10 @@ void CodeGenModule::ClearUnusedCoverageMapping(const Decl *D) {
}
void CodeGenModule::EmitDeferredUnusedCoverageMappings() {
- std::vector<const Decl *> DeferredDecls;
- for (const auto &I : DeferredEmptyCoverageMappingDecls) {
- if (!I.second)
+ for (const auto &Entry : DeferredEmptyCoverageMappingDecls) {
+ if (!Entry.second)
continue;
- DeferredDecls.push_back(I.first);
- }
- // Sort the declarations by their location to make sure that the tests get a
- // predictable order for the coverage mapping for the unused declarations.
- if (CodeGenOpts.DumpCoverageMapping)
- std::sort(DeferredDecls.begin(), DeferredDecls.end(),
- [] (const Decl *LHS, const Decl *RHS) {
- return LHS->getLocStart() < RHS->getLocStart();
- });
- for (const auto *D : DeferredDecls) {
+ const Decl *D = Entry.first;
switch (D->getKind()) {
case Decl::CXXConversion:
case Decl::CXXMethod:
@@ -4414,7 +4501,7 @@ llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty,
// and it's not for EH?
if (!ForEH && !getLangOpts().RTTI)
return llvm::Constant::getNullValue(Int8PtrTy);
-
+
if (ForEH && Ty->isObjCObjectPointerType() &&
LangOpts.ObjCRuntime.isGNUFamily())
return ObjCRuntime->GetEHType(Ty);
@@ -4456,6 +4543,60 @@ llvm::Metadata *CodeGenModule::CreateMetadataIdentifierForType(QualType T) {
return InternalId;
}
+// Generalize pointer types to a void pointer with the qualifiers of the
+// originally pointed-to type, e.g. 'const char *' and 'char * const *'
+// generalize to 'const void *' while 'char *' and 'const char **' generalize to
+// 'void *'.
+static QualType GeneralizeType(ASTContext &Ctx, QualType Ty) {
+ if (!Ty->isPointerType())
+ return Ty;
+
+ return Ctx.getPointerType(
+ QualType(Ctx.VoidTy).withCVRQualifiers(
+ Ty->getPointeeType().getCVRQualifiers()));
+}
+
+// Apply type generalization to a FunctionType's return and argument types
+static QualType GeneralizeFunctionType(ASTContext &Ctx, QualType Ty) {
+ if (auto *FnType = Ty->getAs<FunctionProtoType>()) {
+ SmallVector<QualType, 8> GeneralizedParams;
+ for (auto &Param : FnType->param_types())
+ GeneralizedParams.push_back(GeneralizeType(Ctx, Param));
+
+ return Ctx.getFunctionType(
+ GeneralizeType(Ctx, FnType->getReturnType()),
+ GeneralizedParams, FnType->getExtProtoInfo());
+ }
+
+ if (auto *FnType = Ty->getAs<FunctionNoProtoType>())
+ return Ctx.getFunctionNoProtoType(
+ GeneralizeType(Ctx, FnType->getReturnType()));
+
+ llvm_unreachable("Encountered unknown FunctionType");
+}
+
+llvm::Metadata *CodeGenModule::CreateMetadataIdentifierGeneralized(QualType T) {
+ T = GeneralizeFunctionType(getContext(), T);
+
+ llvm::Metadata *&InternalId = GeneralizedMetadataIdMap[T.getCanonicalType()];
+ if (InternalId)
+ return InternalId;
+
+ if (isExternallyVisible(T->getLinkage())) {
+ std::string OutName;
+ llvm::raw_string_ostream Out(OutName);
+ getCXXABI().getMangleContext().mangleTypeName(T, Out);
+ Out << ".generalized";
+
+ InternalId = llvm::MDString::get(getLLVMContext(), Out.str());
+ } else {
+ InternalId = llvm::MDNode::getDistinct(getLLVMContext(),
+ llvm::ArrayRef<llvm::Metadata *>());
+ }
+
+ return InternalId;
+}
+
/// Returns whether this module needs the "all-vtables" type identifier.
bool CodeGenModule::NeedAllVtablesTypeId() const {
// Returns true if at least one of vtable-based CFI checkers is enabled and
@@ -4497,14 +4638,23 @@ void CodeGenModule::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
// If we have a TargetAttr build up the feature map based on that.
TargetAttr::ParsedTargetAttr ParsedAttr = TD->parse();
+ ParsedAttr.Features.erase(
+ llvm::remove_if(ParsedAttr.Features,
+ [&](const std::string &Feat) {
+ return !Target.isValidFeatureName(
+ StringRef{Feat}.substr(1));
+ }),
+ ParsedAttr.Features.end());
+
// Make a copy of the features as passed on the command line into the
// beginning of the additional features from the function to override.
ParsedAttr.Features.insert(ParsedAttr.Features.begin(),
Target.getTargetOpts().FeaturesAsWritten.begin(),
Target.getTargetOpts().FeaturesAsWritten.end());
- if (ParsedAttr.Architecture != "")
- TargetCPU = ParsedAttr.Architecture ;
+ if (ParsedAttr.Architecture != "" &&
+ Target.isValidCPUName(ParsedAttr.Architecture))
+ TargetCPU = ParsedAttr.Architecture;
// Now populate the feature map, first with the TargetCPU which is either
// the default or a new one from the target attribute string. Then we'll use
@@ -4527,8 +4677,8 @@ llvm::SanitizerStatReport &CodeGenModule::getSanStats() {
llvm::Value *
CodeGenModule::createOpenCLIntToSamplerConversion(const Expr *E,
CodeGenFunction &CGF) {
- llvm::Constant *C = EmitConstantExpr(E, E->getType(), &CGF);
- auto SamplerT = getOpenCLRuntime().getSamplerType();
+ llvm::Constant *C = ConstantEmitter(CGF).emitAbstract(E, E->getType());
+ auto SamplerT = getOpenCLRuntime().getSamplerType(E->getType().getTypePtr());
auto FTy = llvm::FunctionType::get(SamplerT, {C->getType()}, false);
return CGF.Builder.CreateCall(CreateRuntimeFunction(FTy,
"__translate_sampler_initializer"),
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h
index b162e72d1992f..22c4463b2c810 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h
@@ -490,14 +490,16 @@ private:
/// @}
- llvm::DenseMap<const Decl *, bool> DeferredEmptyCoverageMappingDecls;
+ llvm::MapVector<const Decl *, bool> DeferredEmptyCoverageMappingDecls;
std::unique_ptr<CoverageMappingModuleGen> CoverageMapping;
/// Mapping from canonical types to their metadata identifiers. We need to
/// maintain this mapping because identifiers may be formed from distinct
/// MDNodes.
- llvm::DenseMap<QualType, llvm::Metadata *> MetadataIdMap;
+ typedef llvm::DenseMap<QualType, llvm::Metadata *> MetadataTypeMap;
+ MetadataTypeMap MetadataIdMap;
+ MetadataTypeMap GeneralizedMetadataIdMap;
public:
CodeGenModule(ASTContext &C, const HeaderSearchOptions &headersearchopts,
@@ -513,6 +515,9 @@ public:
/// Finalize LLVM code generation.
void Release();
+ /// Return true if we should emit location information for expressions.
+ bool getExpressionLocationsEnabled() const;
+
/// Return a reference to the configured Objective-C runtime.
CGObjCRuntime &getObjCRuntime() {
if (!ObjCRuntime) createObjCRuntime();
@@ -649,25 +654,53 @@ public:
CtorList &getGlobalCtors() { return GlobalCtors; }
CtorList &getGlobalDtors() { return GlobalDtors; }
- llvm::MDNode *getTBAAInfo(QualType QTy);
- llvm::MDNode *getTBAAInfoForVTablePtr();
+ /// getTBAATypeInfo - Get metadata used to describe accesses to objects of
+ /// the given type.
+ llvm::MDNode *getTBAATypeInfo(QualType QTy);
+
+ /// getTBAAAccessInfo - Get TBAA information that describes an access to
+ /// an object of the given type.
+ TBAAAccessInfo getTBAAAccessInfo(QualType AccessType);
+
+ /// getTBAAVTablePtrAccessInfo - Get the TBAA information that describes an
+ /// access to a virtual table pointer.
+ TBAAAccessInfo getTBAAVTablePtrAccessInfo(llvm::Type *VTablePtrType);
+
llvm::MDNode *getTBAAStructInfo(QualType QTy);
- /// Return the path-aware tag for given base type, access node and offset.
- llvm::MDNode *getTBAAStructTagInfo(QualType BaseTy, llvm::MDNode *AccessN,
- uint64_t O);
+
+ /// getTBAABaseTypeInfo - Get metadata that describes the given base access
+ /// type. Return null if the type is not suitable for use in TBAA access tags.
+ llvm::MDNode *getTBAABaseTypeInfo(QualType QTy);
+
+ /// getTBAAAccessTagInfo - Get TBAA tag for a given memory access.
+ llvm::MDNode *getTBAAAccessTagInfo(TBAAAccessInfo Info);
+
+ /// mergeTBAAInfoForCast - Get merged TBAA information for the purposes of
+ /// type casts.
+ TBAAAccessInfo mergeTBAAInfoForCast(TBAAAccessInfo SourceInfo,
+ TBAAAccessInfo TargetInfo);
+
+ /// mergeTBAAInfoForConditionalOperator - Get merged TBAA information for the
+ /// purposes of conditional operator.
+ TBAAAccessInfo mergeTBAAInfoForConditionalOperator(TBAAAccessInfo InfoA,
+ TBAAAccessInfo InfoB);
+
+ /// getTBAAInfoForSubobject - Get TBAA information for an access with a given
+ /// base lvalue.
+ TBAAAccessInfo getTBAAInfoForSubobject(LValue Base, QualType AccessType) {
+ if (Base.getTBAAInfo().isMayAlias())
+ return TBAAAccessInfo::getMayAliasInfo();
+ return getTBAAAccessInfo(AccessType);
+ }
bool isTypeConstant(QualType QTy, bool ExcludeCtorDtor);
bool isPaddedAtomicType(QualType type);
bool isPaddedAtomicType(const AtomicType *type);
- /// Decorate the instruction with a TBAA tag. For scalar TBAA, the tag
- /// is the same as the type. For struct-path aware TBAA, the tag
- /// is different from the type: base type, access type and offset.
- /// When ConvertTypeToTag is true, we create a tag based on the scalar type.
+ /// DecorateInstructionWithTBAA - Decorate the instruction with a TBAA tag.
void DecorateInstructionWithTBAA(llvm::Instruction *Inst,
- llvm::MDNode *TBAAInfo,
- bool ConvertTypeToTag = true);
+ TBAAAccessInfo TBAAInfo);
/// Adds !invariant.barrier !tag to instruction
void DecorateInstructionWithInvariantGroup(llvm::Instruction *I,
@@ -677,7 +710,8 @@ public:
llvm::ConstantInt *getSize(CharUnits numChars);
/// Set the visibility for the given LLVM GlobalValue.
- void setGlobalVisibility(llvm::GlobalValue *GV, const NamedDecl *D) const;
+ void setGlobalVisibility(llvm::GlobalValue *GV, const NamedDecl *D,
+ ForDefinition_t IsForDefinition) const;
/// Set the TLS mode for the given LLVM GlobalValue for the thread-local
/// variable declaration D.
@@ -718,7 +752,7 @@ public:
///
/// For languages without explicit address spaces, if D has default address
/// space, target-specific global or constant address space may be returned.
- unsigned GetGlobalVarAddressSpace(const VarDecl *D);
+ LangAS GetGlobalVarAddressSpace(const VarDecl *D);
/// Return the llvm::Constant for the address of the given global variable.
/// If Ty is non-null and if the global doesn't exist, then it will be created
@@ -942,27 +976,6 @@ public:
llvm::Constant *getMemberPointerConstant(const UnaryOperator *e);
- /// Try to emit the initializer for the given declaration as a constant;
- /// returns 0 if the expression cannot be emitted as a constant.
- llvm::Constant *EmitConstantInit(const VarDecl &D,
- CodeGenFunction *CGF = nullptr);
-
- /// Try to emit the given expression as a constant; returns 0 if the
- /// expression cannot be emitted as a constant.
- llvm::Constant *EmitConstantExpr(const Expr *E, QualType DestType,
- CodeGenFunction *CGF = nullptr);
-
- /// Emit the given constant value as a constant, in the type's scalar
- /// representation.
- llvm::Constant *EmitConstantValue(const APValue &Value, QualType DestType,
- CodeGenFunction *CGF = nullptr);
-
- /// Emit the given constant value as a constant, in the type's memory
- /// representation.
- llvm::Constant *EmitConstantValueForMemory(const APValue &Value,
- QualType DestType,
- CodeGenFunction *CGF = nullptr);
-
/// \brief Emit type info if type of an expression is a variably modified
/// type. Also emit proper debug info for cast types.
void EmitExplicitCastExprType(const ExplicitCastExpr *E,
@@ -1124,7 +1137,8 @@ public:
/// annotations are emitted during finalization of the LLVM code.
void AddGlobalAnnotations(const ValueDecl *D, llvm::GlobalValue *GV);
- bool isInSanitizerBlacklist(llvm::Function *Fn, SourceLocation Loc) const;
+ bool isInSanitizerBlacklist(SanitizerMask Kind, llvm::Function *Fn,
+ SourceLocation Loc) const;
bool isInSanitizerBlacklist(llvm::GlobalVariable *GV, SourceLocation Loc,
QualType Ty,
@@ -1148,8 +1162,7 @@ public:
/// are emitted lazily.
void EmitGlobal(GlobalDecl D);
- bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target,
- bool InEveryTU);
+ bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target);
bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D);
/// Set attributes for a global definition.
@@ -1199,6 +1212,11 @@ public:
/// internal identifiers).
llvm::Metadata *CreateMetadataIdentifierForType(QualType T);
+ /// Create a metadata identifier for the generalization of the given type.
+ /// This may either be an MDString (for external identifiers) or a distinct
+ /// unnamed MDNode (for internal identifiers).
+ llvm::Metadata *CreateMetadataIdentifierGeneralized(QualType T);
+
/// Create and attach type metadata to the given function.
void CreateFunctionTypeMetadata(const FunctionDecl *FD, llvm::Function *F);
@@ -1239,7 +1257,8 @@ private:
/// Set function attributes for a function declaration.
void SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
- bool IsIncompleteFunction, bool IsThunk);
+ bool IsIncompleteFunction, bool IsThunk,
+ ForDefinition_t IsForDefinition);
void EmitGlobalDefinition(GlobalDecl D, llvm::GlobalValue *GV = nullptr);
@@ -1355,6 +1374,7 @@ private:
bool AttrOnCallSite,
llvm::AttrBuilder &FuncAttrs);
};
+
} // end namespace CodeGen
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.cpp
index c3d66c1dabc5e..295893c64fbc8 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.cpp
@@ -22,9 +22,10 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MD5.h"
-static llvm::cl::opt<bool> EnableValueProfiling(
- "enable-value-profiling", llvm::cl::ZeroOrMore,
- llvm::cl::desc("Enable value profiling"), llvm::cl::init(false));
+static llvm::cl::opt<bool>
+ EnableValueProfiling("enable-value-profiling", llvm::cl::ZeroOrMore,
+ llvm::cl::desc("Enable value profiling"),
+ llvm::cl::Hidden, llvm::cl::init(false));
using namespace clang;
using namespace CodeGen;
@@ -47,6 +48,15 @@ void CodeGenPGO::setFuncName(llvm::Function *Fn) {
llvm::createPGOFuncNameMetadata(*Fn, FuncName);
}
+/// The version of the PGO hash algorithm.
+enum PGOHashVersion : unsigned {
+ PGO_HASH_V1,
+ PGO_HASH_V2,
+
+ // Keep this set to the latest hash version.
+ PGO_HASH_LATEST = PGO_HASH_V2
+};
+
namespace {
/// \brief Stable hasher for PGO region counters.
///
@@ -61,6 +71,7 @@ namespace {
class PGOHash {
uint64_t Working;
unsigned Count;
+ PGOHashVersion HashVersion;
llvm::MD5 MD5;
static const int NumBitsPerType = 6;
@@ -93,24 +104,53 @@ public:
BinaryOperatorLAnd,
BinaryOperatorLOr,
BinaryConditionalOperator,
+ // The preceding values are available with PGO_HASH_V1.
+
+ EndOfScope,
+ IfThenBranch,
+ IfElseBranch,
+ GotoStmt,
+ IndirectGotoStmt,
+ BreakStmt,
+ ContinueStmt,
+ ReturnStmt,
+ ThrowExpr,
+ UnaryOperatorLNot,
+ BinaryOperatorLT,
+ BinaryOperatorGT,
+ BinaryOperatorLE,
+ BinaryOperatorGE,
+ BinaryOperatorEQ,
+ BinaryOperatorNE,
+ // The preceding values are available with PGO_HASH_V2.
// Keep this last. It's for the static assert that follows.
LastHashType
};
static_assert(LastHashType <= TooBig, "Too many types in HashType");
- // TODO: When this format changes, take in a version number here, and use the
- // old hash calculation for file formats that used the old hash.
- PGOHash() : Working(0), Count(0) {}
+ PGOHash(PGOHashVersion HashVersion)
+ : Working(0), Count(0), HashVersion(HashVersion), MD5() {}
void combine(HashType Type);
uint64_t finalize();
+ PGOHashVersion getHashVersion() const { return HashVersion; }
};
const int PGOHash::NumBitsPerType;
const unsigned PGOHash::NumTypesPerWord;
const unsigned PGOHash::TooBig;
+/// Get the PGO hash version used in the given indexed profile.
+static PGOHashVersion getPGOHashVersion(llvm::IndexedInstrProfReader *PGOReader,
+ CodeGenModule &CGM) {
+ if (PGOReader->getVersion() <= 4)
+ return PGO_HASH_V1;
+ return PGO_HASH_V2;
+}
+
/// A RecursiveASTVisitor that fills a map of statements to PGO counters.
struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
+ using Base = RecursiveASTVisitor<MapRegionCounters>;
+
/// The next counter value to assign.
unsigned NextCounter;
/// The function hash.
@@ -118,8 +158,9 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
/// The map of statements to counters.
llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
- MapRegionCounters(llvm::DenseMap<const Stmt *, unsigned> &CounterMap)
- : NextCounter(0), CounterMap(CounterMap) {}
+ MapRegionCounters(PGOHashVersion HashVersion,
+ llvm::DenseMap<const Stmt *, unsigned> &CounterMap)
+ : NextCounter(0), Hash(HashVersion), CounterMap(CounterMap) {}
// Blocks and lambdas are handled as separate functions, so we need not
// traverse them in the parent context.
@@ -145,16 +186,66 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
return true;
}
- bool VisitStmt(const Stmt *S) {
- auto Type = getHashType(S);
- if (Type == PGOHash::None)
- return true;
+ /// If \p S gets a fresh counter, update the counter mappings. Return the
+ /// V1 hash of \p S.
+ PGOHash::HashType updateCounterMappings(Stmt *S) {
+ auto Type = getHashType(PGO_HASH_V1, S);
+ if (Type != PGOHash::None)
+ CounterMap[S] = NextCounter++;
+ return Type;
+ }
- CounterMap[S] = NextCounter++;
- Hash.combine(Type);
+ /// Include \p S in the function hash.
+ bool VisitStmt(Stmt *S) {
+ auto Type = updateCounterMappings(S);
+ if (Hash.getHashVersion() != PGO_HASH_V1)
+ Type = getHashType(Hash.getHashVersion(), S);
+ if (Type != PGOHash::None)
+ Hash.combine(Type);
return true;
}
- PGOHash::HashType getHashType(const Stmt *S) {
+
+ bool TraverseIfStmt(IfStmt *If) {
+ // If we used the V1 hash, use the default traversal.
+ if (Hash.getHashVersion() == PGO_HASH_V1)
+ return Base::TraverseIfStmt(If);
+
+ // Otherwise, keep track of which branch we're in while traversing.
+ VisitStmt(If);
+ for (Stmt *CS : If->children()) {
+ if (!CS)
+ continue;
+ if (CS == If->getThen())
+ Hash.combine(PGOHash::IfThenBranch);
+ else if (CS == If->getElse())
+ Hash.combine(PGOHash::IfElseBranch);
+ TraverseStmt(CS);
+ }
+ Hash.combine(PGOHash::EndOfScope);
+ return true;
+ }
+
+// If the statement type \p N is nestable, and its nesting impacts profile
+// stability, define a custom traversal which tracks the end of the statement
+// in the hash (provided we're not using the V1 hash).
+#define DEFINE_NESTABLE_TRAVERSAL(N) \
+ bool Traverse##N(N *S) { \
+ Base::Traverse##N(S); \
+ if (Hash.getHashVersion() != PGO_HASH_V1) \
+ Hash.combine(PGOHash::EndOfScope); \
+ return true; \
+ }
+
+ DEFINE_NESTABLE_TRAVERSAL(WhileStmt)
+ DEFINE_NESTABLE_TRAVERSAL(DoStmt)
+ DEFINE_NESTABLE_TRAVERSAL(ForStmt)
+ DEFINE_NESTABLE_TRAVERSAL(CXXForRangeStmt)
+ DEFINE_NESTABLE_TRAVERSAL(ObjCForCollectionStmt)
+ DEFINE_NESTABLE_TRAVERSAL(CXXTryStmt)
+ DEFINE_NESTABLE_TRAVERSAL(CXXCatchStmt)
+
+ /// Get version \p HashVersion of the PGO hash for \p S.
+ PGOHash::HashType getHashType(PGOHashVersion HashVersion, const Stmt *S) {
switch (S->getStmtClass()) {
default:
break;
@@ -192,9 +283,53 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
return PGOHash::BinaryOperatorLAnd;
if (BO->getOpcode() == BO_LOr)
return PGOHash::BinaryOperatorLOr;
+ if (HashVersion == PGO_HASH_V2) {
+ switch (BO->getOpcode()) {
+ default:
+ break;
+ case BO_LT:
+ return PGOHash::BinaryOperatorLT;
+ case BO_GT:
+ return PGOHash::BinaryOperatorGT;
+ case BO_LE:
+ return PGOHash::BinaryOperatorLE;
+ case BO_GE:
+ return PGOHash::BinaryOperatorGE;
+ case BO_EQ:
+ return PGOHash::BinaryOperatorEQ;
+ case BO_NE:
+ return PGOHash::BinaryOperatorNE;
+ }
+ }
break;
}
}
+
+ if (HashVersion == PGO_HASH_V2) {
+ switch (S->getStmtClass()) {
+ default:
+ break;
+ case Stmt::GotoStmtClass:
+ return PGOHash::GotoStmt;
+ case Stmt::IndirectGotoStmtClass:
+ return PGOHash::IndirectGotoStmt;
+ case Stmt::BreakStmtClass:
+ return PGOHash::BreakStmt;
+ case Stmt::ContinueStmtClass:
+ return PGOHash::ContinueStmt;
+ case Stmt::ReturnStmtClass:
+ return PGOHash::ReturnStmt;
+ case Stmt::CXXThrowExprClass:
+ return PGOHash::ThrowExpr;
+ case Stmt::UnaryOperatorClass: {
+ const UnaryOperator *UO = cast<UnaryOperator>(S);
+ if (UO->getOpcode() == UO_LNot)
+ return PGOHash::UnaryOperatorLNot;
+ break;
+ }
+ }
+ }
+
return PGOHash::None;
}
};
@@ -653,8 +788,14 @@ void CodeGenPGO::assignRegionCounters(GlobalDecl GD, llvm::Function *Fn) {
}
void CodeGenPGO::mapRegionCounters(const Decl *D) {
+ // Use the latest hash version when inserting instrumentation, but use the
+ // version in the indexed profile if we're reading PGO data.
+ PGOHashVersion HashVersion = PGO_HASH_LATEST;
+ if (auto *PGOReader = CGM.getPGOReader())
+ HashVersion = getPGOHashVersion(PGOReader, CGM);
+
RegionCounterMap.reset(new llvm::DenseMap<const Stmt *, unsigned>);
- MapRegionCounters Walker(*RegionCounterMap);
+ MapRegionCounters Walker(HashVersion, *RegionCounterMap);
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
Walker.TraverseDecl(const_cast<FunctionDecl *>(FD));
else if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D))
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.cpp
index 8a75a552d9faa..f394ea288d469 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.cpp
@@ -25,16 +25,18 @@
#include "llvm/IR/Constants.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Metadata.h"
+#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
using namespace clang;
using namespace CodeGen;
-CodeGenTBAA::CodeGenTBAA(ASTContext &Ctx, llvm::LLVMContext& VMContext,
+CodeGenTBAA::CodeGenTBAA(ASTContext &Ctx, llvm::Module &M,
const CodeGenOptions &CGO,
const LangOptions &Features, MangleContext &MContext)
- : Context(Ctx), CodeGenOpts(CGO), Features(Features), MContext(MContext),
- MDHelper(VMContext), Root(nullptr), Char(nullptr) {
-}
+ : Context(Ctx), Module(M), CodeGenOpts(CGO),
+ Features(Features), MContext(MContext), MDHelper(M.getContext()),
+ Root(nullptr), Char(nullptr)
+{}
CodeGenTBAA::~CodeGenTBAA() {
}
@@ -54,10 +56,10 @@ llvm::MDNode *CodeGenTBAA::getRoot() {
return Root;
}
-// For both scalar TBAA and struct-path aware TBAA, the scalar type has the
-// same format: name, parent node, and offset.
-llvm::MDNode *CodeGenTBAA::createTBAAScalarType(StringRef Name,
- llvm::MDNode *Parent) {
+llvm::MDNode *CodeGenTBAA::createScalarTypeNode(StringRef Name,
+ llvm::MDNode *Parent,
+ uint64_t Size) {
+ (void)Size; // TODO: Support generation of size-aware type nodes.
return MDHelper.createTBAAScalarTypeNode(Name, Parent);
}
@@ -67,7 +69,7 @@ llvm::MDNode *CodeGenTBAA::getChar() {
// these special powers only cover user-accessible memory, and doesn't
// include things like vtables.
if (!Char)
- Char = createTBAAScalarType("omnipotent char", getRoot());
+ Char = createScalarTypeNode("omnipotent char", getRoot(), /* Size= */ 1);
return Char;
}
@@ -88,21 +90,27 @@ static bool TypeHasMayAlias(QualType QTy) {
return false;
}
-llvm::MDNode *
-CodeGenTBAA::getTBAAInfo(QualType QTy) {
- // At -O0 or relaxed aliasing, TBAA is not emitted for regular types.
- if (CodeGenOpts.OptimizationLevel == 0 || CodeGenOpts.RelaxedAliasing)
- return nullptr;
-
- // If the type has the may_alias attribute (even on a typedef), it is
- // effectively in the general char alias class.
- if (TypeHasMayAlias(QTy))
- return getChar();
-
- const Type *Ty = Context.getCanonicalType(QTy).getTypePtr();
+/// Check if the given type is a valid base type to be used in access tags.
+static bool isValidBaseType(QualType QTy) {
+ if (QTy->isReferenceType())
+ return false;
+ if (const RecordType *TTy = QTy->getAs<RecordType>()) {
+ const RecordDecl *RD = TTy->getDecl()->getDefinition();
+ // Incomplete types are not valid base access types.
+ if (!RD)
+ return false;
+ if (RD->hasFlexibleArrayMember())
+ return false;
+ // RD can be struct, union, class, interface or enum.
+ // For now, we only handle struct and class.
+ if (RD->isStruct() || RD->isClass())
+ return true;
+ }
+ return false;
+}
- if (llvm::MDNode *N = MetadataCache[Ty])
- return N;
+llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) {
+ uint64_t Size = Context.getTypeSizeInChars(Ty).getQuantity();
// Handle builtin types.
if (const BuiltinType *BTy = dyn_cast<BuiltinType>(Ty)) {
@@ -120,22 +128,21 @@ CodeGenTBAA::getTBAAInfo(QualType QTy) {
// Unsigned types can alias their corresponding signed types.
case BuiltinType::UShort:
- return getTBAAInfo(Context.ShortTy);
+ return getTypeInfo(Context.ShortTy);
case BuiltinType::UInt:
- return getTBAAInfo(Context.IntTy);
+ return getTypeInfo(Context.IntTy);
case BuiltinType::ULong:
- return getTBAAInfo(Context.LongTy);
+ return getTypeInfo(Context.LongTy);
case BuiltinType::ULongLong:
- return getTBAAInfo(Context.LongLongTy);
+ return getTypeInfo(Context.LongLongTy);
case BuiltinType::UInt128:
- return getTBAAInfo(Context.Int128Ty);
+ return getTypeInfo(Context.Int128Ty);
// Treat all other builtin types as distinct types. This includes
// treating wchar_t, char16_t, and char32_t as distinct from their
// "underlying types".
default:
- return MetadataCache[Ty] =
- createTBAAScalarType(BTy->getName(Features), getChar());
+ return createScalarTypeNode(BTy->getName(Features), getChar(), Size);
}
}
@@ -143,14 +150,13 @@ CodeGenTBAA::getTBAAInfo(QualType QTy) {
// an object through a glvalue of other than one of the following types the
// behavior is undefined: [...] a char, unsigned char, or std::byte type."
if (Ty->isStdByteType())
- return MetadataCache[Ty] = getChar();
+ return getChar();
- // Handle pointers.
+ // Handle pointers and references.
// TODO: Implement C++'s type "similarity" and consider dis-"similar"
// pointers distinct.
- if (Ty->isPointerType())
- return MetadataCache[Ty] = createTBAAScalarType("any pointer",
- getChar());
+ if (Ty->isPointerType() || Ty->isReferenceType())
+ return createScalarTypeNode("any pointer", getChar(), Size);
// Enum types are distinct types. In C++ they have "underlying types",
// however they aren't related for TBAA.
@@ -160,20 +166,53 @@ CodeGenTBAA::getTBAAInfo(QualType QTy) {
// TODO: Is there a way to get a program-wide unique name for a
// decl with local linkage or no linkage?
if (!Features.CPlusPlus || !ETy->getDecl()->isExternallyVisible())
- return MetadataCache[Ty] = getChar();
+ return getChar();
SmallString<256> OutName;
llvm::raw_svector_ostream Out(OutName);
MContext.mangleTypeName(QualType(ETy, 0), Out);
- return MetadataCache[Ty] = createTBAAScalarType(OutName, getChar());
+ return createScalarTypeNode(OutName, getChar(), Size);
}
// For now, handle any other kind of type conservatively.
- return MetadataCache[Ty] = getChar();
+ return getChar();
+}
+
+llvm::MDNode *CodeGenTBAA::getTypeInfo(QualType QTy) {
+ // At -O0 or relaxed aliasing, TBAA is not emitted for regular types.
+ if (CodeGenOpts.OptimizationLevel == 0 || CodeGenOpts.RelaxedAliasing)
+ return nullptr;
+
+ // If the type has the may_alias attribute (even on a typedef), it is
+ // effectively in the general char alias class.
+ if (TypeHasMayAlias(QTy))
+ return getChar();
+
+ // We need this function to not fall back to returning the "omnipotent char"
+ // type node for aggregate and union types. Otherwise, any dereference of an
+ // aggregate will result into the may-alias access descriptor, meaning all
+ // subsequent accesses to direct and indirect members of that aggregate will
+ // be considered may-alias too.
+ // TODO: Combine getTypeInfo() and getBaseTypeInfo() into a single function.
+ if (isValidBaseType(QTy))
+ return getBaseTypeInfo(QTy);
+
+ const Type *Ty = Context.getCanonicalType(QTy).getTypePtr();
+ if (llvm::MDNode *N = MetadataCache[Ty])
+ return N;
+
+ // Note that the following helper call is allowed to add new nodes to the
+ // cache, which invalidates all its previously obtained iterators. So we
+ // first generate the node for the type and then add that node to the cache.
+ llvm::MDNode *TypeNode = getTypeInfoHelper(Ty);
+ return MetadataCache[Ty] = TypeNode;
}
-llvm::MDNode *CodeGenTBAA::getTBAAInfoForVTablePtr() {
- return createTBAAScalarType("vtable pointer", getRoot());
+TBAAAccessInfo CodeGenTBAA::getVTablePtrAccessInfo(llvm::Type *VTablePtrType) {
+ llvm::DataLayout DL(&Module);
+ unsigned Size = DL.getPointerTypeSize(VTablePtrType);
+ return TBAAAccessInfo(createScalarTypeNode("vtable pointer", getRoot(), Size),
+ Size);
}
bool
@@ -212,8 +251,8 @@ CodeGenTBAA::CollectFields(uint64_t BaseOffset,
/* Otherwise, treat whatever it is as a field. */
uint64_t Offset = BaseOffset;
uint64_t Size = Context.getTypeSizeInChars(QTy).getQuantity();
- llvm::MDNode *TBAAInfo = MayAlias ? getChar() : getTBAAInfo(QTy);
- llvm::MDNode *TBAATag = getTBAAScalarTagInfo(TBAAInfo);
+ llvm::MDNode *TBAAType = MayAlias ? getChar() : getTypeInfo(QTy);
+ llvm::MDNode *TBAATag = getAccessTagInfo(TBAAAccessInfo(TBAAType, Size));
Fields.push_back(llvm::MDBuilder::TBAAStructField(Offset, Size, TBAATag));
return true;
}
@@ -233,46 +272,23 @@ CodeGenTBAA::getTBAAStructInfo(QualType QTy) {
return StructMetadataCache[Ty] = nullptr;
}
-/// Check if the given type can be handled by path-aware TBAA.
-static bool isTBAAPathStruct(QualType QTy) {
- if (const RecordType *TTy = QTy->getAs<RecordType>()) {
- const RecordDecl *RD = TTy->getDecl()->getDefinition();
- if (RD->hasFlexibleArrayMember())
- return false;
- // RD can be struct, union, class, interface or enum.
- // For now, we only handle struct and class.
- if (RD->isStruct() || RD->isClass())
- return true;
- }
- return false;
-}
-
-llvm::MDNode *
-CodeGenTBAA::getTBAAStructTypeInfo(QualType QTy) {
- const Type *Ty = Context.getCanonicalType(QTy).getTypePtr();
- assert(isTBAAPathStruct(QTy));
-
- if (llvm::MDNode *N = StructTypeMetadataCache[Ty])
- return N;
-
- if (const RecordType *TTy = QTy->getAs<RecordType>()) {
+llvm::MDNode *CodeGenTBAA::getBaseTypeInfoHelper(const Type *Ty) {
+ if (auto *TTy = dyn_cast<RecordType>(Ty)) {
const RecordDecl *RD = TTy->getDecl()->getDefinition();
-
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
- SmallVector <std::pair<llvm::MDNode*, uint64_t>, 4> Fields;
- unsigned idx = 0;
- for (RecordDecl::field_iterator i = RD->field_begin(),
- e = RD->field_end(); i != e; ++i, ++idx) {
- QualType FieldQTy = i->getType();
- llvm::MDNode *FieldNode;
- if (isTBAAPathStruct(FieldQTy))
- FieldNode = getTBAAStructTypeInfo(FieldQTy);
- else
- FieldNode = getTBAAInfo(FieldQTy);
- if (!FieldNode)
- return StructTypeMetadataCache[Ty] = nullptr;
- Fields.push_back(std::make_pair(
- FieldNode, Layout.getFieldOffset(idx) / Context.getCharWidth()));
+ SmallVector<llvm::MDBuilder::TBAAStructField, 4> Fields;
+ for (FieldDecl *Field : RD->fields()) {
+ QualType FieldQTy = Field->getType();
+ llvm::MDNode *TypeNode = isValidBaseType(FieldQTy) ?
+ getBaseTypeInfo(FieldQTy) : getTypeInfo(FieldQTy);
+ if (!TypeNode)
+ return BaseTypeMetadataCache[Ty] = nullptr;
+
+ uint64_t BitOffset = Layout.getFieldOffset(Field->getFieldIndex());
+ uint64_t Offset = Context.toCharUnitsFromBits(BitOffset).getQuantity();
+ uint64_t Size = Context.getTypeSizeInChars(FieldQTy).getQuantity();
+ Fields.push_back(llvm::MDBuilder::TBAAStructField(Offset, Size,
+ TypeNode));
}
SmallString<256> OutName;
@@ -283,47 +299,80 @@ CodeGenTBAA::getTBAAStructTypeInfo(QualType QTy) {
} else {
OutName = RD->getName();
}
+
+ // TODO: Support size-aware type nodes and create one here for the
+ // given aggregate type.
+
// Create the struct type node with a vector of pairs (offset, type).
- return StructTypeMetadataCache[Ty] =
- MDHelper.createTBAAStructTypeNode(OutName, Fields);
+ SmallVector<std::pair<llvm::MDNode*, uint64_t>, 4> OffsetsAndTypes;
+ for (const auto &Field : Fields)
+ OffsetsAndTypes.push_back(std::make_pair(Field.Type, Field.Offset));
+ return MDHelper.createTBAAStructTypeNode(OutName, OffsetsAndTypes);
}
- return StructMetadataCache[Ty] = nullptr;
+ return nullptr;
}
-/// Return a TBAA tag node for both scalar TBAA and struct-path aware TBAA.
-llvm::MDNode *
-CodeGenTBAA::getTBAAStructTagInfo(QualType BaseQTy, llvm::MDNode *AccessNode,
- uint64_t Offset) {
- if (!AccessNode)
+llvm::MDNode *CodeGenTBAA::getBaseTypeInfo(QualType QTy) {
+ if (!isValidBaseType(QTy))
+ return nullptr;
+
+ const Type *Ty = Context.getCanonicalType(QTy).getTypePtr();
+ if (llvm::MDNode *N = BaseTypeMetadataCache[Ty])
+ return N;
+
+ // Note that the following helper call is allowed to add new nodes to the
+ // cache, which invalidates all its previously obtained iterators. So we
+ // first generate the node for the type and then add that node to the cache.
+ llvm::MDNode *TypeNode = getBaseTypeInfoHelper(Ty);
+ return BaseTypeMetadataCache[Ty] = TypeNode;
+}
+
+llvm::MDNode *CodeGenTBAA::getAccessTagInfo(TBAAAccessInfo Info) {
+ assert(!Info.isIncomplete() && "Access to an object of an incomplete type!");
+
+ if (Info.isMayAlias())
+ Info = TBAAAccessInfo(getChar(), Info.Size);
+
+ if (!Info.AccessType)
return nullptr;
if (!CodeGenOpts.StructPathTBAA)
- return getTBAAScalarTagInfo(AccessNode);
+ Info = TBAAAccessInfo(Info.AccessType, Info.Size);
- const Type *BTy = Context.getCanonicalType(BaseQTy).getTypePtr();
- TBAAPathTag PathTag = TBAAPathTag(BTy, AccessNode, Offset);
- if (llvm::MDNode *N = StructTagMetadataCache[PathTag])
+ llvm::MDNode *&N = AccessTagMetadataCache[Info];
+ if (N)
return N;
- llvm::MDNode *BNode = nullptr;
- if (isTBAAPathStruct(BaseQTy))
- BNode = getTBAAStructTypeInfo(BaseQTy);
- if (!BNode)
- return StructTagMetadataCache[PathTag] =
- MDHelper.createTBAAStructTagNode(AccessNode, AccessNode, 0);
+ if (!Info.BaseType) {
+ Info.BaseType = Info.AccessType;
+ assert(!Info.Offset && "Nonzero offset for an access with no base type!");
+ }
+ return N = MDHelper.createTBAAStructTagNode(Info.BaseType, Info.AccessType,
+ Info.Offset);
+}
- return StructTagMetadataCache[PathTag] =
- MDHelper.createTBAAStructTagNode(BNode, AccessNode, Offset);
+TBAAAccessInfo CodeGenTBAA::mergeTBAAInfoForCast(TBAAAccessInfo SourceInfo,
+ TBAAAccessInfo TargetInfo) {
+ if (SourceInfo.isMayAlias() || TargetInfo.isMayAlias())
+ return TBAAAccessInfo::getMayAliasInfo();
+ return TargetInfo;
}
-llvm::MDNode *
-CodeGenTBAA::getTBAAScalarTagInfo(llvm::MDNode *AccessNode) {
- if (!AccessNode)
- return nullptr;
- if (llvm::MDNode *N = ScalarTagMetadataCache[AccessNode])
- return N;
+TBAAAccessInfo
+CodeGenTBAA::mergeTBAAInfoForConditionalOperator(TBAAAccessInfo InfoA,
+ TBAAAccessInfo InfoB) {
+ if (InfoA == InfoB)
+ return InfoA;
+
+ if (!InfoA || !InfoB)
+ return TBAAAccessInfo();
+
+ if (InfoA.isMayAlias() || InfoB.isMayAlias())
+ return TBAAAccessInfo::getMayAliasInfo();
- return ScalarTagMetadataCache[AccessNode] =
- MDHelper.createTBAAStructTagNode(AccessNode, AccessNode, 0);
+ // TODO: Implement the rest of the logic here. For example, two accesses
+ // with same final access types result in an access to an object of that final
+ // access type regardless of their base types.
+ return TBAAAccessInfo::getMayAliasInfo();
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.h
index ddb063d9e88a2..a5b1f66bcd1a1 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.h
@@ -30,20 +30,94 @@ namespace clang {
class Type;
namespace CodeGen {
- class CGRecordLayout;
+class CGRecordLayout;
- struct TBAAPathTag {
- TBAAPathTag(const Type *B, const llvm::MDNode *A, uint64_t O)
- : BaseT(B), AccessN(A), Offset(O) {}
- const Type *BaseT;
- const llvm::MDNode *AccessN;
- uint64_t Offset;
- };
+// TBAAAccessKind - A kind of TBAA memory access descriptor.
+enum class TBAAAccessKind : unsigned {
+ Ordinary,
+ MayAlias,
+ Incomplete,
+};
+
+// TBAAAccessInfo - Describes a memory access in terms of TBAA.
+struct TBAAAccessInfo {
+ TBAAAccessInfo(TBAAAccessKind Kind, llvm::MDNode *BaseType,
+ llvm::MDNode *AccessType, uint64_t Offset, uint64_t Size)
+ : Kind(Kind), BaseType(BaseType), AccessType(AccessType),
+ Offset(Offset), Size(Size)
+ {}
+
+ TBAAAccessInfo(llvm::MDNode *BaseType, llvm::MDNode *AccessType,
+ uint64_t Offset, uint64_t Size)
+ : TBAAAccessInfo(TBAAAccessKind::Ordinary, BaseType, AccessType,
+ Offset, Size)
+ {}
+
+ explicit TBAAAccessInfo(llvm::MDNode *AccessType, uint64_t Size)
+ : TBAAAccessInfo(/* BaseType= */ nullptr, AccessType, /* Offset= */ 0, Size)
+ {}
+
+ TBAAAccessInfo()
+ : TBAAAccessInfo(/* AccessType= */ nullptr, /* Size= */ 0)
+ {}
+
+ static TBAAAccessInfo getMayAliasInfo() {
+ return TBAAAccessInfo(TBAAAccessKind::MayAlias,
+ /* BaseType= */ nullptr, /* AccessType= */ nullptr,
+ /* Offset= */ 0, /* Size= */ 0);
+ }
+
+ bool isMayAlias() const { return Kind == TBAAAccessKind::MayAlias; }
+
+ static TBAAAccessInfo getIncompleteInfo() {
+ return TBAAAccessInfo(TBAAAccessKind::Incomplete,
+ /* BaseType= */ nullptr, /* AccessType= */ nullptr,
+ /* Offset= */ 0, /* Size= */ 0);
+ }
+
+ bool isIncomplete() const { return Kind == TBAAAccessKind::Incomplete; }
+
+ bool operator==(const TBAAAccessInfo &Other) const {
+ return Kind == Other.Kind &&
+ BaseType == Other.BaseType &&
+ AccessType == Other.AccessType &&
+ Offset == Other.Offset &&
+ Size == Other.Size;
+ }
+
+ bool operator!=(const TBAAAccessInfo &Other) const {
+ return !(*this == Other);
+ }
+
+ explicit operator bool() const {
+ return *this != TBAAAccessInfo();
+ }
+
+ /// Kind - The kind of the access descriptor.
+ TBAAAccessKind Kind;
+
+ /// BaseType - The base/leading access type. May be null if this access
+ /// descriptor represents an access that is not considered to be an access
+ /// to an aggregate or union member.
+ llvm::MDNode *BaseType;
+
+ /// AccessType - The final access type. May be null if there is no TBAA
+ /// information available about this access.
+ llvm::MDNode *AccessType;
+
+ /// Offset - The byte offset of the final access within the base one. Must be
+ /// zero if the base access type is not specified.
+ uint64_t Offset;
+
+ /// Size - The size of access, in bytes.
+ uint64_t Size;
+};
/// CodeGenTBAA - This class organizes the cross-module state that is used
/// while lowering AST types to LLVM types.
class CodeGenTBAA {
ASTContext &Context;
+ llvm::Module &Module;
const CodeGenOptions &CodeGenOpts;
const LangOptions &Features;
MangleContext &MContext;
@@ -54,12 +128,10 @@ class CodeGenTBAA {
/// MetadataCache - This maps clang::Types to scalar llvm::MDNodes describing
/// them.
llvm::DenseMap<const Type *, llvm::MDNode *> MetadataCache;
- /// This maps clang::Types to a struct node in the type DAG.
- llvm::DenseMap<const Type *, llvm::MDNode *> StructTypeMetadataCache;
- /// This maps TBAAPathTags to a tag node.
- llvm::DenseMap<TBAAPathTag, llvm::MDNode *> StructTagMetadataCache;
- /// This maps a scalar type to a scalar tag node.
- llvm::DenseMap<const llvm::MDNode *, llvm::MDNode *> ScalarTagMetadataCache;
+ /// This maps clang::Types to a base access type in the type DAG.
+ llvm::DenseMap<const Type *, llvm::MDNode *> BaseTypeMetadataCache;
+ /// This maps TBAA access descriptors to tag nodes.
+ llvm::DenseMap<TBAAAccessInfo, llvm::MDNode *> AccessTagMetadataCache;
/// StructMetadataCache - This maps clang::Types to llvm::MDNodes describing
/// them for struct assignments.
@@ -83,39 +155,52 @@ class CodeGenTBAA {
SmallVectorImpl<llvm::MDBuilder::TBAAStructField> &Fields,
bool MayAlias);
- /// A wrapper function to create a scalar type. For struct-path aware TBAA,
- /// the scalar type has the same format as the struct type: name, offset,
- /// pointer to another node in the type DAG.
- llvm::MDNode *createTBAAScalarType(StringRef Name, llvm::MDNode *Parent);
+ /// createScalarTypeNode - A wrapper function to create a metadata node
+ /// describing a scalar type.
+ llvm::MDNode *createScalarTypeNode(StringRef Name, llvm::MDNode *Parent,
+ uint64_t Size);
+
+ /// getTypeInfoHelper - An internal helper function to generate metadata used
+ /// to describe accesses to objects of the given type.
+ llvm::MDNode *getTypeInfoHelper(const Type *Ty);
+
+ /// getBaseTypeInfoHelper - An internal helper function to generate metadata
+ /// used to describe accesses to objects of the given base type.
+ llvm::MDNode *getBaseTypeInfoHelper(const Type *Ty);
public:
- CodeGenTBAA(ASTContext &Ctx, llvm::LLVMContext &VMContext,
- const CodeGenOptions &CGO,
- const LangOptions &Features,
- MangleContext &MContext);
+ CodeGenTBAA(ASTContext &Ctx, llvm::Module &M, const CodeGenOptions &CGO,
+ const LangOptions &Features, MangleContext &MContext);
~CodeGenTBAA();
- /// getTBAAInfo - Get the TBAA MDNode to be used for a dereference
- /// of the given type.
- llvm::MDNode *getTBAAInfo(QualType QTy);
+ /// getTypeInfo - Get metadata used to describe accesses to objects of the
+ /// given type.
+ llvm::MDNode *getTypeInfo(QualType QTy);
- /// getTBAAInfoForVTablePtr - Get the TBAA MDNode to be used for a
- /// dereference of a vtable pointer.
- llvm::MDNode *getTBAAInfoForVTablePtr();
+ /// getVTablePtrAccessInfo - Get the TBAA information that describes an
+ /// access to a virtual table pointer.
+ TBAAAccessInfo getVTablePtrAccessInfo(llvm::Type *VTablePtrType);
/// getTBAAStructInfo - Get the TBAAStruct MDNode to be used for a memcpy of
/// the given type.
llvm::MDNode *getTBAAStructInfo(QualType QTy);
- /// Get the MDNode in the type DAG for given struct type QType.
- llvm::MDNode *getTBAAStructTypeInfo(QualType QType);
- /// Get the tag MDNode for a given base type, the actual scalar access MDNode
- /// and offset into the base type.
- llvm::MDNode *getTBAAStructTagInfo(QualType BaseQType,
- llvm::MDNode *AccessNode, uint64_t Offset);
+ /// getBaseTypeInfo - Get metadata that describes the given base access type.
+ /// Return null if the type is not suitable for use in TBAA access tags.
+ llvm::MDNode *getBaseTypeInfo(QualType QTy);
+
+ /// getAccessTagInfo - Get TBAA tag for a given memory access.
+ llvm::MDNode *getAccessTagInfo(TBAAAccessInfo Info);
+
+ /// mergeTBAAInfoForCast - Get merged TBAA information for the purpose of
+ /// type casts.
+ TBAAAccessInfo mergeTBAAInfoForCast(TBAAAccessInfo SourceInfo,
+ TBAAAccessInfo TargetInfo);
- /// Get the scalar tag MDNode for a given scalar type.
- llvm::MDNode *getTBAAScalarTagInfo(llvm::MDNode *AccessNode);
+ /// mergeTBAAInfoForConditionalOperator - Get merged TBAA information for the
+ /// purpose of conditional operator.
+ TBAAAccessInfo mergeTBAAInfoForConditionalOperator(TBAAAccessInfo InfoA,
+ TBAAAccessInfo InfoB);
};
} // end namespace CodeGen
@@ -123,32 +208,39 @@ public:
namespace llvm {
-template<> struct DenseMapInfo<clang::CodeGen::TBAAPathTag> {
- static clang::CodeGen::TBAAPathTag getEmptyKey() {
- return clang::CodeGen::TBAAPathTag(
- DenseMapInfo<const clang::Type *>::getEmptyKey(),
- DenseMapInfo<const MDNode *>::getEmptyKey(),
+template<> struct DenseMapInfo<clang::CodeGen::TBAAAccessInfo> {
+ static clang::CodeGen::TBAAAccessInfo getEmptyKey() {
+ unsigned UnsignedKey = DenseMapInfo<unsigned>::getEmptyKey();
+ return clang::CodeGen::TBAAAccessInfo(
+ static_cast<clang::CodeGen::TBAAAccessKind>(UnsignedKey),
+ DenseMapInfo<MDNode *>::getEmptyKey(),
+ DenseMapInfo<MDNode *>::getEmptyKey(),
+ DenseMapInfo<uint64_t>::getEmptyKey(),
DenseMapInfo<uint64_t>::getEmptyKey());
}
- static clang::CodeGen::TBAAPathTag getTombstoneKey() {
- return clang::CodeGen::TBAAPathTag(
- DenseMapInfo<const clang::Type *>::getTombstoneKey(),
- DenseMapInfo<const MDNode *>::getTombstoneKey(),
+ static clang::CodeGen::TBAAAccessInfo getTombstoneKey() {
+ unsigned UnsignedKey = DenseMapInfo<unsigned>::getTombstoneKey();
+ return clang::CodeGen::TBAAAccessInfo(
+ static_cast<clang::CodeGen::TBAAAccessKind>(UnsignedKey),
+ DenseMapInfo<MDNode *>::getTombstoneKey(),
+ DenseMapInfo<MDNode *>::getTombstoneKey(),
+ DenseMapInfo<uint64_t>::getTombstoneKey(),
DenseMapInfo<uint64_t>::getTombstoneKey());
}
- static unsigned getHashValue(const clang::CodeGen::TBAAPathTag &Val) {
- return DenseMapInfo<const clang::Type *>::getHashValue(Val.BaseT) ^
- DenseMapInfo<const MDNode *>::getHashValue(Val.AccessN) ^
- DenseMapInfo<uint64_t>::getHashValue(Val.Offset);
+ static unsigned getHashValue(const clang::CodeGen::TBAAAccessInfo &Val) {
+ auto KindValue = static_cast<unsigned>(Val.Kind);
+ return DenseMapInfo<unsigned>::getHashValue(KindValue) ^
+ DenseMapInfo<MDNode *>::getHashValue(Val.BaseType) ^
+ DenseMapInfo<MDNode *>::getHashValue(Val.AccessType) ^
+ DenseMapInfo<uint64_t>::getHashValue(Val.Offset) ^
+ DenseMapInfo<uint64_t>::getHashValue(Val.Size);
}
- static bool isEqual(const clang::CodeGen::TBAAPathTag &LHS,
- const clang::CodeGen::TBAAPathTag &RHS) {
- return LHS.BaseT == RHS.BaseT &&
- LHS.AccessN == RHS.AccessN &&
- LHS.Offset == RHS.Offset;
+ static bool isEqual(const clang::CodeGen::TBAAAccessInfo &LHS,
+ const clang::CodeGen::TBAAAccessInfo &RHS) {
+ return LHS == RHS;
}
};
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypeCache.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypeCache.h
index 450eab48a3b41..2af7b30eafb4a 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypeCache.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypeCache.h
@@ -15,6 +15,7 @@
#define LLVM_CLANG_LIB_CODEGEN_CODEGENTYPECACHE_H
#include "clang/AST/CharUnits.h"
+#include "clang/Basic/AddressSpaces.h"
#include "llvm/IR/CallingConv.h"
namespace llvm {
@@ -94,7 +95,7 @@ struct CodeGenTypeCache {
unsigned char SizeAlignInBytes;
};
- unsigned ASTAllocaAddressSpace;
+ LangAS ASTAllocaAddressSpace;
CharUnits getSizeSize() const {
return CharUnits::fromQuantity(SizeSizeInBytes);
@@ -114,7 +115,7 @@ struct CodeGenTypeCache {
llvm::CallingConv::ID BuiltinCC;
llvm::CallingConv::ID getBuiltinCC() const { return BuiltinCC; }
- unsigned getASTAllocaAddressSpace() const { return ASTAllocaAddressSpace; }
+ LangAS getASTAllocaAddressSpace() const { return ASTAllocaAddressSpace; }
};
} // end namespace CodeGen
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp
index 9306c4fbaff80..529a13b7adc85 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -443,12 +443,18 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
static_cast<unsigned>(Context.getTypeSize(T)));
break;
- case BuiltinType::Half:
- // Half FP can either be storage-only (lowered to i16) or native.
+ case BuiltinType::Float16:
ResultType =
getTypeForFormat(getLLVMContext(), Context.getFloatTypeSemantics(T),
- Context.getLangOpts().NativeHalfType ||
- Context.getLangOpts().HalfArgsAndReturns);
+ /* UseNativeHalf = */ true);
+ break;
+
+ case BuiltinType::Half:
+ // Half FP can either be storage-only (lowered to i16) or native.
+ ResultType = getTypeForFormat(
+ getLLVMContext(), Context.getFloatTypeSemantics(T),
+ Context.getLangOpts().NativeHalfType ||
+ !Context.getTargetInfo().useFP16ConversionIntrinsics());
break;
case BuiltinType::Float:
case BuiltinType::Double:
@@ -639,7 +645,7 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
break;
}
case Type::Pipe: {
- ResultType = CGM.getOpenCLRuntime().getPipeType();
+ ResultType = CGM.getOpenCLRuntime().getPipeType(cast<PipeType>(Ty));
break;
}
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h
index 9d0e3ded23e47..d082342bf5925 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h
@@ -164,8 +164,6 @@ class CodeGenTypes {
llvm::SmallSet<const Type *, 8> RecordsWithOpaqueMemberPointers;
- unsigned ClangCallConvToLLVMCallConv(CallingConv CC);
-
public:
CodeGenTypes(CodeGenModule &cgm);
~CodeGenTypes();
@@ -180,6 +178,9 @@ public:
llvm::LLVMContext &getLLVMContext() { return TheModule.getContext(); }
const CodeGenOptions &getCodeGenOpts() const;
+ /// Convert clang calling convention to LLVM callilng convention.
+ unsigned ClangCallConvToLLVMCallConv(CallingConv CC);
+
/// ConvertType - Convert type T into a llvm::Type.
llvm::Type *ConvertType(QualType T);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/ConstantEmitter.h b/contrib/llvm/tools/clang/lib/CodeGen/ConstantEmitter.h
new file mode 100644
index 0000000000000..90c9fcd8cf815
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/ConstantEmitter.h
@@ -0,0 +1,178 @@
+//===--- ConstantEmitter.h - IR constant emission ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// A helper class for emitting expressions and values as llvm::Constants
+// and as initializers for global variables.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_CODEGEN_CONSTANTEMITTER_H
+#define LLVM_CLANG_LIB_CODEGEN_CONSTANTEMITTER_H
+
+#include "CodeGenFunction.h"
+#include "CodeGenModule.h"
+
+namespace clang {
+namespace CodeGen {
+
+class ConstantEmitter {
+public:
+ CodeGenModule &CGM;
+ CodeGenFunction *CGF;
+
+private:
+ bool Abstract = false;
+
+ /// Whether non-abstract components of the emitter have been initialized.
+ bool InitializedNonAbstract = false;
+
+ /// Whether the emitter has been finalized.
+ bool Finalized = false;
+
+ /// Whether the constant-emission failed.
+ bool Failed = false;
+
+ /// The AST address space where this (non-abstract) initializer is going.
+ /// Used for generating appropriate placeholders.
+ LangAS DestAddressSpace;
+
+ llvm::SmallVector<std::pair<llvm::Constant *, llvm::GlobalVariable*>, 4>
+ PlaceholderAddresses;
+
+public:
+ ConstantEmitter(CodeGenModule &CGM, CodeGenFunction *CGF = nullptr)
+ : CGM(CGM), CGF(CGF) {}
+
+ /// Initialize this emission in the context of the given function.
+ /// Use this if the expression might contain contextaul references like
+ /// block addresses or PredefinedExprs.
+ ConstantEmitter(CodeGenFunction &CGF)
+ : CGM(CGF.CGM), CGF(&CGF) {}
+
+ ConstantEmitter(const ConstantEmitter &other) = delete;
+ ConstantEmitter &operator=(const ConstantEmitter &other) = delete;
+
+ ~ConstantEmitter();
+
+ /// Is the current emission context abstract?
+ bool isAbstract() const {
+ return Abstract;
+ }
+
+ /// Try to emit the initiaizer of the given declaration as an abstract
+ /// constant. If this succeeds, the emission must be finalized.
+ llvm::Constant *tryEmitForInitializer(const VarDecl &D);
+ llvm::Constant *tryEmitForInitializer(const Expr *E, LangAS destAddrSpace,
+ QualType destType);
+ llvm::Constant *emitForInitializer(const APValue &value, LangAS destAddrSpace,
+ QualType destType);
+
+ void finalize(llvm::GlobalVariable *global);
+
+ // All of the "abstract" emission methods below permit the emission to
+ // be immediately discarded without finalizing anything. Therefore, they
+ // must also promise not to do anything that will, in the future, require
+ // finalization:
+ //
+ // - using the CGF (if present) for anything other than establishing
+ // semantic context; for example, an expression with ignored
+ // side-effects must not be emitted as an abstract expression
+ //
+ // - doing anything that would not be safe to duplicate within an
+ // initializer or to propagate to another context; for example,
+ // side effects, or emitting an initialization that requires a
+ // reference to its current location.
+
+ /// Try to emit the initializer of the given declaration as an abstract
+ /// constant.
+ llvm::Constant *tryEmitAbstractForInitializer(const VarDecl &D);
+
+ /// Emit the result of the given expression as an abstract constant,
+ /// asserting that it succeeded. This is only safe to do when the
+ /// expression is known to be a constant expression with either a fairly
+ /// simple type or a known simple form.
+ llvm::Constant *emitAbstract(const Expr *E, QualType T);
+ llvm::Constant *emitAbstract(SourceLocation loc, const APValue &value,
+ QualType T);
+
+ /// Try to emit the result of the given expression as an abstract constant.
+ llvm::Constant *tryEmitAbstract(const Expr *E, QualType T);
+ llvm::Constant *tryEmitAbstractForMemory(const Expr *E, QualType T);
+
+ llvm::Constant *tryEmitAbstract(const APValue &value, QualType T);
+ llvm::Constant *tryEmitAbstractForMemory(const APValue &value, QualType T);
+
+ llvm::Constant *emitNullForMemory(QualType T) {
+ return emitNullForMemory(CGM, T);
+ }
+ llvm::Constant *emitForMemory(llvm::Constant *C, QualType T) {
+ return emitForMemory(CGM, C, T);
+ }
+
+ static llvm::Constant *emitNullForMemory(CodeGenModule &CGM, QualType T);
+ static llvm::Constant *emitForMemory(CodeGenModule &CGM, llvm::Constant *C,
+ QualType T);
+
+ // These are private helper routines of the constant emitter that
+ // can't actually be private because things are split out into helper
+ // functions and classes.
+
+ llvm::Constant *tryEmitPrivateForVarInit(const VarDecl &D);
+
+ llvm::Constant *tryEmitPrivate(const Expr *E, QualType T);
+ llvm::Constant *tryEmitPrivateForMemory(const Expr *E, QualType T);
+
+ llvm::Constant *tryEmitPrivate(const APValue &value, QualType T);
+ llvm::Constant *tryEmitPrivateForMemory(const APValue &value, QualType T);
+
+ /// Get the address of the current location. This is a constant
+ /// that will resolve, after finalization, to the address of the
+ /// 'signal' value that is registered with the emitter later.
+ llvm::GlobalValue *getCurrentAddrPrivate();
+
+ /// Register a 'signal' value with the emitter to inform it where to
+ /// resolve a placeholder. The signal value must be unique in the
+ /// initializer; it might, for example, be the address of a global that
+ /// refers to the current-address value in its own initializer.
+ ///
+ /// Uses of the placeholder must be properly anchored before finalizing
+ /// the emitter, e.g. by being installed as the initializer of a global
+ /// variable. That is, it must be possible to replaceAllUsesWith
+ /// the placeholder with the proper address of the signal.
+ void registerCurrentAddrPrivate(llvm::Constant *signal,
+ llvm::GlobalValue *placeholder);
+
+private:
+ void initializeNonAbstract(LangAS destAS) {
+ assert(!InitializedNonAbstract);
+ InitializedNonAbstract = true;
+ DestAddressSpace = destAS;
+ }
+ llvm::Constant *markIfFailed(llvm::Constant *init) {
+ if (!init)
+ Failed = true;
+ return init;
+ }
+
+ struct AbstractState {
+ bool OldValue;
+ size_t OldPlaceholdersSize;
+ };
+ AbstractState pushAbstract() {
+ AbstractState saved = { Abstract, PlaceholderAddresses.size() };
+ Abstract = true;
+ return saved;
+ }
+ llvm::Constant *validateAndPopAbstract(llvm::Constant *C, AbstractState save);
+};
+
+}
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.cpp
index a1023473bdd33..89a30dc7040c8 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -29,7 +29,7 @@ using namespace clang;
using namespace CodeGen;
using namespace llvm::coverage;
-void CoverageSourceInfo::SourceRangeSkipped(SourceRange Range) {
+void CoverageSourceInfo::SourceRangeSkipped(SourceRange Range, SourceLocation) {
SkippedRanges.push_back(Range);
}
@@ -45,10 +45,19 @@ class SourceMappingRegion {
/// \brief The region's ending location.
Optional<SourceLocation> LocEnd;
+ /// Whether this region should be emitted after its parent is emitted.
+ bool DeferRegion;
+
+ /// Whether this region is a gap region. The count from a gap region is set
+ /// as the line execution count if there are no other regions on the line.
+ bool GapRegion;
+
public:
SourceMappingRegion(Counter Count, Optional<SourceLocation> LocStart,
- Optional<SourceLocation> LocEnd)
- : Count(Count), LocStart(LocStart), LocEnd(LocEnd) {}
+ Optional<SourceLocation> LocEnd, bool DeferRegion = false,
+ bool GapRegion = false)
+ : Count(Count), LocStart(LocStart), LocEnd(LocEnd),
+ DeferRegion(DeferRegion), GapRegion(GapRegion) {}
const Counter &getCounter() const { return Count; }
@@ -71,6 +80,47 @@ public:
assert(LocEnd && "Region has no end location");
return *LocEnd;
}
+
+ bool isDeferred() const { return DeferRegion; }
+
+ void setDeferred(bool Deferred) { DeferRegion = Deferred; }
+
+ bool isGap() const { return GapRegion; }
+
+ void setGap(bool Gap) { GapRegion = Gap; }
+};
+
+/// Spelling locations for the start and end of a source region.
+struct SpellingRegion {
+ /// The line where the region starts.
+ unsigned LineStart;
+
+ /// The column where the region starts.
+ unsigned ColumnStart;
+
+ /// The line where the region ends.
+ unsigned LineEnd;
+
+ /// The column where the region ends.
+ unsigned ColumnEnd;
+
+ SpellingRegion(SourceManager &SM, SourceLocation LocStart,
+ SourceLocation LocEnd) {
+ LineStart = SM.getSpellingLineNumber(LocStart);
+ ColumnStart = SM.getSpellingColumnNumber(LocStart);
+ LineEnd = SM.getSpellingLineNumber(LocEnd);
+ ColumnEnd = SM.getSpellingColumnNumber(LocEnd);
+ }
+
+ SpellingRegion(SourceManager &SM, SourceMappingRegion &R)
+ : SpellingRegion(SM, R.getStartLoc(), R.getEndLoc()) {}
+
+ /// Check if the start and end locations appear in source order, i.e
+ /// top->bottom, left->right.
+ bool isInSourceOrder() const {
+ return (LineStart < LineEnd) ||
+ (LineStart == LineEnd && ColumnStart <= ColumnEnd);
+ }
};
/// \brief Provides the common functionality for the different
@@ -241,12 +291,9 @@ public:
auto CovFileID = getCoverageFileID(LocStart);
if (!CovFileID)
continue;
- unsigned LineStart = SM.getSpellingLineNumber(LocStart);
- unsigned ColumnStart = SM.getSpellingColumnNumber(LocStart);
- unsigned LineEnd = SM.getSpellingLineNumber(LocEnd);
- unsigned ColumnEnd = SM.getSpellingColumnNumber(LocEnd);
+ SpellingRegion SR{SM, LocStart, LocEnd};
auto Region = CounterMappingRegion::makeSkipped(
- *CovFileID, LineStart, ColumnStart, LineEnd, ColumnEnd);
+ *CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd, SR.ColumnEnd);
// Make sure that we only collect the regions that are inside
// the souce code of this function.
if (Region.LineStart >= FileLineRanges[*CovFileID].first &&
@@ -284,16 +331,19 @@ public:
if (Filter.count(std::make_pair(LocStart, LocEnd)))
continue;
- // Find the spilling locations for the mapping region.
- unsigned LineStart = SM.getSpellingLineNumber(LocStart);
- unsigned ColumnStart = SM.getSpellingColumnNumber(LocStart);
- unsigned LineEnd = SM.getSpellingLineNumber(LocEnd);
- unsigned ColumnEnd = SM.getSpellingColumnNumber(LocEnd);
+ // Find the spelling locations for the mapping region.
+ SpellingRegion SR{SM, LocStart, LocEnd};
+ assert(SR.isInSourceOrder() && "region start and end out of order");
- assert(LineStart <= LineEnd && "region start and end out of order");
- MappingRegions.push_back(CounterMappingRegion::makeRegion(
- Region.getCounter(), *CovFileID, LineStart, ColumnStart, LineEnd,
- ColumnEnd));
+ if (Region.isGap()) {
+ MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
+ Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
+ SR.LineEnd, SR.ColumnEnd));
+ } else {
+ MappingRegions.push_back(CounterMappingRegion::makeRegion(
+ Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
+ SR.LineEnd, SR.ColumnEnd));
+ }
}
}
@@ -317,14 +367,11 @@ public:
"region spans multiple files");
Filter.insert(std::make_pair(ParentLoc, LocEnd));
- unsigned LineStart = SM.getSpellingLineNumber(ParentLoc);
- unsigned ColumnStart = SM.getSpellingColumnNumber(ParentLoc);
- unsigned LineEnd = SM.getSpellingLineNumber(LocEnd);
- unsigned ColumnEnd = SM.getSpellingColumnNumber(LocEnd);
-
+ SpellingRegion SR{SM, ParentLoc, LocEnd};
+ assert(SR.isInSourceOrder() && "region start and end out of order");
MappingRegions.push_back(CounterMappingRegion::makeExpansion(
- *ParentFileID, *ExpandedFileID, LineStart, ColumnStart, LineEnd,
- ColumnEnd));
+ *ParentFileID, *ExpandedFileID, SR.LineStart, SR.ColumnStart,
+ SR.LineEnd, SR.ColumnEnd));
}
return Filter;
}
@@ -389,6 +436,10 @@ struct CounterCoverageMappingBuilder
/// \brief A stack of currently live regions.
std::vector<SourceMappingRegion> RegionStack;
+ /// The currently deferred region: its end location and count can be set once
+ /// its parent has been popped from the region stack.
+ Optional<SourceMappingRegion> DeferredRegion;
+
CounterExpressionBuilder Builder;
/// \brief A location in the most recently visited file or macro.
@@ -397,6 +448,9 @@ struct CounterCoverageMappingBuilder
/// expressions cross file or macro boundaries.
SourceLocation MostRecentLocation;
+ /// Location of the last terminated region.
+ Optional<std::pair<SourceLocation, size_t>> LastTerminatedRegion;
+
/// \brief Return a counter for the subtraction of \c RHS from \c LHS
Counter subtractCounters(Counter LHS, Counter RHS) {
return Builder.subtract(LHS, RHS);
@@ -424,19 +478,84 @@ struct CounterCoverageMappingBuilder
/// used with popRegions to exit a "scope", ending the region that was pushed.
size_t pushRegion(Counter Count, Optional<SourceLocation> StartLoc = None,
Optional<SourceLocation> EndLoc = None) {
- if (StartLoc)
+ if (StartLoc) {
MostRecentLocation = *StartLoc;
+ completeDeferred(Count, MostRecentLocation);
+ }
RegionStack.emplace_back(Count, StartLoc, EndLoc);
return RegionStack.size() - 1;
}
+ /// Complete any pending deferred region by setting its end location and
+ /// count, and then pushing it onto the region stack.
+ size_t completeDeferred(Counter Count, SourceLocation DeferredEndLoc) {
+ size_t Index = RegionStack.size();
+ if (!DeferredRegion)
+ return Index;
+
+ // Consume the pending region.
+ SourceMappingRegion DR = DeferredRegion.getValue();
+ DeferredRegion = None;
+
+ // If the region ends in an expansion, find the expansion site.
+ FileID StartFile = SM.getFileID(DR.getStartLoc());
+ if (SM.getFileID(DeferredEndLoc) != StartFile) {
+ if (isNestedIn(DeferredEndLoc, StartFile)) {
+ do {
+ DeferredEndLoc = getIncludeOrExpansionLoc(DeferredEndLoc);
+ } while (StartFile != SM.getFileID(DeferredEndLoc));
+ } else {
+ return Index;
+ }
+ }
+
+ // The parent of this deferred region ends where the containing decl ends,
+ // so the region isn't useful.
+ if (DR.getStartLoc() == DeferredEndLoc)
+ return Index;
+
+ // If we're visiting statements in non-source order (e.g switch cases or
+ // a loop condition) we can't construct a sensible deferred region.
+ if (!SpellingRegion(SM, DR.getStartLoc(), DeferredEndLoc).isInSourceOrder())
+ return Index;
+
+ DR.setGap(true);
+ DR.setCounter(Count);
+ DR.setEndLoc(DeferredEndLoc);
+ handleFileExit(DeferredEndLoc);
+ RegionStack.push_back(DR);
+ return Index;
+ }
+
+ /// Complete a deferred region created after a terminated region at the
+ /// top-level.
+ void completeTopLevelDeferredRegion(Counter Count,
+ SourceLocation DeferredEndLoc) {
+ if (DeferredRegion || !LastTerminatedRegion)
+ return;
+
+ if (LastTerminatedRegion->second != RegionStack.size())
+ return;
+
+ SourceLocation Start = LastTerminatedRegion->first;
+ if (SM.getFileID(Start) != SM.getMainFileID())
+ return;
+
+ SourceMappingRegion DR = RegionStack.back();
+ DR.setStartLoc(Start);
+ DR.setDeferred(false);
+ DeferredRegion = DR;
+ completeDeferred(Count, DeferredEndLoc);
+ }
+
/// \brief Pop regions from the stack into the function's list of regions.
///
/// Adds all regions from \c ParentIndex to the top of the stack to the
/// function's \c SourceRegions.
void popRegions(size_t ParentIndex) {
assert(RegionStack.size() >= ParentIndex && "parent not in stack");
+ bool ParentOfDeferredRegion = false;
while (RegionStack.size() > ParentIndex) {
SourceMappingRegion &Region = RegionStack.back();
if (Region.hasStartLoc()) {
@@ -467,10 +586,34 @@ struct CounterCoverageMappingBuilder
MostRecentLocation = getIncludeOrExpansionLoc(EndLoc);
assert(SM.isWrittenInSameFile(Region.getStartLoc(), EndLoc));
+ assert(SpellingRegion(SM, Region).isInSourceOrder());
SourceRegions.push_back(Region);
+
+ if (ParentOfDeferredRegion) {
+ ParentOfDeferredRegion = false;
+
+ // If there's an existing deferred region, keep the old one, because
+ // it means there are two consecutive returns (or a similar pattern).
+ if (!DeferredRegion.hasValue() &&
+ // File IDs aren't gathered within macro expansions, so it isn't
+ // useful to try and create a deferred region inside of one.
+ !EndLoc.isMacroID())
+ DeferredRegion =
+ SourceMappingRegion(Counter::getZero(), EndLoc, None);
+ }
+ } else if (Region.isDeferred()) {
+ assert(!ParentOfDeferredRegion && "Consecutive deferred regions");
+ ParentOfDeferredRegion = true;
}
RegionStack.pop_back();
+
+ // If the zero region pushed after the last terminated region no longer
+ // exists, clear its cached information.
+ if (LastTerminatedRegion &&
+ RegionStack.size() < LastTerminatedRegion->second)
+ LastTerminatedRegion = None;
}
+ assert(!ParentOfDeferredRegion && "Deferred region with no parent");
}
/// \brief Return the currently active region.
@@ -481,15 +624,17 @@ struct CounterCoverageMappingBuilder
/// \brief Propagate counts through the children of \c S.
Counter propagateCounts(Counter TopCount, const Stmt *S) {
- size_t Index = pushRegion(TopCount, getStart(S), getEnd(S));
+ SourceLocation StartLoc = getStart(S);
+ SourceLocation EndLoc = getEnd(S);
+ size_t Index = pushRegion(TopCount, StartLoc, EndLoc);
Visit(S);
Counter ExitCount = getRegion().getCounter();
popRegions(Index);
// The statement may be spanned by an expansion. Make sure we handle a file
// exit out of this expansion before moving to the next statement.
- if (SM.isBeforeInTranslationUnit(getStart(S), S->getLocStart()))
- MostRecentLocation = getEnd(S);
+ if (SM.isBeforeInTranslationUnit(StartLoc, S->getLocStart()))
+ MostRecentLocation = EndLoc;
return ExitCount;
}
@@ -577,9 +722,11 @@ struct CounterCoverageMappingBuilder
SourceLocation Loc = MostRecentLocation;
while (isNestedIn(Loc, ParentFile)) {
SourceLocation FileStart = getStartOfFileOrMacro(Loc);
- if (StartLocs.insert(FileStart).second)
+ if (StartLocs.insert(FileStart).second) {
SourceRegions.emplace_back(*ParentCounter, FileStart,
getEndOfFileOrMacro(Loc));
+ assert(SpellingRegion(SM, SourceRegions.back()).isInSourceOrder());
+ }
Loc = getIncludeOrExpansionLoc(Loc);
}
}
@@ -595,15 +742,53 @@ struct CounterCoverageMappingBuilder
handleFileExit(StartLoc);
if (!Region.hasStartLoc())
Region.setStartLoc(StartLoc);
+
+ completeDeferred(Region.getCounter(), StartLoc);
}
/// \brief Mark \c S as a terminator, starting a zero region.
void terminateRegion(const Stmt *S) {
extendRegion(S);
SourceMappingRegion &Region = getRegion();
+ SourceLocation EndLoc = getEnd(S);
if (!Region.hasEndLoc())
- Region.setEndLoc(getEnd(S));
+ Region.setEndLoc(EndLoc);
pushRegion(Counter::getZero());
+ auto &ZeroRegion = getRegion();
+ ZeroRegion.setDeferred(true);
+ LastTerminatedRegion = {EndLoc, RegionStack.size()};
+ }
+
+ /// Find a valid gap range between \p AfterLoc and \p BeforeLoc.
+ Optional<SourceRange> findGapAreaBetween(SourceLocation AfterLoc,
+ SourceLocation BeforeLoc) {
+ // If the start and end locations of the gap are both within the same macro
+ // file, the range may not be in source order.
+ if (AfterLoc.isMacroID() || BeforeLoc.isMacroID())
+ return None;
+ if (!SM.isWrittenInSameFile(AfterLoc, BeforeLoc))
+ return None;
+ return {{AfterLoc, BeforeLoc}};
+ }
+
+ /// Find the source range after \p AfterStmt and before \p BeforeStmt.
+ Optional<SourceRange> findGapAreaBetween(const Stmt *AfterStmt,
+ const Stmt *BeforeStmt) {
+ return findGapAreaBetween(getPreciseTokenLocEnd(getEnd(AfterStmt)),
+ getStart(BeforeStmt));
+ }
+
+ /// Emit a gap region between \p StartLoc and \p EndLoc with the given count.
+ void fillGapAreaWithCount(SourceLocation StartLoc, SourceLocation EndLoc,
+ Counter Count) {
+ if (StartLoc == EndLoc)
+ return;
+ assert(SpellingRegion(SM, StartLoc, EndLoc).isInSourceOrder());
+ handleFileExit(StartLoc);
+ size_t Index = pushRegion(Count, StartLoc, EndLoc);
+ getRegion().setGap(true);
+ handleFileExit(EndLoc);
+ popRegions(Index);
}
/// \brief Keep counts of breaks and continues inside loops.
@@ -617,13 +802,15 @@ struct CounterCoverageMappingBuilder
CoverageMappingModuleGen &CVM,
llvm::DenseMap<const Stmt *, unsigned> &CounterMap, SourceManager &SM,
const LangOptions &LangOpts)
- : CoverageMappingBuilder(CVM, SM, LangOpts), CounterMap(CounterMap) {}
+ : CoverageMappingBuilder(CVM, SM, LangOpts), CounterMap(CounterMap),
+ DeferredRegion(None) {}
/// \brief Write the mapping data to the output stream
void write(llvm::raw_ostream &OS) {
llvm::SmallVector<unsigned, 8> VirtualFileMapping;
gatherFileIDs(VirtualFileMapping);
SourceRegionFilter Filter = emitExpansionRegions();
+ assert(!DeferredRegion && "Deferred region never completed");
emitSourceRegions(Filter);
gatherSkippedRegions();
@@ -644,14 +831,42 @@ struct CounterCoverageMappingBuilder
handleFileExit(getEnd(S));
}
+ /// Determine whether the final deferred region emitted in \p Body should be
+ /// discarded.
+ static bool discardFinalDeferredRegionInDecl(Stmt *Body) {
+ if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
+ Stmt *LastStmt = CS->body_back();
+ if (auto *IfElse = dyn_cast<IfStmt>(LastStmt)) {
+ if (auto *Else = dyn_cast_or_null<CompoundStmt>(IfElse->getElse()))
+ LastStmt = Else->body_back();
+ else
+ LastStmt = IfElse->getElse();
+ }
+ return dyn_cast_or_null<ReturnStmt>(LastStmt);
+ }
+ return false;
+ }
+
void VisitDecl(const Decl *D) {
+ assert(!DeferredRegion && "Deferred region never completed");
+
Stmt *Body = D->getBody();
// Do not propagate region counts into system headers.
if (Body && SM.isInSystemHeader(SM.getSpellingLoc(getStart(Body))))
return;
- propagateCounts(getRegionCounter(Body), Body);
+ Counter ExitCount = propagateCounts(getRegionCounter(Body), Body);
+ assert(RegionStack.empty() && "Regions entered but never exited");
+
+ if (DeferredRegion) {
+ // Complete (or discard) any deferred regions introduced by the last
+ // statement.
+ if (discardFinalDeferredRegionInDecl(Body))
+ DeferredRegion = None;
+ else
+ popRegions(completeDeferred(ExitCount, getEnd(Body)));
+ }
}
void VisitReturnStmt(const ReturnStmt *S) {
@@ -671,10 +886,12 @@ struct CounterCoverageMappingBuilder
void VisitGotoStmt(const GotoStmt *S) { terminateRegion(S); }
void VisitLabelStmt(const LabelStmt *S) {
+ Counter LabelCount = getRegionCounter(S);
SourceLocation Start = getStart(S);
+ completeTopLevelDeferredRegion(LabelCount, Start);
// We can't extendRegion here or we risk overlapping with our new region.
handleFileExit(Start);
- pushRegion(getRegionCounter(S), Start);
+ pushRegion(LabelCount, Start);
Visit(S->getSubStmt());
}
@@ -682,6 +899,8 @@ struct CounterCoverageMappingBuilder
assert(!BreakContinueStack.empty() && "break not in a loop or switch!");
BreakContinueStack.back().BreakCount = addCounters(
BreakContinueStack.back().BreakCount, getRegion().getCounter());
+ // FIXME: a break in a switch should terminate regions for all preceding
+ // case statements, not just the most recent one.
terminateRegion(S);
}
@@ -692,6 +911,16 @@ struct CounterCoverageMappingBuilder
terminateRegion(S);
}
+ void VisitCallExpr(const CallExpr *E) {
+ VisitStmt(E);
+
+ // Terminate the region when we hit a noreturn function.
+ // (This is helpful dealing with switch statements.)
+ QualType CalleeType = E->getCallee()->getType();
+ if (getFunctionExtInfo(*CalleeType).getNoReturn())
+ terminateRegion(E);
+ }
+
void VisitWhileStmt(const WhileStmt *S) {
extendRegion(S);
@@ -710,6 +939,11 @@ struct CounterCoverageMappingBuilder
propagateCounts(CondCount, S->getCond());
adjustForOutOfOrderTraversal(getEnd(S));
+ // The body count applies to the area immediately after the increment.
+ auto Gap = findGapAreaBetween(S->getCond(), S->getBody());
+ if (Gap)
+ fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
+
Counter OutCount =
addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount));
if (OutCount != ParentCount)
@@ -764,6 +998,12 @@ struct CounterCoverageMappingBuilder
adjustForOutOfOrderTraversal(getEnd(S));
}
+ // The body count applies to the area immediately after the increment.
+ auto Gap = findGapAreaBetween(getPreciseTokenLocEnd(S->getRParenLoc()),
+ getStart(S->getBody()));
+ if (Gap)
+ fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
+
Counter OutCount =
addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount));
if (OutCount != ParentCount)
@@ -783,6 +1023,12 @@ struct CounterCoverageMappingBuilder
Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
BreakContinue BC = BreakContinueStack.pop_back_val();
+ // The body count applies to the area immediately after the range.
+ auto Gap = findGapAreaBetween(getPreciseTokenLocEnd(S->getRParenLoc()),
+ getStart(S->getBody()));
+ if (Gap)
+ fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
+
Counter LoopCount =
addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
Counter OutCount =
@@ -803,6 +1049,12 @@ struct CounterCoverageMappingBuilder
Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
BreakContinue BC = BreakContinueStack.pop_back_val();
+ // The body count applies to the area immediately after the collection.
+ auto Gap = findGapAreaBetween(getPreciseTokenLocEnd(S->getRParenLoc()),
+ getStart(S->getBody()));
+ if (Gap)
+ fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
+
Counter LoopCount =
addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
Counter OutCount =
@@ -823,15 +1075,20 @@ struct CounterCoverageMappingBuilder
extendRegion(Body);
if (const auto *CS = dyn_cast<CompoundStmt>(Body)) {
if (!CS->body_empty()) {
- // The body of the switch needs a zero region so that fallthrough counts
- // behave correctly, but it would be misleading to include the braces of
- // the compound statement in the zeroed area, so we need to handle this
- // specially.
+ // Make a region for the body of the switch. If the body starts with
+ // a case, that case will reuse this region; otherwise, this covers
+ // the unreachable code at the beginning of the switch body.
size_t Index =
- pushRegion(Counter::getZero(), getStart(CS->body_front()),
- getEnd(CS->body_back()));
+ pushRegion(Counter::getZero(), getStart(CS->body_front()));
for (const auto *Child : CS->children())
Visit(Child);
+
+ // Set the end for the body of the switch, if it isn't already set.
+ for (size_t i = RegionStack.size(); i != Index; --i) {
+ if (!RegionStack[i - 1].hasEndLoc())
+ RegionStack[i - 1].setEndLoc(getEnd(CS->body_back()));
+ }
+
popRegions(Index);
}
} else
@@ -889,12 +1146,21 @@ struct CounterCoverageMappingBuilder
// counter for the body when looking at the coverage.
propagateCounts(ParentCount, S->getCond());
+ // The 'then' count applies to the area immediately after the condition.
+ auto Gap = findGapAreaBetween(S->getCond(), S->getThen());
+ if (Gap)
+ fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ThenCount);
+
extendRegion(S->getThen());
Counter OutCount = propagateCounts(ThenCount, S->getThen());
Counter ElseCount = subtractCounters(ParentCount, ThenCount);
if (const Stmt *Else = S->getElse()) {
- extendRegion(S->getElse());
+ // The 'else' count applies to the area immediately after the 'then'.
+ Gap = findGapAreaBetween(S->getThen(), Else);
+ if (Gap)
+ fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ElseCount);
+ extendRegion(Else);
OutCount = addCounters(OutCount, propagateCounts(ElseCount, Else));
} else
OutCount = addCounters(OutCount, ElseCount);
@@ -931,25 +1197,34 @@ struct CounterCoverageMappingBuilder
Visit(E->getCond());
if (!isa<BinaryConditionalOperator>(E)) {
+ // The 'then' count applies to the area immediately after the condition.
+ auto Gap =
+ findGapAreaBetween(E->getQuestionLoc(), getStart(E->getTrueExpr()));
+ if (Gap)
+ fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), TrueCount);
+
extendRegion(E->getTrueExpr());
propagateCounts(TrueCount, E->getTrueExpr());
}
+
extendRegion(E->getFalseExpr());
propagateCounts(subtractCounters(ParentCount, TrueCount),
E->getFalseExpr());
}
void VisitBinLAnd(const BinaryOperator *E) {
- extendRegion(E);
- Visit(E->getLHS());
+ extendRegion(E->getLHS());
+ propagateCounts(getRegion().getCounter(), E->getLHS());
+ handleFileExit(getEnd(E->getLHS()));
extendRegion(E->getRHS());
propagateCounts(getRegionCounter(E), E->getRHS());
}
void VisitBinLOr(const BinaryOperator *E) {
- extendRegion(E);
- Visit(E->getLHS());
+ extendRegion(E->getLHS());
+ propagateCounts(getRegion().getCounter(), E->getLHS());
+ handleFileExit(getEnd(E->getLHS()));
extendRegion(E->getRHS());
propagateCounts(getRegionCounter(E), E->getRHS());
@@ -992,6 +1267,9 @@ static void dump(llvm::raw_ostream &OS, StringRef FunctionName,
case CounterMappingRegion::SkippedRegion:
OS << "Skipped,";
break;
+ case CounterMappingRegion::GapRegion:
+ OS << "Gap,";
+ break;
}
OS << "File " << R.FileID << ", " << R.LineStart << ":" << R.ColumnStart
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.h b/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.h
index b6789c2a79f12..d07ed5ebcf2b4 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.h
@@ -39,7 +39,7 @@ class CoverageSourceInfo : public PPCallbacks {
public:
ArrayRef<SourceRange> getSkippedRanges() const { return SkippedRanges; }
- void SourceRangeSkipped(SourceRange Range) override;
+ void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override;
};
namespace CodeGen {
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp b/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp
index bd4cb9a3667b2..c375b82ea9363 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -165,9 +165,17 @@ public:
Address Ptr, QualType ElementType,
const CXXDestructorDecl *Dtor) override;
+ /// Itanium says that an _Unwind_Exception has to be "double-word"
+ /// aligned (and thus the end of it is also so-aligned), meaning 16
+ /// bytes. Of course, that was written for the actual Itanium,
+ /// which is a 64-bit platform. Classically, the ABI doesn't really
+ /// specify the alignment on other platforms, but in practice
+ /// libUnwind declares the struct with __attribute__((aligned)), so
+ /// we assume that alignment here. (It's generally 16 bytes, but
+ /// some targets overwrite it.)
CharUnits getAlignmentOfExnObject() {
- unsigned Align = CGM.getContext().getTargetInfo().getExnObjectAlignment();
- return CGM.getContext().toCharUnitsFromBits(Align);
+ auto align = CGM.getContext().getTargetDefaultAlignForAttributeAligned();
+ return CGM.getContext().toCharUnitsFromBits(align);
}
void emitRethrow(CodeGenFunction &CGF, bool isNoReturn) override;
@@ -292,6 +300,14 @@ public:
// linkage together with vtables when needed.
if (ForVTable && !Thunk->hasLocalLinkage())
Thunk->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
+
+ // Propagate dllexport storage, to enable the linker to generate import
+ // thunks as necessary (e.g. when a parent class has a key function and a
+ // child class doesn't, and the construction vtable for the parent in the
+ // child needs to reference the parent's thunks).
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+ if (MD->hasAttr<DLLExportAttr>())
+ Thunk->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
}
llvm::Value *performThisAdjustment(CodeGenFunction &CGF, Address This,
@@ -373,6 +389,10 @@ public:
void emitCXXStructor(const CXXMethodDecl *MD, StructorType Type) override;
+ std::pair<llvm::Value *, const CXXRecordDecl *>
+ LoadVTablePtr(CodeGenFunction &CGF, Address This,
+ const CXXRecordDecl *RD) override;
+
private:
bool hasAnyUnusedVirtualInlineFunction(const CXXRecordDecl *RD) const {
const auto &VtableLayout =
@@ -546,9 +566,9 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
llvm::Value *MemFnPtr, const MemberPointerType *MPT) {
CGBuilderTy &Builder = CGF.Builder;
- const FunctionProtoType *FPT =
+ const FunctionProtoType *FPT =
MPT->getPointeeType()->getAs<FunctionProtoType>();
- const CXXRecordDecl *RD =
+ const CXXRecordDecl *RD =
cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(
@@ -575,10 +595,10 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
Ptr = Builder.CreateInBoundsGEP(Ptr, Adj);
This = Builder.CreateBitCast(Ptr, This->getType(), "this.adjusted");
ThisPtrForCall = This;
-
+
// Load the function pointer.
llvm::Value *FnAsInt = Builder.CreateExtractValue(MemFnPtr, 0, "memptr.ptr");
-
+
// If the LSB in the function pointer is 1, the function pointer points to
// a virtual function.
llvm::Value *IsVirtual;
@@ -626,7 +646,7 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
CGF.EmitBlock(FnNonVirtual);
llvm::Value *NonVirtualFn =
Builder.CreateIntToPtr(FnAsInt, FTy->getPointerTo(), "memptr.nonvirtualfn");
-
+
// We're done.
CGF.EmitBlock(FnEnd);
llvm::PHINode *CalleePtr = Builder.CreatePHI(FTy->getPointerTo(), 2);
@@ -791,7 +811,7 @@ llvm::Constant *
ItaniumCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {
// Itanium C++ ABI 2.3:
// A NULL pointer is represented as -1.
- if (MPT->isMemberDataPointer())
+ if (MPT->isMemberDataPointer())
return llvm::ConstantInt::get(CGM.PtrDiffTy, -1ULL, /*isSigned=*/true);
llvm::Constant *Zero = llvm::ConstantInt::get(CGM.PtrDiffTy, 0);
@@ -868,7 +888,7 @@ llvm::Constant *ItaniumCXXABI::BuildMemberPointer(const CXXMethodDecl *MD,
(UseARMMethodPtrABI ? 2 : 1) *
ThisAdjustment.getQuantity());
}
-
+
return llvm::ConstantStruct::getAnon(MemPtr);
}
@@ -927,7 +947,7 @@ ItaniumCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
// (L.ptr == 0 && ((L.adj|R.adj) & 1) == 0)))
// The inequality tautologies have exactly the same structure, except
// applying De Morgan's laws.
-
+
llvm::Value *LPtr = Builder.CreateExtractValue(L, 0, "lhs.memptr.ptr");
llvm::Value *RPtr = Builder.CreateExtractValue(R, 0, "rhs.memptr.ptr");
@@ -980,7 +1000,7 @@ ItaniumCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
llvm::Constant::getAllOnesValue(MemPtr->getType());
return Builder.CreateICmpNE(MemPtr, NegativeOne, "memptr.tobool");
}
-
+
// In Itanium, a member function pointer is not null if 'ptr' is not null.
llvm::Value *Ptr = Builder.CreateExtractValue(MemPtr, 0, "memptr.ptr");
@@ -1138,9 +1158,9 @@ static llvm::Constant *getItaniumDynamicCastFn(CodeGenFunction &CGF) {
// const abi::__class_type_info *src,
// const abi::__class_type_info *dst,
// std::ptrdiff_t src2dst_offset);
-
+
llvm::Type *Int8PtrTy = CGF.Int8PtrTy;
- llvm::Type *PtrDiffTy =
+ llvm::Type *PtrDiffTy =
CGF.ConvertType(CGF.getContext().getPointerDiffType());
llvm::Type *Args[4] = { Int8PtrTy, Int8PtrTy, Int8PtrTy, PtrDiffTy };
@@ -1427,8 +1447,9 @@ void ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
if (CGF.CurFuncDecl && CGF.CurFuncDecl->hasAttr<NakedAttr>())
return;
- /// Initialize the 'this' slot.
- EmitThisParam(CGF);
+ /// Initialize the 'this' slot. In the Itanium C++ ABI, no prologue
+ /// adjustments are required, becuase they are all handled by thunks.
+ setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF));
/// Initialize the 'vtt' slot if needed.
if (getStructorImplicitParamDecl(CGF)) {
@@ -1510,7 +1531,7 @@ void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
VTable->setComdat(CGM.getModule().getOrInsertComdat(VTable->getName()));
// Set the right visibility.
- CGM.setGlobalVisibility(VTable, RD);
+ CGM.setGlobalVisibility(VTable, RD, ForDefinition);
// Use pointer alignment for the vtable. Otherwise we would align them based
// on the size of the initializer which doesn't make sense as only single
@@ -1620,6 +1641,7 @@ llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
VTable = CGM.CreateOrReplaceCXXRuntimeVariable(
Name, VTableType, llvm::GlobalValue::ExternalLinkage);
VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
+ CGM.setGlobalVisibility(VTable, RD, NotForDefinition);
if (RD->hasAttr<DLLImportAttr>())
VTable->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
@@ -2111,30 +2133,31 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
(UseARMGuardVarABI && !useInt8GuardVariable)
? Builder.CreateAnd(LI, llvm::ConstantInt::get(CGM.Int8Ty, 1))
: LI;
- llvm::Value *isInitialized = Builder.CreateIsNull(V, "guard.uninitialized");
+ llvm::Value *NeedsInit = Builder.CreateIsNull(V, "guard.uninitialized");
llvm::BasicBlock *InitCheckBlock = CGF.createBasicBlock("init.check");
llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end");
// Check if the first byte of the guard variable is zero.
- Builder.CreateCondBr(isInitialized, InitCheckBlock, EndBlock);
+ CGF.EmitCXXGuardedInitBranch(NeedsInit, InitCheckBlock, EndBlock,
+ CodeGenFunction::GuardKind::VariableGuard, &D);
CGF.EmitBlock(InitCheckBlock);
// Variables used when coping with thread-safe statics and exceptions.
- if (threadsafe) {
+ if (threadsafe) {
// Call __cxa_guard_acquire.
llvm::Value *V
= CGF.EmitNounwindRuntimeCall(getGuardAcquireFn(CGM, guardPtrTy), guard);
-
+
llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init");
-
+
Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"),
InitBlock, EndBlock);
-
+
// Call __cxa_guard_abort along the exceptional edge.
CGF.EHStack.pushCleanup<CallGuardAbort>(EHCleanup, guard);
-
+
CGF.EmitBlock(InitBlock);
}
@@ -2447,11 +2470,11 @@ LValue ItaniumCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF,
/// if it's a base constructor or destructor with virtual bases.
bool ItaniumCXXABI::NeedsVTTParameter(GlobalDecl GD) {
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
-
+
// We don't have any virtual bases, just return early.
if (!MD->getParent()->getNumVBases())
return false;
-
+
// Check if we have a base constructor.
if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base)
return true;
@@ -2459,7 +2482,7 @@ bool ItaniumCXXABI::NeedsVTTParameter(GlobalDecl GD) {
// Check if we have a base destructor.
if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
return true;
-
+
return false;
}
@@ -2648,6 +2671,7 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
case BuiltinType::Float:
case BuiltinType::Double:
case BuiltinType::LongDouble:
+ case BuiltinType::Float16:
case BuiltinType::Float128:
case BuiltinType::Char16:
case BuiltinType::Char32:
@@ -2981,15 +3005,13 @@ static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(CodeGenModule &CGM,
if (RD->hasAttr<DLLImportAttr>() &&
ShouldUseExternalRTTIDescriptor(CGM, Ty))
return llvm::GlobalValue::ExternalLinkage;
- if (RD->isDynamicClass()) {
- llvm::GlobalValue::LinkageTypes LT = CGM.getVTableLinkage(RD);
- // MinGW won't export the RTTI information when there is a key function.
- // Make sure we emit our own copy instead of attempting to dllimport it.
- if (RD->hasAttr<DLLImportAttr>() &&
- llvm::GlobalValue::isAvailableExternallyLinkage(LT))
- LT = llvm::GlobalValue::LinkOnceODRLinkage;
- return LT;
- }
+ // MinGW always uses LinkOnceODRLinkage for type info.
+ if (RD->isDynamicClass() &&
+ !CGM.getContext()
+ .getTargetInfo()
+ .getTriple()
+ .isWindowsGNUEnvironment())
+ return CGM.getVTableLinkage(RD);
}
return llvm::GlobalValue::LinkOnceODRLinkage;
@@ -3648,6 +3670,18 @@ void ItaniumCXXABI::emitCXXStructor(const CXXMethodDecl *MD,
!CGM.TryEmitBaseDestructorAsAlias(DD))
return;
+ // FIXME: The deleting destructor is equivalent to the selected operator
+ // delete if:
+ // * either the delete is a destroying operator delete or the destructor
+ // would be trivial if it weren't virtual,
+ // * the conversion from the 'this' parameter to the first parameter of the
+ // destructor is equivalent to a bitcast,
+ // * the destructor does not have an implicit "this" return, and
+ // * the operator delete has the same calling convention and IR function type
+ // as the destructor.
+ // In such cases we should try to emit the deleting dtor as an alias to the
+ // selected 'operator delete'.
+
llvm::Function *Fn = CGM.codegenCXXStructor(MD, Type);
if (CGType == StructorCodegen::COMDAT) {
@@ -4011,3 +4045,9 @@ ItaniumCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF,
}
return CGF.EmitNounwindRuntimeCall(CGF.CGM.getTerminateFn());
}
+
+std::pair<llvm::Value *, const CXXRecordDecl *>
+ItaniumCXXABI::LoadVTablePtr(CodeGenFunction &CGF, Address This,
+ const CXXRecordDecl *RD) {
+ return {CGF.GetVTablePtr(This, CGM.Int8PtrTy, RD), RD};
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index 1bd2937e47477..ffb3681c2585a 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -244,9 +244,6 @@ public:
void addImplicitStructorParams(CodeGenFunction &CGF, QualType &ResTy,
FunctionArgList &Params) override;
- llvm::Value *adjustThisParameterInVirtualFunctionPrologue(
- CodeGenFunction &CGF, GlobalDecl GD, llvm::Value *This) override;
-
void EmitInstanceFunctionProlog(CodeGenFunction &CGF) override;
AddedStructorArgs
@@ -581,7 +578,7 @@ private:
return GetVBaseOffsetFromVBPtr(CGF, Base, VBPOffset, VBTOffset, VBPtr);
}
- std::pair<Address, llvm::Value *>
+ std::tuple<Address, llvm::Value *, const CXXRecordDecl *>
performBaseAdjustment(CodeGenFunction &CGF, Address Value,
QualType SrcRecordTy);
@@ -748,6 +745,10 @@ public:
llvm::GlobalVariable *getThrowInfo(QualType T) override;
+ std::pair<llvm::Value *, const CXXRecordDecl *>
+ LoadVTablePtr(CodeGenFunction &CGF, Address This,
+ const CXXRecordDecl *RD) override;
+
private:
typedef std::pair<const CXXRecordDecl *, CharUnits> VFTableIdTy;
typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalVariable *> VTablesMapTy;
@@ -929,7 +930,7 @@ void MicrosoftCXXABI::emitBeginCatch(CodeGenFunction &CGF,
/// We need to perform a generic polymorphic operation (like a typeid
/// or a cast), which requires an object with a vfptr. Adjust the
/// address to point to an object with a vfptr.
-std::pair<Address, llvm::Value *>
+std::tuple<Address, llvm::Value *, const CXXRecordDecl *>
MicrosoftCXXABI::performBaseAdjustment(CodeGenFunction &CGF, Address Value,
QualType SrcRecordTy) {
Value = CGF.Builder.CreateBitCast(Value, CGF.Int8PtrTy);
@@ -940,7 +941,8 @@ MicrosoftCXXABI::performBaseAdjustment(CodeGenFunction &CGF, Address Value,
// covers non-virtual base subobjects: a class with its own virtual
// functions would be a candidate to be a primary base.
if (Context.getASTRecordLayout(SrcDecl).hasExtendableVFPtr())
- return std::make_pair(Value, llvm::ConstantInt::get(CGF.Int32Ty, 0));
+ return std::make_tuple(Value, llvm::ConstantInt::get(CGF.Int32Ty, 0),
+ SrcDecl);
// Okay, one of the vbases must have a vfptr, or else this isn't
// actually a polymorphic class.
@@ -959,7 +961,7 @@ MicrosoftCXXABI::performBaseAdjustment(CodeGenFunction &CGF, Address Value,
llvm::Value *Ptr = CGF.Builder.CreateInBoundsGEP(Value.getPointer(), Offset);
CharUnits VBaseAlign =
CGF.CGM.getVBaseAlignment(Value.getAlignment(), SrcDecl, PolymorphicBase);
- return std::make_pair(Address(Ptr, VBaseAlign), Offset);
+ return std::make_tuple(Address(Ptr, VBaseAlign), Offset, PolymorphicBase);
}
bool MicrosoftCXXABI::shouldTypeidBeNullChecked(bool IsDeref,
@@ -990,7 +992,7 @@ llvm::Value *MicrosoftCXXABI::EmitTypeid(CodeGenFunction &CGF,
QualType SrcRecordTy,
Address ThisPtr,
llvm::Type *StdTypeInfoPtrTy) {
- std::tie(ThisPtr, std::ignore) =
+ std::tie(ThisPtr, std::ignore, std::ignore) =
performBaseAdjustment(CGF, ThisPtr, SrcRecordTy);
auto Typeid = emitRTtypeidCall(CGF, ThisPtr.getPointer()).getInstruction();
return CGF.Builder.CreateBitCast(Typeid, StdTypeInfoPtrTy);
@@ -1014,7 +1016,8 @@ llvm::Value *MicrosoftCXXABI::EmitDynamicCastCall(
CGF.CGM.GetAddrOfRTTIDescriptor(DestRecordTy.getUnqualifiedType());
llvm::Value *Offset;
- std::tie(This, Offset) = performBaseAdjustment(CGF, This, SrcRecordTy);
+ std::tie(This, Offset, std::ignore) =
+ performBaseAdjustment(CGF, This, SrcRecordTy);
llvm::Value *ThisPtr = This.getPointer();
Offset = CGF.Builder.CreateTrunc(Offset, CGF.Int32Ty);
@@ -1040,7 +1043,8 @@ llvm::Value *
MicrosoftCXXABI::EmitDynamicCastToVoid(CodeGenFunction &CGF, Address Value,
QualType SrcRecordTy,
QualType DestTy) {
- std::tie(Value, std::ignore) = performBaseAdjustment(CGF, Value, SrcRecordTy);
+ std::tie(Value, std::ignore, std::ignore) =
+ performBaseAdjustment(CGF, Value, SrcRecordTy);
// PVOID __RTCastToVoid(
// PVOID inptr)
@@ -1433,50 +1437,54 @@ void MicrosoftCXXABI::addImplicitStructorParams(CodeGenFunction &CGF,
}
}
-llvm::Value *MicrosoftCXXABI::adjustThisParameterInVirtualFunctionPrologue(
- CodeGenFunction &CGF, GlobalDecl GD, llvm::Value *This) {
- // In this ABI, every virtual function takes a pointer to one of the
- // subobjects that first defines it as the 'this' parameter, rather than a
- // pointer to the final overrider subobject. Thus, we need to adjust it back
- // to the final overrider subobject before use.
- // See comments in the MicrosoftVFTableContext implementation for the details.
- CharUnits Adjustment = getVirtualFunctionPrologueThisAdjustment(GD);
- if (Adjustment.isZero())
- return This;
-
- unsigned AS = cast<llvm::PointerType>(This->getType())->getAddressSpace();
- llvm::Type *charPtrTy = CGF.Int8Ty->getPointerTo(AS),
- *thisTy = This->getType();
-
- This = CGF.Builder.CreateBitCast(This, charPtrTy);
- assert(Adjustment.isPositive());
- This = CGF.Builder.CreateConstInBoundsGEP1_32(CGF.Int8Ty, This,
- -Adjustment.getQuantity());
- return CGF.Builder.CreateBitCast(This, thisTy);
-}
-
void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
// Naked functions have no prolog.
if (CGF.CurFuncDecl && CGF.CurFuncDecl->hasAttr<NakedAttr>())
return;
- EmitThisParam(CGF);
+ // Overridden virtual methods of non-primary bases need to adjust the incoming
+ // 'this' pointer in the prologue. In this hierarchy, C::b will subtract
+ // sizeof(void*) to adjust from B* to C*:
+ // struct A { virtual void a(); };
+ // struct B { virtual void b(); };
+ // struct C : A, B { virtual void b(); };
+ //
+ // Leave the value stored in the 'this' alloca unadjusted, so that the
+ // debugger sees the unadjusted value. Microsoft debuggers require this, and
+ // will apply the ThisAdjustment in the method type information.
+ // FIXME: Do something better for DWARF debuggers, which won't expect this,
+ // without making our codegen depend on debug info settings.
+ llvm::Value *This = loadIncomingCXXThis(CGF);
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
+ if (!CGF.CurFuncIsThunk && MD->isVirtual()) {
+ CharUnits Adjustment = getVirtualFunctionPrologueThisAdjustment(CGF.CurGD);
+ if (!Adjustment.isZero()) {
+ unsigned AS = cast<llvm::PointerType>(This->getType())->getAddressSpace();
+ llvm::Type *charPtrTy = CGF.Int8Ty->getPointerTo(AS),
+ *thisTy = This->getType();
+ This = CGF.Builder.CreateBitCast(This, charPtrTy);
+ assert(Adjustment.isPositive());
+ This = CGF.Builder.CreateConstInBoundsGEP1_32(CGF.Int8Ty, This,
+ -Adjustment.getQuantity());
+ This = CGF.Builder.CreateBitCast(This, thisTy, "this.adjusted");
+ }
+ }
+ setCXXABIThisValue(CGF, This);
- /// If this is a function that the ABI specifies returns 'this', initialize
- /// the return slot to 'this' at the start of the function.
- ///
- /// Unlike the setting of return types, this is done within the ABI
- /// implementation instead of by clients of CGCXXABI because:
- /// 1) getThisValue is currently protected
- /// 2) in theory, an ABI could implement 'this' returns some other way;
- /// HasThisReturn only specifies a contract, not the implementation
+ // If this is a function that the ABI specifies returns 'this', initialize
+ // the return slot to 'this' at the start of the function.
+ //
+ // Unlike the setting of return types, this is done within the ABI
+ // implementation instead of by clients of CGCXXABI because:
+ // 1) getThisValue is currently protected
+ // 2) in theory, an ABI could implement 'this' returns some other way;
+ // HasThisReturn only specifies a contract, not the implementation
if (HasThisReturn(CGF.CurGD))
CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue);
else if (hasMostDerivedReturn(CGF.CurGD))
CGF.Builder.CreateStore(CGF.EmitCastToVoidPtr(getThisValue(CGF)),
CGF.ReturnValue);
- const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
if (isa<CXXConstructorDecl>(MD) && MD->getParent()->getNumVBases()) {
assert(getStructorImplicitParamDecl(CGF) &&
"no implicit parameter for a constructor with virtual bases?");
@@ -1961,7 +1969,7 @@ llvm::Function *MicrosoftCXXABI::EmitVirtualMemPtrThunk(
// Start defining the function.
CGF.StartFunction(GlobalDecl(), FnInfo.getReturnType(), ThunkFn, FnInfo,
FunctionArgs, MD->getLocation(), SourceLocation());
- EmitThisParam(CGF);
+ setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF));
// Load the vfptr and then callee from the vftable. The callee should have
// adjusted 'this' so that the vfptr is at offset zero.
@@ -2461,11 +2469,12 @@ void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
// Test our bit from the guard variable.
llvm::ConstantInt *Bit = llvm::ConstantInt::get(GuardTy, 1ULL << GuardNum);
llvm::LoadInst *LI = Builder.CreateLoad(GuardAddr);
- llvm::Value *IsInitialized =
- Builder.CreateICmpNE(Builder.CreateAnd(LI, Bit), Zero);
+ llvm::Value *NeedsInit =
+ Builder.CreateICmpEQ(Builder.CreateAnd(LI, Bit), Zero);
llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init");
llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end");
- Builder.CreateCondBr(IsInitialized, EndBlock, InitBlock);
+ CGF.EmitCXXGuardedInitBranch(NeedsInit, InitBlock, EndBlock,
+ CodeGenFunction::GuardKind::VariableGuard, &D);
// Set our bit in the guard variable and emit the initializer and add a global
// destructor if appropriate.
@@ -2500,7 +2509,8 @@ void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
Builder.CreateICmpSGT(FirstGuardLoad, InitThreadEpoch);
llvm::BasicBlock *AttemptInitBlock = CGF.createBasicBlock("init.attempt");
llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end");
- Builder.CreateCondBr(IsUninitialized, AttemptInitBlock, EndBlock);
+ CGF.EmitCXXGuardedInitBranch(IsUninitialized, AttemptInitBlock, EndBlock,
+ CodeGenFunction::GuardKind::VariableGuard, &D);
// This BasicBlock attempts to determine whether or not this thread is
// responsible for doing the initialization.
@@ -3803,7 +3813,7 @@ static void emitCXXDestructor(CodeGenModule &CGM, const CXXDestructorDecl *dtor,
if (!dtor->getParent()->getNumVBases() &&
(dtorType == StructorType::Complete || dtorType == StructorType::Base)) {
bool ProducedAlias = !CGM.TryEmitDefinitionAsAlias(
- GlobalDecl(dtor, Dtor_Complete), GlobalDecl(dtor, Dtor_Base), true);
+ GlobalDecl(dtor, Dtor_Complete), GlobalDecl(dtor, Dtor_Base));
if (ProducedAlias) {
if (dtorType == StructorType::Complete)
return;
@@ -3898,7 +3908,7 @@ MicrosoftCXXABI::getAddrOfCXXCtorClosure(const CXXConstructorDecl *CD,
FunctionArgs, CD->getLocation(), SourceLocation());
// Create a scope with an artificial location for the body of this function.
auto AL = ApplyDebugLocation::CreateArtificial(CGF);
- EmitThisParam(CGF);
+ setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF));
llvm::Value *This = getThisValue(CGF);
llvm::Value *SrcVal =
@@ -4241,3 +4251,11 @@ void MicrosoftCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) {
};
CGF.EmitNoreturnRuntimeCallOrInvoke(getThrowFn(), Args);
}
+
+std::pair<llvm::Value *, const CXXRecordDecl *>
+MicrosoftCXXABI::LoadVTablePtr(CodeGenFunction &CGF, Address This,
+ const CXXRecordDecl *RD) {
+ std::tie(This, std::ignore, RD) =
+ performBaseAdjustment(CGF, This, QualType(RD->getTypeForDecl(), 0));
+ return {CGF.GetVTablePtr(This, CGM.Int8PtrTy, RD), RD};
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/ModuleBuilder.cpp b/contrib/llvm/tools/clang/lib/CodeGen/ModuleBuilder.cpp
index fc642850d60ad..8aa9bfb421b4a 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/ModuleBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/ModuleBuilder.cpp
@@ -119,6 +119,14 @@ namespace {
return Builder->GetAddrOfGlobal(global, ForDefinition_t(isForDefinition));
}
+ llvm::Module *StartModule(llvm::StringRef ModuleName,
+ llvm::LLVMContext &C) {
+ assert(!M && "Replacing existing Module?");
+ M.reset(new llvm::Module(ModuleName, C));
+ Initialize(*Ctx);
+ return M.get();
+ }
+
void Initialize(ASTContext &Context) override {
Ctx = &Context;
@@ -317,6 +325,11 @@ llvm::Constant *CodeGenerator::GetAddrOfGlobal(GlobalDecl global,
->GetAddrOfGlobal(global, isForDefinition);
}
+llvm::Module *CodeGenerator::StartModule(llvm::StringRef ModuleName,
+ llvm::LLVMContext &C) {
+ return static_cast<CodeGeneratorImpl*>(this)->StartModule(ModuleName, C);
+}
+
CodeGenerator *clang::CreateLLVMCodeGen(
DiagnosticsEngine &Diags, llvm::StringRef ModuleName,
const HeaderSearchOptions &HeaderSearchOpts,
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/SanitizerMetadata.cpp b/contrib/llvm/tools/clang/lib/CodeGen/SanitizerMetadata.cpp
index 9848e3e452f4b..f891cfbe4bb2b 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/SanitizerMetadata.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/SanitizerMetadata.cpp
@@ -26,7 +26,8 @@ void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV,
QualType Ty, bool IsDynInit,
bool IsBlacklisted) {
if (!CGM.getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address |
- SanitizerKind::KernelAddress))
+ SanitizerKind::KernelAddress |
+ SanitizerKind::HWAddress))
return;
IsDynInit &= !CGM.isInSanitizerBlacklist(GV, Loc, Ty, "init");
IsBlacklisted |= CGM.isInSanitizerBlacklist(GV, Loc, Ty);
@@ -58,7 +59,8 @@ void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV,
void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV,
const VarDecl &D, bool IsDynInit) {
if (!CGM.getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address |
- SanitizerKind::KernelAddress))
+ SanitizerKind::KernelAddress |
+ SanitizerKind::HWAddress))
return;
std::string QualName;
llvm::raw_string_ostream OS(QualName);
@@ -76,7 +78,8 @@ void SanitizerMetadata::disableSanitizerForGlobal(llvm::GlobalVariable *GV) {
// For now, just make sure the global is not modified by the ASan
// instrumentation.
if (CGM.getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address |
- SanitizerKind::KernelAddress))
+ SanitizerKind::KernelAddress |
+ SanitizerKind::HWAddress))
reportGlobalToASan(GV, SourceLocation(), "", QualType(), false, true);
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp
index ece3a407eae3b..4b8006428f8f0 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp
@@ -14,6 +14,7 @@
#include "TargetInfo.h"
#include "ABIInfo.h"
+#include "CGBlocks.h"
#include "CGCXXABI.h"
#include "CGValue.h"
#include "CodeGenFunction.h"
@@ -22,7 +23,9 @@
#include "clang/CodeGen/SwiftCallingConv.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/raw_ostream.h"
@@ -420,18 +423,17 @@ llvm::Constant *TargetCodeGenInfo::getNullPointer(const CodeGen::CodeGenModule &
return llvm::ConstantPointerNull::get(T);
}
-unsigned TargetCodeGenInfo::getGlobalVarAddressSpace(CodeGenModule &CGM,
- const VarDecl *D) const {
+LangAS TargetCodeGenInfo::getGlobalVarAddressSpace(CodeGenModule &CGM,
+ const VarDecl *D) const {
assert(!CGM.getLangOpts().OpenCL &&
!(CGM.getLangOpts().CUDA && CGM.getLangOpts().CUDAIsDevice) &&
"Address space agnostic languages only");
- return D ? D->getType().getAddressSpace()
- : static_cast<unsigned>(LangAS::Default);
+ return D ? D->getType().getAddressSpace() : LangAS::Default;
}
llvm::Value *TargetCodeGenInfo::performAddrSpaceCast(
- CodeGen::CodeGenFunction &CGF, llvm::Value *Src, unsigned SrcAddr,
- unsigned DestAddr, llvm::Type *DestTy, bool isNonNull) const {
+ CodeGen::CodeGenFunction &CGF, llvm::Value *Src, LangAS SrcAddr,
+ LangAS DestAddr, llvm::Type *DestTy, bool isNonNull) const {
// Since target may map different address spaces in AST to the same address
// space, an address space conversion may end up as a bitcast.
if (auto *C = dyn_cast<llvm::Constant>(Src))
@@ -441,13 +443,18 @@ llvm::Value *TargetCodeGenInfo::performAddrSpaceCast(
llvm::Constant *
TargetCodeGenInfo::performAddrSpaceCast(CodeGenModule &CGM, llvm::Constant *Src,
- unsigned SrcAddr, unsigned DestAddr,
+ LangAS SrcAddr, LangAS DestAddr,
llvm::Type *DestTy) const {
// Since target may map different address spaces in AST to the same address
// space, an address space conversion may end up as a bitcast.
return llvm::ConstantExpr::getPointerCast(Src, DestTy);
}
+llvm::SyncScope::ID
+TargetCodeGenInfo::getLLVMSyncScopeID(SyncScope S, llvm::LLVMContext &C) const {
+ return C.getOrInsertSyncScopeID(""); /* default sync scope */
+}
+
static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays);
/// isEmptyField - Return true iff a the field is "empty", that is it
@@ -869,7 +876,10 @@ bool IsX86_MMXType(llvm::Type *IRType) {
static llvm::Type* X86AdjustInlineAsmType(CodeGen::CodeGenFunction &CGF,
StringRef Constraint,
llvm::Type* Ty) {
- if ((Constraint == "y" || Constraint == "&y") && Ty->isVectorTy()) {
+ bool IsMMXCons = llvm::StringSwitch<bool>(Constraint)
+ .Cases("y", "&y", "^Ym", true)
+ .Default(false);
+ if (IsMMXCons && Ty->isVectorTy()) {
if (cast<llvm::VectorType>(Ty)->getBitWidth() != 64) {
// Invalid MMX constraint
return nullptr;
@@ -886,8 +896,14 @@ static llvm::Type* X86AdjustInlineAsmType(CodeGen::CodeGenFunction &CGF,
/// X86_VectorCall calling convention. Shared between x86_32 and x86_64.
static bool isX86VectorTypeForVectorCall(ASTContext &Context, QualType Ty) {
if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) {
- if (BT->isFloatingPoint() && BT->getKind() != BuiltinType::Half)
+ if (BT->isFloatingPoint() && BT->getKind() != BuiltinType::Half) {
+ if (BT->getKind() == BuiltinType::LongDouble) {
+ if (&Context.getTargetInfo().getLongDoubleFormat() ==
+ &llvm::APFloat::x87DoubleExtended())
+ return false;
+ }
return true;
+ }
} else if (const VectorType *VT = Ty->getAs<VectorType>()) {
// vectorcall can pass XMM, YMM, and ZMM vectors. We don't pass SSE1 MMX
// registers specially.
@@ -1041,7 +1057,8 @@ public:
const llvm::Triple &Triple, const CodeGenOptions &Opts);
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &CGM) const override;
+ CodeGen::CodeGenModule &CGM,
+ ForDefinition_t IsForDefinition) const override;
int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const override {
// Darwin uses different dwarf register numbers for EH.
@@ -1070,14 +1087,14 @@ public:
getUBSanFunctionSignature(CodeGen::CodeGenModule &CGM) const override {
unsigned Sig = (0xeb << 0) | // jmp rel8
(0x06 << 8) | // .+0x08
- ('F' << 16) |
- ('T' << 24);
+ ('v' << 16) |
+ ('2' << 24);
return llvm::ConstantInt::get(CGM.Int32Ty, Sig);
}
StringRef getARCRetainAutoreleasedReturnValueMarker() const override {
return "movl\t%ebp, %ebp"
- "\t\t## marker for objc_retainAutoreleaseReturnValue";
+ "\t\t// marker for objc_retainAutoreleaseReturnValue";
}
};
@@ -1900,7 +1917,6 @@ bool X86_32TargetCodeGenInfo::isStructReturnInRegABI(
case llvm::Triple::DragonFly:
case llvm::Triple::FreeBSD:
case llvm::Triple::OpenBSD:
- case llvm::Triple::Bitrig:
case llvm::Triple::Win32:
return true;
default:
@@ -1908,9 +1924,11 @@ bool X86_32TargetCodeGenInfo::isStructReturnInRegABI(
}
}
-void X86_32TargetCodeGenInfo::setTargetAttributes(const Decl *D,
- llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &CGM) const {
+void X86_32TargetCodeGenInfo::setTargetAttributes(
+ const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM,
+ ForDefinition_t IsForDefinition) const {
+ if (!IsForDefinition)
+ return;
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
if (FD->hasAttr<X86ForceAlignArgPointerAttr>()) {
// Get the LLVM function.
@@ -2260,23 +2278,28 @@ public:
llvm::Constant *
getUBSanFunctionSignature(CodeGen::CodeGenModule &CGM) const override {
- unsigned Sig;
- if (getABIInfo().has64BitPointers())
- Sig = (0xeb << 0) | // jmp rel8
- (0x0a << 8) | // .+0x0c
- ('F' << 16) |
- ('T' << 24);
- else
- Sig = (0xeb << 0) | // jmp rel8
- (0x06 << 8) | // .+0x08
- ('F' << 16) |
- ('T' << 24);
+ unsigned Sig = (0xeb << 0) | // jmp rel8
+ (0x06 << 8) | // .+0x08
+ ('v' << 16) |
+ ('2' << 24);
return llvm::ConstantInt::get(CGM.Int32Ty, Sig);
}
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &CGM) const override {
+ CodeGen::CodeGenModule &CGM,
+ ForDefinition_t IsForDefinition) const override {
+ if (!IsForDefinition)
+ return;
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
+ if (FD->hasAttr<X86ForceAlignArgPointerAttr>()) {
+ // Get the LLVM function.
+ auto *Fn = cast<llvm::Function>(GV);
+
+ // Now add the 'alignstack' attribute with a value of 16.
+ llvm::AttrBuilder B;
+ B.addStackAlignmentAttr(16);
+ Fn->addAttributes(llvm::AttributeList::FunctionIndex, B);
+ }
if (FD->hasAttr<AnyX86InterruptAttr>()) {
llvm::Function *Fn = cast<llvm::Function>(GV);
Fn->setCallingConv(llvm::CallingConv::X86_INTR);
@@ -2323,7 +2346,8 @@ public:
Win32StructABI, NumRegisterParameters, false) {}
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &CGM) const override;
+ CodeGen::CodeGenModule &CGM,
+ ForDefinition_t IsForDefinition) const override;
void getDependentLibraryOption(llvm::StringRef Lib,
llvm::SmallString<24> &Opt) const override {
@@ -2351,11 +2375,12 @@ static void addStackProbeSizeTargetAttribute(const Decl *D,
}
}
-void WinX86_32TargetCodeGenInfo::setTargetAttributes(const Decl *D,
- llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &CGM) const {
- X86_32TargetCodeGenInfo::setTargetAttributes(D, GV, CGM);
-
+void WinX86_32TargetCodeGenInfo::setTargetAttributes(
+ const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM,
+ ForDefinition_t IsForDefinition) const {
+ X86_32TargetCodeGenInfo::setTargetAttributes(D, GV, CGM, IsForDefinition);
+ if (!IsForDefinition)
+ return;
addStackProbeSizeTargetAttribute(D, GV, CGM);
}
@@ -2366,7 +2391,8 @@ public:
: TargetCodeGenInfo(new WinX86_64ABIInfo(CGT)) {}
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &CGM) const override;
+ CodeGen::CodeGenModule &CGM,
+ ForDefinition_t IsForDefinition) const override;
int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const override {
return 7;
@@ -2395,12 +2421,22 @@ public:
}
};
-void WinX86_64TargetCodeGenInfo::setTargetAttributes(const Decl *D,
- llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &CGM) const {
- TargetCodeGenInfo::setTargetAttributes(D, GV, CGM);
-
+void WinX86_64TargetCodeGenInfo::setTargetAttributes(
+ const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM,
+ ForDefinition_t IsForDefinition) const {
+ TargetCodeGenInfo::setTargetAttributes(D, GV, CGM, IsForDefinition);
+ if (!IsForDefinition)
+ return;
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
+ if (FD->hasAttr<X86ForceAlignArgPointerAttr>()) {
+ // Get the LLVM function.
+ auto *Fn = cast<llvm::Function>(GV);
+
+ // Now add the 'alignstack' attribute with a value of 16.
+ llvm::AttrBuilder B;
+ B.addStackAlignmentAttr(16);
+ Fn->addAttributes(llvm::AttributeList::FunctionIndex, B);
+ }
if (FD->hasAttr<AnyX86InterruptAttr>()) {
llvm::Function *Fn = cast<llvm::Function>(GV);
Fn->setCallingConv(llvm::CallingConv::X86_INTR);
@@ -3514,18 +3550,27 @@ void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
unsigned FreeSSERegs = IsRegCall ? 16 : 8;
unsigned NeededInt, NeededSSE;
- if (IsRegCall && FI.getReturnType()->getTypePtr()->isRecordType() &&
- !FI.getReturnType()->getTypePtr()->isUnionType()) {
- FI.getReturnInfo() =
- classifyRegCallStructType(FI.getReturnType(), NeededInt, NeededSSE);
- if (FreeIntRegs >= NeededInt && FreeSSERegs >= NeededSSE) {
- FreeIntRegs -= NeededInt;
- FreeSSERegs -= NeededSSE;
- } else {
- FI.getReturnInfo() = getIndirectReturnResult(FI.getReturnType());
- }
- } else if (!getCXXABI().classifyReturnType(FI))
- FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+ if (!getCXXABI().classifyReturnType(FI)) {
+ if (IsRegCall && FI.getReturnType()->getTypePtr()->isRecordType() &&
+ !FI.getReturnType()->getTypePtr()->isUnionType()) {
+ FI.getReturnInfo() =
+ classifyRegCallStructType(FI.getReturnType(), NeededInt, NeededSSE);
+ if (FreeIntRegs >= NeededInt && FreeSSERegs >= NeededSSE) {
+ FreeIntRegs -= NeededInt;
+ FreeSSERegs -= NeededSSE;
+ } else {
+ FI.getReturnInfo() = getIndirectReturnResult(FI.getReturnType());
+ }
+ } else if (IsRegCall && FI.getReturnType()->getAs<ComplexType>()) {
+ // Complex Long Double Type is passed in Memory when Regcall
+ // calling convention is used.
+ const ComplexType *CT = FI.getReturnType()->getAs<ComplexType>();
+ if (getContext().getCanonicalType(CT->getElementType()) ==
+ getContext().LongDoubleTy)
+ FI.getReturnInfo() = getIndirectReturnResult(FI.getReturnType());
+ } else
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+ }
// If the return value is indirect, then the hidden argument is consuming one
// integer register.
@@ -3991,7 +4036,10 @@ Address WinX86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
namespace {
/// PPC32_SVR4_ABIInfo - The 32-bit PowerPC ELF (SVR4) ABI information.
class PPC32_SVR4_ABIInfo : public DefaultABIInfo {
-bool IsSoftFloatABI;
+ bool IsSoftFloatABI;
+
+ CharUnits getParamTypeAlignment(QualType Ty) const;
+
public:
PPC32_SVR4_ABIInfo(CodeGen::CodeGenTypes &CGT, bool SoftFloatABI)
: DefaultABIInfo(CGT), IsSoftFloatABI(SoftFloatABI) {}
@@ -4013,13 +4061,46 @@ public:
bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
llvm::Value *Address) const override;
};
+}
+
+CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const {
+ // Complex types are passed just like their elements
+ if (const ComplexType *CTy = Ty->getAs<ComplexType>())
+ Ty = CTy->getElementType();
+ if (Ty->isVectorType())
+ return CharUnits::fromQuantity(getContext().getTypeSize(Ty) == 128 ? 16
+ : 4);
+
+ // For single-element float/vector structs, we consider the whole type
+ // to have the same alignment requirements as its single element.
+ const Type *AlignTy = nullptr;
+ if (const Type *EltType = isSingleElementStruct(Ty, getContext())) {
+ const BuiltinType *BT = EltType->getAs<BuiltinType>();
+ if ((EltType->isVectorType() && getContext().getTypeSize(EltType) == 128) ||
+ (BT && BT->isFloatingPoint()))
+ AlignTy = EltType;
+ }
+
+ if (AlignTy)
+ return CharUnits::fromQuantity(AlignTy->isVectorType() ? 16 : 4);
+ return CharUnits::fromQuantity(4);
}
// TODO: this implementation is now likely redundant with
// DefaultABIInfo::EmitVAArg.
Address PPC32_SVR4_ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAList,
QualType Ty) const {
+ if (getTarget().getTriple().isOSDarwin()) {
+ auto TI = getContext().getTypeInfoInChars(Ty);
+ TI.second = getParamTypeAlignment(Ty);
+
+ CharUnits SlotSize = CharUnits::fromQuantity(4);
+ return emitVoidPtrVAArg(CGF, VAList, Ty,
+ classifyArgumentType(Ty).isIndirect(), TI, SlotSize,
+ /*AllowHigherAlign=*/true);
+ }
+
const unsigned OverflowLimit = 8;
if (const ComplexType *CTy = Ty->getAs<ComplexType>()) {
// TODO: Implement this. For now ignore.
@@ -4860,7 +4941,7 @@ public:
: TargetCodeGenInfo(new AArch64ABIInfo(CGT, Kind)) {}
StringRef getARCRetainAutoreleasedReturnValueMarker() const override {
- return "mov\tfp, fp\t\t# marker for objc_retainAutoreleaseReturnValue";
+ return "mov\tfp, fp\t\t// marker for objc_retainAutoreleaseReturnValue";
}
int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override {
@@ -4869,6 +4950,22 @@ public:
bool doesReturnSlotInterfereWithArgs() const override { return false; }
};
+
+class WindowsAArch64TargetCodeGenInfo : public AArch64TargetCodeGenInfo {
+public:
+ WindowsAArch64TargetCodeGenInfo(CodeGenTypes &CGT, AArch64ABIInfo::ABIKind K)
+ : AArch64TargetCodeGenInfo(CGT, K) {}
+
+ void getDependentLibraryOption(llvm::StringRef Lib,
+ llvm::SmallString<24> &Opt) const override {
+ Opt = "/DEFAULTLIB:" + qualifyWindowsLibrary(Lib);
+ }
+
+ void getDetectMismatchOption(llvm::StringRef Name, llvm::StringRef Value,
+ llvm::SmallString<32> &Opt) const override {
+ Opt = "/FAILIFMISMATCH:\"" + Name.str() + "=" + Value.str() + "\"";
+ }
+};
}
ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty) const {
@@ -5450,7 +5547,7 @@ public:
}
StringRef getARCRetainAutoreleasedReturnValueMarker() const override {
- return "mov\tr7, r7\t\t@ marker for objc_retainAutoreleaseReturnValue";
+ return "mov\tr7, r7\t\t// marker for objc_retainAutoreleaseReturnValue";
}
bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
@@ -5468,7 +5565,10 @@ public:
}
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &CGM) const override {
+ CodeGen::CodeGenModule &CGM,
+ ForDefinition_t IsForDefinition) const override {
+ if (!IsForDefinition)
+ return;
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
if (!FD)
return;
@@ -5510,7 +5610,8 @@ public:
: ARMTargetCodeGenInfo(CGT, K) {}
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &CGM) const override;
+ CodeGen::CodeGenModule &CGM,
+ ForDefinition_t IsForDefinition) const override;
void getDependentLibraryOption(llvm::StringRef Lib,
llvm::SmallString<24> &Opt) const override {
@@ -5524,8 +5625,11 @@ public:
};
void WindowsARMTargetCodeGenInfo::setTargetAttributes(
- const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const {
- ARMTargetCodeGenInfo::setTargetAttributes(D, GV, CGM);
+ const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM,
+ ForDefinition_t IsForDefinition) const {
+ ARMTargetCodeGenInfo::setTargetAttributes(D, GV, CGM, IsForDefinition);
+ if (!IsForDefinition)
+ return;
addStackProbeSizeTargetAttribute(D, GV, CGM);
}
}
@@ -6051,7 +6155,9 @@ public:
: TargetCodeGenInfo(new NVPTXABIInfo(CGT)) {}
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &M) const override;
+ CodeGen::CodeGenModule &M,
+ ForDefinition_t IsForDefinition) const override;
+
private:
// Adds a NamedMDNode with F, Name, and Operand as operands, and adds the
// resulting MDNode to the nvvm.annotations MDNode.
@@ -6105,9 +6211,11 @@ Address NVPTXABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
llvm_unreachable("NVPTX does not support varargs");
}
-void NVPTXTargetCodeGenInfo::
-setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &M) const{
+void NVPTXTargetCodeGenInfo::setTargetAttributes(
+ const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M,
+ ForDefinition_t IsForDefinition) const {
+ if (!IsForDefinition)
+ return;
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
if (!FD) return;
@@ -6211,7 +6319,7 @@ public:
return occupiesMoreThan(CGT, scalars, /*total*/ 4);
}
bool isSwiftErrorInRegister() const override {
- return true;
+ return false;
}
};
@@ -6543,14 +6651,17 @@ public:
MSP430TargetCodeGenInfo(CodeGenTypes &CGT)
: TargetCodeGenInfo(new DefaultABIInfo(CGT)) {}
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &M) const override;
+ CodeGen::CodeGenModule &M,
+ ForDefinition_t IsForDefinition) const override;
};
}
-void MSP430TargetCodeGenInfo::setTargetAttributes(const Decl *D,
- llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &M) const {
+void MSP430TargetCodeGenInfo::setTargetAttributes(
+ const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M,
+ ForDefinition_t IsForDefinition) const {
+ if (!IsForDefinition)
+ return;
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
if (const MSP430InterruptAttr *attr = FD->getAttr<MSP430InterruptAttr>()) {
// Handle 'interrupt' attribute:
@@ -6609,10 +6720,21 @@ public:
}
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &CGM) const override {
+ CodeGen::CodeGenModule &CGM,
+ ForDefinition_t IsForDefinition) const override {
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
if (!FD) return;
llvm::Function *Fn = cast<llvm::Function>(GV);
+
+ if (FD->hasAttr<MipsLongCallAttr>())
+ Fn->addFnAttr("long-call");
+ else if (FD->hasAttr<MipsShortCallAttr>())
+ Fn->addFnAttr("short-call");
+
+ // Other attributes do not have a meaning for declarations.
+ if (!IsForDefinition)
+ return;
+
if (FD->hasAttr<Mips16Attr>()) {
Fn->addFnAttr("mips16");
}
@@ -6974,7 +7096,10 @@ public:
: TargetCodeGenInfo(new DefaultABIInfo(CGT)) { }
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &CGM) const override {
+ CodeGen::CodeGenModule &CGM,
+ ForDefinition_t IsForDefinition) const override {
+ if (!IsForDefinition)
+ return;
const auto *FD = dyn_cast_or_null<FunctionDecl>(D);
if (!FD) return;
auto *Fn = cast<llvm::Function>(GV);
@@ -7002,11 +7127,15 @@ public:
: DefaultTargetCodeGenInfo(CGT) {}
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &M) const override;
+ CodeGen::CodeGenModule &M,
+ ForDefinition_t IsForDefinition) const override;
};
void TCETargetCodeGenInfo::setTargetAttributes(
- const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const {
+ const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M,
+ ForDefinition_t IsForDefinition) const {
+ if (!IsForDefinition)
+ return;
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
if (!FD) return;
@@ -7302,38 +7431,138 @@ public:
namespace {
class AMDGPUABIInfo final : public DefaultABIInfo {
+private:
+ static const unsigned MaxNumRegsForArgsRet = 16;
+
+ unsigned numRegsForType(QualType Ty) const;
+
+ bool isHomogeneousAggregateBaseType(QualType Ty) const override;
+ bool isHomogeneousAggregateSmallEnough(const Type *Base,
+ uint64_t Members) const override;
+
public:
- explicit AMDGPUABIInfo(CodeGen::CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}
+ explicit AMDGPUABIInfo(CodeGen::CodeGenTypes &CGT) :
+ DefaultABIInfo(CGT) {}
-private:
- ABIArgInfo classifyArgumentType(QualType Ty) const;
+ ABIArgInfo classifyReturnType(QualType RetTy) const;
+ ABIArgInfo classifyKernelArgumentType(QualType Ty) const;
+ ABIArgInfo classifyArgumentType(QualType Ty, unsigned &NumRegsLeft) const;
void computeInfo(CGFunctionInfo &FI) const override;
};
+bool AMDGPUABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const {
+ return true;
+}
+
+bool AMDGPUABIInfo::isHomogeneousAggregateSmallEnough(
+ const Type *Base, uint64_t Members) const {
+ uint32_t NumRegs = (getContext().getTypeSize(Base) + 31) / 32;
+
+ // Homogeneous Aggregates may occupy at most 16 registers.
+ return Members * NumRegs <= MaxNumRegsForArgsRet;
+}
+
+/// Estimate number of registers the type will use when passed in registers.
+unsigned AMDGPUABIInfo::numRegsForType(QualType Ty) const {
+ unsigned NumRegs = 0;
+
+ if (const VectorType *VT = Ty->getAs<VectorType>()) {
+ // Compute from the number of elements. The reported size is based on the
+ // in-memory size, which includes the padding 4th element for 3-vectors.
+ QualType EltTy = VT->getElementType();
+ unsigned EltSize = getContext().getTypeSize(EltTy);
+
+ // 16-bit element vectors should be passed as packed.
+ if (EltSize == 16)
+ return (VT->getNumElements() + 1) / 2;
+
+ unsigned EltNumRegs = (EltSize + 31) / 32;
+ return EltNumRegs * VT->getNumElements();
+ }
+
+ if (const RecordType *RT = Ty->getAs<RecordType>()) {
+ const RecordDecl *RD = RT->getDecl();
+ assert(!RD->hasFlexibleArrayMember());
+
+ for (const FieldDecl *Field : RD->fields()) {
+ QualType FieldTy = Field->getType();
+ NumRegs += numRegsForType(FieldTy);
+ }
+
+ return NumRegs;
+ }
+
+ return (getContext().getTypeSize(Ty) + 31) / 32;
+}
+
void AMDGPUABIInfo::computeInfo(CGFunctionInfo &FI) const {
+ llvm::CallingConv::ID CC = FI.getCallingConvention();
+
if (!getCXXABI().classifyReturnType(FI))
FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
- unsigned CC = FI.getCallingConvention();
- for (auto &Arg : FI.arguments())
- if (CC == llvm::CallingConv::AMDGPU_KERNEL)
- Arg.info = classifyArgumentType(Arg.type);
- else
- Arg.info = DefaultABIInfo::classifyArgumentType(Arg.type);
+ unsigned NumRegsLeft = MaxNumRegsForArgsRet;
+ for (auto &Arg : FI.arguments()) {
+ if (CC == llvm::CallingConv::AMDGPU_KERNEL) {
+ Arg.info = classifyKernelArgumentType(Arg.type);
+ } else {
+ Arg.info = classifyArgumentType(Arg.type, NumRegsLeft);
+ }
+ }
}
-/// \brief Classify argument of given type \p Ty.
-ABIArgInfo AMDGPUABIInfo::classifyArgumentType(QualType Ty) const {
- llvm::StructType *StrTy = dyn_cast<llvm::StructType>(CGT.ConvertType(Ty));
- if (!StrTy) {
- return DefaultABIInfo::classifyArgumentType(Ty);
+ABIArgInfo AMDGPUABIInfo::classifyReturnType(QualType RetTy) const {
+ if (isAggregateTypeForABI(RetTy)) {
+ // Records with non-trivial destructors/copy-constructors should not be
+ // returned by value.
+ if (!getRecordArgABI(RetTy, getCXXABI())) {
+ // Ignore empty structs/unions.
+ if (isEmptyRecord(getContext(), RetTy, true))
+ return ABIArgInfo::getIgnore();
+
+ // Lower single-element structs to just return a regular value.
+ if (const Type *SeltTy = isSingleElementStruct(RetTy, getContext()))
+ return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0)));
+
+ if (const RecordType *RT = RetTy->getAs<RecordType>()) {
+ const RecordDecl *RD = RT->getDecl();
+ if (RD->hasFlexibleArrayMember())
+ return DefaultABIInfo::classifyReturnType(RetTy);
+ }
+
+ // Pack aggregates <= 4 bytes into single VGPR or pair.
+ uint64_t Size = getContext().getTypeSize(RetTy);
+ if (Size <= 16)
+ return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext()));
+
+ if (Size <= 32)
+ return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext()));
+
+ if (Size <= 64) {
+ llvm::Type *I32Ty = llvm::Type::getInt32Ty(getVMContext());
+ return ABIArgInfo::getDirect(llvm::ArrayType::get(I32Ty, 2));
+ }
+
+ if (numRegsForType(RetTy) <= MaxNumRegsForArgsRet)
+ return ABIArgInfo::getDirect();
+ }
}
+ // Otherwise just do the default thing.
+ return DefaultABIInfo::classifyReturnType(RetTy);
+}
+
+/// For kernels all parameters are really passed in a special buffer. It doesn't
+/// make sense to pass anything byval, so everything must be direct.
+ABIArgInfo AMDGPUABIInfo::classifyKernelArgumentType(QualType Ty) const {
+ Ty = useFirstFieldIfTransparentUnion(Ty);
+
+ // TODO: Can we omit empty structs?
+
// Coerce single element structs to its element.
- if (StrTy->getNumElements() == 1) {
- return ABIArgInfo::getDirect();
- }
+ if (const Type *SeltTy = isSingleElementStruct(Ty, getContext()))
+ return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0)));
// If we set CanBeFlattened to true, CodeGen will expand the struct to its
// individual elements, which confuses the Clover OpenCL backend; therefore we
@@ -7341,30 +7570,102 @@ ABIArgInfo AMDGPUABIInfo::classifyArgumentType(QualType Ty) const {
return ABIArgInfo::getDirect(nullptr, 0, nullptr, false);
}
+ABIArgInfo AMDGPUABIInfo::classifyArgumentType(QualType Ty,
+ unsigned &NumRegsLeft) const {
+ assert(NumRegsLeft <= MaxNumRegsForArgsRet && "register estimate underflow");
+
+ Ty = useFirstFieldIfTransparentUnion(Ty);
+
+ if (isAggregateTypeForABI(Ty)) {
+ // Records with non-trivial destructors/copy-constructors should not be
+ // passed by value.
+ if (auto RAA = getRecordArgABI(Ty, getCXXABI()))
+ return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
+
+ // Ignore empty structs/unions.
+ if (isEmptyRecord(getContext(), Ty, true))
+ return ABIArgInfo::getIgnore();
+
+ // Lower single-element structs to just pass a regular value. TODO: We
+ // could do reasonable-size multiple-element structs too, using getExpand(),
+ // though watch out for things like bitfields.
+ if (const Type *SeltTy = isSingleElementStruct(Ty, getContext()))
+ return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0)));
+
+ if (const RecordType *RT = Ty->getAs<RecordType>()) {
+ const RecordDecl *RD = RT->getDecl();
+ if (RD->hasFlexibleArrayMember())
+ return DefaultABIInfo::classifyArgumentType(Ty);
+ }
+
+ // Pack aggregates <= 8 bytes into single VGPR or pair.
+ uint64_t Size = getContext().getTypeSize(Ty);
+ if (Size <= 64) {
+ unsigned NumRegs = (Size + 31) / 32;
+ NumRegsLeft -= std::min(NumRegsLeft, NumRegs);
+
+ if (Size <= 16)
+ return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext()));
+
+ if (Size <= 32)
+ return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext()));
+
+ // XXX: Should this be i64 instead, and should the limit increase?
+ llvm::Type *I32Ty = llvm::Type::getInt32Ty(getVMContext());
+ return ABIArgInfo::getDirect(llvm::ArrayType::get(I32Ty, 2));
+ }
+
+ if (NumRegsLeft > 0) {
+ unsigned NumRegs = numRegsForType(Ty);
+ if (NumRegsLeft >= NumRegs) {
+ NumRegsLeft -= NumRegs;
+ return ABIArgInfo::getDirect();
+ }
+ }
+ }
+
+ // Otherwise just do the default thing.
+ ABIArgInfo ArgInfo = DefaultABIInfo::classifyArgumentType(Ty);
+ if (!ArgInfo.isIndirect()) {
+ unsigned NumRegs = numRegsForType(Ty);
+ NumRegsLeft -= std::min(NumRegs, NumRegsLeft);
+ }
+
+ return ArgInfo;
+}
+
class AMDGPUTargetCodeGenInfo : public TargetCodeGenInfo {
public:
AMDGPUTargetCodeGenInfo(CodeGenTypes &CGT)
: TargetCodeGenInfo(new AMDGPUABIInfo(CGT)) {}
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &M) const override;
+ CodeGen::CodeGenModule &M,
+ ForDefinition_t IsForDefinition) const override;
unsigned getOpenCLKernelCallingConv() const override;
llvm::Constant *getNullPointer(const CodeGen::CodeGenModule &CGM,
llvm::PointerType *T, QualType QT) const override;
- unsigned getASTAllocaAddressSpace() const override {
- return LangAS::FirstTargetAddressSpace +
- getABIInfo().getDataLayout().getAllocaAddrSpace();
+ LangAS getASTAllocaAddressSpace() const override {
+ return getLangASFromTargetAS(
+ getABIInfo().getDataLayout().getAllocaAddrSpace());
}
- unsigned getGlobalVarAddressSpace(CodeGenModule &CGM,
- const VarDecl *D) const override;
+ LangAS getGlobalVarAddressSpace(CodeGenModule &CGM,
+ const VarDecl *D) const override;
+ llvm::SyncScope::ID getLLVMSyncScopeID(SyncScope S,
+ llvm::LLVMContext &C) const override;
+ llvm::Function *
+ createEnqueuedBlockKernel(CodeGenFunction &CGF,
+ llvm::Function *BlockInvokeFunc,
+ llvm::Value *BlockLiteral) const override;
};
}
void AMDGPUTargetCodeGenInfo::setTargetAttributes(
- const Decl *D,
- llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &M) const {
+ const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M,
+ ForDefinition_t IsForDefinition) const {
+ if (!IsForDefinition)
+ return;
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
if (!FD)
return;
@@ -7441,21 +7742,19 @@ llvm::Constant *AMDGPUTargetCodeGenInfo::getNullPointer(
llvm::ConstantPointerNull::get(NPT), PT);
}
-unsigned
+LangAS
AMDGPUTargetCodeGenInfo::getGlobalVarAddressSpace(CodeGenModule &CGM,
const VarDecl *D) const {
assert(!CGM.getLangOpts().OpenCL &&
!(CGM.getLangOpts().CUDA && CGM.getLangOpts().CUDAIsDevice) &&
"Address space agnostic languages only");
- unsigned DefaultGlobalAS =
- LangAS::FirstTargetAddressSpace +
- CGM.getContext().getTargetAddressSpace(LangAS::opencl_global);
+ LangAS DefaultGlobalAS = getLangASFromTargetAS(
+ CGM.getContext().getTargetAddressSpace(LangAS::opencl_global));
if (!D)
return DefaultGlobalAS;
- unsigned AddrSpace = D->getType().getAddressSpace();
- assert(AddrSpace == LangAS::Default ||
- AddrSpace >= LangAS::FirstTargetAddressSpace);
+ LangAS AddrSpace = D->getType().getAddressSpace();
+ assert(AddrSpace == LangAS::Default || isTargetAddressSpace(AddrSpace));
if (AddrSpace != LangAS::Default)
return AddrSpace;
@@ -7466,6 +7765,26 @@ AMDGPUTargetCodeGenInfo::getGlobalVarAddressSpace(CodeGenModule &CGM,
return DefaultGlobalAS;
}
+llvm::SyncScope::ID
+AMDGPUTargetCodeGenInfo::getLLVMSyncScopeID(SyncScope S,
+ llvm::LLVMContext &C) const {
+ StringRef Name;
+ switch (S) {
+ case SyncScope::OpenCLWorkGroup:
+ Name = "workgroup";
+ break;
+ case SyncScope::OpenCLDevice:
+ Name = "agent";
+ break;
+ case SyncScope::OpenCLAllSVMDevices:
+ Name = "";
+ break;
+ case SyncScope::OpenCLSubGroup:
+ Name = "subgroup";
+ }
+ return C.getOrInsertSyncScopeID(Name);
+}
+
//===----------------------------------------------------------------------===//
// SPARC v8 ABI Implementation.
// Based on the SPARC Compliance Definition version 2.4.1.
@@ -8506,7 +8825,8 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
if (getTarget().getABI() == "darwinpcs")
Kind = AArch64ABIInfo::DarwinPCS;
else if (Triple.isOSWindows())
- Kind = AArch64ABIInfo::Win64;
+ return SetCGInfo(
+ new WindowsAArch64TargetCodeGenInfo(Types, AArch64ABIInfo::Win64));
return SetCGInfo(new AArch64TargetCodeGenInfo(Types, Kind));
}
@@ -8636,3 +8956,108 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
return SetCGInfo(new SPIRTargetCodeGenInfo(Types));
}
}
+
+/// Create an OpenCL kernel for an enqueued block.
+///
+/// The kernel has the same function type as the block invoke function. Its
+/// name is the name of the block invoke function postfixed with "_kernel".
+/// It simply calls the block invoke function then returns.
+llvm::Function *
+TargetCodeGenInfo::createEnqueuedBlockKernel(CodeGenFunction &CGF,
+ llvm::Function *Invoke,
+ llvm::Value *BlockLiteral) const {
+ auto *InvokeFT = Invoke->getFunctionType();
+ llvm::SmallVector<llvm::Type *, 2> ArgTys;
+ for (auto &P : InvokeFT->params())
+ ArgTys.push_back(P);
+ auto &C = CGF.getLLVMContext();
+ std::string Name = Invoke->getName().str() + "_kernel";
+ auto *FT = llvm::FunctionType::get(llvm::Type::getVoidTy(C), ArgTys, false);
+ auto *F = llvm::Function::Create(FT, llvm::GlobalValue::InternalLinkage, Name,
+ &CGF.CGM.getModule());
+ auto IP = CGF.Builder.saveIP();
+ auto *BB = llvm::BasicBlock::Create(C, "entry", F);
+ auto &Builder = CGF.Builder;
+ Builder.SetInsertPoint(BB);
+ llvm::SmallVector<llvm::Value *, 2> Args;
+ for (auto &A : F->args())
+ Args.push_back(&A);
+ Builder.CreateCall(Invoke, Args);
+ Builder.CreateRetVoid();
+ Builder.restoreIP(IP);
+ return F;
+}
+
+/// Create an OpenCL kernel for an enqueued block.
+///
+/// The type of the first argument (the block literal) is the struct type
+/// of the block literal instead of a pointer type. The first argument
+/// (block literal) is passed directly by value to the kernel. The kernel
+/// allocates the same type of struct on stack and stores the block literal
+/// to it and passes its pointer to the block invoke function. The kernel
+/// has "enqueued-block" function attribute and kernel argument metadata.
+llvm::Function *AMDGPUTargetCodeGenInfo::createEnqueuedBlockKernel(
+ CodeGenFunction &CGF, llvm::Function *Invoke,
+ llvm::Value *BlockLiteral) const {
+ auto &Builder = CGF.Builder;
+ auto &C = CGF.getLLVMContext();
+
+ auto *BlockTy = BlockLiteral->getType()->getPointerElementType();
+ auto *InvokeFT = Invoke->getFunctionType();
+ llvm::SmallVector<llvm::Type *, 2> ArgTys;
+ llvm::SmallVector<llvm::Metadata *, 8> AddressQuals;
+ llvm::SmallVector<llvm::Metadata *, 8> AccessQuals;
+ llvm::SmallVector<llvm::Metadata *, 8> ArgTypeNames;
+ llvm::SmallVector<llvm::Metadata *, 8> ArgBaseTypeNames;
+ llvm::SmallVector<llvm::Metadata *, 8> ArgTypeQuals;
+ llvm::SmallVector<llvm::Metadata *, 8> ArgNames;
+
+ ArgTys.push_back(BlockTy);
+ ArgTypeNames.push_back(llvm::MDString::get(C, "__block_literal"));
+ AddressQuals.push_back(llvm::ConstantAsMetadata::get(Builder.getInt32(0)));
+ ArgBaseTypeNames.push_back(llvm::MDString::get(C, "__block_literal"));
+ ArgTypeQuals.push_back(llvm::MDString::get(C, ""));
+ AccessQuals.push_back(llvm::MDString::get(C, "none"));
+ ArgNames.push_back(llvm::MDString::get(C, "block_literal"));
+ for (unsigned I = 1, E = InvokeFT->getNumParams(); I < E; ++I) {
+ ArgTys.push_back(InvokeFT->getParamType(I));
+ ArgTypeNames.push_back(llvm::MDString::get(C, "void*"));
+ AddressQuals.push_back(llvm::ConstantAsMetadata::get(Builder.getInt32(3)));
+ AccessQuals.push_back(llvm::MDString::get(C, "none"));
+ ArgBaseTypeNames.push_back(llvm::MDString::get(C, "void*"));
+ ArgTypeQuals.push_back(llvm::MDString::get(C, ""));
+ ArgNames.push_back(
+ llvm::MDString::get(C, (Twine("local_arg") + Twine(I)).str()));
+ }
+ std::string Name = Invoke->getName().str() + "_kernel";
+ auto *FT = llvm::FunctionType::get(llvm::Type::getVoidTy(C), ArgTys, false);
+ auto *F = llvm::Function::Create(FT, llvm::GlobalValue::InternalLinkage, Name,
+ &CGF.CGM.getModule());
+ F->addFnAttr("enqueued-block");
+ auto IP = CGF.Builder.saveIP();
+ auto *BB = llvm::BasicBlock::Create(C, "entry", F);
+ Builder.SetInsertPoint(BB);
+ unsigned BlockAlign = CGF.CGM.getDataLayout().getPrefTypeAlignment(BlockTy);
+ auto *BlockPtr = Builder.CreateAlloca(BlockTy, nullptr);
+ BlockPtr->setAlignment(BlockAlign);
+ Builder.CreateAlignedStore(F->arg_begin(), BlockPtr, BlockAlign);
+ auto *Cast = Builder.CreatePointerCast(BlockPtr, InvokeFT->getParamType(0));
+ llvm::SmallVector<llvm::Value *, 2> Args;
+ Args.push_back(Cast);
+ for (auto I = F->arg_begin() + 1, E = F->arg_end(); I != E; ++I)
+ Args.push_back(I);
+ Builder.CreateCall(Invoke, Args);
+ Builder.CreateRetVoid();
+ Builder.restoreIP(IP);
+
+ F->setMetadata("kernel_arg_addr_space", llvm::MDNode::get(C, AddressQuals));
+ F->setMetadata("kernel_arg_access_qual", llvm::MDNode::get(C, AccessQuals));
+ F->setMetadata("kernel_arg_type", llvm::MDNode::get(C, ArgTypeNames));
+ F->setMetadata("kernel_arg_base_type",
+ llvm::MDNode::get(C, ArgBaseTypeNames));
+ F->setMetadata("kernel_arg_type_qual", llvm::MDNode::get(C, ArgTypeQuals));
+ if (CGF.CGM.getCodeGenOpts().EmitOpenCLArgMetadata)
+ F->setMetadata("kernel_arg_name", llvm::MDNode::get(C, ArgNames));
+
+ return F;
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.h b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.h
index 952ef96c4aef7..d745e420c4a56 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.h
@@ -15,9 +15,11 @@
#ifndef LLVM_CLANG_LIB_CODEGEN_TARGETINFO_H
#define LLVM_CLANG_LIB_CODEGEN_TARGETINFO_H
+#include "CodeGenModule.h"
#include "CGValue.h"
#include "clang/AST/Type.h"
#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SyncScope.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
@@ -34,8 +36,8 @@ class Decl;
namespace CodeGen {
class ABIInfo;
class CallArgList;
-class CodeGenModule;
class CodeGenFunction;
+class CGBlockInfo;
class CGFunctionInfo;
/// TargetCodeGenInfo - This class organizes various target-specific
@@ -55,7 +57,8 @@ public:
/// setTargetAttributes - Provides a convenient hook to handle extra
/// target-specific attributes for the given global.
virtual void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &M) const {}
+ CodeGen::CodeGenModule &M,
+ ForDefinition_t IsForDefinition) const {}
/// emitTargetMD - Provides a convenient hook to handle extra
/// target-specific metadata for the given global.
@@ -233,11 +236,11 @@ public:
/// other than OpenCL and CUDA.
/// If \p D is nullptr, returns the default target favored address space
/// for global variable.
- virtual unsigned getGlobalVarAddressSpace(CodeGenModule &CGM,
- const VarDecl *D) const;
+ virtual LangAS getGlobalVarAddressSpace(CodeGenModule &CGM,
+ const VarDecl *D) const;
/// Get the AST address space for alloca.
- virtual unsigned getASTAllocaAddressSpace() const { return LangAS::Default; }
+ virtual LangAS getASTAllocaAddressSpace() const { return LangAS::Default; }
/// Perform address space cast of an expression of pointer type.
/// \param V is the LLVM value to be casted to another address space.
@@ -246,9 +249,8 @@ public:
/// \param DestTy is the destination LLVM pointer type.
/// \param IsNonNull is the flag indicating \p V is known to be non null.
virtual llvm::Value *performAddrSpaceCast(CodeGen::CodeGenFunction &CGF,
- llvm::Value *V, unsigned SrcAddr,
- unsigned DestAddr,
- llvm::Type *DestTy,
+ llvm::Value *V, LangAS SrcAddr,
+ LangAS DestAddr, llvm::Type *DestTy,
bool IsNonNull = false) const;
/// Perform address space cast of a constant expression of pointer type.
@@ -256,9 +258,45 @@ public:
/// \param SrcAddr is the language address space of \p V.
/// \param DestAddr is the targeted language address space.
/// \param DestTy is the destination LLVM pointer type.
- virtual llvm::Constant *
- performAddrSpaceCast(CodeGenModule &CGM, llvm::Constant *V, unsigned SrcAddr,
- unsigned DestAddr, llvm::Type *DestTy) const;
+ virtual llvm::Constant *performAddrSpaceCast(CodeGenModule &CGM,
+ llvm::Constant *V,
+ LangAS SrcAddr, LangAS DestAddr,
+ llvm::Type *DestTy) const;
+
+ /// Get the syncscope used in LLVM IR.
+ virtual llvm::SyncScope::ID getLLVMSyncScopeID(SyncScope S,
+ llvm::LLVMContext &C) const;
+
+ /// Inteface class for filling custom fields of a block literal for OpenCL.
+ class TargetOpenCLBlockHelper {
+ public:
+ typedef std::pair<llvm::Value *, StringRef> ValueTy;
+ TargetOpenCLBlockHelper() {}
+ virtual ~TargetOpenCLBlockHelper() {}
+ /// Get the custom field types for OpenCL blocks.
+ virtual llvm::SmallVector<llvm::Type *, 1> getCustomFieldTypes() = 0;
+ /// Get the custom field values for OpenCL blocks.
+ virtual llvm::SmallVector<ValueTy, 1>
+ getCustomFieldValues(CodeGenFunction &CGF, const CGBlockInfo &Info) = 0;
+ virtual bool areAllCustomFieldValuesConstant(const CGBlockInfo &Info) = 0;
+ /// Get the custom field values for OpenCL blocks if all values are LLVM
+ /// constants.
+ virtual llvm::SmallVector<llvm::Constant *, 1>
+ getCustomFieldValues(CodeGenModule &CGM, const CGBlockInfo &Info) = 0;
+ };
+ virtual TargetOpenCLBlockHelper *getTargetOpenCLBlockHelper() const {
+ return nullptr;
+ }
+
+ /// Create an OpenCL kernel for an enqueued block. The kernel function is
+ /// a wrapper for the block invoke function with target-specific calling
+ /// convention and ABI as an OpenCL kernel. The wrapper function accepts
+ /// block context and block arguments in target-specific way and calls
+ /// the original block invoke function.
+ virtual llvm::Function *
+ createEnqueuedBlockKernel(CodeGenFunction &CGF,
+ llvm::Function *BlockInvokeFunc,
+ llvm::Value *BlockLiteral) const;
};
} // namespace CodeGen
diff --git a/contrib/llvm/tools/clang/lib/CrossTU/CrossTranslationUnit.cpp b/contrib/llvm/tools/clang/lib/CrossTU/CrossTranslationUnit.cpp
new file mode 100644
index 0000000000000..e20ea7702237c
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CrossTU/CrossTranslationUnit.cpp
@@ -0,0 +1,269 @@
+//===--- CrossTranslationUnit.cpp - -----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the CrossTranslationUnit interface.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/CrossTU/CrossTranslationUnit.h"
+#include "clang/AST/ASTImporter.h"
+#include "clang/AST/Decl.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/CrossTU/CrossTUDiagnostic.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Index/USRGeneration.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+#include <fstream>
+#include <sstream>
+
+namespace clang {
+namespace cross_tu {
+
+namespace {
+// FIXME: This class is will be removed after the transition to llvm::Error.
+class IndexErrorCategory : public std::error_category {
+public:
+ const char *name() const noexcept override { return "clang.index"; }
+
+ std::string message(int Condition) const override {
+ switch (static_cast<index_error_code>(Condition)) {
+ case index_error_code::unspecified:
+ return "An unknown error has occurred.";
+ case index_error_code::missing_index_file:
+ return "The index file is missing.";
+ case index_error_code::invalid_index_format:
+ return "Invalid index file format.";
+ case index_error_code::multiple_definitions:
+ return "Multiple definitions in the index file.";
+ case index_error_code::missing_definition:
+ return "Missing definition from the index file.";
+ case index_error_code::failed_import:
+ return "Failed to import the definition.";
+ case index_error_code::failed_to_get_external_ast:
+ return "Failed to load external AST source.";
+ case index_error_code::failed_to_generate_usr:
+ return "Failed to generate USR.";
+ }
+ llvm_unreachable("Unrecognized index_error_code.");
+ }
+};
+
+static llvm::ManagedStatic<IndexErrorCategory> Category;
+} // end anonymous namespace
+
+char IndexError::ID;
+
+void IndexError::log(raw_ostream &OS) const {
+ OS << Category->message(static_cast<int>(Code)) << '\n';
+}
+
+std::error_code IndexError::convertToErrorCode() const {
+ return std::error_code(static_cast<int>(Code), *Category);
+}
+
+llvm::Expected<llvm::StringMap<std::string>>
+parseCrossTUIndex(StringRef IndexPath, StringRef CrossTUDir) {
+ std::ifstream ExternalFnMapFile(IndexPath);
+ if (!ExternalFnMapFile)
+ return llvm::make_error<IndexError>(index_error_code::missing_index_file,
+ IndexPath.str());
+
+ llvm::StringMap<std::string> Result;
+ std::string Line;
+ unsigned LineNo = 1;
+ while (std::getline(ExternalFnMapFile, Line)) {
+ const size_t Pos = Line.find(" ");
+ if (Pos > 0 && Pos != std::string::npos) {
+ StringRef LineRef{Line};
+ StringRef FunctionLookupName = LineRef.substr(0, Pos);
+ if (Result.count(FunctionLookupName))
+ return llvm::make_error<IndexError>(
+ index_error_code::multiple_definitions, IndexPath.str(), LineNo);
+ StringRef FileName = LineRef.substr(Pos + 1);
+ SmallString<256> FilePath = CrossTUDir;
+ llvm::sys::path::append(FilePath, FileName);
+ Result[FunctionLookupName] = FilePath.str().str();
+ } else
+ return llvm::make_error<IndexError>(
+ index_error_code::invalid_index_format, IndexPath.str(), LineNo);
+ LineNo++;
+ }
+ return Result;
+}
+
+std::string
+createCrossTUIndexString(const llvm::StringMap<std::string> &Index) {
+ std::ostringstream Result;
+ for (const auto &E : Index)
+ Result << E.getKey().str() << " " << E.getValue() << '\n';
+ return Result.str();
+}
+
+CrossTranslationUnitContext::CrossTranslationUnitContext(CompilerInstance &CI)
+ : CI(CI), Context(CI.getASTContext()) {}
+
+CrossTranslationUnitContext::~CrossTranslationUnitContext() {}
+
+std::string CrossTranslationUnitContext::getLookupName(const NamedDecl *ND) {
+ SmallString<128> DeclUSR;
+ bool Ret = index::generateUSRForDecl(ND, DeclUSR); (void)Ret;
+ assert(!Ret && "Unable to generate USR");
+ return DeclUSR.str();
+}
+
+/// Recursively visits the function decls of a DeclContext, and looks up a
+/// function based on USRs.
+const FunctionDecl *
+CrossTranslationUnitContext::findFunctionInDeclContext(const DeclContext *DC,
+ StringRef LookupFnName) {
+ assert(DC && "Declaration Context must not be null");
+ for (const Decl *D : DC->decls()) {
+ const auto *SubDC = dyn_cast<DeclContext>(D);
+ if (SubDC)
+ if (const auto *FD = findFunctionInDeclContext(SubDC, LookupFnName))
+ return FD;
+
+ const auto *ND = dyn_cast<FunctionDecl>(D);
+ const FunctionDecl *ResultDecl;
+ if (!ND || !ND->hasBody(ResultDecl))
+ continue;
+ if (getLookupName(ResultDecl) != LookupFnName)
+ continue;
+ return ResultDecl;
+ }
+ return nullptr;
+}
+
+llvm::Expected<const FunctionDecl *>
+CrossTranslationUnitContext::getCrossTUDefinition(const FunctionDecl *FD,
+ StringRef CrossTUDir,
+ StringRef IndexName) {
+ assert(!FD->hasBody() && "FD has a definition in current translation unit!");
+ const std::string LookupFnName = getLookupName(FD);
+ if (LookupFnName.empty())
+ return llvm::make_error<IndexError>(
+ index_error_code::failed_to_generate_usr);
+ llvm::Expected<ASTUnit *> ASTUnitOrError =
+ loadExternalAST(LookupFnName, CrossTUDir, IndexName);
+ if (!ASTUnitOrError)
+ return ASTUnitOrError.takeError();
+ ASTUnit *Unit = *ASTUnitOrError;
+ if (!Unit)
+ return llvm::make_error<IndexError>(
+ index_error_code::failed_to_get_external_ast);
+ assert(&Unit->getFileManager() ==
+ &Unit->getASTContext().getSourceManager().getFileManager());
+
+ TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl();
+ if (const FunctionDecl *ResultDecl =
+ findFunctionInDeclContext(TU, LookupFnName))
+ return importDefinition(ResultDecl);
+ return llvm::make_error<IndexError>(index_error_code::failed_import);
+}
+
+void CrossTranslationUnitContext::emitCrossTUDiagnostics(const IndexError &IE) {
+ switch (IE.getCode()) {
+ case index_error_code::missing_index_file:
+ Context.getDiagnostics().Report(diag::err_fe_error_opening)
+ << IE.getFileName() << "required by the CrossTU functionality";
+ break;
+ case index_error_code::invalid_index_format:
+ Context.getDiagnostics().Report(diag::err_fnmap_parsing)
+ << IE.getFileName() << IE.getLineNum();
+ break;
+ case index_error_code::multiple_definitions:
+ Context.getDiagnostics().Report(diag::err_multiple_def_index)
+ << IE.getLineNum();
+ break;
+ default:
+ break;
+ }
+}
+
+llvm::Expected<ASTUnit *> CrossTranslationUnitContext::loadExternalAST(
+ StringRef LookupName, StringRef CrossTUDir, StringRef IndexName) {
+ // FIXME: The current implementation only supports loading functions with
+ // a lookup name from a single translation unit. If multiple
+ // translation units contains functions with the same lookup name an
+ // error will be returned.
+ ASTUnit *Unit = nullptr;
+ auto FnUnitCacheEntry = FunctionASTUnitMap.find(LookupName);
+ if (FnUnitCacheEntry == FunctionASTUnitMap.end()) {
+ if (FunctionFileMap.empty()) {
+ SmallString<256> IndexFile = CrossTUDir;
+ if (llvm::sys::path::is_absolute(IndexName))
+ IndexFile = IndexName;
+ else
+ llvm::sys::path::append(IndexFile, IndexName);
+ llvm::Expected<llvm::StringMap<std::string>> IndexOrErr =
+ parseCrossTUIndex(IndexFile, CrossTUDir);
+ if (IndexOrErr)
+ FunctionFileMap = *IndexOrErr;
+ else
+ return IndexOrErr.takeError();
+ }
+
+ auto It = FunctionFileMap.find(LookupName);
+ if (It == FunctionFileMap.end())
+ return llvm::make_error<IndexError>(index_error_code::missing_definition);
+ StringRef ASTFileName = It->second;
+ auto ASTCacheEntry = FileASTUnitMap.find(ASTFileName);
+ if (ASTCacheEntry == FileASTUnitMap.end()) {
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
+ TextDiagnosticPrinter *DiagClient =
+ new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts);
+ IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
+ new DiagnosticsEngine(DiagID, &*DiagOpts, DiagClient));
+
+ std::unique_ptr<ASTUnit> LoadedUnit(ASTUnit::LoadFromASTFile(
+ ASTFileName, CI.getPCHContainerOperations()->getRawReader(),
+ ASTUnit::LoadEverything, Diags, CI.getFileSystemOpts()));
+ Unit = LoadedUnit.get();
+ FileASTUnitMap[ASTFileName] = std::move(LoadedUnit);
+ } else {
+ Unit = ASTCacheEntry->second.get();
+ }
+ FunctionASTUnitMap[LookupName] = Unit;
+ } else {
+ Unit = FnUnitCacheEntry->second;
+ }
+ return Unit;
+}
+
+llvm::Expected<const FunctionDecl *>
+CrossTranslationUnitContext::importDefinition(const FunctionDecl *FD) {
+ ASTImporter &Importer = getOrCreateASTImporter(FD->getASTContext());
+ auto *ToDecl =
+ cast<FunctionDecl>(Importer.Import(const_cast<FunctionDecl *>(FD)));
+ assert(ToDecl->hasBody());
+ assert(FD->hasBody() && "Functions already imported should have body.");
+ return ToDecl;
+}
+
+ASTImporter &
+CrossTranslationUnitContext::getOrCreateASTImporter(ASTContext &From) {
+ auto I = ASTUnitImporterMap.find(From.getTranslationUnitDecl());
+ if (I != ASTUnitImporterMap.end())
+ return *I->second;
+ ASTImporter *NewImporter =
+ new ASTImporter(Context, Context.getSourceManager().getFileManager(),
+ From, From.getSourceManager().getFileManager(), false);
+ ASTUnitImporterMap[From.getTranslationUnitDecl()].reset(NewImporter);
+ return *NewImporter;
+}
+
+} // namespace cross_tu
+} // namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp b/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp
index cf86644fb8cdf..645da50595877 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp
@@ -26,9 +26,9 @@ Compilation::Compilation(const Driver &D, const ToolChain &_DefaultToolChain,
InputArgList *_Args, DerivedArgList *_TranslatedArgs,
bool ContainsError)
: TheDriver(D), DefaultToolChain(_DefaultToolChain), ActiveOffloadMask(0u),
- Args(_Args), TranslatedArgs(_TranslatedArgs), Redirects(nullptr),
- ForDiagnostics(false), ContainsError(ContainsError) {
- // The offloading host toolchain is the default tool chain.
+ Args(_Args), TranslatedArgs(_TranslatedArgs), ForDiagnostics(false),
+ ContainsError(ContainsError) {
+ // The offloading host toolchain is the default toolchain.
OrderedOffloadingToolchains.insert(
std::make_pair(Action::OFK_Host, &DefaultToolChain));
}
@@ -41,14 +41,6 @@ Compilation::~Compilation() {
for (auto Arg : TCArgs)
if (Arg.second != TranslatedArgs)
delete Arg.second;
-
- // Free redirections of stdout/stderr.
- if (Redirects) {
- delete Redirects[0];
- delete Redirects[1];
- delete Redirects[2];
- delete [] Redirects;
- }
}
const DerivedArgList &
@@ -59,9 +51,32 @@ Compilation::getArgsForToolChain(const ToolChain *TC, StringRef BoundArch,
DerivedArgList *&Entry = TCArgs[{TC, BoundArch, DeviceOffloadKind}];
if (!Entry) {
- Entry = TC->TranslateArgs(*TranslatedArgs, BoundArch, DeviceOffloadKind);
- if (!Entry)
- Entry = TranslatedArgs;
+ SmallVector<Arg *, 4> AllocatedArgs;
+ DerivedArgList *OpenMPArgs = nullptr;
+ // Translate OpenMP toolchain arguments provided via the -Xopenmp-target flags.
+ if (DeviceOffloadKind == Action::OFK_OpenMP) {
+ const ToolChain *HostTC = getSingleOffloadToolChain<Action::OFK_Host>();
+ bool SameTripleAsHost = (TC->getTriple() == HostTC->getTriple());
+ OpenMPArgs = TC->TranslateOpenMPTargetArgs(
+ *TranslatedArgs, SameTripleAsHost, AllocatedArgs);
+ }
+
+ if (!OpenMPArgs) {
+ Entry = TC->TranslateArgs(*TranslatedArgs, BoundArch, DeviceOffloadKind);
+ if (!Entry)
+ Entry = TranslatedArgs;
+ } else {
+ Entry = TC->TranslateArgs(*OpenMPArgs, BoundArch, DeviceOffloadKind);
+ if (!Entry)
+ Entry = OpenMPArgs;
+ else
+ delete OpenMPArgs;
+ }
+
+ // Add allocated arguments to the final DAL.
+ for (auto ArgPtr : AllocatedArgs) {
+ Entry->AddSynthesizedArg(ArgPtr);
+ }
}
return *Entry;
@@ -167,16 +182,51 @@ int Compilation::ExecuteCommand(const Command &C,
return ExecutionFailed ? 1 : Res;
}
-void Compilation::ExecuteJobs(
- const JobList &Jobs,
- SmallVectorImpl<std::pair<int, const Command *>> &FailingCommands) const {
+using FailingCommandList = SmallVectorImpl<std::pair<int, const Command *>>;
+
+static bool ActionFailed(const Action *A,
+ const FailingCommandList &FailingCommands) {
+
+ if (FailingCommands.empty())
+ return false;
+
+ // CUDA can have the same input source code compiled multiple times so do not
+ // compiled again if there are already failures. It is OK to abort the CUDA
+ // pipeline on errors.
+ if (A->isOffloading(Action::OFK_Cuda))
+ return true;
+
+ for (const auto &CI : FailingCommands)
+ if (A == &(CI.second->getSource()))
+ return true;
+
+ for (const Action *AI : A->inputs())
+ if (ActionFailed(AI, FailingCommands))
+ return true;
+
+ return false;
+}
+
+static bool InputsOk(const Command &C,
+ const FailingCommandList &FailingCommands) {
+ return !ActionFailed(&C.getSource(), FailingCommands);
+}
+
+void Compilation::ExecuteJobs(const JobList &Jobs,
+ FailingCommandList &FailingCommands) const {
+ // According to UNIX standard, driver need to continue compiling all the
+ // inputs on the command line even one of them failed.
+ // In all but CLMode, execute all the jobs unless the necessary inputs for the
+ // job is missing due to previous failures.
for (const auto &Job : Jobs) {
+ if (!InputsOk(Job, FailingCommands))
+ continue;
const Command *FailingCommand = nullptr;
if (int Res = ExecuteCommand(Job, FailingCommand)) {
FailingCommands.push_back(std::make_pair(Res, FailingCommand));
- // Bail as soon as one command fails, so we don't output duplicate error
- // messages if we die on e.g. the same file.
- return;
+ // Bail as soon as one command fails in cl driver mode.
+ if (TheDriver.IsCLMode())
+ return;
}
}
}
@@ -205,16 +255,13 @@ void Compilation::initCompilationForDiagnostics() {
TranslatedArgs->ClaimAllArgs();
// Redirect stdout/stderr to /dev/null.
- Redirects = new const StringRef*[3]();
- Redirects[0] = nullptr;
- Redirects[1] = new StringRef();
- Redirects[2] = new StringRef();
+ Redirects = {None, {""}, {""}};
}
StringRef Compilation::getSysRoot() const {
return getDriver().SysRoot;
}
-void Compilation::Redirect(const StringRef** Redirects) {
+void Compilation::Redirect(ArrayRef<Optional<StringRef>> Redirects) {
this->Redirects = Redirects;
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/Distro.cpp b/contrib/llvm/tools/clang/lib/Driver/Distro.cpp
index 2df297f3cfc2d..f15c919b9aae1 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Distro.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Distro.cpp
@@ -48,6 +48,7 @@ static Distro::DistroType DetectDistro(vfs::FileSystem &VFS) {
.Case("yakkety", Distro::UbuntuYakkety)
.Case("zesty", Distro::UbuntuZesty)
.Case("artful", Distro::UbuntuArtful)
+ .Case("bionic", Distro::UbuntuBionic)
.Default(Distro::UnknownDistro);
if (Version != Distro::UnknownDistro)
return Version;
@@ -88,6 +89,8 @@ static Distro::DistroType DetectDistro(vfs::FileSystem &VFS) {
return Distro::DebianJessie;
case 9:
return Distro::DebianStretch;
+ case 10:
+ return Distro::DebianBuster;
default:
return Distro::UnknownDistro;
}
@@ -126,6 +129,9 @@ static Distro::DistroType DetectDistro(vfs::FileSystem &VFS) {
if (VFS.exists("/etc/exherbo-release"))
return Distro::Exherbo;
+ if (VFS.exists("/etc/alpine-release"))
+ return Distro::AlpineLinux;
+
if (VFS.exists("/etc/arch-release"))
return Distro::ArchLinux;
diff --git a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp
index ba4d0e836b44e..9ae33b80f8898 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp
@@ -12,7 +12,6 @@
#include "ToolChains/AMDGPU.h"
#include "ToolChains/AVR.h"
#include "ToolChains/Ananas.h"
-#include "ToolChains/Bitrig.h"
#include "ToolChains/Clang.h"
#include "ToolChains/CloudABI.h"
#include "ToolChains/Contiki.h"
@@ -69,6 +68,7 @@
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include <map>
#include <memory>
@@ -87,7 +87,7 @@ Driver::Driver(StringRef ClangExecutable, StringRef DefaultTargetTriple,
: Opts(createDriverOptTable()), Diags(Diags), VFS(std::move(VFS)),
Mode(GCCMode), SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone),
LTOMode(LTOK_None), ClangExecutable(ClangExecutable),
- SysRoot(DEFAULT_SYSROOT), UseStdLib(true),
+ SysRoot(DEFAULT_SYSROOT),
DriverTitle("clang LLVM compiler"), CCPrintOptionsFilename(nullptr),
CCPrintHeadersFilename(nullptr), CCLogDiagnosticsFilename(nullptr),
CCCPrintBindings(false), CCPrintHeaders(false), CCLogDiagnostics(false),
@@ -119,9 +119,8 @@ Driver::Driver(StringRef ClangExecutable, StringRef DefaultTargetTriple,
void Driver::ParseDriverMode(StringRef ProgramName,
ArrayRef<const char *> Args) {
- auto Default = ToolChain::getTargetAndModeFromProgramName(ProgramName);
- StringRef DefaultMode(Default.second);
- setDriverModeFromOption(DefaultMode);
+ ClangNameParts = ToolChain::getTargetAndModeFromProgramName(ProgramName);
+ setDriverModeFromOption(ClangNameParts.DriverMode);
for (const char *ArgPtr : Args) {
// Ingore nullptrs, they are response file's EOL markers
@@ -524,7 +523,7 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
auto &CudaTC = ToolChains[CudaTriple.str() + "/" + HostTriple.str()];
if (!CudaTC) {
CudaTC = llvm::make_unique<toolchains::CudaToolChain>(
- *this, CudaTriple, *HostTC, C.getInputArgs());
+ *this, CudaTriple, *HostTC, C.getInputArgs(), Action::OFK_Cuda);
}
C.addOffloadDeviceToolChain(CudaTC.get(), Action::OFK_Cuda);
}
@@ -579,10 +578,10 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
C.getSingleOffloadToolChain<Action::OFK_Host>();
assert(HostTC && "Host toolchain should be always defined.");
auto &CudaTC =
- ToolChains[TT.str() + "/" + HostTC->getTriple().str()];
+ ToolChains[TT.str() + "/" + HostTC->getTriple().normalize()];
if (!CudaTC)
CudaTC = llvm::make_unique<toolchains::CudaToolChain>(
- *this, TT, *HostTC, C.getInputArgs());
+ *this, TT, *HostTC, C.getInputArgs(), Action::OFK_OpenMP);
TC = CudaTC.get();
} else
TC = &getToolChain(C.getInputArgs(), TT);
@@ -599,8 +598,6 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
//
// TODO: Add support for other offloading programming models here.
//
-
- return;
}
Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
@@ -664,6 +661,7 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
T.setOS(llvm::Triple::Win32);
T.setVendor(llvm::Triple::PC);
T.setEnvironment(llvm::Triple::MSVC);
+ T.setObjectFormat(llvm::Triple::COFF);
DefaultTargetTriple = T.str();
}
if (const Arg *A = Args.getLastArg(options::OPT_target))
@@ -678,8 +676,6 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
SysRoot = A->getValue();
if (const Arg *A = Args.getLastArg(options::OPT__dyld_prefix_EQ))
DyldPrefix = A->getValue();
- if (Args.hasArg(options::OPT_nostdlib))
- UseStdLib = false;
if (const Arg *A = Args.getLastArg(options::OPT_resource_dir))
ResourceDir = A->getValue();
@@ -1126,7 +1122,8 @@ void Driver::PrintHelp(bool ShowHidden) const {
ExcludedFlagsBitmask |= HelpHidden;
getOpts().PrintHelp(llvm::outs(), Name.c_str(), DriverTitle.c_str(),
- IncludedFlagsBitmask, ExcludedFlagsBitmask);
+ IncludedFlagsBitmask, ExcludedFlagsBitmask,
+ /*ShowAllAliases=*/false);
}
void Driver::PrintVersion(const Compilation &C, raw_ostream &OS) const {
@@ -1158,6 +1155,58 @@ static void PrintDiagnosticCategories(raw_ostream &OS) {
OS << i << ',' << DiagnosticIDs::getCategoryNameFromID(i) << '\n';
}
+void Driver::handleAutocompletions(StringRef PassedFlags) const {
+ // Print out all options that start with a given argument. This is used for
+ // shell autocompletion.
+ std::vector<std::string> SuggestedCompletions;
+
+ unsigned short DisableFlags =
+ options::NoDriverOption | options::Unsupported | options::Ignored;
+ // We want to show cc1-only options only when clang is invoked as "clang
+ // -cc1". When clang is invoked as "clang -cc1", we add "#" to the beginning
+ // of an --autocomplete option so that the clang driver can distinguish
+ // whether it is requested to show cc1-only options or not.
+ if (PassedFlags.size() > 0 && PassedFlags[0] == '#') {
+ DisableFlags &= ~options::NoDriverOption;
+ PassedFlags = PassedFlags.substr(1);
+ }
+
+ if (PassedFlags.find(',') == StringRef::npos) {
+ // If the flag is in the form of "--autocomplete=-foo",
+ // we were requested to print out all option names that start with "-foo".
+ // For example, "--autocomplete=-fsyn" is expanded to "-fsyntax-only".
+ SuggestedCompletions = Opts->findByPrefix(PassedFlags, DisableFlags);
+
+ // We have to query the -W flags manually as they're not in the OptTable.
+ // TODO: Find a good way to add them to OptTable instead and them remove
+ // this code.
+ for (StringRef S : DiagnosticIDs::getDiagnosticFlags())
+ if (S.startswith(PassedFlags))
+ SuggestedCompletions.push_back(S);
+ } else {
+ // If the flag is in the form of "--autocomplete=foo,bar", we were
+ // requested to print out all option values for "-foo" that start with
+ // "bar". For example,
+ // "--autocomplete=-stdlib=,l" is expanded to "libc++" and "libstdc++".
+ StringRef Option, Arg;
+ std::tie(Option, Arg) = PassedFlags.split(',');
+ SuggestedCompletions = Opts->suggestValueCompletions(Option, Arg);
+ }
+
+ // Sort the autocomplete candidates so that shells print them out in a
+ // deterministic order. We could sort in any way, but we chose
+ // case-insensitive sorting for consistency with the -help option
+ // which prints out options in the case-insensitive alphabetical order.
+ std::sort(SuggestedCompletions.begin(), SuggestedCompletions.end(),
+ [](StringRef A, StringRef B) {
+ if (int X = A.compare_lower(B))
+ return X < 0;
+ return A.compare(B) > 0;
+ });
+
+ llvm::outs() << llvm::join(SuggestedCompletions, "\n") << '\n';
+}
+
bool Driver::HandleImmediateArgs(const Compilation &C) {
// The order these options are handled in gcc is all over the place, but we
// don't expect inconsistencies w.r.t. that to matter in practice.
@@ -1251,55 +1300,15 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
}
if (Arg *A = C.getArgs().getLastArg(options::OPT_autocomplete)) {
- // Print out all options that start with a given argument. This is used for
- // shell autocompletion.
StringRef PassedFlags = A->getValue();
- std::vector<std::string> SuggestedCompletions;
-
- unsigned short DisableFlags = options::NoDriverOption | options::Unsupported | options::Ignored;
- // We want to show cc1-only options only when clang is invoked as "clang -cc1".
- // When clang is invoked as "clang -cc1", we add "#" to the beginning of an --autocomplete
- // option so that the clang driver can distinguish whether it is requested to show cc1-only options or not.
- if (PassedFlags[0] == '#') {
- DisableFlags &= ~options::NoDriverOption;
- PassedFlags = PassedFlags.substr(1);
- }
-
- if (PassedFlags.find(',') == StringRef::npos) {
- // If the flag is in the form of "--autocomplete=-foo",
- // we were requested to print out all option names that start with "-foo".
- // For example, "--autocomplete=-fsyn" is expanded to "-fsyntax-only".
- SuggestedCompletions = Opts->findByPrefix(PassedFlags, DisableFlags);
-
- // We have to query the -W flags manually as they're not in the OptTable.
- // TODO: Find a good way to add them to OptTable instead and them remove
- // this code.
- for (StringRef S : DiagnosticIDs::getDiagnosticFlags())
- if (S.startswith(PassedFlags))
- SuggestedCompletions.push_back(S);
- } else {
- // If the flag is in the form of "--autocomplete=foo,bar", we were
- // requested to print out all option values for "-foo" that start with
- // "bar". For example,
- // "--autocomplete=-stdlib=,l" is expanded to "libc++" and "libstdc++".
- StringRef Option, Arg;
- std::tie(Option, Arg) = PassedFlags.split(',');
- SuggestedCompletions = Opts->suggestValueCompletions(Option, Arg);
- }
-
- // Sort the autocomplete candidates so that shells print them out in a
- // deterministic order. We could sort in any way, but we chose
- // case-insensitive sorting for consistency with the -help option
- // which prints out options in the case-insensitive alphabetical order.
- std::sort(SuggestedCompletions.begin(), SuggestedCompletions.end(),
- [](StringRef A, StringRef B) { return A.compare_lower(B) < 0; });
-
- llvm::outs() << llvm::join(SuggestedCompletions, "\n") << '\n';
+ handleAutocompletions(PassedFlags);
return false;
}
if (C.getArgs().hasArg(options::OPT_print_libgcc_file_name)) {
ToolChain::RuntimeLibType RLT = TC.GetRuntimeLibType(C.getArgs());
+ const llvm::Triple Triple(TC.ComputeEffectiveClangTriple(C.getArgs()));
+ RegisterEffectiveTriple TripleRAII(TC, Triple);
switch (RLT) {
case ToolChain::RLT_CompilerRT:
llvm::outs() << TC.getCompilerRT(C.getArgs(), "builtins") << "\n";
@@ -3225,6 +3234,12 @@ InputInfo Driver::BuildJobsForActionNoCache(
InputInfoList OffloadDependencesInputInfo;
bool BuildingForOffloadDevice = TargetDeviceOffloadKind != Action::OFK_None;
if (const OffloadAction *OA = dyn_cast<OffloadAction>(A)) {
+ // The 'Darwin' toolchain is initialized only when its arguments are
+ // computed. Get the default arguments for OFK_None to ensure that
+ // initialization is performed before processing the offload action.
+ // FIXME: Remove when darwin's toolchain is initialized during construction.
+ C.getArgsForToolChain(TC, BoundArch, Action::OFK_None);
+
// The offload action is expected to be used in four different situations.
//
// a) Set a toolchain/architecture/kind for a host action:
@@ -3402,7 +3417,7 @@ InputInfo Driver::BuildJobsForActionNoCache(
// Get the unique string identifier for this dependence and cache the
// result.
CachedResults[{A, GetTriplePlusArchString(
- UI.DependentToolChain, UI.DependentBoundArch,
+ UI.DependentToolChain, BoundArch,
UI.DependentOffloadKind)}] = CurI;
}
@@ -3677,7 +3692,12 @@ std::string Driver::GetFilePath(StringRef Name, const ToolChain &TC) const {
return P.str();
}
- SmallString<128> P(ResourceDir);
+ SmallString<128> R(ResourceDir);
+ llvm::sys::path::append(R, Name);
+ if (llvm::sys::fs::exists(Twine(R)))
+ return R.str();
+
+ SmallString<128> P(TC.getCompilerRTPath());
llvm::sys::path::append(P, Name);
if (llvm::sys::fs::exists(Twine(P)))
return P.str();
@@ -3810,9 +3830,6 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
case llvm::Triple::OpenBSD:
TC = llvm::make_unique<toolchains::OpenBSD>(*this, Target, Args);
break;
- case llvm::Triple::Bitrig:
- TC = llvm::make_unique<toolchains::Bitrig>(*this, Target, Args);
- break;
case llvm::Triple::NetBSD:
TC = llvm::make_unique<toolchains::NetBSD>(*this, Target, Args);
break;
@@ -3865,7 +3882,13 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
break;
case llvm::Triple::MSVC:
case llvm::Triple::UnknownEnvironment:
- TC = llvm::make_unique<toolchains::MSVCToolChain>(*this, Target, Args);
+ if (Args.getLastArgValue(options::OPT_fuse_ld_EQ)
+ .startswith_lower("bfd"))
+ TC = llvm::make_unique<toolchains::CrossWindowsToolChain>(
+ *this, Target, Args);
+ else
+ TC =
+ llvm::make_unique<toolchains::MSVCToolChain>(*this, Target, Args);
break;
}
break;
diff --git a/contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp b/contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp
index ac63b96cf96d1..11e7e4c8fe2bd 100644
--- a/contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp
@@ -11,6 +11,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
+#include <cassert>
using namespace clang::driver;
using namespace clang::driver::options;
@@ -40,5 +41,13 @@ public:
}
std::unique_ptr<OptTable> clang::driver::createDriverOptTable() {
- return llvm::make_unique<DriverOptTable>();
+ auto Result = llvm::make_unique<DriverOptTable>();
+ // Options.inc is included in DriverOptions.cpp, and calls OptTable's
+ // addValues function.
+ // Opt is a variable used in the code fragment in Options.inc.
+ OptTable &Opt = *Result;
+#define OPTTABLE_ARG_INIT
+#include "clang/Driver/Options.inc"
+#undef OPTTABLE_ARG_INIT
+ return std::move(Result);
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/Job.cpp b/contrib/llvm/tools/clang/lib/Driver/Job.cpp
index 8b85680f10b14..765c05752d8f3 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Job.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Job.cpp
@@ -14,6 +14,7 @@
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
@@ -307,8 +308,8 @@ void Command::setEnvironment(llvm::ArrayRef<const char *> NewEnvironment) {
Environment.push_back(nullptr);
}
-int Command::Execute(const StringRef **Redirects, std::string *ErrMsg,
- bool *ExecutionFailed) const {
+int Command::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
+ std::string *ErrMsg, bool *ExecutionFailed) const {
SmallVector<const char*, 128> Argv;
const char **Envp;
@@ -378,8 +379,8 @@ static bool ShouldFallback(int ExitCode) {
return ExitCode != 0;
}
-int FallbackCommand::Execute(const StringRef **Redirects, std::string *ErrMsg,
- bool *ExecutionFailed) const {
+int FallbackCommand::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
+ std::string *ErrMsg, bool *ExecutionFailed) const {
int PrimaryStatus = Command::Execute(Redirects, ErrMsg, ExecutionFailed);
if (!ShouldFallback(PrimaryStatus))
return PrimaryStatus;
@@ -410,7 +411,7 @@ void ForceSuccessCommand::Print(raw_ostream &OS, const char *Terminator,
OS << " || (exit 0)" << Terminator;
}
-int ForceSuccessCommand::Execute(const StringRef **Redirects,
+int ForceSuccessCommand::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
std::string *ErrMsg,
bool *ExecutionFailed) const {
int Status = Command::Execute(Redirects, ErrMsg, ExecutionFailed);
diff --git a/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp b/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp
index 7a442c83e1588..f617d8b4551e3 100644
--- a/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp
@@ -29,10 +29,12 @@ enum : SanitizerMask {
NeedsUbsanRt = Undefined | Integer | Nullability | CFI,
NeedsUbsanCxxRt = Vptr | CFI,
NotAllowedWithTrap = Vptr,
- RequiresPIE = DataFlow,
- NeedsUnwindTables = Address | Thread | Memory | DataFlow,
- SupportsCoverage = Address | KernelAddress | Memory | Leak | Undefined |
- Integer | Nullability | DataFlow | Fuzzer,
+ NotAllowedWithMinimalRuntime = Vptr,
+ RequiresPIE = DataFlow | Scudo,
+ NeedsUnwindTables = Address | HWAddress | Thread | Memory | DataFlow,
+ SupportsCoverage = Address | HWAddress | KernelAddress | Memory | Leak |
+ Undefined | Integer | Nullability | DataFlow | Fuzzer |
+ FuzzerNoLink,
RecoverableByDefault = Undefined | Integer | Nullability,
Unrecoverable = Unreachable | Return,
LegacyFsanitizeRecoverMask = Undefined | Integer,
@@ -41,6 +43,7 @@ enum : SanitizerMask {
Nullability | LocalBounds | CFI,
TrappingDefault = CFI,
CFIClasses = CFIVCall | CFINVCall | CFIDerivedCast | CFIUnrelatedCast,
+ CompatibleWithMinimalRuntime = TrappingSupported,
};
enum CoverageFeature {
@@ -55,8 +58,10 @@ enum CoverageFeature {
Coverage8bitCounters = 1 << 8, // Deprecated.
CoverageTracePC = 1 << 9,
CoverageTracePCGuard = 1 << 10,
- CoverageInline8bitCounters = 1 << 12,
CoverageNoPrune = 1 << 11,
+ CoverageInline8bitCounters = 1 << 12,
+ CoveragePCTable = 1 << 13,
+ CoverageStackDepth = 1 << 14,
};
/// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any
@@ -92,6 +97,8 @@ static bool getDefaultBlacklist(const Driver &D, SanitizerMask Kinds,
const char *BlacklistFile = nullptr;
if (Kinds & Address)
BlacklistFile = "asan_blacklist.txt";
+ else if (Kinds & HWAddress)
+ BlacklistFile = "hwasan_blacklist.txt";
else if (Kinds & Memory)
BlacklistFile = "msan_blacklist.txt";
else if (Kinds & Thread)
@@ -100,6 +107,8 @@ static bool getDefaultBlacklist(const Driver &D, SanitizerMask Kinds,
BlacklistFile = "dfsan_abilist.txt";
else if (Kinds & CFI)
BlacklistFile = "cfi_blacklist.txt";
+ else if (Kinds & (Undefined | Integer | Nullability))
+ BlacklistFile = "ubsan_blacklist.txt";
if (BlacklistFile) {
clang::SmallString<64> Path(D.ResourceDir);
@@ -165,19 +174,23 @@ static SanitizerMask parseSanitizeTrapArgs(const Driver &D,
}
bool SanitizerArgs::needsUbsanRt() const {
- return ((Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) ||
- CoverageFeatures) &&
- !Sanitizers.has(Address) && !Sanitizers.has(Memory) &&
- !Sanitizers.has(Thread) && !Sanitizers.has(DataFlow) &&
- !Sanitizers.has(Leak) && !CfiCrossDso;
+ // All of these include ubsan.
+ if (needsAsanRt() || needsMsanRt() || needsHwasanRt() || needsTsanRt() ||
+ needsDfsanRt() || needsLsanRt() || needsCfiDiagRt() || needsScudoRt())
+ return false;
+
+ return (Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) ||
+ CoverageFeatures;
}
bool SanitizerArgs::needsCfiRt() const {
- return !(Sanitizers.Mask & CFI & ~TrapSanitizers.Mask) && CfiCrossDso;
+ return !(Sanitizers.Mask & CFI & ~TrapSanitizers.Mask) && CfiCrossDso &&
+ !ImplicitCfiRuntime;
}
bool SanitizerArgs::needsCfiDiagRt() const {
- return (Sanitizers.Mask & CFI & ~TrapSanitizers.Mask) && CfiCrossDso;
+ return (Sanitizers.Mask & CFI & ~TrapSanitizers.Mask) && CfiCrossDso &&
+ !ImplicitCfiRuntime;
}
bool SanitizerArgs::requiresPIE() const {
@@ -208,6 +221,10 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
SanitizerMask TrappingKinds = parseSanitizeTrapArgs(D, Args);
SanitizerMask InvalidTrappingKinds = TrappingKinds & NotAllowedWithTrap;
+ MinimalRuntime =
+ Args.hasFlag(options::OPT_fsanitize_minimal_runtime,
+ options::OPT_fno_sanitize_minimal_runtime, MinimalRuntime);
+
// The object size sanitizer should not be enabled at -O0.
Arg *OptLevel = Args.getLastArg(options::OPT_O_Group);
bool RemoveObjectSizeAtO0 =
@@ -245,6 +262,18 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
DiagnosedKinds |= KindsToDiagnose;
}
Add &= ~InvalidTrappingKinds;
+
+ if (MinimalRuntime) {
+ if (SanitizerMask KindsToDiagnose =
+ Add & NotAllowedWithMinimalRuntime & ~DiagnosedKinds) {
+ std::string Desc = describeSanitizeArg(*I, KindsToDiagnose);
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << Desc << "-fsanitize-minimal-runtime";
+ DiagnosedKinds |= KindsToDiagnose;
+ }
+ Add &= ~NotAllowedWithMinimalRuntime;
+ }
+
if (SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) {
std::string Desc = describeSanitizeArg(*I, KindsToDiagnose);
D.Diag(diag::err_drv_unsupported_opt_for_target)
@@ -281,11 +310,22 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
// Silently discard any unsupported sanitizers implicitly enabled through
// group expansion.
Add &= ~InvalidTrappingKinds;
+ if (MinimalRuntime) {
+ Add &= ~NotAllowedWithMinimalRuntime;
+ }
Add &= Supported;
- // Enable coverage if the fuzzing flag is set.
if (Add & Fuzzer)
- CoverageFeatures |= CoverageTracePCGuard | CoverageIndirCall | CoverageTraceCmp;
+ Add |= FuzzerNoLink;
+
+ // Enable coverage if the fuzzing flag is set.
+ if (Add & FuzzerNoLink) {
+ CoverageFeatures |= CoverageInline8bitCounters | CoverageIndirCall |
+ CoverageTraceCmp | CoveragePCTable;
+ // Due to TLS differences, stack depth tracking is only enabled on Linux
+ if (TC.getTriple().isOSLinux())
+ CoverageFeatures |= CoverageStackDepth;
+ }
Kinds |= Add;
} else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
@@ -333,17 +373,15 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
// Warn about incompatible groups of sanitizers.
std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
- std::make_pair(Address, Thread), std::make_pair(Address, Memory),
- std::make_pair(Thread, Memory), std::make_pair(Leak, Thread),
- std::make_pair(Leak, Memory), std::make_pair(KernelAddress, Address),
- std::make_pair(KernelAddress, Leak),
- std::make_pair(KernelAddress, Thread),
- std::make_pair(KernelAddress, Memory),
- std::make_pair(Efficiency, Address),
- std::make_pair(Efficiency, Leak),
- std::make_pair(Efficiency, Thread),
- std::make_pair(Efficiency, Memory),
- std::make_pair(Efficiency, KernelAddress)};
+ std::make_pair(Address, Thread | Memory),
+ std::make_pair(Thread, Memory),
+ std::make_pair(Leak, Thread | Memory),
+ std::make_pair(KernelAddress, Address | Leak | Thread | Memory),
+ std::make_pair(HWAddress, Address | Thread | Memory | KernelAddress),
+ std::make_pair(Efficiency, Address | HWAddress | Leak | Thread | Memory |
+ KernelAddress),
+ std::make_pair(Scudo, Address | HWAddress | Leak | Thread | Memory |
+ KernelAddress | Efficiency)};
for (auto G : IncompatibleGroups) {
SanitizerMask Group = G.first;
if (Kinds & Group) {
@@ -456,9 +494,13 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
}
}
MsanUseAfterDtor =
- Args.hasArg(options::OPT_fsanitize_memory_use_after_dtor);
+ Args.hasFlag(options::OPT_fsanitize_memory_use_after_dtor,
+ options::OPT_fno_sanitize_memory_use_after_dtor,
+ MsanUseAfterDtor);
NeedPIE |= !(TC.getTriple().isOSLinux() &&
TC.getTriple().getArch() == llvm::Triple::x86_64);
+ } else {
+ MsanUseAfterDtor = false;
}
if (AllAddedKinds & Thread) {
@@ -479,11 +521,33 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
// Without PIE, external function address may resolve to a PLT record, which
// can not be verified by the target module.
NeedPIE |= CfiCrossDso;
+ CfiICallGeneralizePointers =
+ Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers);
+
+ if (CfiCrossDso && CfiICallGeneralizePointers)
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << "-fsanitize-cfi-cross-dso"
+ << "-fsanitize-cfi-icall-generalize-pointers";
}
Stats = Args.hasFlag(options::OPT_fsanitize_stats,
options::OPT_fno_sanitize_stats, false);
+ if (MinimalRuntime) {
+ SanitizerMask IncompatibleMask =
+ Kinds & ~setGroupBits(CompatibleWithMinimalRuntime);
+ if (IncompatibleMask)
+ D.Diag(clang::diag::err_drv_argument_not_allowed_with)
+ << "-fsanitize-minimal-runtime"
+ << lastArgumentForMask(D, Args, IncompatibleMask);
+
+ SanitizerMask NonTrappingCfi = Kinds & CFI & ~TrappingKinds;
+ if (NonTrappingCfi)
+ D.Diag(clang::diag::err_drv_argument_only_allowed_with)
+ << "fsanitize-minimal-runtime"
+ << "fsanitize-trap=cfi";
+ }
+
// Parse -f(no-)?sanitize-coverage flags if coverage is supported by the
// enabled sanitizers.
for (const auto *Arg : Args) {
@@ -504,7 +568,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
// Disable coverage and not claim the flags if there is at least one
// non-supporting sanitizer.
- if (!(AllAddedKinds & ~setGroupBits(SupportsCoverage))) {
+ if (!(AllAddedKinds & ~AllRemove & ~setGroupBits(SupportsCoverage))) {
Arg->claim();
} else {
CoverageFeatures = 0;
@@ -539,23 +603,34 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
<< "-fsanitize-coverage=trace-pc-guard";
int InsertionPointTypes = CoverageFunc | CoverageBB | CoverageEdge;
+ int InstrumentationTypes =
+ CoverageTracePC | CoverageTracePCGuard | CoverageInline8bitCounters;
if ((CoverageFeatures & InsertionPointTypes) &&
- !(CoverageFeatures &(CoverageTracePC | CoverageTracePCGuard))) {
+ !(CoverageFeatures & InstrumentationTypes)) {
D.Diag(clang::diag::warn_drv_deprecated_arg)
<< "-fsanitize-coverage=[func|bb|edge]"
<< "-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc]";
}
// trace-pc w/o func/bb/edge implies edge.
- if ((CoverageFeatures &
- (CoverageTracePC | CoverageTracePCGuard | CoverageInline8bitCounters)) &&
- !(CoverageFeatures & InsertionPointTypes))
- CoverageFeatures |= CoverageEdge;
+ if (!(CoverageFeatures & InsertionPointTypes)) {
+ if (CoverageFeatures &
+ (CoverageTracePC | CoverageTracePCGuard | CoverageInline8bitCounters))
+ CoverageFeatures |= CoverageEdge;
+
+ if (CoverageFeatures & CoverageStackDepth)
+ CoverageFeatures |= CoverageFunc;
+ }
+
+ SharedRuntime =
+ Args.hasFlag(options::OPT_shared_libsan, options::OPT_static_libsan,
+ TC.getTriple().isAndroid() || TC.getTriple().isOSFuchsia() ||
+ TC.getTriple().isOSDarwin());
+
+ ImplicitCfiRuntime = TC.getTriple().isAndroid();
if (AllAddedKinds & Address) {
- AsanSharedRuntime =
- Args.hasArg(options::OPT_shared_libasan) || TC.getTriple().isAndroid();
- NeedPIE |= TC.getTriple().isAndroid();
+ NeedPIE |= TC.getTriple().isOSFuchsia();
if (Arg *A =
Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
StringRef S = A->getValue();
@@ -589,12 +664,17 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
// globals in ASan is disabled by default on ELF targets.
// See https://sourceware.org/bugzilla/show_bug.cgi?id=19002
AsanGlobalsDeadStripping =
- !TC.getTriple().isOSBinFormatELF() ||
+ !TC.getTriple().isOSBinFormatELF() || TC.getTriple().isOSFuchsia() ||
Args.hasArg(options::OPT_fsanitize_address_globals_dead_stripping);
} else {
AsanUseAfterScope = false;
}
+ if (AllAddedKinds & SafeStack) {
+ // SafeStack runtime is built into the system on Fuchsia.
+ SafeStackRuntime = !TC.getTriple().isOSFuchsia();
+ }
+
// Parse -link-cxx-sanitizer flag.
LinkCXXRuntimes =
Args.hasArg(options::OPT_fsanitize_link_cxx_runtime) || D.CCCIsCXX();
@@ -656,7 +736,9 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc"),
std::make_pair(CoverageTracePCGuard, "-fsanitize-coverage-trace-pc-guard"),
std::make_pair(CoverageInline8bitCounters, "-fsanitize-coverage-inline-8bit-counters"),
- std::make_pair(CoverageNoPrune, "-fsanitize-coverage-no-prune")};
+ std::make_pair(CoveragePCTable, "-fsanitize-coverage-pc-table"),
+ std::make_pair(CoverageNoPrune, "-fsanitize-coverage-no-prune"),
+ std::make_pair(CoverageStackDepth, "-fsanitize-coverage-stack-depth")};
for (auto F : CoverageFlags) {
if (CoverageFeatures & F.first)
CmdArgs.push_back(F.second);
@@ -733,9 +815,15 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
if (CfiCrossDso)
CmdArgs.push_back("-fsanitize-cfi-cross-dso");
+ if (CfiICallGeneralizePointers)
+ CmdArgs.push_back("-fsanitize-cfi-icall-generalize-pointers");
+
if (Stats)
CmdArgs.push_back("-fsanitize-stats");
+ if (MinimalRuntime)
+ CmdArgs.push_back("-fsanitize-minimal-runtime");
+
if (AsanFieldPadding)
CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" +
llvm::utostr(AsanFieldPadding)));
@@ -748,7 +836,7 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
// MSan: Workaround for PR16386.
// ASan: This is mainly to help LSan with cases such as
- // https://code.google.com/p/address-sanitizer/issues/detail?id=373
+ // https://github.com/google/sanitizers/issues/373
// We can't make this conditional on -fsanitize=leak, as that flag shouldn't
// affect compilation.
if (Sanitizers.has(Memory) || Sanitizers.has(Address))
@@ -818,6 +906,8 @@ int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A) {
.Case("trace-pc-guard", CoverageTracePCGuard)
.Case("no-prune", CoverageNoPrune)
.Case("inline-8bit-counters", CoverageInline8bitCounters)
+ .Case("pc-table", CoveragePCTable)
+ .Case("stack-depth", CoverageStackDepth)
.Default(0);
if (F == 0)
D.Diag(clang::diag::err_drv_unsupported_option_argument)
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp
index 12afb18c23a88..f96a1182e3cab 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp
@@ -27,6 +27,8 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Support/TargetParser.h"
#include "llvm/Support/TargetRegistry.h"
@@ -79,6 +81,12 @@ ToolChain::ToolChain(const Driver &D, const llvm::Triple &T,
getFilePaths().push_back(CandidateLibPath);
}
+void ToolChain::setTripleEnvironment(llvm::Triple::EnvironmentType Env) {
+ Triple.setEnvironment(Env);
+ if (EffectiveTriple != llvm::Triple())
+ EffectiveTriple.setEnvironment(Env);
+}
+
ToolChain::~ToolChain() {
}
@@ -90,6 +98,10 @@ bool ToolChain::useIntegratedAs() const {
IsIntegratedAssemblerDefault());
}
+bool ToolChain::useRelaxRelocations() const {
+ return ENABLE_X86_RELAX_RELOCATIONS;
+}
+
const SanitizerArgs& ToolChain::getSanitizerArgs() const {
if (!SanitizerArguments.get())
SanitizerArguments.reset(new SanitizerArgs(*this, Args));
@@ -108,7 +120,7 @@ struct DriverSuffix {
const char *ModeFlag;
};
-const DriverSuffix *FindDriverSuffix(StringRef ProgName) {
+const DriverSuffix *FindDriverSuffix(StringRef ProgName, size_t &Pos) {
// A list of known driver suffixes. Suffixes are compared against the
// program name in order. If there is a match, the frontend type is updated as
// necessary by applying the ModeFlag.
@@ -127,9 +139,13 @@ const DriverSuffix *FindDriverSuffix(StringRef ProgName) {
{"++", "--driver-mode=g++"},
};
- for (size_t i = 0; i < llvm::array_lengthof(DriverSuffixes); ++i)
- if (ProgName.endswith(DriverSuffixes[i].Suffix))
+ for (size_t i = 0; i < llvm::array_lengthof(DriverSuffixes); ++i) {
+ StringRef Suffix(DriverSuffixes[i].Suffix);
+ if (ProgName.endswith(Suffix)) {
+ Pos = ProgName.size() - Suffix.size();
return &DriverSuffixes[i];
+ }
+ }
return nullptr;
}
@@ -144,7 +160,7 @@ std::string normalizeProgramName(llvm::StringRef Argv0) {
return ProgName;
}
-const DriverSuffix *parseDriverSuffix(StringRef ProgName) {
+const DriverSuffix *parseDriverSuffix(StringRef ProgName, size_t &Pos) {
// Try to infer frontend type and default target from the program name by
// comparing it against DriverSuffixes in order.
@@ -152,47 +168,46 @@ const DriverSuffix *parseDriverSuffix(StringRef ProgName) {
// E.g. "x86_64-linux-clang" as interpreted as suffix "clang" with target
// prefix "x86_64-linux". If such a target prefix is found, it may be
// added via -target as implicit first argument.
- const DriverSuffix *DS = FindDriverSuffix(ProgName);
+ const DriverSuffix *DS = FindDriverSuffix(ProgName, Pos);
if (!DS) {
// Try again after stripping any trailing version number:
// clang++3.5 -> clang++
ProgName = ProgName.rtrim("0123456789.");
- DS = FindDriverSuffix(ProgName);
+ DS = FindDriverSuffix(ProgName, Pos);
}
if (!DS) {
// Try again after stripping trailing -component.
// clang++-tot -> clang++
ProgName = ProgName.slice(0, ProgName.rfind('-'));
- DS = FindDriverSuffix(ProgName);
+ DS = FindDriverSuffix(ProgName, Pos);
}
return DS;
}
} // anonymous namespace
-std::pair<std::string, std::string>
+ParsedClangName
ToolChain::getTargetAndModeFromProgramName(StringRef PN) {
std::string ProgName = normalizeProgramName(PN);
- const DriverSuffix *DS = parseDriverSuffix(ProgName);
+ size_t SuffixPos;
+ const DriverSuffix *DS = parseDriverSuffix(ProgName, SuffixPos);
if (!DS)
- return std::make_pair("", "");
- std::string ModeFlag = DS->ModeFlag == nullptr ? "" : DS->ModeFlag;
+ return ParsedClangName();
+ size_t SuffixEnd = SuffixPos + strlen(DS->Suffix);
- std::string::size_type LastComponent =
- ProgName.rfind('-', ProgName.size() - strlen(DS->Suffix));
+ size_t LastComponent = ProgName.rfind('-', SuffixPos);
if (LastComponent == std::string::npos)
- return std::make_pair("", ModeFlag);
+ return ParsedClangName(ProgName.substr(0, SuffixEnd), DS->ModeFlag);
+ std::string ModeSuffix = ProgName.substr(LastComponent + 1,
+ SuffixEnd - LastComponent - 1);
// Infer target from the prefix.
StringRef Prefix(ProgName);
Prefix = Prefix.slice(0, LastComponent);
std::string IgnoredError;
- std::string Target;
- if (llvm::TargetRegistry::lookupTarget(Prefix, IgnoredError)) {
- Target = Prefix;
- }
- return std::make_pair(Target, ModeFlag);
+ bool IsRegistered = llvm::TargetRegistry::lookupTarget(Prefix, IgnoredError);
+ return ParsedClangName{Prefix, ModeSuffix, DS->ModeFlag, IsRegistered};
}
StringRef ToolChain::getDefaultUniversalArchName() const {
@@ -212,6 +227,10 @@ StringRef ToolChain::getDefaultUniversalArchName() const {
}
}
+std::string ToolChain::getInputFilename(const InputInfo &Input) const {
+ return Input.getFilename();
+}
+
bool ToolChain::IsUnwindTablesDefault(const ArgList &Args) const {
return false;
}
@@ -292,15 +311,27 @@ static StringRef getArchNameForCompilerRTLib(const ToolChain &TC,
const llvm::Triple &Triple = TC.getTriple();
bool IsWindows = Triple.isOSWindows();
- if (Triple.isWindowsMSVCEnvironment() && TC.getArch() == llvm::Triple::x86)
- return "i386";
-
if (TC.getArch() == llvm::Triple::arm || TC.getArch() == llvm::Triple::armeb)
return (arm::getARMFloatABI(TC, Args) == arm::FloatABI::Hard && !IsWindows)
? "armhf"
: "arm";
- return TC.getArchName();
+ // For historic reasons, Android library is using i686 instead of i386.
+ if (TC.getArch() == llvm::Triple::x86 && Triple.isAndroid())
+ return "i686";
+
+ return llvm::Triple::getArchTypeName(TC.getArch());
+}
+
+std::string ToolChain::getCompilerRTPath() const {
+ SmallString<128> Path(getDriver().ResourceDir);
+ if (Triple.isOSUnknown()) {
+ llvm::sys::path::append(Path, "lib");
+ } else {
+ StringRef OSLibName = Triple.isOSFreeBSD() ? "freebsd" : getOS();
+ llvm::sys::path::append(Path, "lib", OSLibName);
+ }
+ return Path.str();
}
std::string ToolChain::getCompilerRT(const ArgList &Args, StringRef Component,
@@ -315,9 +346,7 @@ std::string ToolChain::getCompilerRT(const ArgList &Args, StringRef Component,
const char *Suffix = Shared ? (Triple.isOSWindows() ? ".dll" : ".so")
: (IsITANMSVCWindows ? ".lib" : ".a");
- SmallString<128> Path(getDriver().ResourceDir);
- StringRef OSLibName = Triple.isOSFreeBSD() ? "freebsd" : getOS();
- llvm::sys::path::append(Path, "lib", OSLibName);
+ SmallString<128> Path(getCompilerRTPath());
llvm::sys::path::append(Path, Prefix + Twine("clang_rt.") + Component + "-" +
Arch + Env + Suffix);
return Path.str();
@@ -381,7 +410,11 @@ std::string ToolChain::GetLinkerPath() const {
// then use whatever the default system linker is.
return GetProgramPath(getDefaultLinker());
} else {
- llvm::SmallString<8> LinkerName("ld.");
+ llvm::SmallString<8> LinkerName;
+ if (Triple.isOSDarwin())
+ LinkerName.append("ld64.");
+ else
+ LinkerName.append("ld.");
LinkerName.append(UseLinker);
std::string LinkerPath(GetProgramPath(LinkerName.c_str()));
@@ -424,6 +457,13 @@ ObjCRuntime ToolChain::getDefaultObjCRuntime(bool isNonFragile) const {
VersionTuple());
}
+llvm::ExceptionHandling
+ToolChain::GetExceptionModel(const llvm::opt::ArgList &Args) const {
+ if (Triple.isOSWindows() && Triple.getArch() != llvm::Triple::x86)
+ return llvm::ExceptionHandling::WinEH;
+ return llvm::ExceptionHandling::None;
+}
+
bool ToolChain::isThreadModelSupported(const StringRef Model) const {
if (Model == "single") {
// FIXME: 'single' is only supported on ARM and WebAssembly so far.
@@ -500,7 +540,7 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
: tools::arm::getARMTargetCPU(MCPU, MArch, Triple);
StringRef Suffix =
tools::arm::getLLVMArchSuffixForARM(CPU, MArch, Triple);
- bool IsMProfile = ARM::parseArchProfile(Suffix) == ARM::PK_M;
+ bool IsMProfile = ARM::parseArchProfile(Suffix) == ARM::ProfileKind::M;
bool ThumbDefault = IsMProfile || (ARM::parseArchVersion(Suffix) == 7 &&
getTriple().isOSBinFormatMachO());
// FIXME: this is invalid for WindowsCE
@@ -512,11 +552,42 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
else
ArchName = "arm";
- // Assembly files should start in ARM mode, unless arch is M-profile.
- // Windows is always thumb.
- if ((InputType != types::TY_PP_Asm && Args.hasFlag(options::OPT_mthumb,
- options::OPT_mno_thumb, ThumbDefault)) || IsMProfile ||
- getTriple().isOSWindows()) {
+ // Check if ARM ISA was explicitly selected (using -mno-thumb or -marm) for
+ // M-Class CPUs/architecture variants, which is not supported.
+ bool ARMModeRequested = !Args.hasFlag(options::OPT_mthumb,
+ options::OPT_mno_thumb, ThumbDefault);
+ if (IsMProfile && ARMModeRequested) {
+ if (!MCPU.empty())
+ getDriver().Diag(diag::err_cpu_unsupported_isa) << CPU << "ARM";
+ else
+ getDriver().Diag(diag::err_arch_unsupported_isa)
+ << tools::arm::getARMArch(MArch, getTriple()) << "ARM";
+ }
+
+ // Check to see if an explicit choice to use thumb has been made via
+ // -mthumb. For assembler files we must check for -mthumb in the options
+ // passed to the assember via -Wa or -Xassembler.
+ bool IsThumb = false;
+ if (InputType != types::TY_PP_Asm)
+ IsThumb = Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb,
+ ThumbDefault);
+ else {
+ // Ideally we would check for these flags in
+ // CollectArgsForIntegratedAssembler but we can't change the ArchName at
+ // that point. There is no assembler equivalent of -mno-thumb, -marm, or
+ // -mno-arm.
+ for (const Arg *A :
+ Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {
+ for (StringRef Value : A->getValues()) {
+ if (Value == "-mthumb")
+ IsThumb = true;
+ }
+ }
+ }
+ // Assembly files should start in ARM mode, unless arch is M-profile, or
+ // -mthumb has been passed explicitly to the assembler. Windows is always
+ // thumb.
+ if (IsThumb || IsMProfile || getTriple().isOSWindows()) {
if (IsBigEndian)
ArchName = "thumbeb";
else
@@ -643,8 +714,16 @@ void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
DriverArgs.AddAllArgs(CC1Args, options::OPT_stdlib_EQ);
}
+bool ToolChain::ShouldLinkCXXStdlib(const llvm::opt::ArgList &Args) const {
+ return getDriver().CCCIsCXX() &&
+ !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
+ options::OPT_nostdlibxx);
+}
+
void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
+ assert(!Args.hasArg(options::OPT_nostdlibxx) &&
+ "should not have called this");
CXXStdlibType Type = GetCXXStdlibType(Args);
switch (Type) {
@@ -770,3 +849,70 @@ ToolChain::computeMSVCVersion(const Driver *D,
return VersionTuple();
}
+
+llvm::opt::DerivedArgList *ToolChain::TranslateOpenMPTargetArgs(
+ const llvm::opt::DerivedArgList &Args, bool SameTripleAsHost,
+ SmallVectorImpl<llvm::opt::Arg *> &AllocatedArgs) const {
+ DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
+ const OptTable &Opts = getDriver().getOpts();
+ bool Modified = false;
+
+ // Handle -Xopenmp-target flags
+ for (Arg *A : Args) {
+ // Exclude flags which may only apply to the host toolchain.
+ // Do not exclude flags when the host triple (AuxTriple)
+ // matches the current toolchain triple. If it is not present
+ // at all, target and host share a toolchain.
+ if (A->getOption().matches(options::OPT_m_Group)) {
+ if (SameTripleAsHost)
+ DAL->append(A);
+ else
+ Modified = true;
+ continue;
+ }
+
+ unsigned Index;
+ unsigned Prev;
+ bool XOpenMPTargetNoTriple =
+ A->getOption().matches(options::OPT_Xopenmp_target);
+
+ if (A->getOption().matches(options::OPT_Xopenmp_target_EQ)) {
+ // Passing device args: -Xopenmp-target=<triple> -opt=val.
+ if (A->getValue(0) == getTripleString())
+ Index = Args.getBaseArgs().MakeIndex(A->getValue(1));
+ else
+ continue;
+ } else if (XOpenMPTargetNoTriple) {
+ // Passing device args: -Xopenmp-target -opt=val.
+ Index = Args.getBaseArgs().MakeIndex(A->getValue(0));
+ } else {
+ DAL->append(A);
+ continue;
+ }
+
+ // Parse the argument to -Xopenmp-target.
+ Prev = Index;
+ std::unique_ptr<Arg> XOpenMPTargetArg(Opts.ParseOneArg(Args, Index));
+ if (!XOpenMPTargetArg || Index > Prev + 1) {
+ getDriver().Diag(diag::err_drv_invalid_Xopenmp_target_with_args)
+ << A->getAsString(Args);
+ continue;
+ }
+ if (XOpenMPTargetNoTriple && XOpenMPTargetArg &&
+ Args.getAllArgValues(options::OPT_fopenmp_targets_EQ).size() != 1) {
+ getDriver().Diag(diag::err_drv_Xopenmp_target_missing_triple);
+ continue;
+ }
+ XOpenMPTargetArg->setBaseArg(A);
+ A = XOpenMPTargetArg.release();
+ AllocatedArgs.push_back(A);
+ DAL->append(A);
+ Modified = true;
+ }
+
+ if (Modified)
+ return DAL;
+
+ delete DAL;
+ return nullptr;
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/AMDGPU.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/AMDGPU.cpp
index 63e1749e00883..a313bc5c35de1 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/AMDGPU.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/AMDGPU.cpp
@@ -8,9 +8,10 @@
//===----------------------------------------------------------------------===//
#include "AMDGPU.h"
-#include "InputInfo.h"
#include "CommonArgs.h"
+#include "InputInfo.h"
#include "clang/Driver/Compilation.h"
+#include "clang/Driver/DriverDiagnostic.h"
#include "llvm/Option/ArgList.h"
using namespace clang::driver;
@@ -35,11 +36,66 @@ void amdgpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs, Inputs));
}
+void amdgpu::getAMDGPUTargetFeatures(const Driver &D,
+ const llvm::opt::ArgList &Args,
+ std::vector<StringRef> &Features) {
+ if (const Arg *dAbi = Args.getLastArg(options::OPT_mamdgpu_debugger_abi)) {
+ StringRef value = dAbi->getValue();
+ if (value == "1.0") {
+ Features.push_back("+amdgpu-debugger-insert-nops");
+ Features.push_back("+amdgpu-debugger-reserve-regs");
+ Features.push_back("+amdgpu-debugger-emit-prologue");
+ } else {
+ D.Diag(diag::err_drv_clang_unsupported) << dAbi->getAsString(Args);
+ }
+ }
+
+ handleTargetFeaturesGroup(
+ Args, Features, options::OPT_m_amdgpu_Features_Group);
+}
+
/// AMDGPU Toolchain
AMDGPUToolChain::AMDGPUToolChain(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
- : Generic_ELF(D, Triple, Args) { }
+ : Generic_ELF(D, Triple, Args),
+ OptionsDefault({{options::OPT_O, "3"},
+ {options::OPT_cl_std_EQ, "CL1.2"}}) {}
Tool *AMDGPUToolChain::buildLinker() const {
return new tools::amdgpu::Linker(*this);
}
+
+DerivedArgList *
+AMDGPUToolChain::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
+ Action::OffloadKind DeviceOffloadKind) const {
+
+ DerivedArgList *DAL =
+ Generic_ELF::TranslateArgs(Args, BoundArch, DeviceOffloadKind);
+
+ // Do nothing if not OpenCL (-x cl)
+ if (!Args.getLastArgValue(options::OPT_x).equals("cl"))
+ return DAL;
+
+ if (!DAL)
+ DAL = new DerivedArgList(Args.getBaseArgs());
+ for (auto *A : Args)
+ DAL->append(A);
+
+ const OptTable &Opts = getDriver().getOpts();
+
+ // Phase 1 (.cl -> .bc)
+ if (Args.hasArg(options::OPT_c) && Args.hasArg(options::OPT_emit_llvm)) {
+ DAL->AddFlagArg(nullptr, Opts.getOption(getTriple().isArch64Bit()
+ ? options::OPT_m64
+ : options::OPT_m32));
+
+ // Have to check OPT_O4, OPT_O0 & OPT_Ofast separately
+ // as they defined that way in Options.td
+ if (!Args.hasArg(options::OPT_O, options::OPT_O0, options::OPT_O4,
+ options::OPT_Ofast))
+ DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_O),
+ getOptionDefault(options::OPT_O));
+ }
+
+ return DAL;
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/AMDGPU.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/AMDGPU.h
index 9af1e96489ebd..36114d0dabc43 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/AMDGPU.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/AMDGPU.h
@@ -11,13 +11,14 @@
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_AMDGPU_H
#include "Gnu.h"
+#include "clang/Driver/Options.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
+#include <map>
namespace clang {
namespace driver {
namespace tools {
-
namespace amdgpu {
class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
@@ -31,20 +32,35 @@ public:
const char *LinkingOutput) const override;
};
+void getAMDGPUTargetFeatures(const Driver &D, const llvm::opt::ArgList &Args,
+ std::vector<StringRef> &Features);
+
} // end namespace amdgpu
} // end namespace tools
namespace toolchains {
class LLVM_LIBRARY_VISIBILITY AMDGPUToolChain : public Generic_ELF {
+
+private:
+ const std::map<options::ID, const StringRef> OptionsDefault;
+
protected:
Tool *buildLinker() const override;
+ const StringRef getOptionDefault(options::ID OptID) const {
+ auto opt = OptionsDefault.find(OptID);
+ assert(opt != OptionsDefault.end() && "No Default for Option");
+ return opt->second;
+ }
public:
AMDGPUToolChain(const Driver &D, const llvm::Triple &Triple,
- const llvm::opt::ArgList &Args);
+ const llvm::opt::ArgList &Args);
unsigned GetDefaultDwarfVersion() const override { return 2; }
bool IsIntegratedAssemblerDefault() const override { return true; }
+ llvm::opt::DerivedArgList *
+ TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
+ Action::OffloadKind DeviceOffloadKind) const override;
};
} // end namespace toolchains
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Ananas.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Ananas.cpp
index a67e1d2378f5d..ee072cc03e7ca 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Ananas.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Ananas.cpp
@@ -91,11 +91,10 @@ void ananas::Linker::ConstructJob(Compilation &C, const JobAction &JA,
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
- if (D.CCCIsCXX())
- ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (ToolChain.ShouldLinkCXXStdlib(Args))
+ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
CmdArgs.push_back("-lc");
- }
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/AArch64.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
index 554d051fb155c..ad04aedd098eb 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
@@ -20,14 +20,12 @@ using namespace clang;
using namespace llvm::opt;
/// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are
-/// targeting. Set \p A to the Arg corresponding to the -mcpu or -mtune
-/// arguments if they are provided, or to nullptr otherwise.
+/// targeting. Set \p A to the Arg corresponding to the -mcpu argument if it is
+/// provided, or to nullptr otherwise.
std::string aarch64::getAArch64TargetCPU(const ArgList &Args, Arg *&A) {
std::string CPU;
- // If we have -mtune or -mcpu, use that.
- if ((A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ))) {
- CPU = StringRef(A->getValue()).lower();
- } else if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) {
+ // If we have -mcpu, use that.
+ if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) {
StringRef Mcpu = A->getValue();
CPU = Mcpu.split("+").first.lower();
}
@@ -74,7 +72,7 @@ static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU,
if (CPU == "generic") {
Features.push_back("+neon");
} else {
- unsigned ArchKind = llvm::AArch64::parseCPUArch(CPU);
+ llvm::AArch64::ArchKind ArchKind = llvm::AArch64::parseCPUArch(CPU);
if (!llvm::AArch64::getArchFeatures(ArchKind, Features))
return false;
@@ -96,8 +94,8 @@ getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March,
std::string MarchLowerCase = March.lower();
std::pair<StringRef, StringRef> Split = StringRef(MarchLowerCase).split("+");
- unsigned ArchKind = llvm::AArch64::parseArch(Split.first);
- if (ArchKind == static_cast<unsigned>(llvm::AArch64::ArchKind::AK_INVALID) ||
+ llvm::AArch64::ArchKind ArchKind = llvm::AArch64::parseArch(Split.first);
+ if (ArchKind == llvm::AArch64::ArchKind::INVALID ||
!llvm::AArch64::getArchFeatures(ArchKind, Features) ||
(Split.second.size() && !DecodeAArch64Features(D, Split.second, Features)))
return false;
@@ -122,6 +120,12 @@ getAArch64MicroArchFeaturesFromMtune(const Driver &D, StringRef Mtune,
const ArgList &Args,
std::vector<StringRef> &Features) {
std::string MtuneLowerCase = Mtune.lower();
+ // Check CPU name is valid
+ std::vector<StringRef> MtuneFeatures;
+ StringRef Tune;
+ if (!DecodeAArch64Mcpu(D, MtuneLowerCase, Tune, MtuneFeatures))
+ return false;
+
// Handle CPU name is 'native'.
if (MtuneLowerCase == "native")
MtuneLowerCase = llvm::sys::getHostCPUName();
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/ARM.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/ARM.cpp
index 95b86f784f914..44c8871d0e1fc 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/ARM.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/ARM.cpp
@@ -29,8 +29,7 @@ int arm::getARMSubArchVersionNumber(const llvm::Triple &Triple) {
// True if M-profile.
bool arm::isARMMProfile(const llvm::Triple &Triple) {
llvm::StringRef Arch = Triple.getArchName();
- unsigned Profile = llvm::ARM::parseArchProfile(Arch);
- return Profile == llvm::ARM::PK_M;
+ return llvm::ARM::parseArchProfile(Arch) == llvm::ARM::ProfileKind::M;
}
// Get Arch/CPU from args.
@@ -88,6 +87,15 @@ static bool DecodeARMFeatures(const Driver &D, StringRef text,
return true;
}
+static void DecodeARMFeaturesFromCPU(const Driver &D, StringRef CPU,
+ std::vector<StringRef> &Features) {
+ if (CPU != "generic") {
+ llvm::ARM::ArchKind ArchKind = llvm::ARM::parseCPUArch(CPU);
+ unsigned Extension = llvm::ARM::getDefaultExtensions(CPU, ArchKind);
+ llvm::ARM::getExtensionFeatures(Extension, Features);
+ }
+}
+
// Check if -march is valid by checking if it can be canonicalised and parsed.
// getARMArch is used here instead of just checking the -march value in order
// to handle -march=native correctly.
@@ -98,7 +106,7 @@ static void checkARMArchName(const Driver &D, const Arg *A, const ArgList &Args,
std::pair<StringRef, StringRef> Split = ArchName.split("+");
std::string MArch = arm::getARMArch(ArchName, Triple);
- if (llvm::ARM::parseArch(MArch) == llvm::ARM::AK_INVALID ||
+ if (llvm::ARM::parseArch(MArch) == llvm::ARM::ArchKind::INVALID ||
(Split.second.size() && !DecodeARMFeatures(D, Split.second, Features)))
D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
}
@@ -123,6 +131,26 @@ bool arm::useAAPCSForMachO(const llvm::Triple &T) {
T.getOS() == llvm::Triple::UnknownOS || isARMMProfile(T);
}
+// Select mode for reading thread pointer (-mtp=soft/cp15).
+arm::ReadTPMode arm::getReadTPMode(const ToolChain &TC, const ArgList &Args) {
+ if (Arg *A = Args.getLastArg(options::OPT_mtp_mode_EQ)) {
+ const Driver &D = TC.getDriver();
+ arm::ReadTPMode ThreadPointer =
+ llvm::StringSwitch<arm::ReadTPMode>(A->getValue())
+ .Case("cp15", ReadTPMode::Cp15)
+ .Case("soft", ReadTPMode::Soft)
+ .Default(ReadTPMode::Invalid);
+ if (ThreadPointer != ReadTPMode::Invalid)
+ return ThreadPointer;
+ if (StringRef(A->getValue()).empty())
+ D.Diag(diag::err_drv_missing_arg_mtp) << A->getAsString(Args);
+ else
+ D.Diag(diag::err_drv_invalid_mtp) << A->getAsString(Args);
+ return ReadTPMode::Invalid;
+ }
+ return ReadTPMode::Soft;
+}
+
// Select the float ABI as determined by -msoft-float, -mhard-float, and
// -mfloat-abi=.
arm::FloatABI arm::getARMFloatABI(const ToolChain &TC, const ArgList &Args) {
@@ -254,6 +282,7 @@ void arm::getARMTargetFeatures(const ToolChain &TC,
bool KernelOrKext =
Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
arm::FloatABI ABI = arm::getARMFloatABI(TC, Args);
+ arm::ReadTPMode ThreadPointer = arm::getReadTPMode(TC, Args);
const Arg *WaCPU = nullptr, *WaFPU = nullptr;
const Arg *WaHDiv = nullptr, *WaArch = nullptr;
@@ -295,6 +324,9 @@ void arm::getARMTargetFeatures(const ToolChain &TC,
}
}
+ if (ThreadPointer == arm::ReadTPMode::Cp15)
+ Features.push_back("+read-tp-hard");
+
// Check -march. ClangAs gives preference to -Wa,-march=.
const Arg *ArchArg = Args.getLastArg(options::OPT_march_EQ);
StringRef ArchName;
@@ -332,6 +364,8 @@ void arm::getARMTargetFeatures(const ToolChain &TC,
for (auto &F : HostFeatures)
Features.push_back(
Args.MakeArgString((F.second ? "+" : "-") + F.first()));
+ } else if (!CPUName.empty()) {
+ DecodeARMFeaturesFromCPU(D, CPUName, Features);
}
// Honor -mfpu=. ClangAs gives preference to -Wa,-mfpu=.
@@ -393,7 +427,7 @@ void arm::getARMTargetFeatures(const ToolChain &TC,
if (Arg *A = Args.getLastArg(options::OPT_mexecute_only, options::OPT_mno_execute_only)) {
if (A->getOption().matches(options::OPT_mexecute_only)) {
if (getARMSubArchVersionNumber(Triple) < 7 &&
- llvm::ARM::parseArch(Triple.getArchName()) != llvm::ARM::AK_ARMV6T2)
+ llvm::ARM::parseArch(Triple.getArchName()) != llvm::ARM::ArchKind::ARMV6T2)
D.Diag(diag::err_target_unsupported_execute_only) << Triple.getArchName();
else if (Arg *B = Args.getLastArg(options::OPT_mno_movt))
D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args);
@@ -525,11 +559,11 @@ std::string arm::getARMTargetCPU(StringRef CPU, StringRef Arch,
// FIXME: This is redundant with -mcpu, why does LLVM use this.
StringRef arm::getLLVMArchSuffixForARM(StringRef CPU, StringRef Arch,
const llvm::Triple &Triple) {
- unsigned ArchKind;
+ llvm::ARM::ArchKind ArchKind;
if (CPU == "generic") {
std::string ARMArch = tools::arm::getARMArch(Arch, Triple);
ArchKind = llvm::ARM::parseArch(ARMArch);
- if (ArchKind == llvm::ARM::AK_INVALID)
+ if (ArchKind == llvm::ARM::ArchKind::INVALID)
// In case of generic Arch, i.e. "arm",
// extract arch from default cpu of the Triple
ArchKind = llvm::ARM::parseCPUArch(Triple.getARMCPUForArch(ARMArch));
@@ -537,10 +571,10 @@ StringRef arm::getLLVMArchSuffixForARM(StringRef CPU, StringRef Arch,
// FIXME: horrible hack to get around the fact that Cortex-A7 is only an
// armv7k triple if it's actually been specified via "-arch armv7k".
ArchKind = (Arch == "armv7k" || Arch == "thumbv7k")
- ? (unsigned)llvm::ARM::AK_ARMV7K
+ ? llvm::ARM::ArchKind::ARMV7K
: llvm::ARM::parseCPUArch(CPU);
}
- if (ArchKind == llvm::ARM::AK_INVALID)
+ if (ArchKind == llvm::ARM::ArchKind::INVALID)
return "";
return llvm::ARM::getSubArch(ArchKind);
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/ARM.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/ARM.h
index 52afaab762d0a..c1dc168840330 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/ARM.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/ARM.h
@@ -32,6 +32,12 @@ StringRef getLLVMArchSuffixForARM(llvm::StringRef CPU, llvm::StringRef Arch,
void appendEBLinkFlags(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs,
const llvm::Triple &Triple);
+enum class ReadTPMode {
+ Invalid,
+ Soft,
+ Cp15,
+};
+
enum class FloatABI {
Invalid,
Soft,
@@ -40,6 +46,7 @@ enum class FloatABI {
};
FloatABI getARMFloatABI(const ToolChain &TC, const llvm::opt::ArgList &Args);
+ReadTPMode getReadTPMode(const ToolChain &TC, const llvm::opt::ArgList &Args);
bool useAAPCSForMachO(const llvm::Triple &T);
void getARMArchCPUFromArgs(const llvm::opt::ArgList &Args,
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Mips.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Mips.cpp
index b45dcd6db6780..61481a92d0b73 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Mips.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Mips.cpp
@@ -35,7 +35,7 @@ void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple,
// MIPS32r6 is the default for mips(el)?-img-linux-gnu and MIPS64r6 is the
// default for mips64(el)?-img-linux-gnu.
if (Triple.getVendor() == llvm::Triple::ImaginationTechnologies &&
- Triple.getEnvironment() == llvm::Triple::GNU) {
+ Triple.isGNUEnvironment()) {
DefMips32CPU = "mips32r6";
DefMips64CPU = "mips64r6";
}
@@ -227,11 +227,32 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
O.matches(options::OPT_fno_PIE) || O.matches(options::OPT_fno_pie));
}
- if (IsN64 && NonPIC)
+ bool UseAbiCalls = false;
+
+ Arg *ABICallsArg =
+ Args.getLastArg(options::OPT_mabicalls, options::OPT_mno_abicalls);
+ UseAbiCalls =
+ !ABICallsArg || ABICallsArg->getOption().matches(options::OPT_mabicalls);
+
+ if (UseAbiCalls && IsN64 && NonPIC) {
+ D.Diag(diag::warn_drv_unsupported_abicalls);
+ UseAbiCalls = false;
+ }
+
+ if (!UseAbiCalls)
Features.push_back("+noabicalls");
else
- AddTargetFeature(Args, Features, options::OPT_mno_abicalls,
- options::OPT_mabicalls, "noabicalls");
+ Features.push_back("-noabicalls");
+
+ if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,
+ options::OPT_mno_long_calls)) {
+ if (A->getOption().matches(options::OPT_mno_long_calls))
+ Features.push_back("-long-calls");
+ else if (!UseAbiCalls)
+ Features.push_back("+long-calls");
+ else
+ D.Diag(diag::warn_drv_unsupported_longcalls) << (ABICallsArg ? 0 : 1);
+ }
mips::FloatABI FloatABI = mips::getMipsFloatABI(D, Args);
if (FloatABI == mips::FloatABI::Soft) {
@@ -244,14 +265,14 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) {
StringRef Val = StringRef(A->getValue());
if (Val == "2008") {
- if (mips::getSupportedNanEncoding(CPUName) & mips::Nan2008)
+ if (mips::getIEEE754Standard(CPUName) & mips::Std2008)
Features.push_back("+nan2008");
else {
Features.push_back("-nan2008");
D.Diag(diag::warn_target_unsupported_nan2008) << CPUName;
}
} else if (Val == "legacy") {
- if (mips::getSupportedNanEncoding(CPUName) & mips::NanLegacy)
+ if (mips::getIEEE754Standard(CPUName) & mips::Legacy)
Features.push_back("-nan2008");
else {
Features.push_back("+nan2008");
@@ -262,6 +283,28 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
<< A->getOption().getName() << Val;
}
+ if (Arg *A = Args.getLastArg(options::OPT_mabs_EQ)) {
+ StringRef Val = StringRef(A->getValue());
+ if (Val == "2008") {
+ if (mips::getIEEE754Standard(CPUName) & mips::Std2008) {
+ Features.push_back("+abs2008");
+ } else {
+ Features.push_back("-abs2008");
+ D.Diag(diag::warn_target_unsupported_abs2008) << CPUName;
+ }
+ } else if (Val == "legacy") {
+ if (mips::getIEEE754Standard(CPUName) & mips::Legacy) {
+ Features.push_back("-abs2008");
+ } else {
+ Features.push_back("+abs2008");
+ D.Diag(diag::warn_target_unsupported_abslegacy) << CPUName;
+ }
+ } else {
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Val;
+ }
+ }
+
AddTargetFeature(Args, Features, options::OPT_msingle_float,
options::OPT_mdouble_float, "single-float");
AddTargetFeature(Args, Features, options::OPT_mips16, options::OPT_mno_mips16,
@@ -299,32 +342,31 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
options::OPT_modd_spreg, "nooddspreg");
AddTargetFeature(Args, Features, options::OPT_mno_madd4, options::OPT_mmadd4,
"nomadd4");
- AddTargetFeature(Args, Features, options::OPT_mlong_calls,
- options::OPT_mno_long_calls, "long-calls");
- AddTargetFeature(Args, Features, options::OPT_mmt, options::OPT_mno_mt,"mt");
+ AddTargetFeature(Args, Features, options::OPT_mmt, options::OPT_mno_mt, "mt");
}
-mips::NanEncoding mips::getSupportedNanEncoding(StringRef &CPU) {
- // Strictly speaking, mips32r2 and mips64r2 are NanLegacy-only since Nan2008
- // was first introduced in Release 3. However, other compilers have
- // traditionally allowed it for Release 2 so we should do the same.
- return (NanEncoding)llvm::StringSwitch<int>(CPU)
- .Case("mips1", NanLegacy)
- .Case("mips2", NanLegacy)
- .Case("mips3", NanLegacy)
- .Case("mips4", NanLegacy)
- .Case("mips5", NanLegacy)
- .Case("mips32", NanLegacy)
- .Case("mips32r2", NanLegacy | Nan2008)
- .Case("mips32r3", NanLegacy | Nan2008)
- .Case("mips32r5", NanLegacy | Nan2008)
- .Case("mips32r6", Nan2008)
- .Case("mips64", NanLegacy)
- .Case("mips64r2", NanLegacy | Nan2008)
- .Case("mips64r3", NanLegacy | Nan2008)
- .Case("mips64r5", NanLegacy | Nan2008)
- .Case("mips64r6", Nan2008)
- .Default(NanLegacy);
+mips::IEEE754Standard mips::getIEEE754Standard(StringRef &CPU) {
+ // Strictly speaking, mips32r2 and mips64r2 do not conform to the
+ // IEEE754-2008 standard. Support for this standard was first introduced
+ // in Release 3. However, other compilers have traditionally allowed it
+ // for Release 2 so we should do the same.
+ return (IEEE754Standard)llvm::StringSwitch<int>(CPU)
+ .Case("mips1", Legacy)
+ .Case("mips2", Legacy)
+ .Case("mips3", Legacy)
+ .Case("mips4", Legacy)
+ .Case("mips5", Legacy)
+ .Case("mips32", Legacy)
+ .Case("mips32r2", Legacy | Std2008)
+ .Case("mips32r3", Legacy | Std2008)
+ .Case("mips32r5", Legacy | Std2008)
+ .Case("mips32r6", Std2008)
+ .Case("mips64", Legacy)
+ .Case("mips64r2", Legacy | Std2008)
+ .Case("mips64r3", Legacy | Std2008)
+ .Case("mips64r5", Legacy | Std2008)
+ .Case("mips64r6", Std2008)
+ .Default(Std2008);
}
bool mips::hasCompactBranches(StringRef &CPU) {
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Mips.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Mips.h
index 0b788660948c4..89eea9a1514cd 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Mips.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Mips.h
@@ -24,7 +24,7 @@ namespace tools {
bool isMipsArch(llvm::Triple::ArchType Arch);
namespace mips {
-typedef enum { NanLegacy = 1, Nan2008 = 2 } NanEncoding;
+typedef enum { Legacy = 1, Std2008 = 2 } IEEE754Standard;
enum class FloatABI {
Invalid,
@@ -32,7 +32,7 @@ enum class FloatABI {
Hard,
};
-NanEncoding getSupportedNanEncoding(StringRef &CPU);
+IEEE754Standard getIEEE754Standard(StringRef &CPU);
bool hasCompactBranches(StringRef &CPU);
void getMipsCPUAndABI(const llvm::opt::ArgList &Args,
const llvm::Triple &Triple, StringRef &CPUName,
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.cpp
index 541323127f9a8..7c7e1c70e5502 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.cpp
@@ -86,6 +86,18 @@ std::string ppc::getPPCTargetCPU(const ArgList &Args) {
return "";
}
+const char *ppc::getPPCAsmModeForCPU(StringRef Name) {
+ return llvm::StringSwitch<const char *>(Name)
+ .Case("pwr7", "-mpower7")
+ .Case("power7", "-mpower7")
+ .Case("pwr8", "-mpower8")
+ .Case("power8", "-mpower8")
+ .Case("ppc64le", "-mpower8")
+ .Case("pwr9", "-mpower9")
+ .Case("power9", "-mpower9")
+ .Default("-many");
+}
+
void ppc::getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args,
std::vector<StringRef> &Features) {
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.h
index 892eb2c341588..7d7c68101b7b6 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.h
@@ -32,6 +32,7 @@ enum class FloatABI {
FloatABI getPPCFloatABI(const Driver &D, const llvm::opt::ArgList &Args);
std::string getPPCTargetCPU(const llvm::opt::ArgList &Args);
+const char *getPPCAsmModeForCPU(StringRef Name);
void getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args,
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/X86.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/X86.cpp
index a85a7f1f63714..a18b2aa35b03a 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/X86.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/X86.cpp
@@ -101,8 +101,6 @@ const char *x86::getX86TargetCPU(const ArgList &Args,
return "i486";
case llvm::Triple::Haiku:
return "i586";
- case llvm::Triple::Bitrig:
- return "i686";
default:
// Fallback to p4.
return "pentium4";
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/BareMetal.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/BareMetal.cpp
index 28e4f5b0e5836..57a668650e6bc 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/BareMetal.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -184,10 +184,9 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_e, options::OPT_s, options::OPT_t,
options::OPT_Z_Flag, options::OPT_r});
+ if (TC.ShouldLinkCXXStdlib(Args))
+ TC.AddCXXStdlibLibArgs(Args, CmdArgs);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
- if (C.getDriver().CCCIsCXX())
- TC.AddCXXStdlibLibArgs(Args, CmdArgs);
-
CmdArgs.push_back("-lc");
CmdArgs.push_back("-lm");
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/BareMetal.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/BareMetal.h
index 5e9fd9bffdb9e..0bed63332cad0 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/BareMetal.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/BareMetal.h
@@ -37,7 +37,6 @@ public:
bool isPIEDefault() const override { return false; }
bool isPICDefaultForced() const override { return false; }
bool SupportsProfiling() const override { return false; }
- bool SupportsObjCGC() const override { return false; }
RuntimeLibType GetDefaultRuntimeLibType() const override {
return ToolChain::RLT_CompilerRT;
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Bitrig.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Bitrig.cpp
deleted file mode 100644
index d8f541dfbaf1b..0000000000000
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Bitrig.cpp
+++ /dev/null
@@ -1,190 +0,0 @@
-//===--- Bitrig.cpp - Bitrig ToolChain Implementations ----------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Bitrig.h"
-#include "CommonArgs.h"
-#include "clang/Driver/Compilation.h"
-#include "clang/Driver/Options.h"
-#include "llvm/Option/ArgList.h"
-
-using namespace clang::driver;
-using namespace clang::driver::toolchains;
-using namespace clang::driver::tools;
-using namespace clang;
-using namespace llvm::opt;
-
-void bitrig::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
- claimNoWarnArgs(Args);
- ArgStringList CmdArgs;
-
- Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
-
- CmdArgs.push_back("-o");
- CmdArgs.push_back(Output.getFilename());
-
- for (const auto &II : Inputs)
- CmdArgs.push_back(II.getFilename());
-
- const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
-}
-
-void bitrig::Linker::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
- const Driver &D = getToolChain().getDriver();
- ArgStringList CmdArgs;
-
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_shared)) {
- CmdArgs.push_back("-e");
- CmdArgs.push_back("__start");
- }
-
- if (Args.hasArg(options::OPT_static)) {
- CmdArgs.push_back("-Bstatic");
- } else {
- if (Args.hasArg(options::OPT_rdynamic))
- CmdArgs.push_back("-export-dynamic");
- CmdArgs.push_back("--eh-frame-hdr");
- CmdArgs.push_back("-Bdynamic");
- if (Args.hasArg(options::OPT_shared)) {
- CmdArgs.push_back("-shared");
- } else {
- CmdArgs.push_back("-dynamic-linker");
- CmdArgs.push_back("/usr/libexec/ld.so");
- }
- }
-
- if (Output.isFilename()) {
- CmdArgs.push_back("-o");
- CmdArgs.push_back(Output.getFilename());
- } else {
- assert(Output.isNothing() && "Invalid output.");
- }
-
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
- if (!Args.hasArg(options::OPT_shared)) {
- if (Args.hasArg(options::OPT_pg))
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("gcrt0.o")));
- else
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crt0.o")));
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
- } else {
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crtbeginS.o")));
- }
- }
-
- Args.AddAllArgs(CmdArgs,
- {options::OPT_L, options::OPT_T_Group, options::OPT_e});
-
- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
-
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
- if (D.CCCIsCXX()) {
- getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
- if (Args.hasArg(options::OPT_pg))
- CmdArgs.push_back("-lm_p");
- else
- CmdArgs.push_back("-lm");
- }
-
- if (Args.hasArg(options::OPT_pthread)) {
- if (!Args.hasArg(options::OPT_shared) && Args.hasArg(options::OPT_pg))
- CmdArgs.push_back("-lpthread_p");
- else
- CmdArgs.push_back("-lpthread");
- }
-
- if (!Args.hasArg(options::OPT_shared)) {
- if (Args.hasArg(options::OPT_pg))
- CmdArgs.push_back("-lc_p");
- else
- CmdArgs.push_back("-lc");
- }
-
- StringRef MyArch;
- switch (getToolChain().getArch()) {
- case llvm::Triple::arm:
- MyArch = "arm";
- break;
- case llvm::Triple::x86:
- MyArch = "i386";
- break;
- case llvm::Triple::x86_64:
- MyArch = "amd64";
- break;
- default:
- llvm_unreachable("Unsupported architecture");
- }
- CmdArgs.push_back(Args.MakeArgString("-lclang_rt." + MyArch));
- }
-
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
- if (!Args.hasArg(options::OPT_shared))
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
- else
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crtendS.o")));
- }
-
- const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
-}
-
-/// Bitrig - Bitrig tool chain which can call as(1) and ld(1) directly.
-
-Bitrig::Bitrig(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
- : Generic_ELF(D, Triple, Args) {
- getFilePaths().push_back(getDriver().Dir + "/../lib");
- getFilePaths().push_back("/usr/lib");
-}
-
-Tool *Bitrig::buildAssembler() const {
- return new tools::bitrig::Assembler(*this);
-}
-
-Tool *Bitrig::buildLinker() const { return new tools::bitrig::Linker(*this); }
-
-ToolChain::CXXStdlibType Bitrig::GetDefaultCXXStdlibType() const {
- return ToolChain::CST_Libcxx;
-}
-
-void Bitrig::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const {
- std::string Triple = getTriple().str();
- if (StringRef(Triple).startswith("amd64"))
- Triple = "x86_64" + Triple.substr(5);
- addLibStdCXXIncludePaths(getDriver().SysRoot, "/usr/include/c++/stdc++",
- Triple, "", "", "", DriverArgs, CC1Args);
-}
-
-void Bitrig::AddCXXStdlibLibArgs(const ArgList &Args,
- ArgStringList &CmdArgs) const {
- switch (GetCXXStdlibType(Args)) {
- case ToolChain::CST_Libcxx:
- CmdArgs.push_back("-lc++");
- CmdArgs.push_back("-lc++abi");
- CmdArgs.push_back("-lpthread");
- break;
- case ToolChain::CST_Libstdcxx:
- CmdArgs.push_back("-lstdc++");
- break;
- }
-}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Bitrig.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Bitrig.h
deleted file mode 100644
index 6edb2e8c7e8c7..0000000000000
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Bitrig.h
+++ /dev/null
@@ -1,79 +0,0 @@
-//===--- Bitrig.h - Bitrig ToolChain Implementations ------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_BITRIG_H
-#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_BITRIG_H
-
-#include "Gnu.h"
-#include "clang/Driver/Driver.h"
-#include "clang/Driver/ToolChain.h"
-
-namespace clang {
-namespace driver {
-namespace tools {
-/// bitrig -- Directly call GNU Binutils assembler and linker
-namespace bitrig {
-class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {
-public:
- Assembler(const ToolChain &TC)
- : GnuTool("bitrig::Assembler", "assembler", TC) {}
-
- bool hasIntegratedCPP() const override { return false; }
-
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
-};
-
-class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
-public:
- Linker(const ToolChain &TC) : GnuTool("bitrig::Linker", "linker", TC) {}
-
- bool hasIntegratedCPP() const override { return false; }
- bool isLinkJob() const override { return true; }
-
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
-};
-} // end namespace bitrig
-} // end namespace tools
-
-namespace toolchains {
-
-class LLVM_LIBRARY_VISIBILITY Bitrig : public Generic_ELF {
-public:
- Bitrig(const Driver &D, const llvm::Triple &Triple,
- const llvm::opt::ArgList &Args);
-
- bool IsMathErrnoDefault() const override { return false; }
- bool IsObjCNonFragileABIDefault() const override { return true; }
-
- CXXStdlibType GetDefaultCXXStdlibType() const override;
- void addLibStdCxxIncludePaths(
- const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const override;
- void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs) const override;
- unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const override {
- return 1;
- }
-
-protected:
- Tool *buildAssembler() const override;
- Tool *buildLinker() const override;
-};
-
-} // end namespace toolchains
-} // end namespace driver
-} // end namespace clang
-
-#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_BITRIG_H
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Clang.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Clang.cpp
index 497f0b493261a..0a89ff96d3c8e 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Clang.cpp
@@ -15,6 +15,7 @@
#include "Arch/Sparc.h"
#include "Arch/SystemZ.h"
#include "Arch/X86.h"
+#include "AMDGPU.h"
#include "CommonArgs.h"
#include "Hexagon.h"
#include "InputInfo.h"
@@ -273,19 +274,25 @@ static void ParseMRecip(const Driver &D, const ArgList &Args,
OutStrings.push_back(Args.MakeArgString(Out));
}
-static void getHexagonTargetFeatures(const ArgList &Args,
- std::vector<StringRef> &Features) {
- handleTargetFeaturesGroup(Args, Features,
- options::OPT_m_hexagon_Features_Group);
+/// The -mprefer-vector-width option accepts either a positive integer
+/// or the string "none".
+static void ParseMPreferVectorWidth(const Driver &D, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ Arg *A = Args.getLastArg(options::OPT_mprefer_vector_width_EQ);
+ if (!A)
+ return;
- bool UseLongCalls = false;
- if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,
- options::OPT_mno_long_calls)) {
- if (A->getOption().matches(options::OPT_mlong_calls))
- UseLongCalls = true;
+ StringRef Value = A->getValue();
+ if (Value == "none") {
+ CmdArgs.push_back("-mprefer-vector-width=none");
+ } else {
+ unsigned Width;
+ if (Value.getAsInteger(10, Width)) {
+ D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Value;
+ return;
+ }
+ CmdArgs.push_back(Args.MakeArgString("-mprefer-vector-width=" + Value));
}
-
- Features.push_back(UseLongCalls ? "+long-calls" : "-long-calls");
}
static void getWebAssemblyTargetFeatures(const ArgList &Args,
@@ -293,23 +300,6 @@ static void getWebAssemblyTargetFeatures(const ArgList &Args,
handleTargetFeaturesGroup(Args, Features, options::OPT_m_wasm_Features_Group);
}
-static void getAMDGPUTargetFeatures(const Driver &D, const ArgList &Args,
- std::vector<StringRef> &Features) {
- if (const Arg *dAbi = Args.getLastArg(options::OPT_mamdgpu_debugger_abi)) {
- StringRef value = dAbi->getValue();
- if (value == "1.0") {
- Features.push_back("+amdgpu-debugger-insert-nops");
- Features.push_back("+amdgpu-debugger-reserve-regs");
- Features.push_back("+amdgpu-debugger-emit-prologue");
- } else {
- D.Diag(diag::err_drv_clang_unsupported) << dAbi->getAsString(Args);
- }
- }
-
- handleTargetFeaturesGroup(
- Args, Features, options::OPT_m_amdgpu_Features_Group);
-}
-
static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple,
const ArgList &Args, ArgStringList &CmdArgs,
bool ForAS) {
@@ -349,7 +339,7 @@ static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple,
x86::getX86TargetFeatures(D, Triple, Args, Features);
break;
case llvm::Triple::hexagon:
- getHexagonTargetFeatures(Args, Features);
+ hexagon::getHexagonTargetFeatures(D, Args, Features);
break;
case llvm::Triple::wasm32:
case llvm::Triple::wasm64:
@@ -362,7 +352,7 @@ static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple,
break;
case llvm::Triple::r600:
case llvm::Triple::amdgcn:
- getAMDGPUTargetFeatures(D, Args, Features);
+ amdgpu::getAMDGPUTargetFeatures(D, Args, Features);
break;
}
@@ -1360,6 +1350,77 @@ void Clang::AddARMTargetArgs(const llvm::Triple &Triple, const ArgList &Args,
CmdArgs.push_back("-no-implicit-float");
}
+void Clang::RenderTargetOptions(const llvm::Triple &EffectiveTriple,
+ const ArgList &Args, bool KernelOrKext,
+ ArgStringList &CmdArgs) const {
+ const ToolChain &TC = getToolChain();
+
+ // Add the target features
+ getTargetFeatures(TC, EffectiveTriple, Args, CmdArgs, false);
+
+ // Add target specific flags.
+ switch (TC.getArch()) {
+ default:
+ break;
+
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ // Use the effective triple, which takes into account the deployment target.
+ AddARMTargetArgs(EffectiveTriple, Args, CmdArgs, KernelOrKext);
+ CmdArgs.push_back("-fallow-half-arguments-and-returns");
+ break;
+
+ case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_be:
+ AddAArch64TargetArgs(Args, CmdArgs);
+ CmdArgs.push_back("-fallow-half-arguments-and-returns");
+ break;
+
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ AddMIPSTargetArgs(Args, CmdArgs);
+ break;
+
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ case llvm::Triple::ppc64le:
+ AddPPCTargetArgs(Args, CmdArgs);
+ break;
+
+ case llvm::Triple::sparc:
+ case llvm::Triple::sparcel:
+ case llvm::Triple::sparcv9:
+ AddSparcTargetArgs(Args, CmdArgs);
+ break;
+
+ case llvm::Triple::systemz:
+ AddSystemZTargetArgs(Args, CmdArgs);
+ break;
+
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ AddX86TargetArgs(Args, CmdArgs);
+ break;
+
+ case llvm::Triple::lanai:
+ AddLanaiTargetArgs(Args, CmdArgs);
+ break;
+
+ case llvm::Triple::hexagon:
+ AddHexagonTargetArgs(Args, CmdArgs);
+ break;
+
+ case llvm::Triple::wasm32:
+ case llvm::Triple::wasm64:
+ AddWebAssemblyTargetArgs(Args, CmdArgs);
+ break;
+ }
+}
+
void Clang::AddAArch64TargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
@@ -1462,6 +1523,80 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args,
A->claim();
}
+ Arg *GPOpt = Args.getLastArg(options::OPT_mgpopt, options::OPT_mno_gpopt);
+ Arg *ABICalls =
+ Args.getLastArg(options::OPT_mabicalls, options::OPT_mno_abicalls);
+
+ // -mabicalls is the default for many MIPS environments, even with -fno-pic.
+ // -mgpopt is the default for static, -fno-pic environments but these two
+ // options conflict. We want to be certain that -mno-abicalls -mgpopt is
+ // the only case where -mllvm -mgpopt is passed.
+ // NOTE: We need a warning here or in the backend to warn when -mgpopt is
+ // passed explicitly when compiling something with -mabicalls
+ // (implictly) in affect. Currently the warning is in the backend.
+ //
+ // When the ABI in use is N64, we also need to determine the PIC mode that
+ // is in use, as -fno-pic for N64 implies -mno-abicalls.
+ bool NoABICalls =
+ ABICalls && ABICalls->getOption().matches(options::OPT_mno_abicalls);
+
+ llvm::Reloc::Model RelocationModel;
+ unsigned PICLevel;
+ bool IsPIE;
+ std::tie(RelocationModel, PICLevel, IsPIE) =
+ ParsePICArgs(getToolChain(), Args);
+
+ NoABICalls = NoABICalls ||
+ (RelocationModel == llvm::Reloc::Static && ABIName == "n64");
+
+ bool WantGPOpt = GPOpt && GPOpt->getOption().matches(options::OPT_mgpopt);
+ // We quietly ignore -mno-gpopt as the backend defaults to -mno-gpopt.
+ if (NoABICalls && (!GPOpt || WantGPOpt)) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-mgpopt");
+
+ Arg *LocalSData = Args.getLastArg(options::OPT_mlocal_sdata,
+ options::OPT_mno_local_sdata);
+ Arg *ExternSData = Args.getLastArg(options::OPT_mextern_sdata,
+ options::OPT_mno_extern_sdata);
+ Arg *EmbeddedData = Args.getLastArg(options::OPT_membedded_data,
+ options::OPT_mno_embedded_data);
+ if (LocalSData) {
+ CmdArgs.push_back("-mllvm");
+ if (LocalSData->getOption().matches(options::OPT_mlocal_sdata)) {
+ CmdArgs.push_back("-mlocal-sdata=1");
+ } else {
+ CmdArgs.push_back("-mlocal-sdata=0");
+ }
+ LocalSData->claim();
+ }
+
+ if (ExternSData) {
+ CmdArgs.push_back("-mllvm");
+ if (ExternSData->getOption().matches(options::OPT_mextern_sdata)) {
+ CmdArgs.push_back("-mextern-sdata=1");
+ } else {
+ CmdArgs.push_back("-mextern-sdata=0");
+ }
+ ExternSData->claim();
+ }
+
+ if (EmbeddedData) {
+ CmdArgs.push_back("-mllvm");
+ if (EmbeddedData->getOption().matches(options::OPT_membedded_data)) {
+ CmdArgs.push_back("-membedded-data=1");
+ } else {
+ CmdArgs.push_back("-membedded-data=0");
+ }
+ EmbeddedData->claim();
+ }
+
+ } else if ((!ABICalls || (!NoABICalls && ABICalls)) && WantGPOpt)
+ D.Diag(diag::warn_drv_unsupported_gpopt) << (ABICalls ? 0 : 1);
+
+ if (GPOpt)
+ GPOpt->claim();
+
if (Arg *A = Args.getLastArg(options::OPT_mcompact_branches_EQ)) {
StringRef Val = StringRef(A->getValue());
if (mips::hasCompactBranches(CPUName)) {
@@ -1755,7 +1890,7 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
// arg after parsing the '-I' arg.
bool TakeNextArg = false;
- bool UseRelaxRelocations = ENABLE_X86_RELAX_RELOCATIONS;
+ bool UseRelaxRelocations = C.getDefaultToolChain().useRelaxRelocations();
const char *MipsTargetFeature = nullptr;
for (const Arg *A :
Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {
@@ -1775,6 +1910,15 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
switch (C.getDefaultToolChain().getArch()) {
default:
break;
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ if (Value == "-mthumb")
+ // -mthumb has already been processed in ComputeLLVMTriple()
+ // recognize but skip over here.
+ continue;
+ break;
case llvm::Triple::mips:
case llvm::Triple::mipsel:
case llvm::Triple::mips64:
@@ -1894,9 +2038,987 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
}
}
+static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
+ bool OFastEnabled, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ // Handle various floating point optimization flags, mapping them to the
+ // appropriate LLVM code generation flags. This is complicated by several
+ // "umbrella" flags, so we do this by stepping through the flags incrementally
+ // adjusting what we think is enabled/disabled, then at the end settting the
+ // LLVM flags based on the final state.
+ bool HonorINFs = true;
+ bool HonorNaNs = true;
+ // -fmath-errno is the default on some platforms, e.g. BSD-derived OSes.
+ bool MathErrno = TC.IsMathErrnoDefault();
+ bool AssociativeMath = false;
+ bool ReciprocalMath = false;
+ bool SignedZeros = true;
+ bool TrappingMath = true;
+ StringRef DenormalFPMath = "";
+ StringRef FPContract = "";
+
+ for (const Arg *A : Args) {
+ switch (A->getOption().getID()) {
+ // If this isn't an FP option skip the claim below
+ default: continue;
+
+ // Options controlling individual features
+ case options::OPT_fhonor_infinities: HonorINFs = true; break;
+ case options::OPT_fno_honor_infinities: HonorINFs = false; break;
+ case options::OPT_fhonor_nans: HonorNaNs = true; break;
+ case options::OPT_fno_honor_nans: HonorNaNs = false; break;
+ case options::OPT_fmath_errno: MathErrno = true; break;
+ case options::OPT_fno_math_errno: MathErrno = false; break;
+ case options::OPT_fassociative_math: AssociativeMath = true; break;
+ case options::OPT_fno_associative_math: AssociativeMath = false; break;
+ case options::OPT_freciprocal_math: ReciprocalMath = true; break;
+ case options::OPT_fno_reciprocal_math: ReciprocalMath = false; break;
+ case options::OPT_fsigned_zeros: SignedZeros = true; break;
+ case options::OPT_fno_signed_zeros: SignedZeros = false; break;
+ case options::OPT_ftrapping_math: TrappingMath = true; break;
+ case options::OPT_fno_trapping_math: TrappingMath = false; break;
+
+ case options::OPT_fdenormal_fp_math_EQ:
+ DenormalFPMath = A->getValue();
+ break;
+
+ // Validate and pass through -fp-contract option.
+ case options::OPT_ffp_contract: {
+ StringRef Val = A->getValue();
+ if (Val == "fast" || Val == "on" || Val == "off")
+ FPContract = Val;
+ else
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Val;
+ break;
+ }
+
+ case options::OPT_ffinite_math_only:
+ HonorINFs = false;
+ HonorNaNs = false;
+ break;
+ case options::OPT_fno_finite_math_only:
+ HonorINFs = true;
+ HonorNaNs = true;
+ break;
+
+ case options::OPT_funsafe_math_optimizations:
+ AssociativeMath = true;
+ ReciprocalMath = true;
+ SignedZeros = false;
+ TrappingMath = false;
+ break;
+ case options::OPT_fno_unsafe_math_optimizations:
+ AssociativeMath = false;
+ ReciprocalMath = false;
+ SignedZeros = true;
+ TrappingMath = true;
+ // -fno_unsafe_math_optimizations restores default denormal handling
+ DenormalFPMath = "";
+ break;
+
+ case options::OPT_Ofast:
+ // If -Ofast is the optimization level, then -ffast-math should be enabled
+ if (!OFastEnabled)
+ continue;
+ LLVM_FALLTHROUGH;
+ case options::OPT_ffast_math:
+ HonorINFs = false;
+ HonorNaNs = false;
+ MathErrno = false;
+ AssociativeMath = true;
+ ReciprocalMath = true;
+ SignedZeros = false;
+ TrappingMath = false;
+ // If fast-math is set then set the fp-contract mode to fast.
+ FPContract = "fast";
+ break;
+ case options::OPT_fno_fast_math:
+ HonorINFs = true;
+ HonorNaNs = true;
+ // Turning on -ffast-math (with either flag) removes the need for
+ // MathErrno. However, turning *off* -ffast-math merely restores the
+ // toolchain default (which may be false).
+ MathErrno = TC.IsMathErrnoDefault();
+ AssociativeMath = false;
+ ReciprocalMath = false;
+ SignedZeros = true;
+ TrappingMath = true;
+ // -fno_fast_math restores default denormal and fpcontract handling
+ DenormalFPMath = "";
+ FPContract = "";
+ break;
+ }
+
+ // If we handled this option claim it
+ A->claim();
+ }
+
+ if (!HonorINFs)
+ CmdArgs.push_back("-menable-no-infs");
+
+ if (!HonorNaNs)
+ CmdArgs.push_back("-menable-no-nans");
+
+ if (MathErrno)
+ CmdArgs.push_back("-fmath-errno");
+
+ if (!MathErrno && AssociativeMath && ReciprocalMath && !SignedZeros &&
+ !TrappingMath)
+ CmdArgs.push_back("-menable-unsafe-fp-math");
+
+ if (!SignedZeros)
+ CmdArgs.push_back("-fno-signed-zeros");
+
+ if (AssociativeMath && !SignedZeros && !TrappingMath)
+ CmdArgs.push_back("-mreassociate");
+
+ if (ReciprocalMath)
+ CmdArgs.push_back("-freciprocal-math");
+
+ if (!TrappingMath)
+ CmdArgs.push_back("-fno-trapping-math");
+
+ if (!DenormalFPMath.empty())
+ CmdArgs.push_back(
+ Args.MakeArgString("-fdenormal-fp-math=" + DenormalFPMath));
+
+ if (!FPContract.empty())
+ CmdArgs.push_back(Args.MakeArgString("-ffp-contract=" + FPContract));
+
+ ParseMRecip(D, Args, CmdArgs);
+
+ // -ffast-math enables the __FAST_MATH__ preprocessor macro, but check for the
+ // individual features enabled by -ffast-math instead of the option itself as
+ // that's consistent with gcc's behaviour.
+ if (!HonorINFs && !HonorNaNs && !MathErrno && AssociativeMath &&
+ ReciprocalMath && !SignedZeros && !TrappingMath)
+ CmdArgs.push_back("-ffast-math");
+
+ // Handle __FINITE_MATH_ONLY__ similarly.
+ if (!HonorINFs && !HonorNaNs)
+ CmdArgs.push_back("-ffinite-math-only");
+
+ if (const Arg *A = Args.getLastArg(options::OPT_mfpmath_EQ)) {
+ CmdArgs.push_back("-mfpmath");
+ CmdArgs.push_back(A->getValue());
+ }
+}
+
+static void RenderAnalyzerOptions(const ArgList &Args, ArgStringList &CmdArgs,
+ const llvm::Triple &Triple,
+ const InputInfo &Input) {
+ // Enable region store model by default.
+ CmdArgs.push_back("-analyzer-store=region");
+
+ // Treat blocks as analysis entry points.
+ CmdArgs.push_back("-analyzer-opt-analyze-nested-blocks");
+
+ CmdArgs.push_back("-analyzer-eagerly-assume");
+
+ // Add default argument set.
+ if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) {
+ CmdArgs.push_back("-analyzer-checker=core");
+ CmdArgs.push_back("-analyzer-checker=apiModeling");
+
+ if (!Triple.isWindowsMSVCEnvironment()) {
+ CmdArgs.push_back("-analyzer-checker=unix");
+ } else {
+ // Enable "unix" checkers that also work on Windows.
+ CmdArgs.push_back("-analyzer-checker=unix.API");
+ CmdArgs.push_back("-analyzer-checker=unix.Malloc");
+ CmdArgs.push_back("-analyzer-checker=unix.MallocSizeof");
+ CmdArgs.push_back("-analyzer-checker=unix.MismatchedDeallocator");
+ CmdArgs.push_back("-analyzer-checker=unix.cstring.BadSizeArg");
+ CmdArgs.push_back("-analyzer-checker=unix.cstring.NullArg");
+ }
+
+ // Disable some unix checkers for PS4.
+ if (Triple.isPS4CPU()) {
+ CmdArgs.push_back("-analyzer-disable-checker=unix.API");
+ CmdArgs.push_back("-analyzer-disable-checker=unix.Vfork");
+ }
+
+ if (Triple.isOSDarwin())
+ CmdArgs.push_back("-analyzer-checker=osx");
+
+ CmdArgs.push_back("-analyzer-checker=deadcode");
+
+ if (types::isCXX(Input.getType()))
+ CmdArgs.push_back("-analyzer-checker=cplusplus");
+
+ if (!Triple.isPS4CPU()) {
+ CmdArgs.push_back("-analyzer-checker=security.insecureAPI.UncheckedReturn");
+ CmdArgs.push_back("-analyzer-checker=security.insecureAPI.getpw");
+ CmdArgs.push_back("-analyzer-checker=security.insecureAPI.gets");
+ CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mktemp");
+ CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mkstemp");
+ CmdArgs.push_back("-analyzer-checker=security.insecureAPI.vfork");
+ }
+
+ // Default nullability checks.
+ CmdArgs.push_back("-analyzer-checker=nullability.NullPassedToNonnull");
+ CmdArgs.push_back("-analyzer-checker=nullability.NullReturnedFromNonnull");
+ }
+
+ // Set the output format. The default is plist, for (lame) historical reasons.
+ CmdArgs.push_back("-analyzer-output");
+ if (Arg *A = Args.getLastArg(options::OPT__analyzer_output))
+ CmdArgs.push_back(A->getValue());
+ else
+ CmdArgs.push_back("plist");
+
+ // Disable the presentation of standard compiler warnings when using
+ // --analyze. We only want to show static analyzer diagnostics or frontend
+ // errors.
+ CmdArgs.push_back("-w");
+
+ // Add -Xanalyzer arguments when running as analyzer.
+ Args.AddAllArgValues(CmdArgs, options::OPT_Xanalyzer);
+}
+
+static void RenderSSPOptions(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs, bool KernelOrKext) {
+ const llvm::Triple &EffectiveTriple = TC.getEffectiveTriple();
+
+ // NVPTX doesn't support stack protectors; from the compiler's perspective, it
+ // doesn't even have a stack!
+ if (EffectiveTriple.isNVPTX())
+ return;
+
+ // -stack-protector=0 is default.
+ unsigned StackProtectorLevel = 0;
+ unsigned DefaultStackProtectorLevel =
+ TC.GetDefaultStackProtectorLevel(KernelOrKext);
+
+ if (Arg *A = Args.getLastArg(options::OPT_fno_stack_protector,
+ options::OPT_fstack_protector_all,
+ options::OPT_fstack_protector_strong,
+ options::OPT_fstack_protector)) {
+ if (A->getOption().matches(options::OPT_fstack_protector))
+ StackProtectorLevel =
+ std::max<unsigned>(LangOptions::SSPOn, DefaultStackProtectorLevel);
+ else if (A->getOption().matches(options::OPT_fstack_protector_strong))
+ StackProtectorLevel = LangOptions::SSPStrong;
+ else if (A->getOption().matches(options::OPT_fstack_protector_all))
+ StackProtectorLevel = LangOptions::SSPReq;
+ } else {
+ StackProtectorLevel = DefaultStackProtectorLevel;
+ }
+
+ if (StackProtectorLevel) {
+ CmdArgs.push_back("-stack-protector");
+ CmdArgs.push_back(Args.MakeArgString(Twine(StackProtectorLevel)));
+ }
+
+ // --param ssp-buffer-size=
+ for (const Arg *A : Args.filtered(options::OPT__param)) {
+ StringRef Str(A->getValue());
+ if (Str.startswith("ssp-buffer-size=")) {
+ if (StackProtectorLevel) {
+ CmdArgs.push_back("-stack-protector-buffer-size");
+ // FIXME: Verify the argument is a valid integer.
+ CmdArgs.push_back(Args.MakeArgString(Str.drop_front(16)));
+ }
+ A->claim();
+ }
+ }
+}
+
+static void RenderOpenCLOptions(const ArgList &Args, ArgStringList &CmdArgs) {
+ const unsigned ForwardedArguments[] = {
+ options::OPT_cl_opt_disable,
+ options::OPT_cl_strict_aliasing,
+ options::OPT_cl_single_precision_constant,
+ options::OPT_cl_finite_math_only,
+ options::OPT_cl_kernel_arg_info,
+ options::OPT_cl_unsafe_math_optimizations,
+ options::OPT_cl_fast_relaxed_math,
+ options::OPT_cl_mad_enable,
+ options::OPT_cl_no_signed_zeros,
+ options::OPT_cl_denorms_are_zero,
+ options::OPT_cl_fp32_correctly_rounded_divide_sqrt,
+ };
+
+ if (Arg *A = Args.getLastArg(options::OPT_cl_std_EQ)) {
+ std::string CLStdStr = std::string("-cl-std=") + A->getValue();
+ CmdArgs.push_back(Args.MakeArgString(CLStdStr));
+ }
+
+ for (const auto &Arg : ForwardedArguments)
+ if (const auto *A = Args.getLastArg(Arg))
+ CmdArgs.push_back(Args.MakeArgString(A->getOption().getPrefixedName()));
+}
+
+static void RenderARCMigrateToolOptions(const Driver &D, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ bool ARCMTEnabled = false;
+ if (!Args.hasArg(options::OPT_fno_objc_arc, options::OPT_fobjc_arc)) {
+ if (const Arg *A = Args.getLastArg(options::OPT_ccc_arcmt_check,
+ options::OPT_ccc_arcmt_modify,
+ options::OPT_ccc_arcmt_migrate)) {
+ ARCMTEnabled = true;
+ switch (A->getOption().getID()) {
+ default: llvm_unreachable("missed a case");
+ case options::OPT_ccc_arcmt_check:
+ CmdArgs.push_back("-arcmt-check");
+ break;
+ case options::OPT_ccc_arcmt_modify:
+ CmdArgs.push_back("-arcmt-modify");
+ break;
+ case options::OPT_ccc_arcmt_migrate:
+ CmdArgs.push_back("-arcmt-migrate");
+ CmdArgs.push_back("-mt-migrate-directory");
+ CmdArgs.push_back(A->getValue());
+
+ Args.AddLastArg(CmdArgs, options::OPT_arcmt_migrate_report_output);
+ Args.AddLastArg(CmdArgs, options::OPT_arcmt_migrate_emit_arc_errors);
+ break;
+ }
+ }
+ } else {
+ Args.ClaimAllArgs(options::OPT_ccc_arcmt_check);
+ Args.ClaimAllArgs(options::OPT_ccc_arcmt_modify);
+ Args.ClaimAllArgs(options::OPT_ccc_arcmt_migrate);
+ }
+
+ if (const Arg *A = Args.getLastArg(options::OPT_ccc_objcmt_migrate)) {
+ if (ARCMTEnabled)
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << A->getAsString(Args) << "-ccc-arcmt-migrate";
+
+ CmdArgs.push_back("-mt-migrate-directory");
+ CmdArgs.push_back(A->getValue());
+
+ if (!Args.hasArg(options::OPT_objcmt_migrate_literals,
+ options::OPT_objcmt_migrate_subscripting,
+ options::OPT_objcmt_migrate_property)) {
+ // None specified, means enable them all.
+ CmdArgs.push_back("-objcmt-migrate-literals");
+ CmdArgs.push_back("-objcmt-migrate-subscripting");
+ CmdArgs.push_back("-objcmt-migrate-property");
+ } else {
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_literals);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_subscripting);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property);
+ }
+ } else {
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_literals);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_subscripting);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_all);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_readonly_property);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_readwrite_property);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property_dot_syntax);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_annotation);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_instancetype);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_nsmacros);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_protocol_conformance);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_atomic_property);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_returns_innerpointer_property);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_ns_nonatomic_iosonly);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_designated_init);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_whitelist_dir_path);
+ }
+}
+
+static void RenderBuiltinOptions(const ToolChain &TC, const llvm::Triple &T,
+ const ArgList &Args, ArgStringList &CmdArgs) {
+ // -fbuiltin is default unless -mkernel is used.
+ bool UseBuiltins =
+ Args.hasFlag(options::OPT_fbuiltin, options::OPT_fno_builtin,
+ !Args.hasArg(options::OPT_mkernel));
+ if (!UseBuiltins)
+ CmdArgs.push_back("-fno-builtin");
+
+ // -ffreestanding implies -fno-builtin.
+ if (Args.hasArg(options::OPT_ffreestanding))
+ UseBuiltins = false;
+
+ // Process the -fno-builtin-* options.
+ for (const auto &Arg : Args) {
+ const Option &O = Arg->getOption();
+ if (!O.matches(options::OPT_fno_builtin_))
+ continue;
+
+ Arg->claim();
+
+ // If -fno-builtin is specified, then there's no need to pass the option to
+ // the frontend.
+ if (!UseBuiltins)
+ continue;
+
+ StringRef FuncName = Arg->getValue();
+ CmdArgs.push_back(Args.MakeArgString("-fno-builtin-" + FuncName));
+ }
+
+ // le32-specific flags:
+ // -fno-math-builtin: clang should not convert math builtins to intrinsics
+ // by default.
+ if (TC.getArch() == llvm::Triple::le32)
+ CmdArgs.push_back("-fno-math-builtin");
+}
+
+static void RenderModulesOptions(Compilation &C, const Driver &D,
+ const ArgList &Args, const InputInfo &Input,
+ const InputInfo &Output,
+ ArgStringList &CmdArgs, bool &HaveModules) {
+ // -fmodules enables the use of precompiled modules (off by default).
+ // Users can pass -fno-cxx-modules to turn off modules support for
+ // C++/Objective-C++ programs.
+ bool HaveClangModules = false;
+ if (Args.hasFlag(options::OPT_fmodules, options::OPT_fno_modules, false)) {
+ bool AllowedInCXX = Args.hasFlag(options::OPT_fcxx_modules,
+ options::OPT_fno_cxx_modules, true);
+ if (AllowedInCXX || !types::isCXX(Input.getType())) {
+ CmdArgs.push_back("-fmodules");
+ HaveClangModules = true;
+ }
+ }
+
+ HaveModules = HaveClangModules;
+ if (Args.hasArg(options::OPT_fmodules_ts)) {
+ CmdArgs.push_back("-fmodules-ts");
+ HaveModules = true;
+ }
+
+ // -fmodule-maps enables implicit reading of module map files. By default,
+ // this is enabled if we are using Clang's flavor of precompiled modules.
+ if (Args.hasFlag(options::OPT_fimplicit_module_maps,
+ options::OPT_fno_implicit_module_maps, HaveClangModules))
+ CmdArgs.push_back("-fimplicit-module-maps");
+
+ // -fmodules-decluse checks that modules used are declared so (off by default)
+ if (Args.hasFlag(options::OPT_fmodules_decluse,
+ options::OPT_fno_modules_decluse, false))
+ CmdArgs.push_back("-fmodules-decluse");
+
+ // -fmodules-strict-decluse is like -fmodule-decluse, but also checks that
+ // all #included headers are part of modules.
+ if (Args.hasFlag(options::OPT_fmodules_strict_decluse,
+ options::OPT_fno_modules_strict_decluse, false))
+ CmdArgs.push_back("-fmodules-strict-decluse");
+
+ // -fno-implicit-modules turns off implicitly compiling modules on demand.
+ if (!Args.hasFlag(options::OPT_fimplicit_modules,
+ options::OPT_fno_implicit_modules, HaveClangModules)) {
+ if (HaveModules)
+ CmdArgs.push_back("-fno-implicit-modules");
+ } else if (HaveModules) {
+ // -fmodule-cache-path specifies where our implicitly-built module files
+ // should be written.
+ SmallString<128> Path;
+ if (Arg *A = Args.getLastArg(options::OPT_fmodules_cache_path))
+ Path = A->getValue();
+
+ if (C.isForDiagnostics()) {
+ // When generating crash reports, we want to emit the modules along with
+ // the reproduction sources, so we ignore any provided module path.
+ Path = Output.getFilename();
+ llvm::sys::path::replace_extension(Path, ".cache");
+ llvm::sys::path::append(Path, "modules");
+ } else if (Path.empty()) {
+ // No module path was provided: use the default.
+ llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/false, Path);
+ llvm::sys::path::append(Path, "org.llvm.clang.");
+ appendUserToPath(Path);
+ llvm::sys::path::append(Path, "ModuleCache");
+ }
+
+ const char Arg[] = "-fmodules-cache-path=";
+ Path.insert(Path.begin(), Arg, Arg + strlen(Arg));
+ CmdArgs.push_back(Args.MakeArgString(Path));
+ }
+
+ if (HaveModules) {
+ // -fprebuilt-module-path specifies where to load the prebuilt module files.
+ for (const Arg *A : Args.filtered(options::OPT_fprebuilt_module_path)) {
+ CmdArgs.push_back(Args.MakeArgString(
+ std::string("-fprebuilt-module-path=") + A->getValue()));
+ A->claim();
+ }
+ }
+
+ // -fmodule-name specifies the module that is currently being built (or
+ // used for header checking by -fmodule-maps).
+ Args.AddLastArg(CmdArgs, options::OPT_fmodule_name_EQ);
+
+ // -fmodule-map-file can be used to specify files containing module
+ // definitions.
+ Args.AddAllArgs(CmdArgs, options::OPT_fmodule_map_file);
+
+ // -fbuiltin-module-map can be used to load the clang
+ // builtin headers modulemap file.
+ if (Args.hasArg(options::OPT_fbuiltin_module_map)) {
+ SmallString<128> BuiltinModuleMap(D.ResourceDir);
+ llvm::sys::path::append(BuiltinModuleMap, "include");
+ llvm::sys::path::append(BuiltinModuleMap, "module.modulemap");
+ if (llvm::sys::fs::exists(BuiltinModuleMap))
+ CmdArgs.push_back(
+ Args.MakeArgString("-fmodule-map-file=" + BuiltinModuleMap));
+ }
+
+ // The -fmodule-file=<name>=<file> form specifies the mapping of module
+ // names to precompiled module files (the module is loaded only if used).
+ // The -fmodule-file=<file> form can be used to unconditionally load
+ // precompiled module files (whether used or not).
+ if (HaveModules)
+ Args.AddAllArgs(CmdArgs, options::OPT_fmodule_file);
+ else
+ Args.ClaimAllArgs(options::OPT_fmodule_file);
+
+ // When building modules and generating crashdumps, we need to dump a module
+ // dependency VFS alongside the output.
+ if (HaveClangModules && C.isForDiagnostics()) {
+ SmallString<128> VFSDir(Output.getFilename());
+ llvm::sys::path::replace_extension(VFSDir, ".cache");
+ // Add the cache directory as a temp so the crash diagnostics pick it up.
+ C.addTempFile(Args.MakeArgString(VFSDir));
+
+ llvm::sys::path::append(VFSDir, "vfs");
+ CmdArgs.push_back("-module-dependency-dir");
+ CmdArgs.push_back(Args.MakeArgString(VFSDir));
+ }
+
+ if (HaveClangModules)
+ Args.AddLastArg(CmdArgs, options::OPT_fmodules_user_build_path);
+
+ // Pass through all -fmodules-ignore-macro arguments.
+ Args.AddAllArgs(CmdArgs, options::OPT_fmodules_ignore_macro);
+ Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_interval);
+ Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_after);
+
+ Args.AddLastArg(CmdArgs, options::OPT_fbuild_session_timestamp);
+
+ if (Arg *A = Args.getLastArg(options::OPT_fbuild_session_file)) {
+ if (Args.hasArg(options::OPT_fbuild_session_timestamp))
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << A->getAsString(Args) << "-fbuild-session-timestamp";
+
+ llvm::sys::fs::file_status Status;
+ if (llvm::sys::fs::status(A->getValue(), Status))
+ D.Diag(diag::err_drv_no_such_file) << A->getValue();
+ CmdArgs.push_back(
+ Args.MakeArgString("-fbuild-session-timestamp=" +
+ Twine((uint64_t)Status.getLastModificationTime()
+ .time_since_epoch()
+ .count())));
+ }
+
+ if (Args.getLastArg(options::OPT_fmodules_validate_once_per_build_session)) {
+ if (!Args.getLastArg(options::OPT_fbuild_session_timestamp,
+ options::OPT_fbuild_session_file))
+ D.Diag(diag::err_drv_modules_validate_once_requires_timestamp);
+
+ Args.AddLastArg(CmdArgs,
+ options::OPT_fmodules_validate_once_per_build_session);
+ }
+
+ Args.AddLastArg(CmdArgs, options::OPT_fmodules_validate_system_headers);
+ Args.AddLastArg(CmdArgs, options::OPT_fmodules_disable_diagnostic_validation);
+}
+
+static void RenderCharacterOptions(const ArgList &Args, const llvm::Triple &T,
+ ArgStringList &CmdArgs) {
+ // -fsigned-char is default.
+ if (const Arg *A = Args.getLastArg(options::OPT_fsigned_char,
+ options::OPT_fno_signed_char,
+ options::OPT_funsigned_char,
+ options::OPT_fno_unsigned_char)) {
+ if (A->getOption().matches(options::OPT_funsigned_char) ||
+ A->getOption().matches(options::OPT_fno_signed_char)) {
+ CmdArgs.push_back("-fno-signed-char");
+ }
+ } else if (!isSignedCharDefault(T)) {
+ CmdArgs.push_back("-fno-signed-char");
+ }
+
+ if (const Arg *A = Args.getLastArg(options::OPT_fshort_wchar,
+ options::OPT_fno_short_wchar)) {
+ if (A->getOption().matches(options::OPT_fshort_wchar)) {
+ CmdArgs.push_back("-fwchar-type=short");
+ CmdArgs.push_back("-fno-signed-wchar");
+ } else {
+ bool IsARM = T.isARM() || T.isThumb() || T.isAArch64();
+ CmdArgs.push_back("-fwchar-type=int");
+ if (IsARM && !(T.isOSWindows() || T.getOS() == llvm::Triple::NetBSD ||
+ T.getOS() == llvm::Triple::OpenBSD))
+ CmdArgs.push_back("-fno-signed-wchar");
+ else
+ CmdArgs.push_back("-fsigned-wchar");
+ }
+ }
+}
+
+static void RenderObjCOptions(const ToolChain &TC, const Driver &D,
+ const llvm::Triple &T, const ArgList &Args,
+ ObjCRuntime &Runtime, bool InferCovariantReturns,
+ const InputInfo &Input, ArgStringList &CmdArgs) {
+ const llvm::Triple::ArchType Arch = TC.getArch();
+
+ // -fobjc-dispatch-method is only relevant with the nonfragile-abi, and legacy
+ // is the default. Except for deployment target of 10.5, next runtime is
+ // always legacy dispatch and -fno-objc-legacy-dispatch gets ignored silently.
+ if (Runtime.isNonFragile()) {
+ if (!Args.hasFlag(options::OPT_fobjc_legacy_dispatch,
+ options::OPT_fno_objc_legacy_dispatch,
+ Runtime.isLegacyDispatchDefaultForArch(Arch))) {
+ if (TC.UseObjCMixedDispatch())
+ CmdArgs.push_back("-fobjc-dispatch-method=mixed");
+ else
+ CmdArgs.push_back("-fobjc-dispatch-method=non-legacy");
+ }
+ }
+
+ // When ObjectiveC legacy runtime is in effect on MacOSX, turn on the option
+ // to do Array/Dictionary subscripting by default.
+ if (Arch == llvm::Triple::x86 && T.isMacOSX() &&
+ !T.isMacOSXVersionLT(10, 7) &&
+ Runtime.getKind() == ObjCRuntime::FragileMacOSX && Runtime.isNeXTFamily())
+ CmdArgs.push_back("-fobjc-subscripting-legacy-runtime");
+
+ // Allow -fno-objc-arr to trump -fobjc-arr/-fobjc-arc.
+ // NOTE: This logic is duplicated in ToolChains.cpp.
+ if (isObjCAutoRefCount(Args)) {
+ TC.CheckObjCARC();
+
+ CmdArgs.push_back("-fobjc-arc");
+
+ // FIXME: It seems like this entire block, and several around it should be
+ // wrapped in isObjC, but for now we just use it here as this is where it
+ // was being used previously.
+ if (types::isCXX(Input.getType()) && types::isObjC(Input.getType())) {
+ if (TC.GetCXXStdlibType(Args) == ToolChain::CST_Libcxx)
+ CmdArgs.push_back("-fobjc-arc-cxxlib=libc++");
+ else
+ CmdArgs.push_back("-fobjc-arc-cxxlib=libstdc++");
+ }
+
+ // Allow the user to enable full exceptions code emission.
+ // We default off for Objective-C, on for Objective-C++.
+ if (Args.hasFlag(options::OPT_fobjc_arc_exceptions,
+ options::OPT_fno_objc_arc_exceptions,
+ /*default=*/types::isCXX(Input.getType())))
+ CmdArgs.push_back("-fobjc-arc-exceptions");
+ }
+
+ // Silence warning for full exception code emission options when explicitly
+ // set to use no ARC.
+ if (Args.hasArg(options::OPT_fno_objc_arc)) {
+ Args.ClaimAllArgs(options::OPT_fobjc_arc_exceptions);
+ Args.ClaimAllArgs(options::OPT_fno_objc_arc_exceptions);
+ }
+
+ // -fobjc-infer-related-result-type is the default, except in the Objective-C
+ // rewriter.
+ if (InferCovariantReturns)
+ CmdArgs.push_back("-fno-objc-infer-related-result-type");
+
+ // Pass down -fobjc-weak or -fno-objc-weak if present.
+ if (types::isObjC(Input.getType())) {
+ auto WeakArg =
+ Args.getLastArg(options::OPT_fobjc_weak, options::OPT_fno_objc_weak);
+ if (!WeakArg) {
+ // nothing to do
+ } else if (!Runtime.allowsWeak()) {
+ if (WeakArg->getOption().matches(options::OPT_fobjc_weak))
+ D.Diag(diag::err_objc_weak_unsupported);
+ } else {
+ WeakArg->render(Args, CmdArgs);
+ }
+ }
+}
+
+static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ bool CaretDefault = true;
+ bool ColumnDefault = true;
+
+ if (const Arg *A = Args.getLastArg(options::OPT__SLASH_diagnostics_classic,
+ options::OPT__SLASH_diagnostics_column,
+ options::OPT__SLASH_diagnostics_caret)) {
+ switch (A->getOption().getID()) {
+ case options::OPT__SLASH_diagnostics_caret:
+ CaretDefault = true;
+ ColumnDefault = true;
+ break;
+ case options::OPT__SLASH_diagnostics_column:
+ CaretDefault = false;
+ ColumnDefault = true;
+ break;
+ case options::OPT__SLASH_diagnostics_classic:
+ CaretDefault = false;
+ ColumnDefault = false;
+ break;
+ }
+ }
+
+ // -fcaret-diagnostics is default.
+ if (!Args.hasFlag(options::OPT_fcaret_diagnostics,
+ options::OPT_fno_caret_diagnostics, CaretDefault))
+ CmdArgs.push_back("-fno-caret-diagnostics");
+
+ // -fdiagnostics-fixit-info is default, only pass non-default.
+ if (!Args.hasFlag(options::OPT_fdiagnostics_fixit_info,
+ options::OPT_fno_diagnostics_fixit_info))
+ CmdArgs.push_back("-fno-diagnostics-fixit-info");
+
+ // Enable -fdiagnostics-show-option by default.
+ if (Args.hasFlag(options::OPT_fdiagnostics_show_option,
+ options::OPT_fno_diagnostics_show_option))
+ CmdArgs.push_back("-fdiagnostics-show-option");
+
+ if (const Arg *A =
+ Args.getLastArg(options::OPT_fdiagnostics_show_category_EQ)) {
+ CmdArgs.push_back("-fdiagnostics-show-category");
+ CmdArgs.push_back(A->getValue());
+ }
+
+ if (Args.hasFlag(options::OPT_fdiagnostics_show_hotness,
+ options::OPT_fno_diagnostics_show_hotness, false))
+ CmdArgs.push_back("-fdiagnostics-show-hotness");
+
+ if (const Arg *A =
+ Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) {
+ std::string Opt =
+ std::string("-fdiagnostics-hotness-threshold=") + A->getValue();
+ CmdArgs.push_back(Args.MakeArgString(Opt));
+ }
+
+ if (const Arg *A = Args.getLastArg(options::OPT_fdiagnostics_format_EQ)) {
+ CmdArgs.push_back("-fdiagnostics-format");
+ CmdArgs.push_back(A->getValue());
+ }
+
+ if (const Arg *A = Args.getLastArg(
+ options::OPT_fdiagnostics_show_note_include_stack,
+ options::OPT_fno_diagnostics_show_note_include_stack)) {
+ const Option &O = A->getOption();
+ if (O.matches(options::OPT_fdiagnostics_show_note_include_stack))
+ CmdArgs.push_back("-fdiagnostics-show-note-include-stack");
+ else
+ CmdArgs.push_back("-fno-diagnostics-show-note-include-stack");
+ }
+
+ // Color diagnostics are parsed by the driver directly from argv and later
+ // re-parsed to construct this job; claim any possible color diagnostic here
+ // to avoid warn_drv_unused_argument and diagnose bad
+ // OPT_fdiagnostics_color_EQ values.
+ for (const Arg *A : Args) {
+ const Option &O = A->getOption();
+ if (!O.matches(options::OPT_fcolor_diagnostics) &&
+ !O.matches(options::OPT_fdiagnostics_color) &&
+ !O.matches(options::OPT_fno_color_diagnostics) &&
+ !O.matches(options::OPT_fno_diagnostics_color) &&
+ !O.matches(options::OPT_fdiagnostics_color_EQ))
+ continue;
+
+ if (O.matches(options::OPT_fdiagnostics_color_EQ)) {
+ StringRef Value(A->getValue());
+ if (Value != "always" && Value != "never" && Value != "auto")
+ D.Diag(diag::err_drv_clang_unsupported)
+ << ("-fdiagnostics-color=" + Value).str();
+ }
+ A->claim();
+ }
+
+ if (D.getDiags().getDiagnosticOptions().ShowColors)
+ CmdArgs.push_back("-fcolor-diagnostics");
+
+ if (Args.hasArg(options::OPT_fansi_escape_codes))
+ CmdArgs.push_back("-fansi-escape-codes");
+
+ if (!Args.hasFlag(options::OPT_fshow_source_location,
+ options::OPT_fno_show_source_location))
+ CmdArgs.push_back("-fno-show-source-location");
+
+ if (Args.hasArg(options::OPT_fdiagnostics_absolute_paths))
+ CmdArgs.push_back("-fdiagnostics-absolute-paths");
+
+ if (!Args.hasFlag(options::OPT_fshow_column, options::OPT_fno_show_column,
+ ColumnDefault))
+ CmdArgs.push_back("-fno-show-column");
+
+ if (!Args.hasFlag(options::OPT_fspell_checking,
+ options::OPT_fno_spell_checking))
+ CmdArgs.push_back("-fno-spell-checking");
+}
+
+static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
+ const llvm::Triple &T, const ArgList &Args,
+ bool EmitCodeView, bool IsWindowsMSVC,
+ ArgStringList &CmdArgs,
+ codegenoptions::DebugInfoKind &DebugInfoKind,
+ const Arg *&SplitDWARFArg) {
+ if (Args.hasFlag(options::OPT_fdebug_info_for_profiling,
+ options::OPT_fno_debug_info_for_profiling, false))
+ CmdArgs.push_back("-fdebug-info-for-profiling");
+
+ // The 'g' groups options involve a somewhat intricate sequence of decisions
+ // about what to pass from the driver to the frontend, but by the time they
+ // reach cc1 they've been factored into three well-defined orthogonal choices:
+ // * what level of debug info to generate
+ // * what dwarf version to write
+ // * what debugger tuning to use
+ // This avoids having to monkey around further in cc1 other than to disable
+ // codeview if not running in a Windows environment. Perhaps even that
+ // decision should be made in the driver as well though.
+ unsigned DWARFVersion = 0;
+ llvm::DebuggerKind DebuggerTuning = TC.getDefaultDebuggerTuning();
+
+ bool SplitDWARFInlining =
+ Args.hasFlag(options::OPT_fsplit_dwarf_inlining,
+ options::OPT_fno_split_dwarf_inlining, true);
+
+ Args.ClaimAllArgs(options::OPT_g_Group);
+
+ SplitDWARFArg = Args.getLastArg(options::OPT_gsplit_dwarf);
+
+ if (const Arg *A = Args.getLastArg(options::OPT_g_Group)) {
+ // If the last option explicitly specified a debug-info level, use it.
+ if (A->getOption().matches(options::OPT_gN_Group)) {
+ DebugInfoKind = DebugLevelToInfoKind(*A);
+ // If you say "-gsplit-dwarf -gline-tables-only", -gsplit-dwarf loses.
+ // But -gsplit-dwarf is not a g_group option, hence we have to check the
+ // order explicitly. If -gsplit-dwarf wins, we fix DebugInfoKind later.
+ // This gets a bit more complicated if you've disabled inline info in the
+ // skeleton CUs (SplitDWARFInlining) - then there's value in composing
+ // split-dwarf and line-tables-only, so let those compose naturally in
+ // that case.
+ // And if you just turned off debug info, (-gsplit-dwarf -g0) - do that.
+ if (SplitDWARFArg) {
+ if (A->getIndex() > SplitDWARFArg->getIndex()) {
+ if (DebugInfoKind == codegenoptions::NoDebugInfo ||
+ (DebugInfoKind == codegenoptions::DebugLineTablesOnly &&
+ SplitDWARFInlining))
+ SplitDWARFArg = nullptr;
+ } else if (SplitDWARFInlining)
+ DebugInfoKind = codegenoptions::NoDebugInfo;
+ }
+ } else {
+ // For any other 'g' option, use Limited.
+ DebugInfoKind = codegenoptions::LimitedDebugInfo;
+ }
+ }
+
+ // If a debugger tuning argument appeared, remember it.
+ if (const Arg *A =
+ Args.getLastArg(options::OPT_gTune_Group, options::OPT_ggdbN_Group)) {
+ if (A->getOption().matches(options::OPT_glldb))
+ DebuggerTuning = llvm::DebuggerKind::LLDB;
+ else if (A->getOption().matches(options::OPT_gsce))
+ DebuggerTuning = llvm::DebuggerKind::SCE;
+ else
+ DebuggerTuning = llvm::DebuggerKind::GDB;
+ }
+
+ // If a -gdwarf argument appeared, remember it.
+ if (const Arg *A =
+ Args.getLastArg(options::OPT_gdwarf_2, options::OPT_gdwarf_3,
+ options::OPT_gdwarf_4, options::OPT_gdwarf_5))
+ DWARFVersion = DwarfVersionNum(A->getSpelling());
+
+ // Forward -gcodeview. EmitCodeView might have been set by CL-compatibility
+ // argument parsing.
+ if (Args.hasArg(options::OPT_gcodeview) || EmitCodeView) {
+ // DWARFVersion remains at 0 if no explicit choice was made.
+ CmdArgs.push_back("-gcodeview");
+ } else if (DWARFVersion == 0 &&
+ DebugInfoKind != codegenoptions::NoDebugInfo) {
+ DWARFVersion = TC.GetDefaultDwarfVersion();
+ }
+
+ // We ignore flag -gstrict-dwarf for now.
+ // And we handle flag -grecord-gcc-switches later with DWARFDebugFlags.
+ Args.ClaimAllArgs(options::OPT_g_flags_Group);
+
+ // Column info is included by default for everything except SCE and CodeView.
+ // Clang doesn't track end columns, just starting columns, which, in theory,
+ // is fine for CodeView (and PDB). In practice, however, the Microsoft
+ // debuggers don't handle missing end columns well, so it's better not to
+ // include any column info.
+ if (Args.hasFlag(options::OPT_gcolumn_info, options::OPT_gno_column_info,
+ /*Default=*/!(IsWindowsMSVC && EmitCodeView) &&
+ DebuggerTuning != llvm::DebuggerKind::SCE))
+ CmdArgs.push_back("-dwarf-column-info");
+
+ // FIXME: Move backend command line options to the module.
+ // If -gline-tables-only is the last option it wins.
+ if (DebugInfoKind != codegenoptions::DebugLineTablesOnly &&
+ Args.hasArg(options::OPT_gmodules)) {
+ DebugInfoKind = codegenoptions::LimitedDebugInfo;
+ CmdArgs.push_back("-dwarf-ext-refs");
+ CmdArgs.push_back("-fmodule-format=obj");
+ }
+
+ // -gsplit-dwarf should turn on -g and enable the backend dwarf
+ // splitting and extraction.
+ // FIXME: Currently only works on Linux.
+ if (T.isOSLinux()) {
+ if (!SplitDWARFInlining)
+ CmdArgs.push_back("-fno-split-dwarf-inlining");
+
+ if (SplitDWARFArg) {
+ if (DebugInfoKind == codegenoptions::NoDebugInfo)
+ DebugInfoKind = codegenoptions::LimitedDebugInfo;
+ CmdArgs.push_back("-enable-split-dwarf");
+ }
+ }
+
+ // After we've dealt with all combinations of things that could
+ // make DebugInfoKind be other than None or DebugLineTablesOnly,
+ // figure out if we need to "upgrade" it to standalone debug info.
+ // We parse these two '-f' options whether or not they will be used,
+ // to claim them even if you wrote "-fstandalone-debug -gline-tables-only"
+ bool NeedFullDebug = Args.hasFlag(options::OPT_fstandalone_debug,
+ options::OPT_fno_standalone_debug,
+ TC.GetDefaultStandaloneDebug());
+ if (DebugInfoKind == codegenoptions::LimitedDebugInfo && NeedFullDebug)
+ DebugInfoKind = codegenoptions::FullDebugInfo;
+
+ RenderDebugEnablingArgs(Args, CmdArgs, DebugInfoKind, DWARFVersion,
+ DebuggerTuning);
+
+ // -fdebug-macro turns on macro debug info generation.
+ if (Args.hasFlag(options::OPT_fdebug_macro, options::OPT_fno_debug_macro,
+ false))
+ CmdArgs.push_back("-debug-info-macro");
+
+ // -ggnu-pubnames turns on gnu style pubnames in the backend.
+ if (Args.hasArg(options::OPT_ggnu_pubnames))
+ CmdArgs.push_back("-ggnu-pubnames");
+
+ // -gdwarf-aranges turns on the emission of the aranges section in the
+ // backend.
+ // Always enabled for SCE tuning.
+ if (Args.hasArg(options::OPT_gdwarf_aranges) ||
+ DebuggerTuning == llvm::DebuggerKind::SCE) {
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-generate-arange-section");
+ }
+
+ if (Args.hasFlag(options::OPT_fdebug_types_section,
+ options::OPT_fno_debug_types_section, false)) {
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-generate-type-units");
+ }
+
+ // Decide how to render forward declarations of template instantiations.
+ // SCE wants full descriptions, others just get them in the name.
+ if (DebuggerTuning == llvm::DebuggerKind::SCE)
+ CmdArgs.push_back("-debug-forward-template-params");
+
+ // Do we need to explicitly import anonymous namespaces into the parent scope?
+ if (DebuggerTuning == llvm::DebuggerKind::SCE)
+ CmdArgs.push_back("-dwarf-explicit-import");
+
+ RenderDebugInfoCompressionArgs(Args, CmdArgs, D);
+}
+
void Clang::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const ArgList &Args, const char *LinkingOutput) const {
+ const llvm::Triple &RawTriple = getToolChain().getTriple();
const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
const std::string &TripleStr = Triple.getTriple();
@@ -1918,18 +3040,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Inputs.size() == 1) &&
"Unable to handle multiple inputs.");
- bool IsWindowsGNU = getToolChain().getTriple().isWindowsGNUEnvironment();
- bool IsWindowsCygnus =
- getToolChain().getTriple().isWindowsCygwinEnvironment();
- bool IsWindowsMSVC = getToolChain().getTriple().isWindowsMSVCEnvironment();
- bool IsPS4CPU = getToolChain().getTriple().isPS4CPU();
- bool IsIAMCU = getToolChain().getTriple().isOSIAMCU();
+ const llvm::Triple *AuxTriple =
+ IsCuda ? getToolChain().getAuxTriple() : nullptr;
+
+ bool IsWindowsGNU = RawTriple.isWindowsGNUEnvironment();
+ bool IsWindowsCygnus = RawTriple.isWindowsCygwinEnvironment();
+ bool IsWindowsMSVC = RawTriple.isWindowsMSVCEnvironment();
+ bool IsIAMCU = RawTriple.isOSIAMCU();
// Adjust IsWindowsXYZ for CUDA compilations. Even when compiling in device
// mode (i.e., getToolchain().getTriple() is NVPTX, not Windows), we need to
// pass Windows-specific flags to cc1.
if (IsCuda) {
- const llvm::Triple *AuxTriple = getToolChain().getAuxTriple();
IsWindowsMSVC |= AuxTriple && AuxTriple->isWindowsMSVCEnvironment();
IsWindowsGNU |= AuxTriple && AuxTriple->isWindowsGNUEnvironment();
IsWindowsCygnus |= AuxTriple && AuxTriple->isWindowsCygwinEnvironment();
@@ -2073,8 +3195,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// The Darwin and PS4 linkers currently use the legacy LTO API, which
// does not support LTO unit features (CFI, whole program vtable opt)
// under ThinLTO.
- if (!(getToolChain().getTriple().isOSDarwin() ||
- getToolChain().getTriple().isPS4()) ||
+ if (!(RawTriple.isOSDarwin() || RawTriple.isPS4()) ||
D.getLTOMode() == LTOK_Full)
CmdArgs.push_back("-flto-unit");
}
@@ -2121,78 +3242,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_static))
CmdArgs.push_back("-static-define");
- if (isa<AnalyzeJobAction>(JA)) {
- // Enable region store model by default.
- CmdArgs.push_back("-analyzer-store=region");
-
- // Treat blocks as analysis entry points.
- CmdArgs.push_back("-analyzer-opt-analyze-nested-blocks");
-
- CmdArgs.push_back("-analyzer-eagerly-assume");
-
- // Add default argument set.
- if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) {
- CmdArgs.push_back("-analyzer-checker=core");
- CmdArgs.push_back("-analyzer-checker=apiModeling");
-
- if (!IsWindowsMSVC) {
- CmdArgs.push_back("-analyzer-checker=unix");
- } else {
- // Enable "unix" checkers that also work on Windows.
- CmdArgs.push_back("-analyzer-checker=unix.API");
- CmdArgs.push_back("-analyzer-checker=unix.Malloc");
- CmdArgs.push_back("-analyzer-checker=unix.MallocSizeof");
- CmdArgs.push_back("-analyzer-checker=unix.MismatchedDeallocator");
- CmdArgs.push_back("-analyzer-checker=unix.cstring.BadSizeArg");
- CmdArgs.push_back("-analyzer-checker=unix.cstring.NullArg");
- }
-
- // Disable some unix checkers for PS4.
- if (IsPS4CPU) {
- CmdArgs.push_back("-analyzer-disable-checker=unix.API");
- CmdArgs.push_back("-analyzer-disable-checker=unix.Vfork");
- }
-
- if (getToolChain().getTriple().getVendor() == llvm::Triple::Apple)
- CmdArgs.push_back("-analyzer-checker=osx");
-
- CmdArgs.push_back("-analyzer-checker=deadcode");
-
- if (types::isCXX(Input.getType()))
- CmdArgs.push_back("-analyzer-checker=cplusplus");
-
- if (!IsPS4CPU) {
- CmdArgs.push_back(
- "-analyzer-checker=security.insecureAPI.UncheckedReturn");
- CmdArgs.push_back("-analyzer-checker=security.insecureAPI.getpw");
- CmdArgs.push_back("-analyzer-checker=security.insecureAPI.gets");
- CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mktemp");
- CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mkstemp");
- CmdArgs.push_back("-analyzer-checker=security.insecureAPI.vfork");
- }
-
- // Default nullability checks.
- CmdArgs.push_back("-analyzer-checker=nullability.NullPassedToNonnull");
- CmdArgs.push_back(
- "-analyzer-checker=nullability.NullReturnedFromNonnull");
- }
-
- // Set the output format. The default is plist, for (lame) historical
- // reasons.
- CmdArgs.push_back("-analyzer-output");
- if (Arg *A = Args.getLastArg(options::OPT__analyzer_output))
- CmdArgs.push_back(A->getValue());
- else
- CmdArgs.push_back("plist");
-
- // Disable the presentation of standard compiler warnings when
- // using --analyze. We only want to show static analyzer diagnostics
- // or frontend errors.
- CmdArgs.push_back("-w");
-
- // Add -Xanalyzer arguments when running as analyzer.
- Args.AddAllArgValues(CmdArgs, options::OPT_Xanalyzer);
- }
+ if (isa<AnalyzeJobAction>(JA))
+ RenderAnalyzerOptions(Args, CmdArgs, Triple, Input);
CheckCodeGenerationOptions(D, Args);
@@ -2270,6 +3321,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
true))
CmdArgs.push_back("-fno-jump-tables");
+ if (Args.hasFlag(options::OPT_fprofile_sample_accurate,
+ options::OPT_fno_profile_sample_accurate, false))
+ CmdArgs.push_back("-fprofile-sample-accurate");
+
if (!Args.hasFlag(options::OPT_fpreserve_as_comments,
options::OPT_fno_preserve_as_comments, true))
CmdArgs.push_back("-fno-preserve-as-comments");
@@ -2283,7 +3338,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_freg_struct_return)) {
if (getToolChain().getArch() != llvm::Triple::x86) {
D.Diag(diag::err_drv_unsupported_opt_for_target)
- << A->getSpelling() << getToolChain().getTriple().str();
+ << A->getSpelling() << RawTriple.str();
} else if (A->getOption().matches(options::OPT_fpcc_struct_return)) {
CmdArgs.push_back("-fpcc-struct-return");
} else {
@@ -2295,7 +3350,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasFlag(options::OPT_mrtd, options::OPT_mno_rtd, false))
CmdArgs.push_back("-fdefault-calling-conv=stdcall");
- if (shouldUseFramePointer(Args, getToolChain().getTriple()))
+ if (shouldUseFramePointer(Args, RawTriple))
CmdArgs.push_back("-mdisable-fp-elim");
if (!Args.hasFlag(options::OPT_fzero_initialized_in_bss,
options::OPT_fno_zero_initialized_in_bss))
@@ -2308,7 +3363,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
OFastEnabled ? options::OPT_Ofast : options::OPT_fstrict_aliasing;
// We turn strict aliasing off by default if we're in CL mode, since MSVC
// doesn't do any TBAA.
- bool TBAAOnByDefault = !getToolChain().getDriver().IsCLMode();
+ bool TBAAOnByDefault = !D.IsCLMode();
if (!Args.hasFlag(options::OPT_fstrict_aliasing, StrictAliasingAliasOption,
options::OPT_fno_strict_aliasing, TBAAOnByDefault))
CmdArgs.push_back("-relaxed-aliasing");
@@ -2332,164 +3387,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_optimize_sibling_calls))
CmdArgs.push_back("-mdisable-tail-calls");
+ Args.AddLastArg(CmdArgs, options::OPT_ffine_grained_bitfield_accesses,
+ options::OPT_fno_fine_grained_bitfield_accesses);
+
// Handle segmented stacks.
if (Args.hasArg(options::OPT_fsplit_stack))
CmdArgs.push_back("-split-stacks");
- // Handle various floating point optimization flags, mapping them to the
- // appropriate LLVM code generation flags. This is complicated by several
- // "umbrella" flags, so we do this by stepping through the flags incrementally
- // adjusting what we think is enabled/disabled, then at the end settting the
- // LLVM flags based on the final state.
- bool HonorInfs = true;
- bool HonorNans = true;
- // -fmath-errno is the default on some platforms, e.g. BSD-derived OSes.
- bool MathErrno = getToolChain().IsMathErrnoDefault();
- bool AssociativeMath = false;
- bool ReciprocalMath = false;
- bool SignedZeros = true;
- bool TrappingMath = true;
- StringRef DenormalFpMath = "";
- StringRef FpContract = "";
-
- for (Arg *A : Args) {
- switch (A->getOption().getID()) {
- // If this isn't an FP option skip the claim below
- default:
- continue;
-
- // Options controlling individual features
- case options::OPT_fhonor_infinities: HonorInfs = true; break;
- case options::OPT_fno_honor_infinities: HonorInfs = false; break;
- case options::OPT_fhonor_nans: HonorNans = true; break;
- case options::OPT_fno_honor_nans: HonorNans = false; break;
- case options::OPT_fmath_errno: MathErrno = true; break;
- case options::OPT_fno_math_errno: MathErrno = false; break;
- case options::OPT_fassociative_math: AssociativeMath = true; break;
- case options::OPT_fno_associative_math: AssociativeMath = false; break;
- case options::OPT_freciprocal_math: ReciprocalMath = true; break;
- case options::OPT_fno_reciprocal_math: ReciprocalMath = false; break;
- case options::OPT_fsigned_zeros: SignedZeros = true; break;
- case options::OPT_fno_signed_zeros: SignedZeros = false; break;
- case options::OPT_ftrapping_math: TrappingMath = true; break;
- case options::OPT_fno_trapping_math: TrappingMath = false; break;
-
- case options::OPT_fdenormal_fp_math_EQ:
- DenormalFpMath = A->getValue();
- break;
-
- // Validate and pass through -fp-contract option.
- case options::OPT_ffp_contract: {
- StringRef Val = A->getValue();
- if (Val == "fast" || Val == "on" || Val == "off") {
- FpContract = Val;
- } else {
- D.Diag(diag::err_drv_unsupported_option_argument)
- << A->getOption().getName() << Val;
- }
- break;
- }
-
- case options::OPT_ffinite_math_only:
- HonorInfs = false;
- HonorNans = false;
- break;
- case options::OPT_fno_finite_math_only:
- HonorInfs = true;
- HonorNans = true;
- break;
-
- case options::OPT_funsafe_math_optimizations:
- AssociativeMath = true;
- ReciprocalMath = true;
- SignedZeros = false;
- TrappingMath = false;
- break;
- case options::OPT_fno_unsafe_math_optimizations:
- AssociativeMath = false;
- ReciprocalMath = false;
- SignedZeros = true;
- TrappingMath = true;
- // -fno_unsafe_math_optimizations restores default denormal handling
- DenormalFpMath = "";
- break;
-
- case options::OPT_Ofast:
- // If -Ofast is the optimization level, then -ffast-math should be enabled
- if (!OFastEnabled)
- continue;
- LLVM_FALLTHROUGH;
- case options::OPT_ffast_math:
- HonorInfs = false;
- HonorNans = false;
- MathErrno = false;
- AssociativeMath = true;
- ReciprocalMath = true;
- SignedZeros = false;
- TrappingMath = false;
- // If fast-math is set then set the fp-contract mode to fast.
- FpContract = "fast";
- break;
- case options::OPT_fno_fast_math:
- HonorInfs = true;
- HonorNans = true;
- // Turning on -ffast-math (with either flag) removes the need for
- // MathErrno. However, turning *off* -ffast-math merely restores the
- // toolchain default (which may be false).
- MathErrno = getToolChain().IsMathErrnoDefault();
- AssociativeMath = false;
- ReciprocalMath = false;
- SignedZeros = true;
- TrappingMath = true;
- // -fno_fast_math restores default denormal and fpcontract handling
- DenormalFpMath = "";
- FpContract = "";
- break;
- }
- // If we handled this option claim it
- A->claim();
- }
-
- if (!HonorInfs)
- CmdArgs.push_back("-menable-no-infs");
-
- if (!HonorNans)
- CmdArgs.push_back("-menable-no-nans");
-
- if (MathErrno)
- CmdArgs.push_back("-fmath-errno");
-
- if (!MathErrno && AssociativeMath && ReciprocalMath && !SignedZeros &&
- !TrappingMath)
- CmdArgs.push_back("-menable-unsafe-fp-math");
-
- if (!SignedZeros)
- CmdArgs.push_back("-fno-signed-zeros");
-
- if (ReciprocalMath)
- CmdArgs.push_back("-freciprocal-math");
-
- if (!TrappingMath)
- CmdArgs.push_back("-fno-trapping-math");
-
- if (!DenormalFpMath.empty())
- CmdArgs.push_back(Args.MakeArgString("-fdenormal-fp-math="+DenormalFpMath));
-
- if (!FpContract.empty())
- CmdArgs.push_back(Args.MakeArgString("-ffp-contract="+FpContract));
-
- ParseMRecip(getToolChain().getDriver(), Args, CmdArgs);
-
- // -ffast-math enables the __FAST_MATH__ preprocessor macro, but check for the
- // individual features enabled by -ffast-math instead of the option itself as
- // that's consistent with gcc's behaviour.
- if (!HonorInfs && !HonorNans && !MathErrno && AssociativeMath &&
- ReciprocalMath && !SignedZeros && !TrappingMath)
- CmdArgs.push_back("-ffast-math");
-
- // Handle __FINITE_MATH_ONLY__ similarly.
- if (!HonorInfs && !HonorNans)
- CmdArgs.push_back("-ffinite-math-only");
+ RenderFloatingPointOptions(getToolChain(), D, OFastEnabled, Args, CmdArgs);
// Decide whether to use verbose asm. Verbose assembly is the default on
// toolchains which have the integrated assembler on by default.
@@ -2516,13 +3421,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Enable -mconstructor-aliases except on darwin, where we have to work around
// a linker bug (see <rdar://problem/7651567>), and CUDA device code, where
// aliases aren't supported.
- if (!getToolChain().getTriple().isOSDarwin() &&
- !getToolChain().getTriple().isNVPTX())
+ if (!RawTriple.isOSDarwin() && !RawTriple.isNVPTX())
CmdArgs.push_back("-mconstructor-aliases");
// Darwin's kernel doesn't support guard variables; just die if we
// try to use them.
- if (KernelOrKext && getToolChain().getTriple().isOSDarwin())
+ if (KernelOrKext && RawTriple.isOSDarwin())
CmdArgs.push_back("-fforbid-guard-variables");
if (Args.hasFlag(options::OPT_mms_bitfields, options::OPT_mno_ms_bitfields,
@@ -2536,6 +3440,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-mpie-copy-relocations");
}
+ if (Args.hasFlag(options::OPT_fno_plt, options::OPT_fplt, false)) {
+ CmdArgs.push_back("-fno-plt");
+ }
+
+ // -fhosted is default.
+ // TODO: Audit uses of KernelOrKext and see where it'd be more appropriate to
+ // use Freestanding.
+ bool Freestanding =
+ Args.hasFlag(options::OPT_ffreestanding, options::OPT_fhosted, false) ||
+ KernelOrKext;
+ if (Freestanding)
+ CmdArgs.push_back("-ffreestanding");
+
// This is a coarse approximation of what llvm-gcc actually does, both
// -fasynchronous-unwind-tables and -fnon-call-exceptions interact in more
// complicated ways.
@@ -2544,7 +3461,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_asynchronous_unwind_tables,
(getToolChain().IsUnwindTablesDefault(Args) ||
getToolChain().getSanitizerArgs().needsUnwindTables()) &&
- !KernelOrKext);
+ !Freestanding);
if (Args.hasFlag(options::OPT_funwind_tables, options::OPT_fno_unwind_tables,
AsynchronousUnwindTables))
CmdArgs.push_back("-munwind-tables");
@@ -2572,108 +3489,47 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(CPU));
}
- if (const Arg *A = Args.getLastArg(options::OPT_mfpmath_EQ)) {
- CmdArgs.push_back("-mfpmath");
- CmdArgs.push_back(A->getValue());
- }
-
- // Add the target features
- getTargetFeatures(getToolChain(), Triple, Args, CmdArgs, false);
-
- // Add target specific flags.
- switch (getToolChain().getArch()) {
- default:
- break;
-
- case llvm::Triple::arm:
- case llvm::Triple::armeb:
- case llvm::Triple::thumb:
- case llvm::Triple::thumbeb:
- // Use the effective triple, which takes into account the deployment target.
- AddARMTargetArgs(Triple, Args, CmdArgs, KernelOrKext);
- break;
-
- case llvm::Triple::aarch64:
- case llvm::Triple::aarch64_be:
- AddAArch64TargetArgs(Args, CmdArgs);
- break;
-
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- AddMIPSTargetArgs(Args, CmdArgs);
- break;
-
- case llvm::Triple::ppc:
- case llvm::Triple::ppc64:
- case llvm::Triple::ppc64le:
- AddPPCTargetArgs(Args, CmdArgs);
- break;
-
- case llvm::Triple::sparc:
- case llvm::Triple::sparcel:
- case llvm::Triple::sparcv9:
- AddSparcTargetArgs(Args, CmdArgs);
- break;
-
- case llvm::Triple::systemz:
- AddSystemZTargetArgs(Args, CmdArgs);
- break;
-
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- AddX86TargetArgs(Args, CmdArgs);
- break;
-
- case llvm::Triple::lanai:
- AddLanaiTargetArgs(Args, CmdArgs);
- break;
-
- case llvm::Triple::hexagon:
- AddHexagonTargetArgs(Args, CmdArgs);
- break;
-
- case llvm::Triple::wasm32:
- case llvm::Triple::wasm64:
- AddWebAssemblyTargetArgs(Args, CmdArgs);
- break;
- }
+ RenderTargetOptions(Triple, Args, KernelOrKext, CmdArgs);
- // The 'g' groups options involve a somewhat intricate sequence of decisions
- // about what to pass from the driver to the frontend, but by the time they
- // reach cc1 they've been factored into three well-defined orthogonal choices:
- // * what level of debug info to generate
- // * what dwarf version to write
- // * what debugger tuning to use
- // This avoids having to monkey around further in cc1 other than to disable
- // codeview if not running in a Windows environment. Perhaps even that
- // decision should be made in the driver as well though.
- unsigned DwarfVersion = 0;
- llvm::DebuggerKind DebuggerTuning = getToolChain().getDefaultDebuggerTuning();
// These two are potentially updated by AddClangCLArgs.
codegenoptions::DebugInfoKind DebugInfoKind = codegenoptions::NoDebugInfo;
bool EmitCodeView = false;
// Add clang-cl arguments.
types::ID InputType = Input.getType();
- if (getToolChain().getDriver().IsCLMode())
+ if (D.IsCLMode())
AddClangCLArgs(Args, InputType, CmdArgs, &DebugInfoKind, &EmitCodeView);
+ const Arg *SplitDWARFArg = nullptr;
+ RenderDebugOptions(getToolChain(), D, RawTriple, Args, EmitCodeView,
+ IsWindowsMSVC, CmdArgs, DebugInfoKind, SplitDWARFArg);
+
+ // Add the split debug info name to the command lines here so we
+ // can propagate it to the backend.
+ bool SplitDWARF = SplitDWARFArg && RawTriple.isOSLinux() &&
+ (isa<AssembleJobAction>(JA) || isa<CompileJobAction>(JA) ||
+ isa<BackendJobAction>(JA));
+ const char *SplitDWARFOut;
+ if (SplitDWARF) {
+ CmdArgs.push_back("-split-dwarf-file");
+ SplitDWARFOut = SplitDebugName(Args, Input);
+ CmdArgs.push_back(SplitDWARFOut);
+ }
+
// Pass the linker version in use.
if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) {
CmdArgs.push_back("-target-linker-version");
CmdArgs.push_back(A->getValue());
}
- if (!shouldUseLeafFramePointer(Args, getToolChain().getTriple()))
+ if (!shouldUseLeafFramePointer(Args, RawTriple))
CmdArgs.push_back("-momit-leaf-frame-pointer");
// Explicitly error on some things we know we don't support and can't just
// ignore.
if (!Args.hasArg(options::OPT_fallow_unsupported)) {
Arg *Unsupported;
- if (types::isCXX(InputType) && getToolChain().getTriple().isOSDarwin() &&
+ if (types::isCXX(InputType) && RawTriple.isOSDarwin() &&
getToolChain().getArch() == llvm::Triple::x86) {
if ((Unsupported = Args.getLastArg(options::OPT_fapple_kext)) ||
(Unsupported = Args.getLastArg(options::OPT_mkernel)))
@@ -2706,139 +3562,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
: "-");
}
- bool splitDwarfInlining =
- Args.hasFlag(options::OPT_fsplit_dwarf_inlining,
- options::OPT_fno_split_dwarf_inlining, true);
-
- Args.ClaimAllArgs(options::OPT_g_Group);
- Arg *SplitDwarfArg = Args.getLastArg(options::OPT_gsplit_dwarf);
- if (Arg *A = Args.getLastArg(options::OPT_g_Group)) {
- // If the last option explicitly specified a debug-info level, use it.
- if (A->getOption().matches(options::OPT_gN_Group)) {
- DebugInfoKind = DebugLevelToInfoKind(*A);
- // If you say "-gsplit-dwarf -gline-tables-only", -gsplit-dwarf loses.
- // But -gsplit-dwarf is not a g_group option, hence we have to check the
- // order explicitly. (If -gsplit-dwarf wins, we fix DebugInfoKind later.)
- // This gets a bit more complicated if you've disabled inline info in the
- // skeleton CUs (splitDwarfInlining) - then there's value in composing
- // split-dwarf and line-tables-only, so let those compose naturally in
- // that case.
- // And if you just turned off debug info, (-gsplit-dwarf -g0) - do that.
- if (SplitDwarfArg) {
- if (A->getIndex() > SplitDwarfArg->getIndex()) {
- if (DebugInfoKind == codegenoptions::NoDebugInfo ||
- (DebugInfoKind == codegenoptions::DebugLineTablesOnly &&
- splitDwarfInlining))
- SplitDwarfArg = nullptr;
- } else if (splitDwarfInlining)
- DebugInfoKind = codegenoptions::NoDebugInfo;
- }
- } else
- // For any other 'g' option, use Limited.
- DebugInfoKind = codegenoptions::LimitedDebugInfo;
- }
-
- // If a debugger tuning argument appeared, remember it.
- if (Arg *A = Args.getLastArg(options::OPT_gTune_Group,
- options::OPT_ggdbN_Group)) {
- if (A->getOption().matches(options::OPT_glldb))
- DebuggerTuning = llvm::DebuggerKind::LLDB;
- else if (A->getOption().matches(options::OPT_gsce))
- DebuggerTuning = llvm::DebuggerKind::SCE;
- else
- DebuggerTuning = llvm::DebuggerKind::GDB;
- }
-
- // If a -gdwarf argument appeared, remember it.
- if (Arg *A = Args.getLastArg(options::OPT_gdwarf_2, options::OPT_gdwarf_3,
- options::OPT_gdwarf_4, options::OPT_gdwarf_5))
- DwarfVersion = DwarfVersionNum(A->getSpelling());
-
- // Forward -gcodeview. EmitCodeView might have been set by CL-compatibility
- // argument parsing.
- if (Args.hasArg(options::OPT_gcodeview) || EmitCodeView) {
- // DwarfVersion remains at 0 if no explicit choice was made.
- CmdArgs.push_back("-gcodeview");
- } else if (DwarfVersion == 0 &&
- DebugInfoKind != codegenoptions::NoDebugInfo) {
- DwarfVersion = getToolChain().GetDefaultDwarfVersion();
- }
-
- // We ignore flag -gstrict-dwarf for now.
- // And we handle flag -grecord-gcc-switches later with DwarfDebugFlags.
- Args.ClaimAllArgs(options::OPT_g_flags_Group);
-
- // Column info is included by default for everything except PS4 and CodeView.
- // Clang doesn't track end columns, just starting columns, which, in theory,
- // is fine for CodeView (and PDB). In practice, however, the Microsoft
- // debuggers don't handle missing end columns well, so it's better not to
- // include any column info.
- if (Args.hasFlag(options::OPT_gcolumn_info, options::OPT_gno_column_info,
- /*Default=*/ !IsPS4CPU && !(IsWindowsMSVC && EmitCodeView)))
- CmdArgs.push_back("-dwarf-column-info");
-
- // FIXME: Move backend command line options to the module.
- // If -gline-tables-only is the last option it wins.
- if (DebugInfoKind != codegenoptions::DebugLineTablesOnly &&
- Args.hasArg(options::OPT_gmodules)) {
- DebugInfoKind = codegenoptions::LimitedDebugInfo;
- CmdArgs.push_back("-dwarf-ext-refs");
- CmdArgs.push_back("-fmodule-format=obj");
- }
-
- // -gsplit-dwarf should turn on -g and enable the backend dwarf
- // splitting and extraction.
- // FIXME: Currently only works on Linux.
- if (getToolChain().getTriple().isOSLinux()) {
- if (!splitDwarfInlining)
- CmdArgs.push_back("-fno-split-dwarf-inlining");
- if (SplitDwarfArg) {
- if (DebugInfoKind == codegenoptions::NoDebugInfo)
- DebugInfoKind = codegenoptions::LimitedDebugInfo;
- CmdArgs.push_back("-enable-split-dwarf");
- }
- }
-
- // After we've dealt with all combinations of things that could
- // make DebugInfoKind be other than None or DebugLineTablesOnly,
- // figure out if we need to "upgrade" it to standalone debug info.
- // We parse these two '-f' options whether or not they will be used,
- // to claim them even if you wrote "-fstandalone-debug -gline-tables-only"
- bool NeedFullDebug = Args.hasFlag(options::OPT_fstandalone_debug,
- options::OPT_fno_standalone_debug,
- getToolChain().GetDefaultStandaloneDebug());
- if (DebugInfoKind == codegenoptions::LimitedDebugInfo && NeedFullDebug)
- DebugInfoKind = codegenoptions::FullDebugInfo;
- RenderDebugEnablingArgs(Args, CmdArgs, DebugInfoKind, DwarfVersion,
- DebuggerTuning);
-
- // -fdebug-macro turns on macro debug info generation.
- if (Args.hasFlag(options::OPT_fdebug_macro, options::OPT_fno_debug_macro,
- false))
- CmdArgs.push_back("-debug-info-macro");
-
- // -ggnu-pubnames turns on gnu style pubnames in the backend.
- if (Args.hasArg(options::OPT_ggnu_pubnames)) {
- CmdArgs.push_back("-backend-option");
- CmdArgs.push_back("-generate-gnu-dwarf-pub-sections");
- }
-
- // -gdwarf-aranges turns on the emission of the aranges section in the
- // backend.
- // Always enabled on the PS4.
- if (Args.hasArg(options::OPT_gdwarf_aranges) || IsPS4CPU) {
- CmdArgs.push_back("-backend-option");
- CmdArgs.push_back("-generate-arange-section");
- }
-
- if (Args.hasFlag(options::OPT_fdebug_types_section,
- options::OPT_fno_debug_types_section, false)) {
- CmdArgs.push_back("-backend-option");
- CmdArgs.push_back("-generate-type-units");
- }
-
- RenderDebugInfoCompressionArgs(Args, CmdArgs, D);
-
bool UseSeparateSections = isUseSeparateSections(Triple);
if (Args.hasFlag(options::OPT_ffunction_sections,
@@ -2855,7 +3578,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_unique_section_names, true))
CmdArgs.push_back("-fno-unique-section-names");
- Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions);
+ if (auto *A = Args.getLastArg(
+ options::OPT_finstrument_functions,
+ options::OPT_finstrument_functions_after_inlining,
+ options::OPT_finstrument_function_entry_bare))
+ A->render(Args, CmdArgs);
addPGOAndCoverageFlags(C, D, Output, Args, CmdArgs);
@@ -2863,7 +3590,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
ABICompatArg->render(Args, CmdArgs);
// Add runtime flag for PS4 when PGO or Coverage are enabled.
- if (getToolChain().getTriple().isPS4CPU())
+ if (RawTriple.isPS4CPU())
PS4cpu::addProfileRTArgs(getToolChain(), Args, CmdArgs);
// Pass options for controlling the default header search paths.
@@ -2883,75 +3610,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_working_directory);
- bool ARCMTEnabled = false;
- if (!Args.hasArg(options::OPT_fno_objc_arc, options::OPT_fobjc_arc)) {
- if (const Arg *A = Args.getLastArg(options::OPT_ccc_arcmt_check,
- options::OPT_ccc_arcmt_modify,
- options::OPT_ccc_arcmt_migrate)) {
- ARCMTEnabled = true;
- switch (A->getOption().getID()) {
- default:
- llvm_unreachable("missed a case");
- case options::OPT_ccc_arcmt_check:
- CmdArgs.push_back("-arcmt-check");
- break;
- case options::OPT_ccc_arcmt_modify:
- CmdArgs.push_back("-arcmt-modify");
- break;
- case options::OPT_ccc_arcmt_migrate:
- CmdArgs.push_back("-arcmt-migrate");
- CmdArgs.push_back("-mt-migrate-directory");
- CmdArgs.push_back(A->getValue());
-
- Args.AddLastArg(CmdArgs, options::OPT_arcmt_migrate_report_output);
- Args.AddLastArg(CmdArgs, options::OPT_arcmt_migrate_emit_arc_errors);
- break;
- }
- }
- } else {
- Args.ClaimAllArgs(options::OPT_ccc_arcmt_check);
- Args.ClaimAllArgs(options::OPT_ccc_arcmt_modify);
- Args.ClaimAllArgs(options::OPT_ccc_arcmt_migrate);
- }
-
- if (const Arg *A = Args.getLastArg(options::OPT_ccc_objcmt_migrate)) {
- if (ARCMTEnabled) {
- D.Diag(diag::err_drv_argument_not_allowed_with) << A->getAsString(Args)
- << "-ccc-arcmt-migrate";
- }
- CmdArgs.push_back("-mt-migrate-directory");
- CmdArgs.push_back(A->getValue());
-
- if (!Args.hasArg(options::OPT_objcmt_migrate_literals,
- options::OPT_objcmt_migrate_subscripting,
- options::OPT_objcmt_migrate_property)) {
- // None specified, means enable them all.
- CmdArgs.push_back("-objcmt-migrate-literals");
- CmdArgs.push_back("-objcmt-migrate-subscripting");
- CmdArgs.push_back("-objcmt-migrate-property");
- } else {
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_literals);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_subscripting);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property);
- }
- } else {
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_literals);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_subscripting);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_all);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_readonly_property);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_readwrite_property);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property_dot_syntax);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_annotation);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_instancetype);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_nsmacros);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_protocol_conformance);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_atomic_property);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_returns_innerpointer_property);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_ns_nonatomic_iosonly);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_designated_init);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_whitelist_dir_path);
- }
+ RenderARCMigrateToolOptions(D, Args, CmdArgs);
// Add preprocessing options like -I, -D, etc. if we are using the
// preprocessor.
@@ -3196,14 +3855,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_ftlsmodel_EQ);
- // -fhosted is default.
- bool IsHosted = true;
- if (Args.hasFlag(options::OPT_ffreestanding, options::OPT_fhosted, false) ||
- KernelOrKext) {
- CmdArgs.push_back("-ffreestanding");
- IsHosted = false;
- }
-
// Forward -f (flag) options which we can pass directly.
Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions);
@@ -3228,7 +3879,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_openmp, false) &&
(JA.isDeviceOffloading(Action::OFK_None) ||
JA.isDeviceOffloading(Action::OFK_OpenMP))) {
- switch (getToolChain().getDriver().getOpenMPRuntime(Args)) {
+ switch (D.getOpenMPRuntime(Args)) {
case Driver::OMPRT_OMP:
case Driver::OMPRT_IOMP5:
// Clang can generate useful OpenMP code for these two runtime libraries.
@@ -3309,49 +3960,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_pthread);
- // -stack-protector=0 is default.
- unsigned StackProtectorLevel = 0;
- // NVPTX doesn't support stack protectors; from the compiler's perspective, it
- // doesn't even have a stack!
- if (!Triple.isNVPTX()) {
- if (Arg *A = Args.getLastArg(options::OPT_fno_stack_protector,
- options::OPT_fstack_protector_all,
- options::OPT_fstack_protector_strong,
- options::OPT_fstack_protector)) {
- if (A->getOption().matches(options::OPT_fstack_protector)) {
- StackProtectorLevel = std::max<unsigned>(
- LangOptions::SSPOn,
- getToolChain().GetDefaultStackProtectorLevel(KernelOrKext));
- } else if (A->getOption().matches(options::OPT_fstack_protector_strong))
- StackProtectorLevel = LangOptions::SSPStrong;
- else if (A->getOption().matches(options::OPT_fstack_protector_all))
- StackProtectorLevel = LangOptions::SSPReq;
- } else {
- StackProtectorLevel =
- getToolChain().GetDefaultStackProtectorLevel(KernelOrKext);
- // Only use a default stack protector on Darwin in case -ffreestanding
- // is not specified.
- if (Triple.isOSDarwin() && !IsHosted)
- StackProtectorLevel = 0;
- }
- }
- if (StackProtectorLevel) {
- CmdArgs.push_back("-stack-protector");
- CmdArgs.push_back(Args.MakeArgString(Twine(StackProtectorLevel)));
- }
-
- // --param ssp-buffer-size=
- for (const Arg *A : Args.filtered(options::OPT__param)) {
- StringRef Str(A->getValue());
- if (Str.startswith("ssp-buffer-size=")) {
- if (StackProtectorLevel) {
- CmdArgs.push_back("-stack-protector-buffer-size");
- // FIXME: Verify the argument is a valid integer.
- CmdArgs.push_back(Args.MakeArgString(Str.drop_front(16)));
- }
- A->claim();
- }
- }
+ RenderSSPOptions(getToolChain(), Args, CmdArgs, KernelOrKext);
// Translate -mstackrealign
if (Args.hasFlag(options::OPT_mstackrealign, options::OPT_mno_stackrealign,
@@ -3372,20 +3981,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-mstack-probe-size=0");
}
- switch (getToolChain().getArch()) {
- case llvm::Triple::aarch64:
- case llvm::Triple::aarch64_be:
- case llvm::Triple::arm:
- case llvm::Triple::armeb:
- case llvm::Triple::thumb:
- case llvm::Triple::thumbeb:
- CmdArgs.push_back("-fallow-half-arguments-and-returns");
- break;
-
- default:
- break;
- }
-
if (Arg *A = Args.getLastArg(options::OPT_mrestrict_it,
options::OPT_mno_restrict_it)) {
if (A->getOption().matches(options::OPT_mrestrict_it)) {
@@ -3404,44 +3999,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
// Forward -cl options to -cc1
- if (Args.getLastArg(options::OPT_cl_opt_disable)) {
- CmdArgs.push_back("-cl-opt-disable");
- }
- if (Args.getLastArg(options::OPT_cl_strict_aliasing)) {
- CmdArgs.push_back("-cl-strict-aliasing");
- }
- if (Args.getLastArg(options::OPT_cl_single_precision_constant)) {
- CmdArgs.push_back("-cl-single-precision-constant");
- }
- if (Args.getLastArg(options::OPT_cl_finite_math_only)) {
- CmdArgs.push_back("-cl-finite-math-only");
- }
- if (Args.getLastArg(options::OPT_cl_kernel_arg_info)) {
- CmdArgs.push_back("-cl-kernel-arg-info");
- }
- if (Args.getLastArg(options::OPT_cl_unsafe_math_optimizations)) {
- CmdArgs.push_back("-cl-unsafe-math-optimizations");
- }
- if (Args.getLastArg(options::OPT_cl_fast_relaxed_math)) {
- CmdArgs.push_back("-cl-fast-relaxed-math");
- }
- if (Args.getLastArg(options::OPT_cl_mad_enable)) {
- CmdArgs.push_back("-cl-mad-enable");
- }
- if (Args.getLastArg(options::OPT_cl_no_signed_zeros)) {
- CmdArgs.push_back("-cl-no-signed-zeros");
- }
- if (Arg *A = Args.getLastArg(options::OPT_cl_std_EQ)) {
- std::string CLStdStr = "-cl-std=";
- CLStdStr += A->getValue();
- CmdArgs.push_back(Args.MakeArgString(CLStdStr));
- }
- if (Args.getLastArg(options::OPT_cl_denorms_are_zero)) {
- CmdArgs.push_back("-cl-denorms-are-zero");
- }
- if (Args.getLastArg(options::OPT_cl_fp32_correctly_rounded_divide_sqrt)) {
- CmdArgs.push_back("-cl-fp32-correctly-rounded-divide-sqrt");
- }
+ RenderOpenCLOptions(Args, CmdArgs);
// Forward -f options with positive and negative forms; we translate
// these by hand.
@@ -3453,36 +4011,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
A->render(Args, CmdArgs);
}
- if (Args.hasFlag(options::OPT_fdebug_info_for_profiling,
- options::OPT_fno_debug_info_for_profiling, false))
- CmdArgs.push_back("-fdebug-info-for-profiling");
-
- // -fbuiltin is default unless -mkernel is used.
- bool UseBuiltins =
- Args.hasFlag(options::OPT_fbuiltin, options::OPT_fno_builtin,
- !Args.hasArg(options::OPT_mkernel));
- if (!UseBuiltins)
- CmdArgs.push_back("-fno-builtin");
-
- // -ffreestanding implies -fno-builtin.
- if (Args.hasArg(options::OPT_ffreestanding))
- UseBuiltins = false;
-
- // Process the -fno-builtin-* options.
- for (const auto &Arg : Args) {
- const Option &O = Arg->getOption();
- if (!O.matches(options::OPT_fno_builtin_))
- continue;
-
- Arg->claim();
- // If -fno-builtin is specified, then there's no need to pass the option to
- // the frontend.
- if (!UseBuiltins)
- continue;
-
- StringRef FuncName = Arg->getValue();
- CmdArgs.push_back(Args.MakeArgString("-fno-builtin-" + FuncName));
- }
+ RenderBuiltinOptions(getToolChain(), RawTriple, Args, CmdArgs);
if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
options::OPT_fno_assume_sane_operator_new))
@@ -3501,163 +4030,21 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fblocks-runtime-optional");
}
+ // -fencode-extended-block-signature=1 is default.
+ if (getToolChain().IsEncodeExtendedBlockSignatureDefault())
+ CmdArgs.push_back("-fencode-extended-block-signature");
+
if (Args.hasFlag(options::OPT_fcoroutines_ts, options::OPT_fno_coroutines_ts,
false) &&
types::isCXX(InputType)) {
CmdArgs.push_back("-fcoroutines-ts");
}
- // -fmodules enables the use of precompiled modules (off by default).
- // Users can pass -fno-cxx-modules to turn off modules support for
- // C++/Objective-C++ programs.
- bool HaveClangModules = false;
- if (Args.hasFlag(options::OPT_fmodules, options::OPT_fno_modules, false)) {
- bool AllowedInCXX = Args.hasFlag(options::OPT_fcxx_modules,
- options::OPT_fno_cxx_modules, true);
- if (AllowedInCXX || !types::isCXX(InputType)) {
- CmdArgs.push_back("-fmodules");
- HaveClangModules = true;
- }
- }
-
- bool HaveAnyModules = HaveClangModules;
- if (Args.hasArg(options::OPT_fmodules_ts)) {
- CmdArgs.push_back("-fmodules-ts");
- HaveAnyModules = true;
- }
-
- // -fmodule-maps enables implicit reading of module map files. By default,
- // this is enabled if we are using Clang's flavor of precompiled modules.
- if (Args.hasFlag(options::OPT_fimplicit_module_maps,
- options::OPT_fno_implicit_module_maps, HaveClangModules)) {
- CmdArgs.push_back("-fimplicit-module-maps");
- }
-
- // -fmodules-decluse checks that modules used are declared so (off by
- // default).
- if (Args.hasFlag(options::OPT_fmodules_decluse,
- options::OPT_fno_modules_decluse, false)) {
- CmdArgs.push_back("-fmodules-decluse");
- }
-
- // -fmodules-strict-decluse is like -fmodule-decluse, but also checks that
- // all #included headers are part of modules.
- if (Args.hasFlag(options::OPT_fmodules_strict_decluse,
- options::OPT_fno_modules_strict_decluse, false)) {
- CmdArgs.push_back("-fmodules-strict-decluse");
- }
-
- // -fno-implicit-modules turns off implicitly compiling modules on demand.
- if (!Args.hasFlag(options::OPT_fimplicit_modules,
- options::OPT_fno_implicit_modules, HaveClangModules)) {
- if (HaveAnyModules)
- CmdArgs.push_back("-fno-implicit-modules");
- } else if (HaveAnyModules) {
- // -fmodule-cache-path specifies where our implicitly-built module files
- // should be written.
- SmallString<128> Path;
- if (Arg *A = Args.getLastArg(options::OPT_fmodules_cache_path))
- Path = A->getValue();
- if (C.isForDiagnostics()) {
- // When generating crash reports, we want to emit the modules along with
- // the reproduction sources, so we ignore any provided module path.
- Path = Output.getFilename();
- llvm::sys::path::replace_extension(Path, ".cache");
- llvm::sys::path::append(Path, "modules");
- } else if (Path.empty()) {
- // No module path was provided: use the default.
- llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/false, Path);
- llvm::sys::path::append(Path, "org.llvm.clang.");
- appendUserToPath(Path);
- llvm::sys::path::append(Path, "ModuleCache");
- }
- const char Arg[] = "-fmodules-cache-path=";
- Path.insert(Path.begin(), Arg, Arg + strlen(Arg));
- CmdArgs.push_back(Args.MakeArgString(Path));
- }
-
- if (HaveAnyModules) {
- // -fprebuilt-module-path specifies where to load the prebuilt module files.
- for (const Arg *A : Args.filtered(options::OPT_fprebuilt_module_path))
- CmdArgs.push_back(Args.MakeArgString(
- std::string("-fprebuilt-module-path=") + A->getValue()));
- }
-
- // -fmodule-name specifies the module that is currently being built (or
- // used for header checking by -fmodule-maps).
- Args.AddLastArg(CmdArgs, options::OPT_fmodule_name_EQ);
-
- // -fmodule-map-file can be used to specify files containing module
- // definitions.
- Args.AddAllArgs(CmdArgs, options::OPT_fmodule_map_file);
-
- // -fbuiltin-module-map can be used to load the clang
- // builtin headers modulemap file.
- if (Args.hasArg(options::OPT_fbuiltin_module_map)) {
- SmallString<128> BuiltinModuleMap(getToolChain().getDriver().ResourceDir);
- llvm::sys::path::append(BuiltinModuleMap, "include");
- llvm::sys::path::append(BuiltinModuleMap, "module.modulemap");
- if (llvm::sys::fs::exists(BuiltinModuleMap)) {
- CmdArgs.push_back(Args.MakeArgString("-fmodule-map-file=" +
- BuiltinModuleMap));
- }
- }
-
- // -fmodule-file can be used to specify files containing precompiled modules.
- if (HaveAnyModules)
- Args.AddAllArgs(CmdArgs, options::OPT_fmodule_file);
- else
- Args.ClaimAllArgs(options::OPT_fmodule_file);
-
- // When building modules and generating crashdumps, we need to dump a module
- // dependency VFS alongside the output.
- if (HaveClangModules && C.isForDiagnostics()) {
- SmallString<128> VFSDir(Output.getFilename());
- llvm::sys::path::replace_extension(VFSDir, ".cache");
- // Add the cache directory as a temp so the crash diagnostics pick it up.
- C.addTempFile(Args.MakeArgString(VFSDir));
-
- llvm::sys::path::append(VFSDir, "vfs");
- CmdArgs.push_back("-module-dependency-dir");
- CmdArgs.push_back(Args.MakeArgString(VFSDir));
- }
-
- if (HaveClangModules)
- Args.AddLastArg(CmdArgs, options::OPT_fmodules_user_build_path);
-
- // Pass through all -fmodules-ignore-macro arguments.
- Args.AddAllArgs(CmdArgs, options::OPT_fmodules_ignore_macro);
- Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_interval);
- Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_after);
-
- Args.AddLastArg(CmdArgs, options::OPT_fbuild_session_timestamp);
-
- if (Arg *A = Args.getLastArg(options::OPT_fbuild_session_file)) {
- if (Args.hasArg(options::OPT_fbuild_session_timestamp))
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << A->getAsString(Args) << "-fbuild-session-timestamp";
-
- llvm::sys::fs::file_status Status;
- if (llvm::sys::fs::status(A->getValue(), Status))
- D.Diag(diag::err_drv_no_such_file) << A->getValue();
- CmdArgs.push_back(
- Args.MakeArgString("-fbuild-session-timestamp=" +
- Twine((uint64_t)Status.getLastModificationTime()
- .time_since_epoch()
- .count())));
- }
-
- if (Args.getLastArg(options::OPT_fmodules_validate_once_per_build_session)) {
- if (!Args.getLastArg(options::OPT_fbuild_session_timestamp,
- options::OPT_fbuild_session_file))
- D.Diag(diag::err_drv_modules_validate_once_requires_timestamp);
-
- Args.AddLastArg(CmdArgs,
- options::OPT_fmodules_validate_once_per_build_session);
- }
+ Args.AddLastArg(CmdArgs, options::OPT_fdouble_square_bracket_attributes,
+ options::OPT_fno_double_square_bracket_attributes);
- Args.AddLastArg(CmdArgs, options::OPT_fmodules_validate_system_headers);
- Args.AddLastArg(CmdArgs, options::OPT_fmodules_disable_diagnostic_validation);
+ bool HaveModules = false;
+ RenderModulesOptions(C, D, Args, Input, Output, CmdArgs, HaveModules);
// -faccess-control is default.
if (Args.hasFlag(options::OPT_fno_access_control,
@@ -3681,28 +4068,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
getToolChain().getArch() == llvm::Triple::hexagon))
CmdArgs.push_back("-fshort-enums");
- // -fsigned-char is default.
- if (Arg *A = Args.getLastArg(
- options::OPT_fsigned_char, options::OPT_fno_signed_char,
- options::OPT_funsigned_char, options::OPT_fno_unsigned_char)) {
- if (A->getOption().matches(options::OPT_funsigned_char) ||
- A->getOption().matches(options::OPT_fno_signed_char)) {
- CmdArgs.push_back("-fno-signed-char");
- }
- } else if (!isSignedCharDefault(getToolChain().getTriple())) {
- CmdArgs.push_back("-fno-signed-char");
- }
+ RenderCharacterOptions(Args, AuxTriple ? *AuxTriple : RawTriple, CmdArgs);
// -fuse-cxa-atexit is default.
if (!Args.hasFlag(
options::OPT_fuse_cxa_atexit, options::OPT_fno_use_cxa_atexit,
- !IsWindowsCygnus && !IsWindowsGNU &&
- getToolChain().getTriple().getOS() != llvm::Triple::Solaris &&
+ !RawTriple.isOSWindows() &&
+ RawTriple.getOS() != llvm::Triple::Solaris &&
getToolChain().getArch() != llvm::Triple::hexagon &&
getToolChain().getArch() != llvm::Triple::xcore &&
- ((getToolChain().getTriple().getVendor() !=
- llvm::Triple::MipsTechnologies) ||
- getToolChain().getTriple().hasEnvironment())) ||
+ ((RawTriple.getVendor() != llvm::Triple::MipsTechnologies) ||
+ RawTriple.hasEnvironment())) ||
KernelOrKext)
CmdArgs.push_back("-fno-use-cxa-atexit");
@@ -3724,8 +4100,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_ms_extensions, true))))
CmdArgs.push_back("-fms-compatibility");
- VersionTuple MSVT =
- getToolChain().computeMSVCVersion(&getToolChain().getDriver(), Args);
+ VersionTuple MSVT = getToolChain().computeMSVCVersion(&D, Args);
if (!MSVT.empty())
CmdArgs.push_back(
Args.MakeArgString("-fms-compatibility-version=" + MSVT.getAsString()));
@@ -3736,7 +4111,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (const Arg *StdArg = Args.getLastArg(options::OPT__SLASH_std)) {
LanguageStandard = llvm::StringSwitch<StringRef>(StdArg->getValue())
.Case("c++14", "-std=c++14")
- .Case("c++latest", "-std=c++1z")
+ .Case("c++17", "-std=c++17")
+ .Case("c++latest", "-std=c++2a")
.Default("");
if (LanguageStandard.empty())
D.Diag(clang::diag::warn_drv_unused_argument)
@@ -3760,7 +4136,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -fno-declspec is default, except for PS4.
if (Args.hasFlag(options::OPT_fdeclspec, options::OPT_fno_declspec,
- getToolChain().getTriple().isPS4()))
+ RawTriple.isPS4()))
CmdArgs.push_back("-fdeclspec");
else if (Args.hasArg(options::OPT_fno_declspec))
CmdArgs.push_back("-fno-declspec"); // Explicitly disabling __declspec.
@@ -3772,8 +4148,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
!IsWindowsMSVC || IsMSVC2015Compatible))
CmdArgs.push_back("-fno-threadsafe-statics");
- // -fno-delayed-template-parsing is default, except for Windows where MSVC STL
- // needs it.
+ // -fno-delayed-template-parsing is default, except when targetting MSVC.
+ // Many old Windows SDK versions require this to parse.
+ // FIXME: MSVC introduced /Zc:twoPhase- to disable this behavior in their
+ // compiler. We should be able to disable this by default at some point.
if (Args.hasFlag(options::OPT_fdelayed_template_parsing,
options::OPT_fno_delayed_template_parsing, IsWindowsMSVC))
CmdArgs.push_back("-fdelayed-template-parsing");
@@ -3799,90 +4177,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fexperimental_new_pass_manager,
options::OPT_fno_experimental_new_pass_manager);
- ObjCRuntime objcRuntime = AddObjCRuntimeArgs(Args, CmdArgs, rewriteKind);
-
- // -fobjc-dispatch-method is only relevant with the nonfragile-abi, and
- // legacy is the default. Except for deployment target of 10.5,
- // next runtime is always legacy dispatch and -fno-objc-legacy-dispatch
- // gets ignored silently.
- if (objcRuntime.isNonFragile()) {
- if (!Args.hasFlag(options::OPT_fobjc_legacy_dispatch,
- options::OPT_fno_objc_legacy_dispatch,
- objcRuntime.isLegacyDispatchDefaultForArch(
- getToolChain().getArch()))) {
- if (getToolChain().UseObjCMixedDispatch())
- CmdArgs.push_back("-fobjc-dispatch-method=mixed");
- else
- CmdArgs.push_back("-fobjc-dispatch-method=non-legacy");
- }
- }
-
- // When ObjectiveC legacy runtime is in effect on MacOSX,
- // turn on the option to do Array/Dictionary subscripting
- // by default.
- if (getToolChain().getArch() == llvm::Triple::x86 &&
- getToolChain().getTriple().isMacOSX() &&
- !getToolChain().getTriple().isMacOSXVersionLT(10, 7) &&
- objcRuntime.getKind() == ObjCRuntime::FragileMacOSX &&
- objcRuntime.isNeXTFamily())
- CmdArgs.push_back("-fobjc-subscripting-legacy-runtime");
-
- // -fencode-extended-block-signature=1 is default.
- if (getToolChain().IsEncodeExtendedBlockSignatureDefault()) {
- CmdArgs.push_back("-fencode-extended-block-signature");
- }
-
- // Allow -fno-objc-arr to trump -fobjc-arr/-fobjc-arc.
- // NOTE: This logic is duplicated in ToolChains.cpp.
- bool ARC = isObjCAutoRefCount(Args);
- if (ARC) {
- getToolChain().CheckObjCARC();
-
- CmdArgs.push_back("-fobjc-arc");
-
- // FIXME: It seems like this entire block, and several around it should be
- // wrapped in isObjC, but for now we just use it here as this is where it
- // was being used previously.
- if (types::isCXX(InputType) && types::isObjC(InputType)) {
- if (getToolChain().GetCXXStdlibType(Args) == ToolChain::CST_Libcxx)
- CmdArgs.push_back("-fobjc-arc-cxxlib=libc++");
- else
- CmdArgs.push_back("-fobjc-arc-cxxlib=libstdc++");
- }
-
- // Allow the user to enable full exceptions code emission.
- // We define off for Objective-CC, on for Objective-C++.
- if (Args.hasFlag(options::OPT_fobjc_arc_exceptions,
- options::OPT_fno_objc_arc_exceptions,
- /*default*/ types::isCXX(InputType)))
- CmdArgs.push_back("-fobjc-arc-exceptions");
- }
-
- // Silence warning for full exception code emission options when explicitly
- // set to use no ARC.
- if (Args.hasArg(options::OPT_fno_objc_arc)) {
- Args.ClaimAllArgs(options::OPT_fobjc_arc_exceptions);
- Args.ClaimAllArgs(options::OPT_fno_objc_arc_exceptions);
- }
-
- // -fobjc-infer-related-result-type is the default, except in the Objective-C
- // rewriter.
- if (rewriteKind != RK_None)
- CmdArgs.push_back("-fno-objc-infer-related-result-type");
-
- // Pass down -fobjc-weak or -fno-objc-weak if present.
- if (types::isObjC(InputType)) {
- auto WeakArg = Args.getLastArg(options::OPT_fobjc_weak,
- options::OPT_fno_objc_weak);
- if (!WeakArg) {
- // nothing to do
- } else if (!objcRuntime.allowsWeak()) {
- if (WeakArg->getOption().matches(options::OPT_fobjc_weak))
- D.Diag(diag::err_objc_weak_unsupported);
- } else {
- WeakArg->render(Args, CmdArgs);
- }
- }
+ ObjCRuntime Runtime = AddObjCRuntimeArgs(Args, CmdArgs, rewriteKind);
+ RenderObjCOptions(getToolChain(), D, RawTriple, Args, Runtime,
+ rewriteKind != RK_None, Input, CmdArgs);
if (Args.hasFlag(options::OPT_fapplication_extension,
options::OPT_fno_application_extension, false))
@@ -3890,12 +4187,36 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Handle GCC-style exception args.
if (!C.getDriver().IsCLMode())
- addExceptionArgs(Args, InputType, getToolChain(), KernelOrKext, objcRuntime,
+ addExceptionArgs(Args, InputType, getToolChain(), KernelOrKext, Runtime,
CmdArgs);
- if (Args.hasArg(options::OPT_fsjlj_exceptions) ||
- getToolChain().UseSjLjExceptions(Args))
- CmdArgs.push_back("-fsjlj-exceptions");
+ // Handle exception personalities
+ Arg *A = Args.getLastArg(options::OPT_fsjlj_exceptions,
+ options::OPT_fseh_exceptions,
+ options::OPT_fdwarf_exceptions);
+ if (A) {
+ const Option &Opt = A->getOption();
+ if (Opt.matches(options::OPT_fsjlj_exceptions))
+ CmdArgs.push_back("-fsjlj-exceptions");
+ if (Opt.matches(options::OPT_fseh_exceptions))
+ CmdArgs.push_back("-fseh-exceptions");
+ if (Opt.matches(options::OPT_fdwarf_exceptions))
+ CmdArgs.push_back("-fdwarf-exceptions");
+ } else {
+ switch (getToolChain().GetExceptionModel(Args)) {
+ default:
+ break;
+ case llvm::ExceptionHandling::DwarfCFI:
+ CmdArgs.push_back("-fdwarf-exceptions");
+ break;
+ case llvm::ExceptionHandling::SjLj:
+ CmdArgs.push_back("-fsjlj-exceptions");
+ break;
+ case llvm::ExceptionHandling::WinEH:
+ CmdArgs.push_back("-fseh-exceptions");
+ break;
+ }
+ }
// C++ "sane" operator new.
if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
@@ -3941,12 +4262,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_mno_constant_cfstrings))
CmdArgs.push_back("-fno-constant-cfstrings");
- // -fshort-wchar default varies depending on platform; only
- // pass if specified.
- if (Arg *A = Args.getLastArg(options::OPT_fshort_wchar,
- options::OPT_fno_short_wchar))
- A->render(Args, CmdArgs);
-
// -fno-pascal-strings is default, only pass non-default.
if (Args.hasFlag(options::OPT_fpascal_strings,
options::OPT_fno_pascal_strings, false))
@@ -3971,7 +4286,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
MaxTypeAlignStr += A->getValue();
CmdArgs.push_back(Args.MakeArgString(MaxTypeAlignStr));
}
- } else if (getToolChain().getTriple().isOSDarwin()) {
+ } else if (RawTriple.isOSDarwin()) {
if (!SkipMaxTypeAlign) {
std::string MaxTypeAlignStr = "-fmax-type-align=16";
CmdArgs.push_back(Args.MakeArgString(MaxTypeAlignStr));
@@ -3979,8 +4294,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
// -fcommon is the default unless compiling kernel code or the target says so
- bool NoCommonDefault =
- KernelOrKext || isNoCommonDefault(getToolChain().getTriple());
+ bool NoCommonDefault = KernelOrKext || isNoCommonDefault(RawTriple);
if (!Args.hasFlag(options::OPT_fcommon, options::OPT_fno_common,
!NoCommonDefault))
CmdArgs.push_back("-fno-common");
@@ -4013,113 +4327,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
<< value;
}
- bool CaretDefault = true;
- bool ColumnDefault = true;
- if (Arg *DiagArg = Args.getLastArg(options::OPT__SLASH_diagnostics_classic,
- options::OPT__SLASH_diagnostics_column,
- options::OPT__SLASH_diagnostics_caret)) {
- switch (DiagArg->getOption().getID()) {
- case options::OPT__SLASH_diagnostics_caret:
- CaretDefault = true;
- ColumnDefault = true;
- break;
- case options::OPT__SLASH_diagnostics_column:
- CaretDefault = false;
- ColumnDefault = true;
- break;
- case options::OPT__SLASH_diagnostics_classic:
- CaretDefault = false;
- ColumnDefault = false;
- break;
- }
- }
-
- // -fcaret-diagnostics is default.
- if (!Args.hasFlag(options::OPT_fcaret_diagnostics,
- options::OPT_fno_caret_diagnostics, CaretDefault))
- CmdArgs.push_back("-fno-caret-diagnostics");
-
- // -fdiagnostics-fixit-info is default, only pass non-default.
- if (!Args.hasFlag(options::OPT_fdiagnostics_fixit_info,
- options::OPT_fno_diagnostics_fixit_info))
- CmdArgs.push_back("-fno-diagnostics-fixit-info");
-
- // Enable -fdiagnostics-show-option by default.
- if (Args.hasFlag(options::OPT_fdiagnostics_show_option,
- options::OPT_fno_diagnostics_show_option))
- CmdArgs.push_back("-fdiagnostics-show-option");
-
- if (const Arg *A =
- Args.getLastArg(options::OPT_fdiagnostics_show_category_EQ)) {
- CmdArgs.push_back("-fdiagnostics-show-category");
- CmdArgs.push_back(A->getValue());
- }
-
- if (Args.hasFlag(options::OPT_fdiagnostics_show_hotness,
- options::OPT_fno_diagnostics_show_hotness, false))
- CmdArgs.push_back("-fdiagnostics-show-hotness");
-
- if (const Arg *A =
- Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) {
- std::string Opt = std::string("-fdiagnostics-hotness-threshold=") + A->getValue();
- CmdArgs.push_back(Args.MakeArgString(Opt));
- }
-
- if (const Arg *A = Args.getLastArg(options::OPT_fdiagnostics_format_EQ)) {
- CmdArgs.push_back("-fdiagnostics-format");
- CmdArgs.push_back(A->getValue());
- }
-
- if (Arg *A = Args.getLastArg(
- options::OPT_fdiagnostics_show_note_include_stack,
- options::OPT_fno_diagnostics_show_note_include_stack)) {
- if (A->getOption().matches(
- options::OPT_fdiagnostics_show_note_include_stack))
- CmdArgs.push_back("-fdiagnostics-show-note-include-stack");
- else
- CmdArgs.push_back("-fno-diagnostics-show-note-include-stack");
- }
-
- // Color diagnostics are parsed by the driver directly from argv
- // and later re-parsed to construct this job; claim any possible
- // color diagnostic here to avoid warn_drv_unused_argument and
- // diagnose bad OPT_fdiagnostics_color_EQ values.
- for (Arg *A : Args) {
- const Option &O = A->getOption();
- if (!O.matches(options::OPT_fcolor_diagnostics) &&
- !O.matches(options::OPT_fdiagnostics_color) &&
- !O.matches(options::OPT_fno_color_diagnostics) &&
- !O.matches(options::OPT_fno_diagnostics_color) &&
- !O.matches(options::OPT_fdiagnostics_color_EQ))
- continue;
- if (O.matches(options::OPT_fdiagnostics_color_EQ)) {
- StringRef Value(A->getValue());
- if (Value != "always" && Value != "never" && Value != "auto")
- getToolChain().getDriver().Diag(diag::err_drv_clang_unsupported)
- << ("-fdiagnostics-color=" + Value).str();
- }
- A->claim();
- }
- if (D.getDiags().getDiagnosticOptions().ShowColors)
- CmdArgs.push_back("-fcolor-diagnostics");
-
- if (Args.hasArg(options::OPT_fansi_escape_codes))
- CmdArgs.push_back("-fansi-escape-codes");
-
- if (!Args.hasFlag(options::OPT_fshow_source_location,
- options::OPT_fno_show_source_location))
- CmdArgs.push_back("-fno-show-source-location");
-
- if (Args.hasArg(options::OPT_fdiagnostics_absolute_paths))
- CmdArgs.push_back("-fdiagnostics-absolute-paths");
-
- if (!Args.hasFlag(options::OPT_fshow_column, options::OPT_fno_show_column,
- ColumnDefault))
- CmdArgs.push_back("-fno-show-column");
-
- if (!Args.hasFlag(options::OPT_fspell_checking,
- options::OPT_fno_spell_checking))
- CmdArgs.push_back("-fno-spell-checking");
+ RenderDiagnosticsOptions(D, Args, CmdArgs);
// -fno-asm-blocks is default.
if (Args.hasFlag(options::OPT_fasm_blocks, options::OPT_fno_asm_blocks,
@@ -4149,6 +4357,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_slp_vectorize, EnableSLPVec))
CmdArgs.push_back("-vectorize-slp");
+ ParseMPreferVectorWidth(D, Args, CmdArgs);
+
if (Arg *A = Args.getLastArg(options::OPT_fshow_overloads_EQ))
A->render(Args, CmdArgs);
@@ -4178,13 +4388,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_apple_pragma_pack, false))
CmdArgs.push_back("-fapple-pragma-pack");
- // le32-specific flags:
- // -fno-math-builtin: clang should not convert math builtins to intrinsics
- // by default.
- if (getToolChain().getArch() == llvm::Triple::le32) {
- CmdArgs.push_back("-fno-math-builtin");
- }
-
if (Args.hasFlag(options::OPT_fsave_optimization_record,
options::OPT_fno_save_optimization_record, false)) {
CmdArgs.push_back("-opt-record-file");
@@ -4194,10 +4397,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(A->getValue());
} else {
SmallString<128> F;
- if (Output.isFilename() && (Args.hasArg(options::OPT_c) ||
- Args.hasArg(options::OPT_S))) {
- F = Output.getFilename();
- } else {
+
+ if (Args.hasArg(options::OPT_c) || Args.hasArg(options::OPT_S)) {
+ if (Arg *FinalOutput = Args.getLastArg(options::OPT_o))
+ F = FinalOutput->getValue();
+ }
+
+ if (F.empty()) {
// Use the input filename.
F = llvm::sys::path::stem(Input.getBaseInput());
@@ -4219,20 +4425,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
-// Default to -fno-builtin-str{cat,cpy} on Darwin for ARM.
-//
-// FIXME: Now that PR4941 has been fixed this can be enabled.
-#if 0
- if (getToolChain().getTriple().isOSDarwin() &&
- (getToolChain().getArch() == llvm::Triple::arm ||
- getToolChain().getArch() == llvm::Triple::thumb)) {
- if (!Args.hasArg(options::OPT_fbuiltin_strcat))
- CmdArgs.push_back("-fno-builtin-strcat");
- if (!Args.hasArg(options::OPT_fbuiltin_strcpy))
- CmdArgs.push_back("-fno-builtin-strcpy");
- }
-#endif
-
bool RewriteImports = Args.hasFlag(options::OPT_frewrite_imports,
options::OPT_fno_rewrite_imports, false);
if (RewriteImports)
@@ -4244,7 +4436,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// nice to enable this when doing a crashdump for modules as well.
if (Args.hasFlag(options::OPT_frewrite_includes,
options::OPT_fno_rewrite_includes, false) ||
- (C.isForDiagnostics() && (RewriteImports || !HaveAnyModules)))
+ (C.isForDiagnostics() && (RewriteImports || !HaveModules)))
CmdArgs.push_back("-frewrite-includes");
// Only allow -traditional or -traditional-cpp outside in preprocessing modes.
@@ -4366,7 +4558,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_undef);
- const char *Exec = getToolChain().getDriver().getClangProgramPath();
+ const char *Exec = D.getClangProgramPath();
// Optionally embed the -cc1 level arguments into the debug info, for build
// analysis.
@@ -4392,18 +4584,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(Flags));
}
- // Add the split debug info name to the command lines here so we
- // can propagate it to the backend.
- bool SplitDwarf = SplitDwarfArg && getToolChain().getTriple().isOSLinux() &&
- (isa<AssembleJobAction>(JA) || isa<CompileJobAction>(JA) ||
- isa<BackendJobAction>(JA));
- const char *SplitDwarfOut;
- if (SplitDwarf) {
- CmdArgs.push_back("-split-dwarf-file");
- SplitDwarfOut = SplitDebugName(Args, Input);
- CmdArgs.push_back(SplitDwarfOut);
- }
-
// Host-side cuda compilation receives device-side outputs as Inputs[1...].
// Include them with -fcuda-include-gpubinary.
if (IsCuda && Inputs.size() > 1)
@@ -4476,8 +4656,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Handle the debug info splitting at object creation time if we're
// creating an object.
// TODO: Currently only works on linux with newer objcopy.
- if (SplitDwarf && Output.getType() == types::TY_Object)
- SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output, SplitDwarfOut);
+ if (SplitDWARF && Output.getType() == types::TY_Object)
+ SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output, SplitDWARFOut);
if (Arg *A = Args.getLastArg(options::OPT_pg))
if (Args.hasArg(options::OPT_fomit_frame_pointer))
@@ -4752,7 +4932,9 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
// Both /showIncludes and /E (and /EP) write to stdout. Allowing both
// would produce interleaved output, so ignore /showIncludes in such cases.
- if (!Args.hasArg(options::OPT_E) && !Args.hasArg(options::OPT__SLASH_EP))
+ if ((!Args.hasArg(options::OPT_E) && !Args.hasArg(options::OPT__SLASH_EP)) ||
+ (Args.hasArg(options::OPT__SLASH_P) &&
+ Args.hasArg(options::OPT__SLASH_EP) && !Args.hasArg(options::OPT_E)))
if (Arg *A = Args.getLastArg(options::OPT_show_includes))
A->render(Args, CmdArgs);
@@ -4841,7 +5023,8 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
// Parse the default calling convention options.
if (Arg *CCArg =
Args.getLastArg(options::OPT__SLASH_Gd, options::OPT__SLASH_Gr,
- options::OPT__SLASH_Gz, options::OPT__SLASH_Gv)) {
+ options::OPT__SLASH_Gz, options::OPT__SLASH_Gv,
+ options::OPT__SLASH_Gregcall)) {
unsigned DCCOptId = CCArg->getOption().getID();
const char *DCCFlag = nullptr;
bool ArchSupported = true;
@@ -4862,6 +5045,10 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
ArchSupported = Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64;
DCCFlag = "-fdefault-calling-conv=vectorcall";
break;
+ case options::OPT__SLASH_Gregcall:
+ ArchSupported = Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64;
+ DCCFlag = "-fdefault-calling-conv=regcall";
+ break;
}
// MSVC doesn't warn if /Gr or /Gz is used on x64, so we don't either.
@@ -5176,12 +5363,15 @@ void OffloadBundler::ConstructJob(Compilation &C, const JobAction &JA,
if (I)
Triples += ',';
+ // Find ToolChain for this input.
Action::OffloadKind CurKind = Action::OFK_Host;
const ToolChain *CurTC = &getToolChain();
const Action *CurDep = JA.getInputs()[I];
if (const auto *OA = dyn_cast<OffloadAction>(CurDep)) {
+ CurTC = nullptr;
OA->doOnEachDependence([&](Action *A, const ToolChain *TC, const char *) {
+ assert(CurTC == nullptr && "Expected one dependence!");
CurKind = A->getOffloadingDeviceKind();
CurTC = TC;
});
@@ -5202,7 +5392,17 @@ void OffloadBundler::ConstructJob(Compilation &C, const JobAction &JA,
for (unsigned I = 0; I < Inputs.size(); ++I) {
if (I)
UB += ',';
- UB += Inputs[I].getFilename();
+
+ // Find ToolChain for this input.
+ const ToolChain *CurTC = &getToolChain();
+ if (const auto *OA = dyn_cast<OffloadAction>(JA.getInputs()[I])) {
+ CurTC = nullptr;
+ OA->doOnEachDependence([&](Action *, const ToolChain *TC, const char *) {
+ assert(CurTC == nullptr && "Expected one dependence!");
+ CurTC = TC;
+ });
+ }
+ UB += CurTC->getInputFilename(Inputs[I]);
}
CmdArgs.push_back(TCArgs.MakeArgString(UB));
@@ -5262,7 +5462,7 @@ void OffloadBundler::ConstructJobMultipleOutputs(
for (unsigned I = 0; I < Outputs.size(); ++I) {
if (I)
UB += ',';
- UB += Outputs[I].getFilename();
+ UB += DepInfo[I].DependentToolChain->getInputFilename(Outputs[I]);
}
CmdArgs.push_back(TCArgs.MakeArgString(UB));
CmdArgs.push_back("-unbundle");
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Clang.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Clang.h
index d53c3b4413c83..e23822b9c6781 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Clang.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Clang.h
@@ -42,6 +42,10 @@ private:
const InputInfo &Output,
const InputInfoList &Inputs) const;
+ void RenderTargetOptions(const llvm::Triple &EffectiveTriple,
+ const llvm::opt::ArgList &Args, bool KernelOrKext,
+ llvm::opt::ArgStringList &CmdArgs) const;
+
void AddAArch64TargetArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
void AddARMTargetArgs(const llvm::Triple &Triple,
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/CloudABI.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/CloudABI.cpp
index 0f6c712c5d28e..cdf807f7f91ff 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/CloudABI.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/CloudABI.cpp
@@ -80,9 +80,9 @@ void cloudabi::Linker::ConstructJob(Compilation &C, const JobAction &JA,
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
+ if (ToolChain.ShouldLinkCXXStdlib(Args))
+ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
- if (D.CCCIsCXX())
- ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lc");
CmdArgs.push_back("-lcompiler_rt");
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/CommonArgs.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 00bd60bc24bba..ab51a8c3cc901 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -320,6 +320,8 @@ std::string tools::getCPUName(const ArgList &Args, const llvm::Triple &T,
return TargetCPUName;
}
+ case llvm::Triple::bpfel:
+ case llvm::Triple::bpfeb:
case llvm::Triple::sparc:
case llvm::Triple::sparcel:
case llvm::Triple::sparcv9:
@@ -376,8 +378,20 @@ void tools::AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args,
// as gold requires -plugin to come before any -plugin-opt that -Wl might
// forward.
CmdArgs.push_back("-plugin");
- std::string Plugin =
- ToolChain.getDriver().Dir + "/../lib" CLANG_LIBDIR_SUFFIX "/LLVMgold.so";
+
+#if defined(LLVM_ON_WIN32)
+ const char *Suffix = ".dll";
+#elif defined(__APPLE__)
+ const char *Suffix = ".dylib";
+#else
+ const char *Suffix = ".so";
+#endif
+
+ SmallString<1024> Plugin;
+ llvm::sys::path::native(Twine(ToolChain.getDriver().Dir) +
+ "/../lib" CLANG_LIBDIR_SUFFIX "/LLVMgold" +
+ Suffix,
+ Plugin);
CmdArgs.push_back(Args.MakeArgString(Plugin));
// Try to pass driver level flags relevant to LTO code generation down to
@@ -440,6 +454,14 @@ void tools::AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args,
CmdArgs.push_back(
Args.MakeArgString(Twine("-plugin-opt=sample-profile=") + FName));
}
+
+ // Need this flag to turn on new pass manager via Gold plugin.
+ if (Args.hasFlag(options::OPT_fexperimental_new_pass_manager,
+ options::OPT_fno_experimental_new_pass_manager,
+ /* Default */ false)) {
+ CmdArgs.push_back("-plugin-opt=new-pass-manager");
+ }
+
}
void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args,
@@ -522,7 +544,7 @@ void tools::linkSanitizerRuntimeDeps(const ToolChain &TC,
CmdArgs.push_back("-lrt");
}
CmdArgs.push_back("-lm");
- // There's no libdl on FreeBSD or RTEMS.
+ // There's no libdl on all OSes.
if (TC.getTriple().getOS() != llvm::Triple::FreeBSD &&
TC.getTriple().getOS() != llvm::Triple::NetBSD &&
TC.getTriple().getOS() != llvm::Triple::RTEMS)
@@ -538,26 +560,44 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
SmallVectorImpl<StringRef> &RequiredSymbols) {
const SanitizerArgs &SanArgs = TC.getSanitizerArgs();
// Collect shared runtimes.
- if (SanArgs.needsAsanRt() && SanArgs.needsSharedAsanRt()) {
- SharedRuntimes.push_back("asan");
+ if (SanArgs.needsSharedRt()) {
+ if (SanArgs.needsAsanRt()) {
+ SharedRuntimes.push_back("asan");
+ if (!Args.hasArg(options::OPT_shared) && !TC.getTriple().isAndroid())
+ HelperStaticRuntimes.push_back("asan-preinit");
+ }
+ if (SanArgs.needsUbsanRt()) {
+ if (SanArgs.requiresMinimalRuntime()) {
+ SharedRuntimes.push_back("ubsan_minimal");
+ } else {
+ SharedRuntimes.push_back("ubsan_standalone");
+ }
+ }
+ if (SanArgs.needsScudoRt())
+ SharedRuntimes.push_back("scudo");
+ if (SanArgs.needsHwasanRt())
+ SharedRuntimes.push_back("hwasan");
}
+
// The stats_client library is also statically linked into DSOs.
if (SanArgs.needsStatsRt())
StaticRuntimes.push_back("stats_client");
// Collect static runtimes.
- if (Args.hasArg(options::OPT_shared) || TC.getTriple().isAndroid()) {
- // Don't link static runtimes into DSOs or if compiling for Android.
+ if (Args.hasArg(options::OPT_shared) || SanArgs.needsSharedRt()) {
+ // Don't link static runtimes into DSOs or if -shared-libasan.
return;
}
if (SanArgs.needsAsanRt()) {
- if (SanArgs.needsSharedAsanRt()) {
- HelperStaticRuntimes.push_back("asan-preinit");
- } else {
- StaticRuntimes.push_back("asan");
- if (SanArgs.linkCXXRuntimes())
- StaticRuntimes.push_back("asan_cxx");
- }
+ StaticRuntimes.push_back("asan");
+ if (SanArgs.linkCXXRuntimes())
+ StaticRuntimes.push_back("asan_cxx");
+ }
+
+ if (SanArgs.needsHwasanRt()) {
+ StaticRuntimes.push_back("hwasan");
+ if (SanArgs.linkCXXRuntimes())
+ StaticRuntimes.push_back("hwasan_cxx");
}
if (SanArgs.needsDfsanRt())
StaticRuntimes.push_back("dfsan");
@@ -574,9 +614,13 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
StaticRuntimes.push_back("tsan_cxx");
}
if (SanArgs.needsUbsanRt()) {
- StaticRuntimes.push_back("ubsan_standalone");
- if (SanArgs.linkCXXRuntimes())
- StaticRuntimes.push_back("ubsan_standalone_cxx");
+ if (SanArgs.requiresMinimalRuntime()) {
+ StaticRuntimes.push_back("ubsan_minimal");
+ } else {
+ StaticRuntimes.push_back("ubsan_standalone");
+ if (SanArgs.linkCXXRuntimes())
+ StaticRuntimes.push_back("ubsan_standalone_cxx");
+ }
}
if (SanArgs.needsSafeStackRt()) {
NonWholeStaticRuntimes.push_back("safestack");
@@ -595,19 +639,13 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
}
if (SanArgs.needsEsanRt())
StaticRuntimes.push_back("esan");
+ if (SanArgs.needsScudoRt()) {
+ StaticRuntimes.push_back("scudo");
+ if (SanArgs.linkCXXRuntimes())
+ StaticRuntimes.push_back("scudo_cxx");
+ }
}
-static void addLibFuzzerRuntime(const ToolChain &TC,
- const ArgList &Args,
- ArgStringList &CmdArgs) {
- StringRef ParentDir = llvm::sys::path::parent_path(TC.getDriver().InstalledDir);
- SmallString<128> P(ParentDir);
- llvm::sys::path::append(P, "lib", "libLLVMFuzzer.a");
- CmdArgs.push_back(Args.MakeArgString(P));
- TC.AddCXXStdlibLibArgs(Args, CmdArgs);
-}
-
-
// Should be called before we add system libraries (C++ ABI, libstdc++/libc++,
// C runtime, etc). Returns true if sanitizer system deps need to be linked in.
bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
@@ -617,10 +655,14 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
collectSanitizerRuntimes(TC, Args, SharedRuntimes, StaticRuntimes,
NonWholeStaticRuntimes, HelperStaticRuntimes,
RequiredSymbols);
+
// Inject libfuzzer dependencies.
if (TC.getSanitizerArgs().needsFuzzer()
&& !Args.hasArg(options::OPT_shared)) {
- addLibFuzzerRuntime(TC, Args, CmdArgs);
+
+ addSanitizerRuntime(TC, Args, CmdArgs, "fuzzer", false, true);
+ if (!Args.hasArg(clang::driver::options::OPT_nostdlibxx))
+ TC.AddCXXStdlibLibArgs(Args, CmdArgs);
}
for (auto RT : SharedRuntimes)
@@ -691,7 +733,8 @@ void tools::SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T,
ExtractArgs.push_back(Output.getFilename());
ExtractArgs.push_back(OutFile);
- const char *Exec = Args.MakeArgString(TC.GetProgramPath("objcopy"));
+ const char *Exec =
+ Args.MakeArgString(TC.GetProgramPath(CLANG_DEFAULT_OBJCOPY));
InputInfo II(types::TY_Object, Output.getFilename(), Output.getFilename());
// First extract the dwo sections.
@@ -999,15 +1042,7 @@ void tools::AddRunTimeLibs(const ToolChain &TC, const Driver &D,
switch (RLT) {
case ToolChain::RLT_CompilerRT:
- switch (TC.getTriple().getOS()) {
- default:
- llvm_unreachable("unsupported OS");
- case llvm::Triple::Win32:
- case llvm::Triple::Linux:
- case llvm::Triple::Fuchsia:
- CmdArgs.push_back(TC.getCompilerRTArgString(Args, "builtins"));
- break;
- }
+ CmdArgs.push_back(TC.getCompilerRTArgString(Args, "builtins"));
break;
case ToolChain::RLT_Libgcc:
// Make sure libgcc is not used under MSVC environment by default
@@ -1023,3 +1058,128 @@ void tools::AddRunTimeLibs(const ToolChain &TC, const Driver &D,
break;
}
}
+
+/// Add OpenMP linker script arguments at the end of the argument list so that
+/// the fat binary is built by embedding each of the device images into the
+/// host. The linker script also defines a few symbols required by the code
+/// generation so that the images can be easily retrieved at runtime by the
+/// offloading library. This should be used only in tool chains that support
+/// linker scripts.
+void tools::AddOpenMPLinkerScript(const ToolChain &TC, Compilation &C,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args, ArgStringList &CmdArgs,
+ const JobAction &JA) {
+
+ // If this is not an OpenMP host toolchain, we don't need to do anything.
+ if (!JA.isHostOffloading(Action::OFK_OpenMP))
+ return;
+
+ // Create temporary linker script. Keep it if save-temps is enabled.
+ const char *LKS;
+ SmallString<256> Name = llvm::sys::path::filename(Output.getFilename());
+ if (C.getDriver().isSaveTempsEnabled()) {
+ llvm::sys::path::replace_extension(Name, "lk");
+ LKS = C.getArgs().MakeArgString(Name.c_str());
+ } else {
+ llvm::sys::path::replace_extension(Name, "");
+ Name = C.getDriver().GetTemporaryPath(Name, "lk");
+ LKS = C.addTempFile(C.getArgs().MakeArgString(Name.c_str()));
+ }
+
+ // Add linker script option to the command.
+ CmdArgs.push_back("-T");
+ CmdArgs.push_back(LKS);
+
+ // Create a buffer to write the contents of the linker script.
+ std::string LksBuffer;
+ llvm::raw_string_ostream LksStream(LksBuffer);
+
+ // Get the OpenMP offload tool chains so that we can extract the triple
+ // associated with each device input.
+ auto OpenMPToolChains = C.getOffloadToolChains<Action::OFK_OpenMP>();
+ assert(OpenMPToolChains.first != OpenMPToolChains.second &&
+ "No OpenMP toolchains??");
+
+ // Track the input file name and device triple in order to build the script,
+ // inserting binaries in the designated sections.
+ SmallVector<std::pair<std::string, const char *>, 8> InputBinaryInfo;
+
+ // Add commands to embed target binaries. We ensure that each section and
+ // image is 16-byte aligned. This is not mandatory, but increases the
+ // likelihood of data to be aligned with a cache block in several main host
+ // machines.
+ LksStream << "/*\n";
+ LksStream << " OpenMP Offload Linker Script\n";
+ LksStream << " *** Automatically generated by Clang ***\n";
+ LksStream << "*/\n";
+ LksStream << "TARGET(binary)\n";
+ auto DTC = OpenMPToolChains.first;
+ for (auto &II : Inputs) {
+ const Action *A = II.getAction();
+ // Is this a device linking action?
+ if (A && isa<LinkJobAction>(A) &&
+ A->isDeviceOffloading(Action::OFK_OpenMP)) {
+ assert(DTC != OpenMPToolChains.second &&
+ "More device inputs than device toolchains??");
+ InputBinaryInfo.push_back(std::make_pair(
+ DTC->second->getTriple().normalize(), II.getFilename()));
+ ++DTC;
+ LksStream << "INPUT(" << II.getFilename() << ")\n";
+ }
+ }
+
+ assert(DTC == OpenMPToolChains.second &&
+ "Less device inputs than device toolchains??");
+
+ LksStream << "SECTIONS\n";
+ LksStream << "{\n";
+
+ // Put each target binary into a separate section.
+ for (const auto &BI : InputBinaryInfo) {
+ LksStream << " .omp_offloading." << BI.first << " :\n";
+ LksStream << " ALIGN(0x10)\n";
+ LksStream << " {\n";
+ LksStream << " PROVIDE_HIDDEN(.omp_offloading.img_start." << BI.first
+ << " = .);\n";
+ LksStream << " " << BI.second << "\n";
+ LksStream << " PROVIDE_HIDDEN(.omp_offloading.img_end." << BI.first
+ << " = .);\n";
+ LksStream << " }\n";
+ }
+
+ // Add commands to define host entries begin and end. We use 1-byte subalign
+ // so that the linker does not add any padding and the elements in this
+ // section form an array.
+ LksStream << " .omp_offloading.entries :\n";
+ LksStream << " ALIGN(0x10)\n";
+ LksStream << " SUBALIGN(0x01)\n";
+ LksStream << " {\n";
+ LksStream << " PROVIDE_HIDDEN(.omp_offloading.entries_begin = .);\n";
+ LksStream << " *(.omp_offloading.entries)\n";
+ LksStream << " PROVIDE_HIDDEN(.omp_offloading.entries_end = .);\n";
+ LksStream << " }\n";
+ LksStream << "}\n";
+ LksStream << "INSERT BEFORE .data\n";
+ LksStream.flush();
+
+ // Dump the contents of the linker script if the user requested that. We
+ // support this option to enable testing of behavior with -###.
+ if (C.getArgs().hasArg(options::OPT_fopenmp_dump_offload_linker_script))
+ llvm::errs() << LksBuffer;
+
+ // If this is a dry run, do not create the linker script file.
+ if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH))
+ return;
+
+ // Open script file and write the contents.
+ std::error_code EC;
+ llvm::raw_fd_ostream Lksf(LKS, EC, llvm::sys::fs::F_None);
+
+ if (EC) {
+ C.getDriver().Diag(clang::diag::err_unable_to_make_temp) << EC.message();
+ return;
+ }
+
+ Lksf << LksBuffer;
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/CommonArgs.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/CommonArgs.h
index fdeb6669b0a8d..012f5b9f87ae9 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/CommonArgs.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/CommonArgs.h
@@ -39,6 +39,13 @@ void AddRunTimeLibs(const ToolChain &TC, const Driver &D,
llvm::opt::ArgStringList &CmdArgs,
const llvm::opt::ArgList &Args);
+void AddOpenMPLinkerScript(const ToolChain &TC, Compilation &C,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs,
+ const JobAction &JA);
+
const char *SplitDebugName(const llvm::opt::ArgList &Args,
const InputInfo &Input);
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/CrossWindows.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/CrossWindows.cpp
index 04b71c48cd4cd..5049033c41372 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/CrossWindows.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/CrossWindows.cpp
@@ -36,6 +36,7 @@ void tools::CrossWindows::Assembler::ConstructJob(
llvm_unreachable("unsupported architecture");
case llvm::Triple::arm:
case llvm::Triple::thumb:
+ case llvm::Triple::aarch64:
break;
case llvm::Triple::x86:
CmdArgs.push_back("--32");
@@ -98,6 +99,9 @@ void tools::CrossWindows::Linker::ConstructJob(
// FIXME: this is incorrect for WinCE
CmdArgs.push_back("thumb2pe");
break;
+ case llvm::Triple::aarch64:
+ CmdArgs.push_back("arm64pe");
+ break;
case llvm::Triple::x86:
CmdArgs.push_back("i386pe");
EntryPoint.append("_");
@@ -111,6 +115,7 @@ void tools::CrossWindows::Linker::ConstructJob(
switch (T.getArch()) {
default:
llvm_unreachable("unsupported architecture");
+ case llvm::Triple::aarch64:
case llvm::Triple::arm:
case llvm::Triple::thumb:
case llvm::Triple::x86_64:
@@ -160,8 +165,7 @@ void tools::CrossWindows::Linker::ConstructJob(
TC.AddFilePathLibArgs(Args, CmdArgs);
AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
- if (D.CCCIsCXX() && !Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (TC.ShouldLinkCXXStdlib(Args)) {
bool StaticCXX = Args.hasArg(options::OPT_static_libstdcxx) &&
!Args.hasArg(options::OPT_static);
if (StaticCXX)
@@ -203,16 +207,7 @@ void tools::CrossWindows::Linker::ConstructJob(
CrossWindowsToolChain::CrossWindowsToolChain(const Driver &D,
const llvm::Triple &T,
const llvm::opt::ArgList &Args)
- : Generic_GCC(D, T, Args) {
- if (D.CCCIsCXX() && GetCXXStdlibType(Args) == ToolChain::CST_Libstdcxx) {
- const std::string &SysRoot = D.SysRoot;
-
- // libstdc++ resides in /usr/lib, but depends on libgcc which is placed in
- // /usr/lib/gcc.
- getFilePaths().push_back(SysRoot + "/usr/lib");
- getFilePaths().push_back(SysRoot + "/usr/lib/gcc");
- }
-}
+ : Generic_GCC(D, T, Args) {}
bool CrossWindowsToolChain::IsUnwindTablesDefault(const ArgList &Args) const {
// FIXME: all non-x86 targets need unwind tables, however, LLVM currently does
@@ -261,43 +256,21 @@ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
void CrossWindowsToolChain::
AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
- const llvm::Triple &Triple = getTriple();
const std::string &SysRoot = getDriver().SysRoot;
if (DriverArgs.hasArg(options::OPT_nostdinc) ||
DriverArgs.hasArg(options::OPT_nostdincxx))
return;
- switch (GetCXXStdlibType(DriverArgs)) {
- case ToolChain::CST_Libcxx:
+ if (GetCXXStdlibType(DriverArgs) == ToolChain::CST_Libcxx)
addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include/c++/v1");
- break;
-
- case ToolChain::CST_Libstdcxx:
- addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include/c++");
- addSystemInclude(DriverArgs, CC1Args,
- SysRoot + "/usr/include/c++/" + Triple.str());
- addSystemInclude(DriverArgs, CC1Args,
- SysRoot + "/usr/include/c++/backwards");
- }
}
void CrossWindowsToolChain::
AddCXXStdlibLibArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
- switch (GetCXXStdlibType(DriverArgs)) {
- case ToolChain::CST_Libcxx:
+ if (GetCXXStdlibType(DriverArgs) == ToolChain::CST_Libcxx)
CC1Args.push_back("-lc++");
- break;
- case ToolChain::CST_Libstdcxx:
- CC1Args.push_back("-lstdc++");
- CC1Args.push_back("-lmingw32");
- CC1Args.push_back("-lmingwex");
- CC1Args.push_back("-lgcc");
- CC1Args.push_back("-lmoldname");
- CC1Args.push_back("-lmingw32");
- break;
- }
}
clang::SanitizerMask CrossWindowsToolChain::getSupportedSanitizers() const {
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Cuda.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Cuda.cpp
index 935a5a37ada52..bc4820797b2f4 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Cuda.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Cuda.cpp
@@ -9,8 +9,11 @@
#include "Cuda.h"
#include "InputInfo.h"
+#include "CommonArgs.h"
#include "clang/Basic/Cuda.h"
+#include "clang/Config/config.h"
#include "clang/Basic/VirtualFileSystem.h"
+#include "clang/Driver/Distro.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
@@ -47,6 +50,8 @@ static CudaVersion ParseCudaVersionFile(llvm::StringRef V) {
return CudaVersion::CUDA_75;
if (Major == 8 && Minor == 0)
return CudaVersion::CUDA_80;
+ if (Major == 9 && Minor == 0)
+ return CudaVersion::CUDA_90;
return CudaVersion::UNKNOWN;
}
@@ -71,6 +76,11 @@ CudaInstallationDetector::CudaInstallationDetector(
CudaPathCandidates.push_back(D.SysRoot + "/usr/local/cuda");
for (const char *Ver : Versions)
CudaPathCandidates.push_back(D.SysRoot + "/usr/local/cuda-" + Ver);
+
+ if (Distro(D.getVFS()).IsDebian())
+ // Special case for Debian to have nvidia-cuda-toolkit work
+ // out of the box. More info on http://bugs.debian.org/882505
+ CudaPathCandidates.push_back(D.SysRoot + "/usr/lib/cuda");
}
for (const auto &CudaPath : CudaPathCandidates) {
@@ -83,8 +93,7 @@ CudaInstallationDetector::CudaInstallationDetector(
LibDevicePath = InstallPath + "/nvvm/libdevice";
auto &FS = D.getVFS();
- if (!(FS.exists(IncludePath) && FS.exists(BinPath) &&
- FS.exists(LibDevicePath)))
+ if (!(FS.exists(IncludePath) && FS.exists(BinPath)))
continue;
// On Linux, we have both lib and lib64 directories, and we need to choose
@@ -110,47 +119,64 @@ CudaInstallationDetector::CudaInstallationDetector(
Version = ParseCudaVersionFile((*VersionFile)->getBuffer());
}
- std::error_code EC;
- for (llvm::sys::fs::directory_iterator LI(LibDevicePath, EC), LE;
- !EC && LI != LE; LI = LI.increment(EC)) {
- StringRef FilePath = LI->path();
- StringRef FileName = llvm::sys::path::filename(FilePath);
- // Process all bitcode filenames that look like libdevice.compute_XX.YY.bc
- const StringRef LibDeviceName = "libdevice.";
- if (!(FileName.startswith(LibDeviceName) && FileName.endswith(".bc")))
- continue;
- StringRef GpuArch = FileName.slice(
- LibDeviceName.size(), FileName.find('.', LibDeviceName.size()));
- LibDeviceMap[GpuArch] = FilePath.str();
- // Insert map entries for specifc devices with this compute
- // capability. NVCC's choice of the libdevice library version is
- // rather peculiar and depends on the CUDA version.
- if (GpuArch == "compute_20") {
- LibDeviceMap["sm_20"] = FilePath;
- LibDeviceMap["sm_21"] = FilePath;
- LibDeviceMap["sm_32"] = FilePath;
- } else if (GpuArch == "compute_30") {
- LibDeviceMap["sm_30"] = FilePath;
- if (Version < CudaVersion::CUDA_80) {
- LibDeviceMap["sm_50"] = FilePath;
- LibDeviceMap["sm_52"] = FilePath;
- LibDeviceMap["sm_53"] = FilePath;
- }
- LibDeviceMap["sm_60"] = FilePath;
- LibDeviceMap["sm_61"] = FilePath;
- LibDeviceMap["sm_62"] = FilePath;
- } else if (GpuArch == "compute_35") {
- LibDeviceMap["sm_35"] = FilePath;
- LibDeviceMap["sm_37"] = FilePath;
- } else if (GpuArch == "compute_50") {
- if (Version >= CudaVersion::CUDA_80) {
- LibDeviceMap["sm_50"] = FilePath;
- LibDeviceMap["sm_52"] = FilePath;
- LibDeviceMap["sm_53"] = FilePath;
+ if (Version == CudaVersion::CUDA_90) {
+ // CUDA-9 uses single libdevice file for all GPU variants.
+ std::string FilePath = LibDevicePath + "/libdevice.10.bc";
+ if (FS.exists(FilePath)) {
+ for (const char *GpuArch :
+ {"sm_20", "sm_30", "sm_32", "sm_35", "sm_50", "sm_52", "sm_53",
+ "sm_60", "sm_61", "sm_62", "sm_70"})
+ LibDeviceMap[GpuArch] = FilePath;
+ }
+ } else {
+ std::error_code EC;
+ for (llvm::sys::fs::directory_iterator LI(LibDevicePath, EC), LE;
+ !EC && LI != LE; LI = LI.increment(EC)) {
+ StringRef FilePath = LI->path();
+ StringRef FileName = llvm::sys::path::filename(FilePath);
+ // Process all bitcode filenames that look like
+ // libdevice.compute_XX.YY.bc
+ const StringRef LibDeviceName = "libdevice.";
+ if (!(FileName.startswith(LibDeviceName) && FileName.endswith(".bc")))
+ continue;
+ StringRef GpuArch = FileName.slice(
+ LibDeviceName.size(), FileName.find('.', LibDeviceName.size()));
+ LibDeviceMap[GpuArch] = FilePath.str();
+ // Insert map entries for specifc devices with this compute
+ // capability. NVCC's choice of the libdevice library version is
+ // rather peculiar and depends on the CUDA version.
+ if (GpuArch == "compute_20") {
+ LibDeviceMap["sm_20"] = FilePath;
+ LibDeviceMap["sm_21"] = FilePath;
+ LibDeviceMap["sm_32"] = FilePath;
+ } else if (GpuArch == "compute_30") {
+ LibDeviceMap["sm_30"] = FilePath;
+ if (Version < CudaVersion::CUDA_80) {
+ LibDeviceMap["sm_50"] = FilePath;
+ LibDeviceMap["sm_52"] = FilePath;
+ LibDeviceMap["sm_53"] = FilePath;
+ }
+ LibDeviceMap["sm_60"] = FilePath;
+ LibDeviceMap["sm_61"] = FilePath;
+ LibDeviceMap["sm_62"] = FilePath;
+ } else if (GpuArch == "compute_35") {
+ LibDeviceMap["sm_35"] = FilePath;
+ LibDeviceMap["sm_37"] = FilePath;
+ } else if (GpuArch == "compute_50") {
+ if (Version >= CudaVersion::CUDA_80) {
+ LibDeviceMap["sm_50"] = FilePath;
+ LibDeviceMap["sm_52"] = FilePath;
+ LibDeviceMap["sm_53"] = FilePath;
+ }
}
}
}
+ // Check that we have found at least one libdevice that we can link in if
+ // -nocudalib hasn't been specified.
+ if (LibDeviceMap.empty() && !Args.hasArg(options::OPT_nocudalib))
+ continue;
+
IsValid = true;
break;
}
@@ -185,15 +211,17 @@ void CudaInstallationDetector::AddCudaIncludeArgs(
void CudaInstallationDetector::CheckCudaVersionSupportsArch(
CudaArch Arch) const {
if (Arch == CudaArch::UNKNOWN || Version == CudaVersion::UNKNOWN ||
- ArchsWithVersionTooLowErrors.count(Arch) > 0)
+ ArchsWithBadVersion.count(Arch) > 0)
return;
- auto RequiredVersion = MinVersionForCudaArch(Arch);
- if (Version < RequiredVersion) {
- ArchsWithVersionTooLowErrors.insert(Arch);
- D.Diag(diag::err_drv_cuda_version_too_low)
- << InstallPath << CudaArchToString(Arch) << CudaVersionToString(Version)
- << CudaVersionToString(RequiredVersion);
+ auto MinVersion = MinVersionForCudaArch(Arch);
+ auto MaxVersion = MaxVersionForCudaArch(Arch);
+ if (Version < MinVersion || Version > MaxVersion) {
+ ArchsWithBadVersion.insert(Arch);
+ D.Diag(diag::err_drv_cuda_version_unsupported)
+ << CudaArchToString(Arch) << CudaVersionToString(MinVersion)
+ << CudaVersionToString(MaxVersion) << InstallPath
+ << CudaVersionToString(Version);
}
}
@@ -212,8 +240,18 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
static_cast<const toolchains::CudaToolChain &>(getToolChain());
assert(TC.getTriple().isNVPTX() && "Wrong platform");
+ StringRef GPUArchName;
+ // If this is an OpenMP action we need to extract the device architecture
+ // from the -march=arch option. This option may come from -Xopenmp-target
+ // flag or the default value.
+ if (JA.isDeviceOffloading(Action::OFK_OpenMP)) {
+ GPUArchName = Args.getLastArgValue(options::OPT_march_EQ);
+ assert(!GPUArchName.empty() && "Must have an architecture passed in.");
+ } else
+ GPUArchName = JA.getOffloadingArch();
+
// Obtain architecture from the action.
- CudaArch gpu_arch = StringToCudaArch(JA.getOffloadingArch());
+ CudaArch gpu_arch = StringToCudaArch(GPUArchName);
assert(gpu_arch != CudaArch::UNKNOWN &&
"Device action expected to have an architecture.");
@@ -262,16 +300,27 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-O0");
}
+ // Pass -v to ptxas if it was passed to the driver.
+ if (Args.hasArg(options::OPT_v))
+ CmdArgs.push_back("-v");
+
CmdArgs.push_back("--gpu-name");
CmdArgs.push_back(Args.MakeArgString(CudaArchToString(gpu_arch)));
CmdArgs.push_back("--output-file");
- CmdArgs.push_back(Args.MakeArgString(Output.getFilename()));
+ CmdArgs.push_back(Args.MakeArgString(TC.getInputFilename(Output)));
for (const auto& II : Inputs)
CmdArgs.push_back(Args.MakeArgString(II.getFilename()));
for (const auto& A : Args.getAllArgValues(options::OPT_Xcuda_ptxas))
CmdArgs.push_back(Args.MakeArgString(A));
+ // In OpenMP we need to generate relocatable code.
+ if (JA.isOffloading(Action::OFK_OpenMP) &&
+ Args.hasFlag(options::OPT_fopenmp_relocatable_target,
+ options::OPT_fnoopenmp_relocatable_target,
+ /*Default=*/ true))
+ CmdArgs.push_back("-c");
+
const char *Exec;
if (Arg *A = Args.getLastArg(options::OPT_ptxas_path_EQ))
Exec = A->getValue();
@@ -324,16 +373,108 @@ void NVPTX::Linker::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
+void NVPTX::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const auto &TC =
+ static_cast<const toolchains::CudaToolChain &>(getToolChain());
+ assert(TC.getTriple().isNVPTX() && "Wrong platform");
+
+ ArgStringList CmdArgs;
+
+ // OpenMP uses nvlink to link cubin files. The result will be embedded in the
+ // host binary by the host linker.
+ assert(!JA.isHostOffloading(Action::OFK_OpenMP) &&
+ "CUDA toolchain not expected for an OpenMP host device.");
+
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else
+ assert(Output.isNothing() && "Invalid output.");
+ if (Args.hasArg(options::OPT_g_Flag))
+ CmdArgs.push_back("-g");
+
+ if (Args.hasArg(options::OPT_v))
+ CmdArgs.push_back("-v");
+
+ StringRef GPUArch =
+ Args.getLastArgValue(options::OPT_march_EQ);
+ assert(!GPUArch.empty() && "At least one GPU Arch required for ptxas.");
+
+ CmdArgs.push_back("-arch");
+ CmdArgs.push_back(Args.MakeArgString(GPUArch));
+
+ // Add paths specified in LIBRARY_PATH environment variable as -L options.
+ addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH");
+
+ // Add paths for the default clang library path.
+ SmallString<256> DefaultLibPath =
+ llvm::sys::path::parent_path(TC.getDriver().Dir);
+ llvm::sys::path::append(DefaultLibPath, "lib" CLANG_LIBDIR_SUFFIX);
+ CmdArgs.push_back(Args.MakeArgString(Twine("-L") + DefaultLibPath));
+
+ // Add linking against library implementing OpenMP calls on NVPTX target.
+ CmdArgs.push_back("-lomptarget-nvptx");
+
+ for (const auto &II : Inputs) {
+ if (II.getType() == types::TY_LLVM_IR ||
+ II.getType() == types::TY_LTO_IR ||
+ II.getType() == types::TY_LTO_BC ||
+ II.getType() == types::TY_LLVM_BC) {
+ C.getDriver().Diag(diag::err_drv_no_linker_llvm_support)
+ << getToolChain().getTripleString();
+ continue;
+ }
+
+ // Currently, we only pass the input files to the linker, we do not pass
+ // any libraries that may be valid only for the host.
+ if (!II.isFilename())
+ continue;
+
+ const char *CubinF = C.addTempFile(
+ C.getArgs().MakeArgString(getToolChain().getInputFilename(II)));
+
+ CmdArgs.push_back(CubinF);
+ }
+
+ AddOpenMPLinkerScript(getToolChain(), C, Output, Inputs, Args, CmdArgs, JA);
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("nvlink"));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+}
+
/// CUDA toolchain. Our assembler is ptxas, and our "linker" is fatbinary,
/// which isn't properly a linker but nonetheless performs the step of stitching
/// together object files from the assembler into a single blob.
CudaToolChain::CudaToolChain(const Driver &D, const llvm::Triple &Triple,
- const ToolChain &HostTC, const ArgList &Args)
+ const ToolChain &HostTC, const ArgList &Args,
+ const Action::OffloadKind OK)
: ToolChain(D, Triple, Args), HostTC(HostTC),
- CudaInstallation(D, HostTC.getTriple(), Args) {
+ CudaInstallation(D, HostTC.getTriple(), Args), OK(OK) {
if (CudaInstallation.isValid())
getProgramPaths().push_back(CudaInstallation.getBinPath());
+ // Lookup binaries into the driver directory, this is used to
+ // discover the clang-offload-bundler executable.
+ getProgramPaths().push_back(getDriver().Dir);
+}
+
+std::string CudaToolChain::getInputFilename(const InputInfo &Input) const {
+ // Only object files are changed, for example assembly files keep their .s
+ // extensions. CUDA also continues to use .o as they don't use nvlink but
+ // fatbinary.
+ if (!(OK == Action::OFK_OpenMP && Input.getType() == types::TY_Object))
+ return ToolChain::getInputFilename(Input);
+
+ // Replace extension for object files with cubin because nvlink relies on
+ // these particular file names.
+ SmallString<256> Filename(ToolChain::getInputFilename(Input));
+ llvm::sys::path::replace_extension(Filename, "cubin");
+ return Filename.str();
}
void CudaToolChain::addClangTargetOptions(
@@ -358,14 +499,18 @@ void CudaToolChain::addClangTargetOptions(
if (DriverArgs.hasFlag(options::OPT_fcuda_approx_transcendentals,
options::OPT_fno_cuda_approx_transcendentals, false))
CC1Args.push_back("-fcuda-approx-transcendentals");
-
- if (DriverArgs.hasArg(options::OPT_nocudalib))
- return;
}
+ if (DriverArgs.hasArg(options::OPT_nocudalib))
+ return;
+
std::string LibDeviceFile = CudaInstallation.getLibDeviceFile(GpuArch);
if (LibDeviceFile.empty()) {
+ if (DeviceOffloadingKind == Action::OFK_OpenMP &&
+ DriverArgs.hasArg(options::OPT_S))
+ return;
+
getDriver().Diag(diag::err_drv_no_cuda_libdevice) << GpuArch;
return;
}
@@ -373,11 +518,17 @@ void CudaToolChain::addClangTargetOptions(
CC1Args.push_back("-mlink-cuda-bitcode");
CC1Args.push_back(DriverArgs.MakeArgString(LibDeviceFile));
- // Libdevice in CUDA-7.0 requires PTX version that's more recent
- // than LLVM defaults to. Use PTX4.2 which is the PTX version that
- // came with CUDA-7.0.
- CC1Args.push_back("-target-feature");
- CC1Args.push_back("+ptx42");
+ if (CudaInstallation.version() >= CudaVersion::CUDA_90) {
+ // CUDA-9 uses new instructions that are only available in PTX6.0
+ CC1Args.push_back("-target-feature");
+ CC1Args.push_back("+ptx60");
+ } else {
+ // Libdevice in CUDA-7.0 requires PTX version that's more recent
+ // than LLVM defaults to. Use PTX4.2 which is the PTX version that
+ // came with CUDA-7.0.
+ CC1Args.push_back("-target-feature");
+ CC1Args.push_back("+ptx42");
+ }
}
void CudaToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
@@ -405,11 +556,11 @@ CudaToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
// For OpenMP device offloading, append derived arguments. Make sure
// flags are not duplicated.
- // TODO: Append the compute capability.
+ // Also append the compute capability.
if (DeviceOffloadKind == Action::OFK_OpenMP) {
- for (Arg *A : Args){
+ for (Arg *A : Args) {
bool IsDuplicate = false;
- for (Arg *DALArg : *DAL){
+ for (Arg *DALArg : *DAL) {
if (A == DALArg) {
IsDuplicate = true;
break;
@@ -418,6 +569,12 @@ CudaToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
if (!IsDuplicate)
DAL->append(A);
}
+
+ StringRef Arch = DAL->getLastArgValue(options::OPT_march_EQ);
+ if (Arch.empty())
+ DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ),
+ CLANG_OPENMP_NVPTX_DEFAULT_ARCH);
+
return DAL;
}
@@ -467,6 +624,8 @@ Tool *CudaToolChain::buildAssembler() const {
}
Tool *CudaToolChain::buildLinker() const {
+ if (OK == Action::OFK_OpenMP)
+ return new tools::NVPTX::OpenMPLinker(*this);
return new tools::NVPTX::Linker(*this);
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Cuda.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Cuda.h
index e66fc23d82f35..3d08cec1643ee 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Cuda.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Cuda.h
@@ -40,7 +40,7 @@ private:
// CUDA architectures for which we have raised an error in
// CheckCudaVersionSupportsArch.
- mutable llvm::SmallSet<CudaArch, 4> ArchsWithVersionTooLowErrors;
+ mutable llvm::SmallSet<CudaArch, 4> ArchsWithBadVersion;
public:
CudaInstallationDetector(const Driver &D, const llvm::Triple &HostTriple,
@@ -112,6 +112,20 @@ class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
const char *LinkingOutput) const override;
};
+class LLVM_LIBRARY_VISIBILITY OpenMPLinker : public Tool {
+ public:
+ OpenMPLinker(const ToolChain &TC)
+ : Tool("NVPTX::OpenMPLinker", "fatbinary", TC, RF_Full, llvm::sys::WEM_UTF8,
+ "--options-file") {}
+
+ bool hasIntegratedCPP() const override { return false; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+
} // end namespace NVPTX
} // end namespace tools
@@ -120,12 +134,15 @@ namespace toolchains {
class LLVM_LIBRARY_VISIBILITY CudaToolChain : public ToolChain {
public:
CudaToolChain(const Driver &D, const llvm::Triple &Triple,
- const ToolChain &HostTC, const llvm::opt::ArgList &Args);
+ const ToolChain &HostTC, const llvm::opt::ArgList &Args,
+ const Action::OffloadKind OK);
- virtual const llvm::Triple *getAuxTriple() const override {
+ const llvm::Triple *getAuxTriple() const override {
return &HostTC.getTriple();
}
+ std::string getInputFilename(const InputInfo &Input) const override;
+
llvm::opt::DerivedArgList *
TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
Action::OffloadKind DeviceOffloadKind) const override;
@@ -141,7 +158,7 @@ public:
bool isPIEDefault() const override { return false; }
bool isPICDefaultForced() const override { return false; }
bool SupportsProfiling() const override { return false; }
- bool SupportsObjCGC() const override { return false; }
+ bool IsMathErrnoDefault() const override { return false; }
void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
@@ -169,6 +186,9 @@ public:
protected:
Tool *buildAssembler() const override; // ptxas
Tool *buildLinker() const override; // fatbinary (ok, not really a linker)
+
+private:
+ const Action::OffloadKind OK;
};
} // end namespace toolchains
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Darwin.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Darwin.cpp
index 32103a6120d40..28efa86538edf 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -10,6 +10,7 @@
#include "Darwin.h"
#include "Arch/ARM.h"
#include "CommonArgs.h"
+#include "clang/Basic/AlignedAllocation.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Driver/Compilation.h"
@@ -67,14 +68,14 @@ llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) {
void darwin::setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str) {
const llvm::Triple::ArchType Arch = getArchTypeForMachOArchName(Str);
- unsigned ArchKind = llvm::ARM::parseArch(Str);
+ llvm::ARM::ArchKind ArchKind = llvm::ARM::parseArch(Str);
T.setArch(Arch);
if (Str == "x86_64h")
T.setArchName(Str);
- else if (ArchKind == llvm::ARM::AK_ARMV6M ||
- ArchKind == llvm::ARM::AK_ARMV7M ||
- ArchKind == llvm::ARM::AK_ARMV7EM) {
+ else if (ArchKind == llvm::ARM::ArchKind::ARMV6M ||
+ ArchKind == llvm::ARM::ArchKind::ARMV7M ||
+ ArchKind == llvm::ARM::ArchKind::ARMV7EM) {
T.setOS(llvm::Triple::UnknownOS);
T.setObjectFormat(llvm::Triple::MachO);
}
@@ -493,7 +494,7 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (getToolChain().getSanitizerArgs().needsSafeStackRt()) {
getMachOToolChain().AddLinkRuntimeLib(Args, CmdArgs,
"libclang_rt.safestack_osx.a",
- /*AlwaysLink=*/true);
+ toolchains::Darwin::RLO_AlwaysLink);
}
Args.AddAllArgs(CmdArgs, options::OPT_L);
@@ -548,10 +549,9 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.MakeArgString(Twine("-threads=") + llvm::to_string(Parallelism)));
}
+ if (getToolChain().ShouldLinkCXXStdlib(Args))
+ getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
- if (getToolChain().getDriver().CCCIsCXX())
- getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
-
// link_ssp spec is empty.
// Let the tool chain choose which runtime library to link.
@@ -739,8 +739,8 @@ static const char *ArmMachOArchName(StringRef Arch) {
}
static const char *ArmMachOArchNameCPU(StringRef CPU) {
- unsigned ArchKind = llvm::ARM::parseCPUArch(CPU);
- if (ArchKind == llvm::ARM::AK_INVALID)
+ llvm::ARM::ArchKind ArchKind = llvm::ARM::parseCPUArch(CPU);
+ if (ArchKind == llvm::ARM::ArchKind::INVALID)
return nullptr;
StringRef Arch = llvm::ARM::getArchName(ArchKind);
@@ -897,10 +897,11 @@ unsigned DarwinClang::GetDefaultDwarfVersion() const {
}
void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,
- StringRef DarwinLibName, bool AlwaysLink,
- bool IsEmbedded, bool AddRPath) const {
+ StringRef DarwinLibName,
+ RuntimeLinkOptions Opts) const {
SmallString<128> Dir(getDriver().ResourceDir);
- llvm::sys::path::append(Dir, "lib", IsEmbedded ? "macho_embedded" : "darwin");
+ llvm::sys::path::append(
+ Dir, "lib", (Opts & RLO_IsEmbedded) ? "macho_embedded" : "darwin");
SmallString<128> P(Dir);
llvm::sys::path::append(P, DarwinLibName);
@@ -908,14 +909,19 @@ void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,
// For now, allow missing resource libraries to support developers who may
// not have compiler-rt checked out or integrated into their build (unless
// we explicitly force linking with this library).
- if (AlwaysLink || getVFS().exists(P))
- CmdArgs.push_back(Args.MakeArgString(P));
+ if ((Opts & RLO_AlwaysLink) || getVFS().exists(P)) {
+ const char *LibArg = Args.MakeArgString(P);
+ if (Opts & RLO_FirstLink)
+ CmdArgs.insert(CmdArgs.begin(), LibArg);
+ else
+ CmdArgs.push_back(LibArg);
+ }
// Adding the rpaths might negatively interact when other rpaths are involved,
// so we should make sure we add the rpaths last, after all user-specified
// rpaths. This is currently true from this place, but we need to be
// careful if this function is ever called before user's rpaths are emitted.
- if (AddRPath) {
+ if (Opts & RLO_AddRPath) {
assert(DarwinLibName.endswith(".dylib") && "must be a dynamic library");
// Add @executable_path to rpath to support having the dylib copied with
@@ -930,30 +936,15 @@ void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,
}
}
-void MachO::AddFuzzerLinkArgs(const ArgList &Args, ArgStringList &CmdArgs) const {
-
- // Go up one directory from Clang to find the libfuzzer archive file.
- StringRef ParentDir = llvm::sys::path::parent_path(getDriver().InstalledDir);
- SmallString<128> P(ParentDir);
- llvm::sys::path::append(P, "lib", "libLLVMFuzzer.a");
- CmdArgs.push_back(Args.MakeArgString(P));
-
- // Libfuzzer is written in C++ and requires libcxx.
- AddCXXStdlibLibArgs(Args, CmdArgs);
-}
-
StringRef Darwin::getPlatformFamily() const {
switch (TargetPlatform) {
case DarwinPlatformKind::MacOS:
return "MacOSX";
case DarwinPlatformKind::IPhoneOS:
- case DarwinPlatformKind::IPhoneOSSimulator:
return "iPhone";
case DarwinPlatformKind::TvOS:
- case DarwinPlatformKind::TvOSSimulator:
return "AppleTV";
case DarwinPlatformKind::WatchOS:
- case DarwinPlatformKind::WatchOSSimulator:
return "Watch";
}
llvm_unreachable("Unsupported platform");
@@ -977,39 +968,65 @@ StringRef Darwin::getOSLibraryNameSuffix() const {
case DarwinPlatformKind::MacOS:
return "osx";
case DarwinPlatformKind::IPhoneOS:
- return "ios";
- case DarwinPlatformKind::IPhoneOSSimulator:
- return "iossim";
+ return TargetEnvironment == NativeEnvironment ? "ios" : "iossim";
case DarwinPlatformKind::TvOS:
- return "tvos";
- case DarwinPlatformKind::TvOSSimulator:
- return "tvossim";
+ return TargetEnvironment == NativeEnvironment ? "tvos" : "tvossim";
case DarwinPlatformKind::WatchOS:
- return "watchos";
- case DarwinPlatformKind::WatchOSSimulator:
- return "watchossim";
+ return TargetEnvironment == NativeEnvironment ? "watchos" : "watchossim";
}
llvm_unreachable("Unsupported platform");
}
+/// Check if the link command contains a symbol export directive.
+static bool hasExportSymbolDirective(const ArgList &Args) {
+ for (Arg *A : Args) {
+ if (!A->getOption().matches(options::OPT_Wl_COMMA) &&
+ !A->getOption().matches(options::OPT_Xlinker))
+ continue;
+ if (A->containsValue("-exported_symbols_list") ||
+ A->containsValue("-exported_symbol"))
+ return true;
+ }
+ return false;
+}
+
+/// Add an export directive for \p Symbol to the link command.
+static void addExportedSymbol(ArgStringList &CmdArgs, const char *Symbol) {
+ CmdArgs.push_back("-exported_symbol");
+ CmdArgs.push_back(Symbol);
+}
+
void Darwin::addProfileRTLibs(const ArgList &Args,
ArgStringList &CmdArgs) const {
if (!needsProfileRT(Args)) return;
- AddLinkRuntimeLib(Args, CmdArgs, (Twine("libclang_rt.profile_") +
- getOSLibraryNameSuffix() + ".a").str(),
- /*AlwaysLink*/ true);
+ AddLinkRuntimeLib(
+ Args, CmdArgs,
+ (Twine("libclang_rt.profile_") + getOSLibraryNameSuffix() + ".a").str(),
+ RuntimeLinkOptions(RLO_AlwaysLink | RLO_FirstLink));
+
+ // If we have a symbol export directive and we're linking in the profile
+ // runtime, automatically export symbols necessary to implement some of the
+ // runtime's functionality.
+ if (hasExportSymbolDirective(Args)) {
+ addExportedSymbol(CmdArgs, "_VPMergeHook");
+ addExportedSymbol(CmdArgs, "___llvm_profile_filename");
+ addExportedSymbol(CmdArgs, "___llvm_profile_raw_version");
+ addExportedSymbol(CmdArgs, "_lprofCurFilename");
+ }
}
void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args,
ArgStringList &CmdArgs,
- StringRef Sanitizer) const {
- AddLinkRuntimeLib(
- Args, CmdArgs,
- (Twine("libclang_rt.") + Sanitizer + "_" +
- getOSLibraryNameSuffix() + "_dynamic.dylib").str(),
- /*AlwaysLink*/ true, /*IsEmbedded*/ false,
- /*AddRPath*/ true);
+ StringRef Sanitizer,
+ bool Shared) const {
+ auto RLO = RuntimeLinkOptions(RLO_AlwaysLink | (Shared ? RLO_AddRPath : 0U));
+ AddLinkRuntimeLib(Args, CmdArgs,
+ (Twine("libclang_rt.") + Sanitizer + "_" +
+ getOSLibraryNameSuffix() +
+ (Shared ? "_dynamic.dylib" : ".a"))
+ .str(),
+ RLO);
}
ToolChain::RuntimeLibType DarwinClang::GetRuntimeLibType(
@@ -1050,16 +1067,23 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
if (Sanitize.needsLsanRt())
AddLinkSanitizerLibArgs(Args, CmdArgs, "lsan");
if (Sanitize.needsUbsanRt())
- AddLinkSanitizerLibArgs(Args, CmdArgs, "ubsan");
+ AddLinkSanitizerLibArgs(Args, CmdArgs,
+ Sanitize.requiresMinimalRuntime() ? "ubsan_minimal"
+ : "ubsan",
+ Sanitize.needsSharedRt());
if (Sanitize.needsTsanRt())
AddLinkSanitizerLibArgs(Args, CmdArgs, "tsan");
- if (Sanitize.needsFuzzer() && !Args.hasArg(options::OPT_dynamiclib))
- AddFuzzerLinkArgs(Args, CmdArgs);
+ if (Sanitize.needsFuzzer() && !Args.hasArg(options::OPT_dynamiclib)) {
+ AddLinkSanitizerLibArgs(Args, CmdArgs, "fuzzer", /*shared=*/false);
+
+ // Libfuzzer is written in C++ and requires libcxx.
+ AddCXXStdlibLibArgs(Args, CmdArgs);
+ }
if (Sanitize.needsStatsRt()) {
StringRef OS = isTargetMacOS() ? "osx" : "iossim";
AddLinkRuntimeLib(Args, CmdArgs,
(Twine("libclang_rt.stats_client_") + OS + ".a").str(),
- /*AlwaysLink=*/true);
+ RLO_AlwaysLink);
AddLinkSanitizerLibArgs(Args, CmdArgs, "stats");
}
if (Sanitize.needsEsanRt())
@@ -1139,28 +1163,132 @@ static std::string getSystemOrSDKMacOSVersion(StringRef MacOSSDKVersion) {
return MacOSSDKVersion;
}
-void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
- const OptTable &Opts = getDriver().getOpts();
+namespace {
- // Support allowing the SDKROOT environment variable used by xcrun and other
- // Xcode tools to define the default sysroot, by making it the default for
- // isysroot.
- if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
- // Warn if the path does not exist.
- if (!getVFS().exists(A->getValue()))
- getDriver().Diag(clang::diag::warn_missing_sysroot) << A->getValue();
- } else {
- if (char *env = ::getenv("SDKROOT")) {
- // We only use this value as the default if it is an absolute path,
- // exists, and it is not the root path.
- if (llvm::sys::path::is_absolute(env) && getVFS().exists(env) &&
- StringRef(env) != "/") {
- Args.append(Args.MakeSeparateArg(
- nullptr, Opts.getOption(options::OPT_isysroot), env));
- }
+/// The Darwin OS that was selected or inferred from arguments / environment.
+struct DarwinPlatform {
+ enum SourceKind {
+ /// The OS was specified using the -target argument.
+ TargetArg,
+ /// The OS was specified using the -m<os>-version-min argument.
+ OSVersionArg,
+ /// The OS was specified using the OS_DEPLOYMENT_TARGET environment.
+ DeploymentTargetEnv,
+ /// The OS was inferred from the SDK.
+ InferredFromSDK,
+ /// The OS was inferred from the -arch.
+ InferredFromArch
+ };
+
+ using DarwinPlatformKind = Darwin::DarwinPlatformKind;
+
+ DarwinPlatformKind getPlatform() const { return Platform; }
+
+ StringRef getOSVersion() const {
+ if (Kind == OSVersionArg)
+ return Argument->getValue();
+ return OSVersion;
+ }
+
+ /// Returns true if the target OS was explicitly specified.
+ bool isExplicitlySpecified() const { return Kind <= DeploymentTargetEnv; }
+
+ /// Adds the -m<os>-version-min argument to the compiler invocation.
+ void addOSVersionMinArgument(DerivedArgList &Args, const OptTable &Opts) {
+ if (Argument)
+ return;
+ assert(Kind != TargetArg && Kind != OSVersionArg && "Invalid kind");
+ options::ID Opt;
+ switch (Platform) {
+ case DarwinPlatformKind::MacOS:
+ Opt = options::OPT_mmacosx_version_min_EQ;
+ break;
+ case DarwinPlatformKind::IPhoneOS:
+ Opt = options::OPT_miphoneos_version_min_EQ;
+ break;
+ case DarwinPlatformKind::TvOS:
+ Opt = options::OPT_mtvos_version_min_EQ;
+ break;
+ case DarwinPlatformKind::WatchOS:
+ Opt = options::OPT_mwatchos_version_min_EQ;
+ break;
+ }
+ Argument = Args.MakeJoinedArg(nullptr, Opts.getOption(Opt), OSVersion);
+ Args.append(Argument);
+ }
+
+ /// Returns the OS version with the argument / environment variable that
+ /// specified it.
+ std::string getAsString(DerivedArgList &Args, const OptTable &Opts) {
+ switch (Kind) {
+ case TargetArg:
+ case OSVersionArg:
+ case InferredFromSDK:
+ case InferredFromArch:
+ assert(Argument && "OS version argument not yet inferred");
+ return Argument->getAsString(Args);
+ case DeploymentTargetEnv:
+ return (llvm::Twine(EnvVarName) + "=" + OSVersion).str();
+ }
+ llvm_unreachable("Unsupported Darwin Source Kind");
+ }
+
+ static DarwinPlatform createOSVersionArg(DarwinPlatformKind Platform,
+ Arg *A) {
+ return DarwinPlatform(OSVersionArg, Platform, A);
+ }
+ static DarwinPlatform createDeploymentTargetEnv(DarwinPlatformKind Platform,
+ StringRef EnvVarName,
+ StringRef Value) {
+ DarwinPlatform Result(DeploymentTargetEnv, Platform, Value);
+ Result.EnvVarName = EnvVarName;
+ return Result;
+ }
+ static DarwinPlatform createFromSDK(DarwinPlatformKind Platform,
+ StringRef Value) {
+ return DarwinPlatform(InferredFromSDK, Platform, Value);
+ }
+ static DarwinPlatform createFromArch(llvm::Triple::OSType OS,
+ StringRef Value) {
+ DarwinPlatformKind Platform;
+ switch (OS) {
+ case llvm::Triple::Darwin:
+ case llvm::Triple::MacOSX:
+ Platform = DarwinPlatformKind::MacOS;
+ break;
+ case llvm::Triple::IOS:
+ Platform = DarwinPlatformKind::IPhoneOS;
+ break;
+ case llvm::Triple::TvOS:
+ Platform = DarwinPlatformKind::TvOS;
+ break;
+ case llvm::Triple::WatchOS:
+ Platform = DarwinPlatformKind::WatchOS;
+ break;
+ default:
+ llvm_unreachable("Unable to infer Darwin variant");
}
+ return DarwinPlatform(InferredFromArch, Platform, Value);
}
+private:
+ DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, Arg *Argument)
+ : Kind(Kind), Platform(Platform), Argument(Argument) {}
+ DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, StringRef Value)
+ : Kind(Kind), Platform(Platform), OSVersion(Value), Argument(nullptr) {}
+
+ SourceKind Kind;
+ DarwinPlatformKind Platform;
+ std::string OSVersion;
+ Arg *Argument;
+ StringRef EnvVarName;
+};
+
+/// Returns the deployment target that's specified using the -m<os>-version-min
+/// argument.
+Optional<DarwinPlatform>
+getDeploymentTargetFromOSVersionArg(DerivedArgList &Args,
+ const Driver &TheDriver) {
Arg *OSXVersion = Args.getLastArg(options::OPT_mmacosx_version_min_EQ);
Arg *iOSVersion = Args.getLastArg(options::OPT_miphoneos_version_min_EQ,
options::OPT_mios_simulator_version_min_EQ);
@@ -1170,232 +1298,249 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
Arg *WatchOSVersion =
Args.getLastArg(options::OPT_mwatchos_version_min_EQ,
options::OPT_mwatchos_simulator_version_min_EQ);
+ if (OSXVersion) {
+ if (iOSVersion || TvOSVersion || WatchOSVersion) {
+ TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
+ << OSXVersion->getAsString(Args)
+ << (iOSVersion ? iOSVersion
+ : TvOSVersion ? TvOSVersion : WatchOSVersion)
+ ->getAsString(Args);
+ }
+ return DarwinPlatform::createOSVersionArg(Darwin::MacOS, OSXVersion);
+ } else if (iOSVersion) {
+ if (TvOSVersion || WatchOSVersion) {
+ TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
+ << iOSVersion->getAsString(Args)
+ << (TvOSVersion ? TvOSVersion : WatchOSVersion)->getAsString(Args);
+ }
+ return DarwinPlatform::createOSVersionArg(Darwin::IPhoneOS, iOSVersion);
+ } else if (TvOSVersion) {
+ if (WatchOSVersion) {
+ TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
+ << TvOSVersion->getAsString(Args)
+ << WatchOSVersion->getAsString(Args);
+ }
+ return DarwinPlatform::createOSVersionArg(Darwin::TvOS, TvOSVersion);
+ } else if (WatchOSVersion)
+ return DarwinPlatform::createOSVersionArg(Darwin::WatchOS, WatchOSVersion);
+ return None;
+}
- unsigned Major, Minor, Micro;
- bool HadExtra;
+/// Returns the deployment target that's specified using the
+/// OS_DEPLOYMENT_TARGET environment variable.
+Optional<DarwinPlatform>
+getDeploymentTargetFromEnvironmentVariables(const Driver &TheDriver,
+ const llvm::Triple &Triple) {
+ std::string Targets[Darwin::LastDarwinPlatform + 1];
+ const char *EnvVars[] = {
+ "MACOSX_DEPLOYMENT_TARGET",
+ "IPHONEOS_DEPLOYMENT_TARGET",
+ "TVOS_DEPLOYMENT_TARGET",
+ "WATCHOS_DEPLOYMENT_TARGET",
+ };
+ static_assert(llvm::array_lengthof(EnvVars) == Darwin::LastDarwinPlatform + 1,
+ "Missing platform");
+ for (const auto &I : llvm::enumerate(llvm::makeArrayRef(EnvVars))) {
+ if (char *Env = ::getenv(I.value()))
+ Targets[I.index()] = Env;
+ }
- // The iOS deployment target that is explicitly specified via a command line
- // option or an environment variable.
- std::string ExplicitIOSDeploymentTargetStr;
+ // Do not allow conflicts with the watchOS target.
+ if (!Targets[Darwin::WatchOS].empty() &&
+ (!Targets[Darwin::IPhoneOS].empty() || !Targets[Darwin::TvOS].empty())) {
+ TheDriver.Diag(diag::err_drv_conflicting_deployment_targets)
+ << "WATCHOS_DEPLOYMENT_TARGET"
+ << (!Targets[Darwin::IPhoneOS].empty() ? "IPHONEOS_DEPLOYMENT_TARGET"
+ : "TVOS_DEPLOYMENT_TARGET");
+ }
- if (iOSVersion)
- ExplicitIOSDeploymentTargetStr = iOSVersion->getAsString(Args);
+ // Do not allow conflicts with the tvOS target.
+ if (!Targets[Darwin::TvOS].empty() && !Targets[Darwin::IPhoneOS].empty()) {
+ TheDriver.Diag(diag::err_drv_conflicting_deployment_targets)
+ << "TVOS_DEPLOYMENT_TARGET"
+ << "IPHONEOS_DEPLOYMENT_TARGET";
+ }
- // Add a macro to differentiate between m(iphone|tv|watch)os-version-min=X.Y and
- // -m(iphone|tv|watch)simulator-version-min=X.Y.
- if (Args.hasArg(options::OPT_mios_simulator_version_min_EQ) ||
- Args.hasArg(options::OPT_mtvos_simulator_version_min_EQ) ||
- Args.hasArg(options::OPT_mwatchos_simulator_version_min_EQ))
- Args.append(Args.MakeSeparateArg(nullptr, Opts.getOption(options::OPT_D),
- " __APPLE_EMBEDDED_SIMULATOR__=1"));
+ // Allow conflicts among OSX and iOS for historical reasons, but choose the
+ // default platform.
+ if (!Targets[Darwin::MacOS].empty() &&
+ (!Targets[Darwin::IPhoneOS].empty() ||
+ !Targets[Darwin::WatchOS].empty() || !Targets[Darwin::TvOS].empty())) {
+ if (Triple.getArch() == llvm::Triple::arm ||
+ Triple.getArch() == llvm::Triple::aarch64 ||
+ Triple.getArch() == llvm::Triple::thumb)
+ Targets[Darwin::MacOS] = "";
+ else
+ Targets[Darwin::IPhoneOS] = Targets[Darwin::WatchOS] =
+ Targets[Darwin::TvOS] = "";
+ }
- if (OSXVersion && (iOSVersion || TvOSVersion || WatchOSVersion)) {
- getDriver().Diag(diag::err_drv_argument_not_allowed_with)
- << OSXVersion->getAsString(Args)
- << (iOSVersion ? iOSVersion :
- TvOSVersion ? TvOSVersion : WatchOSVersion)->getAsString(Args);
- iOSVersion = TvOSVersion = WatchOSVersion = nullptr;
- } else if (iOSVersion && (TvOSVersion || WatchOSVersion)) {
- getDriver().Diag(diag::err_drv_argument_not_allowed_with)
- << iOSVersion->getAsString(Args)
- << (TvOSVersion ? TvOSVersion : WatchOSVersion)->getAsString(Args);
- TvOSVersion = WatchOSVersion = nullptr;
- } else if (TvOSVersion && WatchOSVersion) {
- getDriver().Diag(diag::err_drv_argument_not_allowed_with)
- << TvOSVersion->getAsString(Args)
- << WatchOSVersion->getAsString(Args);
- WatchOSVersion = nullptr;
- } else if (!OSXVersion && !iOSVersion && !TvOSVersion && !WatchOSVersion) {
- // If no deployment target was specified on the command line, check for
- // environment defines.
- std::string OSXTarget;
- std::string iOSTarget;
- std::string TvOSTarget;
- std::string WatchOSTarget;
+ for (const auto &Target : llvm::enumerate(llvm::makeArrayRef(Targets))) {
+ if (!Target.value().empty())
+ return DarwinPlatform::createDeploymentTargetEnv(
+ (Darwin::DarwinPlatformKind)Target.index(), EnvVars[Target.index()],
+ Target.value());
+ }
+ return None;
+}
- if (char *env = ::getenv("MACOSX_DEPLOYMENT_TARGET"))
- OSXTarget = env;
- if (char *env = ::getenv("IPHONEOS_DEPLOYMENT_TARGET"))
- iOSTarget = env;
- if (char *env = ::getenv("TVOS_DEPLOYMENT_TARGET"))
- TvOSTarget = env;
- if (char *env = ::getenv("WATCHOS_DEPLOYMENT_TARGET"))
- WatchOSTarget = env;
+/// Tries to infer the deployment target from the SDK specified by -isysroot
+/// (or SDKROOT).
+Optional<DarwinPlatform> inferDeploymentTargetFromSDK(DerivedArgList &Args) {
+ const Arg *A = Args.getLastArg(options::OPT_isysroot);
+ if (!A)
+ return None;
+ StringRef isysroot = A->getValue();
+ StringRef SDK = Darwin::getSDKName(isysroot);
+ if (!SDK.size())
+ return None;
+ // Slice the version number out.
+ // Version number is between the first and the last number.
+ size_t StartVer = SDK.find_first_of("0123456789");
+ size_t EndVer = SDK.find_last_of("0123456789");
+ if (StartVer != StringRef::npos && EndVer > StartVer) {
+ StringRef Version = SDK.slice(StartVer, EndVer + 1);
+ if (SDK.startswith("iPhoneOS") || SDK.startswith("iPhoneSimulator"))
+ return DarwinPlatform::createFromSDK(Darwin::IPhoneOS, Version);
+ else if (SDK.startswith("MacOSX"))
+ return DarwinPlatform::createFromSDK(Darwin::MacOS,
+ getSystemOrSDKMacOSVersion(Version));
+ else if (SDK.startswith("WatchOS") || SDK.startswith("WatchSimulator"))
+ return DarwinPlatform::createFromSDK(Darwin::WatchOS, Version);
+ else if (SDK.startswith("AppleTVOS") || SDK.startswith("AppleTVSimulator"))
+ return DarwinPlatform::createFromSDK(Darwin::TvOS, Version);
+ }
+ return None;
+}
- if (!iOSTarget.empty())
- ExplicitIOSDeploymentTargetStr =
- std::string("IPHONEOS_DEPLOYMENT_TARGET=") + iOSTarget;
+std::string getOSVersion(llvm::Triple::OSType OS, const llvm::Triple &Triple,
+ const Driver &TheDriver) {
+ unsigned Major, Minor, Micro;
+ switch (OS) {
+ case llvm::Triple::Darwin:
+ case llvm::Triple::MacOSX:
+ if (!Triple.getMacOSXVersion(Major, Minor, Micro))
+ TheDriver.Diag(diag::err_drv_invalid_darwin_version)
+ << Triple.getOSName();
+ break;
+ case llvm::Triple::IOS:
+ Triple.getiOSVersion(Major, Minor, Micro);
+ break;
+ case llvm::Triple::TvOS:
+ Triple.getOSVersion(Major, Minor, Micro);
+ break;
+ case llvm::Triple::WatchOS:
+ Triple.getWatchOSVersion(Major, Minor, Micro);
+ break;
+ default:
+ llvm_unreachable("Unexpected OS type");
+ break;
+ }
- // If there is no command-line argument to specify the Target version and
- // no environment variable defined, see if we can set the default based
- // on -isysroot.
- if (OSXTarget.empty() && iOSTarget.empty() && WatchOSTarget.empty() &&
- TvOSTarget.empty() && Args.hasArg(options::OPT_isysroot)) {
- if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
- StringRef isysroot = A->getValue();
- StringRef SDK = getSDKName(isysroot);
- if (SDK.size() > 0) {
- // Slice the version number out.
- // Version number is between the first and the last number.
- size_t StartVer = SDK.find_first_of("0123456789");
- size_t EndVer = SDK.find_last_of("0123456789");
- if (StartVer != StringRef::npos && EndVer > StartVer) {
- StringRef Version = SDK.slice(StartVer, EndVer + 1);
- if (SDK.startswith("iPhoneOS") ||
- SDK.startswith("iPhoneSimulator"))
- iOSTarget = Version;
- else if (SDK.startswith("MacOSX"))
- OSXTarget = getSystemOrSDKMacOSVersion(Version);
- else if (SDK.startswith("WatchOS") ||
- SDK.startswith("WatchSimulator"))
- WatchOSTarget = Version;
- else if (SDK.startswith("AppleTVOS") ||
- SDK.startswith("AppleTVSimulator"))
- TvOSTarget = Version;
- }
- }
- }
- }
+ std::string OSVersion;
+ llvm::raw_string_ostream(OSVersion) << Major << '.' << Minor << '.' << Micro;
+ return OSVersion;
+}
- // If no OS targets have been specified, try to guess platform from -target
- // or arch name and compute the version from the triple.
- if (OSXTarget.empty() && iOSTarget.empty() && TvOSTarget.empty() &&
- WatchOSTarget.empty()) {
- llvm::Triple::OSType OSTy = llvm::Triple::UnknownOS;
+/// Tries to infer the target OS from the -arch.
+Optional<DarwinPlatform>
+inferDeploymentTargetFromArch(DerivedArgList &Args, const Darwin &Toolchain,
+ const llvm::Triple &Triple,
+ const Driver &TheDriver) {
+ llvm::Triple::OSType OSTy = llvm::Triple::UnknownOS;
- // Set the OSTy based on -target if -arch isn't present.
- if (Args.hasArg(options::OPT_target) && !Args.hasArg(options::OPT_arch)) {
- OSTy = getTriple().getOS();
- } else {
- StringRef MachOArchName = getMachOArchName(Args);
- if (MachOArchName == "armv7" || MachOArchName == "armv7s" ||
- MachOArchName == "arm64")
- OSTy = llvm::Triple::IOS;
- else if (MachOArchName == "armv7k")
- OSTy = llvm::Triple::WatchOS;
- else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" &&
- MachOArchName != "armv7em")
- OSTy = llvm::Triple::MacOSX;
- }
+ // Set the OSTy based on -target if -arch isn't present.
+ if (Args.hasArg(options::OPT_target) && !Args.hasArg(options::OPT_arch)) {
+ OSTy = Triple.getOS();
+ } else {
+ StringRef MachOArchName = Toolchain.getMachOArchName(Args);
+ if (MachOArchName == "armv7" || MachOArchName == "armv7s" ||
+ MachOArchName == "arm64")
+ OSTy = llvm::Triple::IOS;
+ else if (MachOArchName == "armv7k")
+ OSTy = llvm::Triple::WatchOS;
+ else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" &&
+ MachOArchName != "armv7em")
+ OSTy = llvm::Triple::MacOSX;
+ }
+ if (OSTy == llvm::Triple::UnknownOS)
+ return None;
+ return DarwinPlatform::createFromArch(OSTy,
+ getOSVersion(OSTy, Triple, TheDriver));
+}
- if (OSTy != llvm::Triple::UnknownOS) {
- unsigned Major, Minor, Micro;
- std::string *OSTarget;
+} // namespace
- switch (OSTy) {
- case llvm::Triple::Darwin:
- case llvm::Triple::MacOSX:
- if (!getTriple().getMacOSXVersion(Major, Minor, Micro))
- getDriver().Diag(diag::err_drv_invalid_darwin_version)
- << getTriple().getOSName();
- OSTarget = &OSXTarget;
- break;
- case llvm::Triple::IOS:
- getTriple().getiOSVersion(Major, Minor, Micro);
- OSTarget = &iOSTarget;
- break;
- case llvm::Triple::TvOS:
- getTriple().getOSVersion(Major, Minor, Micro);
- OSTarget = &TvOSTarget;
- break;
- case llvm::Triple::WatchOS:
- getTriple().getWatchOSVersion(Major, Minor, Micro);
- OSTarget = &WatchOSTarget;
- break;
- default:
- llvm_unreachable("Unexpected OS type");
- break;
- }
+void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
+ const OptTable &Opts = getDriver().getOpts();
- llvm::raw_string_ostream(*OSTarget) << Major << '.' << Minor << '.'
- << Micro;
+ // Support allowing the SDKROOT environment variable used by xcrun and other
+ // Xcode tools to define the default sysroot, by making it the default for
+ // isysroot.
+ if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
+ // Warn if the path does not exist.
+ if (!getVFS().exists(A->getValue()))
+ getDriver().Diag(clang::diag::warn_missing_sysroot) << A->getValue();
+ } else {
+ if (char *env = ::getenv("SDKROOT")) {
+ // We only use this value as the default if it is an absolute path,
+ // exists, and it is not the root path.
+ if (llvm::sys::path::is_absolute(env) && getVFS().exists(env) &&
+ StringRef(env) != "/") {
+ Args.append(Args.MakeSeparateArg(
+ nullptr, Opts.getOption(options::OPT_isysroot), env));
}
}
-
- // Do not allow conflicts with the watchOS target.
- if (!WatchOSTarget.empty() && (!iOSTarget.empty() || !TvOSTarget.empty())) {
- getDriver().Diag(diag::err_drv_conflicting_deployment_targets)
- << "WATCHOS_DEPLOYMENT_TARGET"
- << (!iOSTarget.empty() ? "IPHONEOS_DEPLOYMENT_TARGET" :
- "TVOS_DEPLOYMENT_TARGET");
- }
-
- // Do not allow conflicts with the tvOS target.
- if (!TvOSTarget.empty() && !iOSTarget.empty()) {
- getDriver().Diag(diag::err_drv_conflicting_deployment_targets)
- << "TVOS_DEPLOYMENT_TARGET"
- << "IPHONEOS_DEPLOYMENT_TARGET";
- }
-
- // Allow conflicts among OSX and iOS for historical reasons, but choose the
- // default platform.
- if (!OSXTarget.empty() && (!iOSTarget.empty() ||
- !WatchOSTarget.empty() ||
- !TvOSTarget.empty())) {
- if (getTriple().getArch() == llvm::Triple::arm ||
- getTriple().getArch() == llvm::Triple::aarch64 ||
- getTriple().getArch() == llvm::Triple::thumb)
- OSXTarget = "";
- else
- iOSTarget = WatchOSTarget = TvOSTarget = "";
- }
-
- if (!OSXTarget.empty()) {
- const Option O = Opts.getOption(options::OPT_mmacosx_version_min_EQ);
- OSXVersion = Args.MakeJoinedArg(nullptr, O, OSXTarget);
- Args.append(OSXVersion);
- } else if (!iOSTarget.empty()) {
- const Option O = Opts.getOption(options::OPT_miphoneos_version_min_EQ);
- iOSVersion = Args.MakeJoinedArg(nullptr, O, iOSTarget);
- Args.append(iOSVersion);
- } else if (!TvOSTarget.empty()) {
- const Option O = Opts.getOption(options::OPT_mtvos_version_min_EQ);
- TvOSVersion = Args.MakeJoinedArg(nullptr, O, TvOSTarget);
- Args.append(TvOSVersion);
- } else if (!WatchOSTarget.empty()) {
- const Option O = Opts.getOption(options::OPT_mwatchos_version_min_EQ);
- WatchOSVersion = Args.MakeJoinedArg(nullptr, O, WatchOSTarget);
- Args.append(WatchOSVersion);
- }
}
- DarwinPlatformKind Platform;
- if (OSXVersion)
- Platform = MacOS;
- else if (iOSVersion)
- Platform = IPhoneOS;
- else if (TvOSVersion)
- Platform = TvOS;
- else if (WatchOSVersion)
- Platform = WatchOS;
- else
- llvm_unreachable("Unable to infer Darwin variant");
+ // The OS target can be specified using the -m<os>version-min argument.
+ Optional<DarwinPlatform> OSTarget =
+ getDeploymentTargetFromOSVersionArg(Args, getDriver());
+ // If no deployment target was specified on the command line, check for
+ // environment defines.
+ if (!OSTarget)
+ OSTarget =
+ getDeploymentTargetFromEnvironmentVariables(getDriver(), getTriple());
+ // If there is no command-line argument to specify the Target version and
+ // no environment variable defined, see if we can set the default based
+ // on -isysroot.
+ if (!OSTarget)
+ OSTarget = inferDeploymentTargetFromSDK(Args);
+ // If no OS targets have been specified, try to guess platform from -target
+ // or arch name and compute the version from the triple.
+ if (!OSTarget)
+ OSTarget =
+ inferDeploymentTargetFromArch(Args, *this, getTriple(), getDriver());
+
+ assert(OSTarget && "Unable to infer Darwin variant");
+ OSTarget->addOSVersionMinArgument(Args, Opts);
+ DarwinPlatformKind Platform = OSTarget->getPlatform();
+ unsigned Major, Minor, Micro;
+ bool HadExtra;
// Set the tool chain target information.
if (Platform == MacOS) {
- assert((!iOSVersion && !TvOSVersion && !WatchOSVersion) &&
- "Unknown target platform!");
- if (!Driver::GetReleaseVersion(OSXVersion->getValue(), Major, Minor, Micro,
- HadExtra) ||
+ if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
+ Micro, HadExtra) ||
HadExtra || Major != 10 || Minor >= 100 || Micro >= 100)
getDriver().Diag(diag::err_drv_invalid_version_number)
- << OSXVersion->getAsString(Args);
+ << OSTarget->getAsString(Args, Opts);
} else if (Platform == IPhoneOS) {
- assert(iOSVersion && "Unknown target platform!");
- if (!Driver::GetReleaseVersion(iOSVersion->getValue(), Major, Minor, Micro,
- HadExtra) ||
+ if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
+ Micro, HadExtra) ||
HadExtra || Major >= 100 || Minor >= 100 || Micro >= 100)
getDriver().Diag(diag::err_drv_invalid_version_number)
- << iOSVersion->getAsString(Args);
+ << OSTarget->getAsString(Args, Opts);
+ ;
// For 32-bit targets, the deployment target for iOS has to be earlier than
// iOS 11.
if (getTriple().isArch32Bit() && Major >= 11) {
// If the deployment target is explicitly specified, print a diagnostic.
- if (!ExplicitIOSDeploymentTargetStr.empty()) {
+ if (OSTarget->isExplicitlySpecified()) {
getDriver().Diag(diag::warn_invalid_ios_deployment_target)
- << ExplicitIOSDeploymentTargetStr;
- // Otherwise, set it to 10.99.99.
+ << OSTarget->getAsString(Args, Opts);
+ // Otherwise, set it to 10.99.99.
} else {
Major = 10;
Minor = 99;
@@ -1403,32 +1548,27 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
}
}
} else if (Platform == TvOS) {
- if (!Driver::GetReleaseVersion(TvOSVersion->getValue(), Major, Minor,
- Micro, HadExtra) || HadExtra ||
- Major >= 100 || Minor >= 100 || Micro >= 100)
+ if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
+ Micro, HadExtra) ||
+ HadExtra || Major >= 100 || Minor >= 100 || Micro >= 100)
getDriver().Diag(diag::err_drv_invalid_version_number)
- << TvOSVersion->getAsString(Args);
+ << OSTarget->getAsString(Args, Opts);
} else if (Platform == WatchOS) {
- if (!Driver::GetReleaseVersion(WatchOSVersion->getValue(), Major, Minor,
- Micro, HadExtra) || HadExtra ||
- Major >= 10 || Minor >= 100 || Micro >= 100)
+ if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
+ Micro, HadExtra) ||
+ HadExtra || Major >= 10 || Minor >= 100 || Micro >= 100)
getDriver().Diag(diag::err_drv_invalid_version_number)
- << WatchOSVersion->getAsString(Args);
+ << OSTarget->getAsString(Args, Opts);
} else
llvm_unreachable("unknown kind of Darwin platform");
+ DarwinEnvironmentKind Environment = NativeEnvironment;
// Recognize iOS targets with an x86 architecture as the iOS simulator.
- if (iOSVersion && (getTriple().getArch() == llvm::Triple::x86 ||
- getTriple().getArch() == llvm::Triple::x86_64))
- Platform = IPhoneOSSimulator;
- if (TvOSVersion && (getTriple().getArch() == llvm::Triple::x86 ||
- getTriple().getArch() == llvm::Triple::x86_64))
- Platform = TvOSSimulator;
- if (WatchOSVersion && (getTriple().getArch() == llvm::Triple::x86 ||
- getTriple().getArch() == llvm::Triple::x86_64))
- Platform = WatchOSSimulator;
+ if (Platform != MacOS && (getTriple().getArch() == llvm::Triple::x86 ||
+ getTriple().getArch() == llvm::Triple::x86_64))
+ Environment = Simulator;
- setTarget(Platform, Major, Minor, Micro);
+ setTarget(Platform, Environment, Major, Minor, Micro);
if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
StringRef SDK = getSDKName(A->getValue());
@@ -1741,23 +1881,28 @@ void MachO::AddLinkRuntimeLibArgs(const ArgList &Args,
: "soft";
CompilerRT += Args.hasArg(options::OPT_fPIC) ? "_pic.a" : "_static.a";
- AddLinkRuntimeLib(Args, CmdArgs, CompilerRT, false, true);
+ AddLinkRuntimeLib(Args, CmdArgs, CompilerRT, RLO_IsEmbedded);
}
bool Darwin::isAlignedAllocationUnavailable() const {
+ llvm::Triple::OSType OS;
+
switch (TargetPlatform) {
case MacOS: // Earlier than 10.13.
- return TargetVersion < VersionTuple(10U, 13U, 0U);
+ OS = llvm::Triple::MacOSX;
+ break;
case IPhoneOS:
- case IPhoneOSSimulator:
- case TvOS:
- case TvOSSimulator: // Earlier than 11.0.
- return TargetVersion < VersionTuple(11U, 0U, 0U);
- case WatchOS:
- case WatchOSSimulator: // Earlier than 4.0.
- return TargetVersion < VersionTuple(4U, 0U, 0U);
+ OS = llvm::Triple::IOS;
+ break;
+ case TvOS: // Earlier than 11.0.
+ OS = llvm::Triple::TvOS;
+ break;
+ case WatchOS: // Earlier than 4.0.
+ OS = llvm::Triple::WatchOS;
+ break;
}
- llvm_unreachable("Unsupported platform");
+
+ return TargetVersion < alignedAllocMinVersion(OS);
}
void Darwin::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
@@ -1840,7 +1985,7 @@ bool MachO::IsUnwindTablesDefault(const ArgList &Args) const {
// Unwind tables are not emitted if -fno-exceptions is supplied (except when
// targeting x86_64).
return getArch() == llvm::Triple::x86_64 ||
- (!UseSjLjExceptions(Args) &&
+ (GetExceptionModel(Args) != llvm::ExceptionHandling::SjLj &&
Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions,
true));
}
@@ -1851,15 +1996,18 @@ bool MachO::UseDwarfDebugFlags() const {
return false;
}
-bool Darwin::UseSjLjExceptions(const ArgList &Args) const {
+llvm::ExceptionHandling Darwin::GetExceptionModel(const ArgList &Args) const {
// Darwin uses SjLj exceptions on ARM.
if (getTriple().getArch() != llvm::Triple::arm &&
getTriple().getArch() != llvm::Triple::thumb)
- return false;
+ return llvm::ExceptionHandling::None;
// Only watchOS uses the new DWARF/Compact unwinding method.
llvm::Triple Triple(ComputeLLVMTriple(Args));
- return !Triple.isWatchABI();
+ if(Triple.isWatchABI())
+ return llvm::ExceptionHandling::DwarfCFI;
+
+ return llvm::ExceptionHandling::SjLj;
}
bool Darwin::SupportsEmbeddedBitcode() const {
@@ -2000,8 +2148,6 @@ void Darwin::addStartObjectFileArgs(const ArgList &Args,
}
}
-bool Darwin::SupportsObjCGC() const { return isTargetMacOS(); }
-
void Darwin::CheckObjCARC() const {
if (isTargetIOSBased() || isTargetWatchOSBased() ||
(isTargetMacOS() && !isMacosxVersionLT(10, 6)))
@@ -2015,6 +2161,8 @@ SanitizerMask Darwin::getSupportedSanitizers() const {
Res |= SanitizerKind::Address;
Res |= SanitizerKind::Leak;
Res |= SanitizerKind::Fuzzer;
+ Res |= SanitizerKind::FuzzerNoLink;
+ Res |= SanitizerKind::Function;
if (isTargetMacOS()) {
if (!isMacosxVersionLT(10, 9))
Res |= SanitizerKind::Vptr;
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Darwin.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Darwin.h
index 77c569e8f865d..87d553bd7e0b2 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Darwin.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Darwin.h
@@ -152,10 +152,11 @@ public:
llvm::opt::ArgStringList &CmdArgs) const {}
/// Add the linker arguments to link the compiler runtime library.
+ ///
+ /// FIXME: This API is intended for use with embedded libraries only, and is
+ /// misleadingly named.
virtual void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
- virtual void AddFuzzerLinkArgs(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs) const;
virtual void addStartObjectFileArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const {
@@ -171,10 +172,26 @@ public:
/// Is the target either iOS or an iOS simulator?
bool isTargetIOSBased() const { return false; }
+ /// Options to control how a runtime library is linked.
+ enum RuntimeLinkOptions : unsigned {
+ /// Link the library in even if it can't be found in the VFS.
+ RLO_AlwaysLink = 1 << 0,
+
+ /// Use the embedded runtime from the macho_embedded directory.
+ RLO_IsEmbedded = 1 << 1,
+
+ /// Emit rpaths for @executable_path as well as the resource directory.
+ RLO_AddRPath = 1 << 2,
+
+ /// Link the library in before any others.
+ RLO_FirstLink = 1 << 3,
+ };
+
+ /// Add a runtime library to the list of items to link.
void AddLinkRuntimeLib(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs,
- StringRef DarwinLibName, bool AlwaysLink = false,
- bool IsEmbedded = false, bool AddRPath = false) const;
+ StringRef DarwinLibName,
+ RuntimeLinkOptions Opts = RuntimeLinkOptions()) const;
/// Add any profiling runtime libraries that are needed. This is essentially a
/// MachO specific version of addProfileRT in Tools.cpp.
@@ -228,12 +245,11 @@ public:
bool SupportsProfiling() const override;
- bool SupportsObjCGC() const override { return false; }
-
bool UseDwarfDebugFlags() const override;
- bool UseSjLjExceptions(const llvm::opt::ArgList &Args) const override {
- return false;
+ llvm::ExceptionHandling
+ GetExceptionModel(const llvm::opt::ArgList &Args) const override {
+ return llvm::ExceptionHandling::None;
}
/// }
@@ -252,14 +268,17 @@ public:
enum DarwinPlatformKind {
MacOS,
IPhoneOS,
- IPhoneOSSimulator,
TvOS,
- TvOSSimulator,
WatchOS,
- WatchOSSimulator
+ LastDarwinPlatform = WatchOS
+ };
+ enum DarwinEnvironmentKind {
+ NativeEnvironment,
+ Simulator,
};
mutable DarwinPlatformKind TargetPlatform;
+ mutable DarwinEnvironmentKind TargetEnvironment;
/// The OS version we are targeting.
mutable VersionTuple TargetVersion;
@@ -301,29 +320,34 @@ protected:
// FIXME: Eliminate these ...Target functions and derive separate tool chains
// for these targets and put version in constructor.
- void setTarget(DarwinPlatformKind Platform, unsigned Major, unsigned Minor,
- unsigned Micro) const {
+ void setTarget(DarwinPlatformKind Platform, DarwinEnvironmentKind Environment,
+ unsigned Major, unsigned Minor, unsigned Micro) const {
// FIXME: For now, allow reinitialization as long as values don't
// change. This will go away when we move away from argument translation.
if (TargetInitialized && TargetPlatform == Platform &&
+ TargetEnvironment == Environment &&
TargetVersion == VersionTuple(Major, Minor, Micro))
return;
assert(!TargetInitialized && "Target already initialized!");
TargetInitialized = true;
TargetPlatform = Platform;
+ TargetEnvironment = Environment;
TargetVersion = VersionTuple(Major, Minor, Micro);
+ if (Environment == Simulator)
+ const_cast<Darwin *>(this)->setTripleEnvironment(llvm::Triple::Simulator);
}
bool isTargetIPhoneOS() const {
assert(TargetInitialized && "Target not initialized!");
- return TargetPlatform == IPhoneOS || TargetPlatform == TvOS;
+ return (TargetPlatform == IPhoneOS || TargetPlatform == TvOS) &&
+ TargetEnvironment == NativeEnvironment;
}
bool isTargetIOSSimulator() const {
assert(TargetInitialized && "Target not initialized!");
- return TargetPlatform == IPhoneOSSimulator ||
- TargetPlatform == TvOSSimulator;
+ return (TargetPlatform == IPhoneOS || TargetPlatform == TvOS) &&
+ TargetEnvironment == Simulator;
}
bool isTargetIOSBased() const {
@@ -333,32 +357,32 @@ protected:
bool isTargetTvOS() const {
assert(TargetInitialized && "Target not initialized!");
- return TargetPlatform == TvOS;
+ return TargetPlatform == TvOS && TargetEnvironment == NativeEnvironment;
}
bool isTargetTvOSSimulator() const {
assert(TargetInitialized && "Target not initialized!");
- return TargetPlatform == TvOSSimulator;
+ return TargetPlatform == TvOS && TargetEnvironment == Simulator;
}
bool isTargetTvOSBased() const {
assert(TargetInitialized && "Target not initialized!");
- return TargetPlatform == TvOS || TargetPlatform == TvOSSimulator;
+ return TargetPlatform == TvOS;
}
bool isTargetWatchOS() const {
assert(TargetInitialized && "Target not initialized!");
- return TargetPlatform == WatchOS;
+ return TargetPlatform == WatchOS && TargetEnvironment == NativeEnvironment;
}
bool isTargetWatchOSSimulator() const {
assert(TargetInitialized && "Target not initialized!");
- return TargetPlatform == WatchOSSimulator;
+ return TargetPlatform == WatchOS && TargetEnvironment == Simulator;
}
bool isTargetWatchOSBased() const {
assert(TargetInitialized && "Target not initialized!");
- return TargetPlatform == WatchOS || TargetPlatform == WatchOSSimulator;
+ return TargetPlatform == WatchOS;
}
bool isTargetMacOS() const {
@@ -394,10 +418,11 @@ protected:
Action::OffloadKind DeviceOffloadKind) const override;
StringRef getPlatformFamily() const;
- static StringRef getSDKName(StringRef isysroot);
StringRef getOSLibraryNameSuffix() const;
public:
+ static StringRef getSDKName(StringRef isysroot);
+
/// }
/// @name ToolChain Implementation
/// {
@@ -438,11 +463,10 @@ public:
return 0;
}
- bool SupportsObjCGC() const override;
-
void CheckObjCARC() const override;
- bool UseSjLjExceptions(const llvm::opt::ArgList &Args) const override;
+ llvm::ExceptionHandling GetExceptionModel(
+ const llvm::opt::ArgList &Args) const override;
bool SupportsEmbeddedBitcode() const override;
@@ -489,7 +513,8 @@ public:
private:
void AddLinkSanitizerLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs,
- StringRef Sanitizer) const;
+ StringRef Sanitizer,
+ bool shared = true) const;
};
} // end namespace toolchains
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/DragonFly.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/DragonFly.cpp
index bd2c7fc6c4bd2..648469e4cec51 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/DragonFly.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/DragonFly.cpp
@@ -127,7 +127,8 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
if (D.CCCIsCXX()) {
- getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (getToolChain().ShouldLinkCXXStdlib(Args))
+ getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lm");
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/FreeBSD.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/FreeBSD.cpp
index c6626e922eef8..dd0334b9c28bd 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/FreeBSD.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/FreeBSD.cpp
@@ -240,7 +240,8 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
addOpenMPRuntime(CmdArgs, ToolChain, Args);
if (D.CCCIsCXX()) {
- ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (ToolChain.ShouldLinkCXXStdlib(Args))
+ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
if (Args.hasArg(options::OPT_pg))
CmdArgs.push_back("-lm_p");
else
@@ -358,17 +359,18 @@ Tool *FreeBSD::buildAssembler() const {
Tool *FreeBSD::buildLinker() const { return new tools::freebsd::Linker(*this); }
-bool FreeBSD::UseSjLjExceptions(const ArgList &Args) const {
+llvm::ExceptionHandling FreeBSD::GetExceptionModel(const ArgList &Args) const {
// FreeBSD uses SjLj exceptions on ARM oabi.
switch (getTriple().getEnvironment()) {
case llvm::Triple::GNUEABIHF:
case llvm::Triple::GNUEABI:
case llvm::Triple::EABI:
- return false;
-
+ return llvm::ExceptionHandling::None;
default:
- return (getTriple().getArch() == llvm::Triple::arm ||
- getTriple().getArch() == llvm::Triple::thumb);
+ if (getTriple().getArch() == llvm::Triple::arm ||
+ getTriple().getArch() == llvm::Triple::thumb)
+ return llvm::ExceptionHandling::SjLj;
+ return llvm::ExceptionHandling::None;
}
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/FreeBSD.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/FreeBSD.h
index 25e9df72bc80f..2943e1cacfbb9 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/FreeBSD.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/FreeBSD.h
@@ -66,7 +66,8 @@ public:
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
- bool UseSjLjExceptions(const llvm::opt::ArgList &Args) const override;
+ llvm::ExceptionHandling GetExceptionModel(
+ const llvm::opt::ArgList &Args) const override;
bool isPIEDefault() const override;
SanitizerMask getSupportedSanitizers() const override;
unsigned GetDefaultDwarfVersion() const override { return 2; }
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Fuchsia.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Fuchsia.cpp
index 78053aafd16e5..10ee7b7829be4 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Fuchsia.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Fuchsia.cpp
@@ -14,6 +14,7 @@
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
+#include "clang/Driver/SanitizerArgs.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/Path.h"
@@ -43,10 +44,8 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.ClaimAllArgs(options::OPT_w);
const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
- if (llvm::sys::path::stem(Exec).equals_lower("lld")) {
- CmdArgs.push_back("-flavor");
- CmdArgs.push_back("gnu");
-
+ if (llvm::sys::path::filename(Exec).equals_lower("ld.lld") ||
+ llvm::sys::path::stem(Exec).equals_lower("ld.lld")) {
CmdArgs.push_back("-z");
CmdArgs.push_back("rodynamic");
}
@@ -63,27 +62,28 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_s))
CmdArgs.push_back("-s");
- if (Args.hasArg(options::OPT_r))
+ if (Args.hasArg(options::OPT_r)) {
CmdArgs.push_back("-r");
- else
+ } else {
CmdArgs.push_back("--build-id");
+ CmdArgs.push_back("--hash-style=gnu");
+ }
- if (!Args.hasArg(options::OPT_static))
- CmdArgs.push_back("--eh-frame-hdr");
+ CmdArgs.push_back("--eh-frame-hdr");
if (Args.hasArg(options::OPT_static))
CmdArgs.push_back("-Bstatic");
else if (Args.hasArg(options::OPT_shared))
CmdArgs.push_back("-shared");
- if (!Args.hasArg(options::OPT_static)) {
- if (Args.hasArg(options::OPT_rdynamic))
- CmdArgs.push_back("-export-dynamic");
-
- if (!Args.hasArg(options::OPT_shared)) {
- CmdArgs.push_back("-dynamic-linker");
- CmdArgs.push_back(Args.MakeArgString(D.DyldPrefix + "ld.so.1"));
- }
+ if (!Args.hasArg(options::OPT_shared)) {
+ std::string Dyld = D.DyldPrefix;
+ if (ToolChain.getSanitizerArgs().needsAsanRt() &&
+ ToolChain.getSanitizerArgs().needsSharedRt())
+ Dyld += "asan/";
+ Dyld += "ld.so.1";
+ CmdArgs.push_back("-dynamic-linker");
+ CmdArgs.push_back(Args.MakeArgString(Dyld));
}
CmdArgs.push_back("-o");
@@ -100,6 +100,8 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
ToolChain.AddFilePathLibArgs(Args, CmdArgs);
+ addSanitizerRuntimes(ToolChain, Args, CmdArgs);
+
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
@@ -107,13 +109,8 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-Bdynamic");
if (D.CCCIsCXX()) {
- bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
- !Args.hasArg(options::OPT_static);
- if (OnlyLibstdcxxStatic)
- CmdArgs.push_back("-Bstatic");
- ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
- if (OnlyLibstdcxxStatic)
- CmdArgs.push_back("-Bdynamic");
+ if (ToolChain.ShouldLinkCXXStdlib(Args))
+ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lm");
}
@@ -282,5 +279,6 @@ void Fuchsia::AddCXXStdlibLibArgs(const ArgList &Args,
SanitizerMask Fuchsia::getSupportedSanitizers() const {
SanitizerMask Res = ToolChain::getSupportedSanitizers();
Res |= SanitizerKind::SafeStack;
+ Res |= SanitizerKind::Address;
return Res;
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Fuchsia.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Fuchsia.h
index a723a99dfa3bf..6f438deca7ff1 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Fuchsia.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Fuchsia.h
@@ -42,12 +42,17 @@ public:
bool HasNativeLLVMSupport() const override { return true; }
bool IsIntegratedAssemblerDefault() const override { return true; }
+ bool IsMathErrnoDefault() const override { return false; }
+ bool useRelaxRelocations() const override { return true; };
RuntimeLibType GetDefaultRuntimeLibType() const override {
return ToolChain::RLT_CompilerRT;
}
CXXStdlibType GetDefaultCXXStdlibType() const override {
return ToolChain::CST_Libcxx;
}
+ bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override {
+ return true;
+ }
bool isPICDefault() const override { return false; }
bool isPIEDefault() const override { return true; }
bool isPICDefaultForced() const override { return false; }
@@ -78,7 +83,7 @@ public:
llvm::opt::ArgStringList &CmdArgs) const override;
const char *getDefaultLinker() const override {
- return "lld";
+ return "ld.lld";
}
protected:
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Gnu.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Gnu.cpp
index 72a9f85ba389a..7845781f12c42 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -11,6 +11,7 @@
#include "Linux.h"
#include "Arch/ARM.h"
#include "Arch/Mips.h"
+#include "Arch/PPC.h"
#include "Arch/Sparc.h"
#include "Arch/SystemZ.h"
#include "CommonArgs.h"
@@ -41,6 +42,22 @@ static bool forwardToGCC(const Option &O) {
!O.hasFlag(options::DriverOption) && !O.hasFlag(options::LinkerInput);
}
+// Switch CPU names not recognized by GNU assembler to a close CPU that it does
+// recognize, instead of a lower march from being picked in the absence of a cpu
+// flag.
+static void normalizeCPUNamesForAssembler(const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
+ StringRef CPUArg(A->getValue());
+ if (CPUArg.equals_lower("krait"))
+ CmdArgs.push_back("-mcpu=cortex-a15");
+ else if(CPUArg.equals_lower("kryo"))
+ CmdArgs.push_back("-mcpu=cortex-a57");
+ else
+ Args.AddLastArg(CmdArgs, options::OPT_mcpu_EQ);
+ }
+}
+
void tools::gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -203,133 +220,12 @@ void tools::gcc::Linker::RenderExtraToolArgs(const JobAction &JA,
// The types are (hopefully) good enough.
}
-/// Add OpenMP linker script arguments at the end of the argument list so that
-/// the fat binary is built by embedding each of the device images into the
-/// host. The linker script also defines a few symbols required by the code
-/// generation so that the images can be easily retrieved at runtime by the
-/// offloading library. This should be used only in tool chains that support
-/// linker scripts.
-static void AddOpenMPLinkerScript(const ToolChain &TC, Compilation &C,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args, ArgStringList &CmdArgs,
- const JobAction &JA) {
-
- // If this is not an OpenMP host toolchain, we don't need to do anything.
- if (!JA.isHostOffloading(Action::OFK_OpenMP))
- return;
-
- // Create temporary linker script. Keep it if save-temps is enabled.
- const char *LKS;
- SmallString<256> Name = llvm::sys::path::filename(Output.getFilename());
- if (C.getDriver().isSaveTempsEnabled()) {
- llvm::sys::path::replace_extension(Name, "lk");
- LKS = C.getArgs().MakeArgString(Name.c_str());
- } else {
- llvm::sys::path::replace_extension(Name, "");
- Name = C.getDriver().GetTemporaryPath(Name, "lk");
- LKS = C.addTempFile(C.getArgs().MakeArgString(Name.c_str()));
- }
-
- // Add linker script option to the command.
- CmdArgs.push_back("-T");
- CmdArgs.push_back(LKS);
-
- // Create a buffer to write the contents of the linker script.
- std::string LksBuffer;
- llvm::raw_string_ostream LksStream(LksBuffer);
-
- // Get the OpenMP offload tool chains so that we can extract the triple
- // associated with each device input.
- auto OpenMPToolChains = C.getOffloadToolChains<Action::OFK_OpenMP>();
- assert(OpenMPToolChains.first != OpenMPToolChains.second &&
- "No OpenMP toolchains??");
-
- // Track the input file name and device triple in order to build the script,
- // inserting binaries in the designated sections.
- SmallVector<std::pair<std::string, const char *>, 8> InputBinaryInfo;
-
- // Add commands to embed target binaries. We ensure that each section and
- // image is 16-byte aligned. This is not mandatory, but increases the
- // likelihood of data to be aligned with a cache block in several main host
- // machines.
- LksStream << "/*\n";
- LksStream << " OpenMP Offload Linker Script\n";
- LksStream << " *** Automatically generated by Clang ***\n";
- LksStream << "*/\n";
- LksStream << "TARGET(binary)\n";
- auto DTC = OpenMPToolChains.first;
- for (auto &II : Inputs) {
- const Action *A = II.getAction();
- // Is this a device linking action?
- if (A && isa<LinkJobAction>(A) &&
- A->isDeviceOffloading(Action::OFK_OpenMP)) {
- assert(DTC != OpenMPToolChains.second &&
- "More device inputs than device toolchains??");
- InputBinaryInfo.push_back(std::make_pair(
- DTC->second->getTriple().normalize(), II.getFilename()));
- ++DTC;
- LksStream << "INPUT(" << II.getFilename() << ")\n";
- }
- }
-
- assert(DTC == OpenMPToolChains.second &&
- "Less device inputs than device toolchains??");
-
- LksStream << "SECTIONS\n";
- LksStream << "{\n";
-
- // Put each target binary into a separate section.
- for (const auto &BI : InputBinaryInfo) {
- LksStream << " .omp_offloading." << BI.first << " :\n";
- LksStream << " ALIGN(0x10)\n";
- LksStream << " {\n";
- LksStream << " PROVIDE_HIDDEN(.omp_offloading.img_start." << BI.first
- << " = .);\n";
- LksStream << " " << BI.second << "\n";
- LksStream << " PROVIDE_HIDDEN(.omp_offloading.img_end." << BI.first
- << " = .);\n";
- LksStream << " }\n";
- }
-
- // Add commands to define host entries begin and end. We use 1-byte subalign
- // so that the linker does not add any padding and the elements in this
- // section form an array.
- LksStream << " .omp_offloading.entries :\n";
- LksStream << " ALIGN(0x10)\n";
- LksStream << " SUBALIGN(0x01)\n";
- LksStream << " {\n";
- LksStream << " PROVIDE_HIDDEN(.omp_offloading.entries_begin = .);\n";
- LksStream << " *(.omp_offloading.entries)\n";
- LksStream << " PROVIDE_HIDDEN(.omp_offloading.entries_end = .);\n";
- LksStream << " }\n";
- LksStream << "}\n";
- LksStream << "INSERT BEFORE .data\n";
- LksStream.flush();
-
- // Dump the contents of the linker script if the user requested that. We
- // support this option to enable testing of behavior with -###.
- if (C.getArgs().hasArg(options::OPT_fopenmp_dump_offload_linker_script))
- llvm::errs() << LksBuffer;
-
- // If this is a dry run, do not create the linker script file.
- if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH))
- return;
-
- // Open script file and write the contents.
- std::error_code EC;
- llvm::raw_fd_ostream Lksf(LKS, EC, llvm::sys::fs::F_None);
-
- if (EC) {
- C.getDriver().Diag(clang::diag::err_unable_to_make_temp) << EC.message();
- return;
- }
-
- Lksf << LksBuffer;
-}
-
static bool addXRayRuntime(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs) {
+ // Do not add the XRay runtime to shared libraries.
+ if (Args.hasArg(options::OPT_shared))
+ return false;
+
if (Args.hasFlag(options::OPT_fxray_instrument,
options::OPT_fnoxray_instrument, false)) {
CmdArgs.push_back("-whole-archive");
@@ -337,6 +233,7 @@ static bool addXRayRuntime(const ToolChain &TC, const ArgList &Args,
CmdArgs.push_back("-no-whole-archive");
return true;
}
+
return false;
}
@@ -347,7 +244,8 @@ static void linkXRayRuntimeDeps(const ToolChain &TC, const ArgList &Args,
CmdArgs.push_back("-lrt");
CmdArgs.push_back("-lm");
- if (TC.getTriple().getOS() != llvm::Triple::FreeBSD)
+ if (TC.getTriple().getOS() != llvm::Triple::FreeBSD &&
+ TC.getTriple().getOS() != llvm::Triple::NetBSD)
CmdArgs.push_back("-ldl");
}
@@ -401,6 +299,17 @@ static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) {
}
}
+static bool getPIE(const ArgList &Args, const toolchains::Linux &ToolChain) {
+ if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_static))
+ return false;
+
+ Arg *A = Args.getLastArg(options::OPT_pie, options::OPT_no_pie,
+ options::OPT_nopie);
+ if (!A)
+ return ToolChain.isPIEDefault();
+ return A->getOption().matches(options::OPT_pie);
+}
+
void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -415,9 +324,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const llvm::Triple::ArchType Arch = ToolChain.getArch();
const bool isAndroid = ToolChain.getTriple().isAndroid();
const bool IsIAMCU = ToolChain.getTriple().isOSIAMCU();
- const bool IsPIE =
- !Args.hasArg(options::OPT_shared) && !Args.hasArg(options::OPT_static) &&
- (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault());
+ const bool IsPIE = getPIE(Args, ToolChain);
const bool HasCRTBeginEndFiles =
ToolChain.getTriple().hasEnvironment() ||
(ToolChain.getTriple().getVendor() != llvm::Triple::MipsTechnologies);
@@ -560,13 +467,15 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (D.CCCIsCXX() &&
!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
- bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
- !Args.hasArg(options::OPT_static);
- if (OnlyLibstdcxxStatic)
- CmdArgs.push_back("-Bstatic");
- ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
- if (OnlyLibstdcxxStatic)
- CmdArgs.push_back("-Bdynamic");
+ if (ToolChain.ShouldLinkCXXStdlib(Args)) {
+ bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
+ !Args.hasArg(options::OPT_static);
+ if (OnlyLibstdcxxStatic)
+ CmdArgs.push_back("-Bstatic");
+ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (OnlyLibstdcxxStatic)
+ CmdArgs.push_back("-Bdynamic");
+ }
CmdArgs.push_back("-lm");
}
// Silence warnings when linking C code with a C++ '-stdlib' argument.
@@ -693,22 +602,28 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
else
CmdArgs.push_back("--64");
break;
- case llvm::Triple::ppc:
+ case llvm::Triple::ppc: {
CmdArgs.push_back("-a32");
CmdArgs.push_back("-mppc");
- CmdArgs.push_back("-many");
+ CmdArgs.push_back(
+ ppc::getPPCAsmModeForCPU(getCPUName(Args, getToolChain().getTriple())));
break;
- case llvm::Triple::ppc64:
+ }
+ case llvm::Triple::ppc64: {
CmdArgs.push_back("-a64");
CmdArgs.push_back("-mppc64");
- CmdArgs.push_back("-many");
+ CmdArgs.push_back(
+ ppc::getPPCAsmModeForCPU(getCPUName(Args, getToolChain().getTriple())));
break;
- case llvm::Triple::ppc64le:
+ }
+ case llvm::Triple::ppc64le: {
CmdArgs.push_back("-a64");
CmdArgs.push_back("-mppc64");
- CmdArgs.push_back("-many");
CmdArgs.push_back("-mlittle-endian");
+ CmdArgs.push_back(
+ ppc::getPPCAsmModeForCPU(getCPUName(Args, getToolChain().getTriple())));
break;
+ }
case llvm::Triple::sparc:
case llvm::Triple::sparcel: {
CmdArgs.push_back("-32");
@@ -754,23 +669,16 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
}
Args.AddLastArg(CmdArgs, options::OPT_march_EQ);
+ normalizeCPUNamesForAssembler(Args, CmdArgs);
- // FIXME: remove krait check when GNU tools support krait cpu
- // for now replace it with -mcpu=cortex-a15 to avoid a lower
- // march from being picked in the absence of a cpu flag.
- Arg *A;
- if ((A = Args.getLastArg(options::OPT_mcpu_EQ)) &&
- StringRef(A->getValue()).equals_lower("krait"))
- CmdArgs.push_back("-mcpu=cortex-a15");
- else
- Args.AddLastArg(CmdArgs, options::OPT_mcpu_EQ);
Args.AddLastArg(CmdArgs, options::OPT_mfpu_EQ);
break;
}
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be: {
Args.AddLastArg(CmdArgs, options::OPT_march_EQ);
- Args.AddLastArg(CmdArgs, options::OPT_mcpu_EQ);
+ normalizeCPUNamesForAssembler(Args, CmdArgs);
+
break;
}
case llvm::Triple::mips:
@@ -1427,12 +1335,12 @@ bool clang::driver::findMIPSMultilibs(const Driver &D,
if (TargetTriple.getVendor() == llvm::Triple::MipsTechnologies &&
TargetTriple.getOS() == llvm::Triple::Linux &&
- TargetTriple.getEnvironment() == llvm::Triple::GNU)
+ TargetTriple.isGNUEnvironment())
return findMipsMtiMultilibs(Flags, NonExistent, Result);
if (TargetTriple.getVendor() == llvm::Triple::ImaginationTechnologies &&
TargetTriple.getOS() == llvm::Triple::Linux &&
- TargetTriple.getEnvironment() == llvm::Triple::GNU)
+ TargetTriple.isGNUEnvironment())
return findMipsImgMultilibs(Flags, NonExistent, Result);
if (findMipsCsMultilibs(Flags, NonExistent, Result))
@@ -1482,7 +1390,7 @@ static void findAndroidArmMultilibs(const Driver &D,
bool IsV7SubArch = TargetTriple.getSubArch() == llvm::Triple::ARMSubArch_v7;
bool IsThumbMode = IsThumbArch ||
Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, false) ||
- (IsArmArch && llvm::ARM::parseArchISA(Arch) == llvm::ARM::IK_THUMB);
+ (IsArmArch && llvm::ARM::parseArchISA(Arch) == llvm::ARM::ISAKind::THUMB);
bool IsArmV7Mode = (IsArmArch || IsThumbArch) &&
(llvm::ARM::parseArchVersion(Arch) == 7 ||
(IsArmArch && Arch == "" && IsV7SubArch));
@@ -2468,7 +2376,8 @@ void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs,
getTriple().getArch() == llvm::Triple::aarch64 ||
getTriple().getArch() == llvm::Triple::aarch64_be ||
(getTriple().getOS() == llvm::Triple::Linux &&
- (!V.isOlderThan(4, 7, 0) || getTriple().isAndroid())) ||
+ ((!GCCInstallation.isValid() || !V.isOlderThan(4, 7, 0)) ||
+ getTriple().isAndroid())) ||
getTriple().getOS() == llvm::Triple::NaCl ||
(getTriple().getVendor() == llvm::Triple::MipsTechnologies &&
!getTriple().hasEnvironment()) ||
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Hexagon.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Hexagon.cpp
index 9bf1590e6a37e..f21af5b4dcf50 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Hexagon.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Hexagon.cpp
@@ -27,6 +27,101 @@ using namespace clang::driver::toolchains;
using namespace clang;
using namespace llvm::opt;
+// Default hvx-length for various versions.
+static StringRef getDefaultHvxLength(StringRef Cpu) {
+ return llvm::StringSwitch<StringRef>(Cpu)
+ .Case("v60", "64b")
+ .Case("v62", "64b")
+ .Case("v65", "64b")
+ .Default("128b");
+}
+
+static void handleHVXWarnings(const Driver &D, const ArgList &Args) {
+ // Handle deprecated HVX double warnings.
+ if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_double))
+ D.Diag(diag::warn_drv_deprecated_arg)
+ << A->getAsString(Args) << "-mhvx-length=128B";
+ if (Arg *A = Args.getLastArg(options::OPT_mno_hexagon_hvx_double))
+ D.Diag(diag::warn_drv_deprecated_arg) << A->getAsString(Args) << "-mno-hvx";
+ // Handle the unsupported values passed to mhvx-length.
+ if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_length_EQ)) {
+ StringRef Val = A->getValue();
+ if (Val != "64B" && Val != "128B")
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Val;
+ }
+}
+
+// Handle hvx target features explicitly.
+static void handleHVXTargetFeatures(const Driver &D, const ArgList &Args,
+ std::vector<StringRef> &Features,
+ bool &HasHVX) {
+ // Handle HVX warnings.
+ handleHVXWarnings(D, Args);
+
+ // Add the +hvx* features based on commandline flags.
+ StringRef HVXFeature, HVXLength;
+ StringRef Cpu(toolchains::HexagonToolChain::GetTargetCPUVersion(Args));
+
+ // Handle -mhvx, -mhvx=, -mno-hvx, -mno-hvx-double.
+ if (Arg *A = Args.getLastArg(
+ options::OPT_mno_hexagon_hvx, options::OPT_mno_hexagon_hvx_double,
+ options::OPT_mhexagon_hvx, options::OPT_mhexagon_hvx_EQ)) {
+ if (A->getOption().matches(options::OPT_mno_hexagon_hvx) ||
+ A->getOption().matches(options::OPT_mno_hexagon_hvx_double)) {
+ return;
+ } else if (A->getOption().matches(options::OPT_mhexagon_hvx_EQ)) {
+ HasHVX = true;
+ HVXFeature = Cpu = A->getValue();
+ HVXFeature = Args.MakeArgString(llvm::Twine("+hvx") + HVXFeature.lower());
+ } else if (A->getOption().matches(options::OPT_mhexagon_hvx)) {
+ HasHVX = true;
+ HVXFeature = Args.MakeArgString(llvm::Twine("+hvx") + Cpu);
+ }
+ Features.push_back(HVXFeature);
+ }
+
+ // Handle -mhvx-length=, -mhvx-double.
+ if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_length_EQ,
+ options::OPT_mhexagon_hvx_double)) {
+ // These falgs are valid only if HVX in enabled.
+ if (!HasHVX)
+ D.Diag(diag::err_drv_invalid_hvx_length);
+ else if (A->getOption().matches(options::OPT_mhexagon_hvx_length_EQ))
+ HVXLength = A->getValue();
+ else if (A->getOption().matches(options::OPT_mhexagon_hvx_double))
+ HVXLength = "128b";
+ }
+ // Default hvx-length based on Cpu.
+ else if (HasHVX)
+ HVXLength = getDefaultHvxLength(Cpu);
+
+ if (!HVXLength.empty()) {
+ HVXFeature =
+ Args.MakeArgString(llvm::Twine("+hvx-length") + HVXLength.lower());
+ Features.push_back(HVXFeature);
+ }
+}
+
+// Hexagon target features.
+void hexagon::getHexagonTargetFeatures(const Driver &D, const ArgList &Args,
+ std::vector<StringRef> &Features) {
+ handleTargetFeaturesGroup(Args, Features,
+ options::OPT_m_hexagon_Features_Group);
+
+ bool UseLongCalls = false;
+ if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,
+ options::OPT_mno_long_calls)) {
+ if (A->getOption().matches(options::OPT_mlong_calls))
+ UseLongCalls = true;
+ }
+
+ Features.push_back(UseLongCalls ? "+long-calls" : "-long-calls");
+
+ bool HasHVX(false);
+ handleHVXTargetFeatures(D, Args, Features, HasHVX);
+}
+
// Hexagon tools start.
void hexagon::Assembler::RenderExtraToolArgs(const JobAction &JA,
ArgStringList &CmdArgs) const {
@@ -248,7 +343,8 @@ constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
//----------------------------------------------------------------------------
if (IncStdLib && IncDefLibs) {
if (D.CCCIsCXX()) {
- HTC.AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (HTC.ShouldLinkCXXStdlib(Args))
+ HTC.AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lm");
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Hexagon.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Hexagon.h
index 7f9a6b2f34b92..229a08c76dfbc 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Hexagon.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Hexagon.h
@@ -50,6 +50,10 @@ public:
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};
+
+void getHexagonTargetFeatures(const Driver &D, const llvm::opt::ArgList &Args,
+ std::vector<StringRef> &Features);
+
} // end namespace hexagon.
} // end namespace tools
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Linux.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Linux.cpp
index 08a27fa7fed10..1301cdf114ae1 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Linux.cpp
@@ -210,7 +210,12 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
Distro Distro(D.getVFS());
- if (Distro.IsOpenSUSE() || Distro.IsUbuntu()) {
+ if (Distro.IsAlpineLinux()) {
+ ExtraOpts.push_back("-z");
+ ExtraOpts.push_back("now");
+ }
+
+ if (Distro.IsOpenSUSE() || Distro.IsUbuntu() || Distro.IsAlpineLinux()) {
ExtraOpts.push_back("-z");
ExtraOpts.push_back("relro");
}
@@ -232,7 +237,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
// Android loader does not support .gnu.hash.
// Hexagon linker/loader does not support .gnu.hash
if (!IsMips && !IsAndroid && !IsHexagon) {
- if (Distro.IsRedhat() || Distro.IsOpenSUSE() ||
+ if (Distro.IsRedhat() || Distro.IsOpenSUSE() || Distro.IsAlpineLinux() ||
(Distro.IsUbuntu() && Distro >= Distro::UbuntuMaverick))
ExtraOpts.push_back("--hash-style=gnu");
@@ -248,7 +253,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
ExtraOpts.push_back("--build-id");
#endif
- if (Distro.IsOpenSUSE())
+ if (IsAndroid || Distro.IsOpenSUSE())
ExtraOpts.push_back("--enable-new-dtags");
// The selection of paths to try here is designed to match the patterns which
@@ -810,7 +815,10 @@ void Linux::AddIAMCUIncludeArgs(const ArgList &DriverArgs,
}
}
-bool Linux::isPIEDefault() const { return getSanitizerArgs().requiresPIE(); }
+bool Linux::isPIEDefault() const {
+ return (getTriple().isAndroid() && !getTriple().isAndroidVersionLT(16)) ||
+ getTriple().isMusl() || getSanitizerArgs().requiresPIE();
+}
SanitizerMask Linux::getSupportedSanitizers() const {
const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
@@ -828,12 +836,13 @@ SanitizerMask Linux::getSupportedSanitizers() const {
SanitizerMask Res = ToolChain::getSupportedSanitizers();
Res |= SanitizerKind::Address;
Res |= SanitizerKind::Fuzzer;
+ Res |= SanitizerKind::FuzzerNoLink;
Res |= SanitizerKind::KernelAddress;
Res |= SanitizerKind::Vptr;
Res |= SanitizerKind::SafeStack;
if (IsX86_64 || IsMIPS64 || IsAArch64)
Res |= SanitizerKind::DataFlow;
- if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsArmArch)
+ if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsArmArch || IsPowerPC64)
Res |= SanitizerKind::Leak;
if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64)
Res |= SanitizerKind::Thread;
@@ -841,9 +850,12 @@ SanitizerMask Linux::getSupportedSanitizers() const {
Res |= SanitizerKind::Memory;
if (IsX86_64 || IsMIPS64)
Res |= SanitizerKind::Efficiency;
- if (IsX86 || IsX86_64) {
+ if (IsX86 || IsX86_64)
Res |= SanitizerKind::Function;
- }
+ if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsArmArch)
+ Res |= SanitizerKind::Scudo;
+ if (IsAArch64)
+ Res |= SanitizerKind::HWAddress;
return Res;
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/MSVC.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/MSVC.cpp
index 7978a6941cb85..ae41ee9e22cf1 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/MSVC.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/MSVC.cpp
@@ -375,7 +375,7 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (TC.getSanitizerArgs().needsAsanRt()) {
CmdArgs.push_back(Args.MakeArgString("-debug"));
CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
- if (TC.getSanitizerArgs().needsSharedAsanRt() ||
+ if (TC.getSanitizerArgs().needsSharedRt() ||
Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) {
for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"})
CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
@@ -1266,9 +1266,8 @@ VersionTuple MSVCToolChain::computeMSVCVersion(const Driver *D,
if (MSVT.empty() &&
Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
IsWindowsMSVC)) {
- // -fms-compatibility-version=18.00 is default.
- // FIXME: Consider bumping this to 19 (MSVC2015) soon.
- MSVT = VersionTuple(18);
+ // -fms-compatibility-version=19.11 is default, aka 2017
+ MSVT = VersionTuple(19, 11);
}
return MSVT;
}
@@ -1317,24 +1316,26 @@ static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL,
case '2':
case 'x':
case 'd':
- if (&OptChar == ExpandChar) {
- if (OptChar == 'd') {
- DAL.AddFlagArg(A, Opts.getOption(options::OPT_O0));
- } else {
- if (OptChar == '1') {
- DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
- } else if (OptChar == '2' || OptChar == 'x') {
- DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
- DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
- }
- if (SupportsForcingFramePointer &&
- !DAL.hasArgNoClaim(options::OPT_fno_omit_frame_pointer))
- DAL.AddFlagArg(A,
- Opts.getOption(options::OPT_fomit_frame_pointer));
- if (OptChar == '1' || OptChar == '2')
- DAL.AddFlagArg(A,
- Opts.getOption(options::OPT_ffunction_sections));
+ // Ignore /O[12xd] flags that aren't the last one on the command line.
+ // Only the last one gets expanded.
+ if (&OptChar != ExpandChar) {
+ A->claim();
+ break;
+ }
+ if (OptChar == 'd') {
+ DAL.AddFlagArg(A, Opts.getOption(options::OPT_O0));
+ } else {
+ if (OptChar == '1') {
+ DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
+ } else if (OptChar == '2' || OptChar == 'x') {
+ DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
+ DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
}
+ if (SupportsForcingFramePointer &&
+ !DAL.hasArgNoClaim(options::OPT_fno_omit_frame_pointer))
+ DAL.AddFlagArg(A, Opts.getOption(options::OPT_fomit_frame_pointer));
+ if (OptChar == '1' || OptChar == '2')
+ DAL.AddFlagArg(A, Opts.getOption(options::OPT_ffunction_sections));
}
break;
case 'b':
@@ -1430,9 +1431,7 @@ MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
// First step is to search for the character we'd like to expand.
const char *ExpandChar = nullptr;
- for (Arg *A : Args) {
- if (!A->getOption().matches(options::OPT__SLASH_O))
- continue;
+ for (Arg *A : Args.filtered(options::OPT__SLASH_O)) {
StringRef OptStr = A->getValue();
for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
char OptChar = OptStr[I];
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/MinGW.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/MinGW.cpp
index 632b76d92bddf..572ea803f2dc7 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/MinGW.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/MinGW.cpp
@@ -82,6 +82,9 @@ void tools::MinGW::Linker::AddLibGCC(const ArgList &Args,
CmdArgs.push_back("-lmoldname");
CmdArgs.push_back("-lmingwex");
+ for (auto Lib : Args.getAllArgValues(options::OPT_l))
+ if (StringRef(Lib).startswith("msvcr") || Lib == "ucrtbase")
+ return;
CmdArgs.push_back("-lmsvcrt");
}
@@ -104,14 +107,6 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// handled somewhere else.
Args.ClaimAllArgs(options::OPT_w);
- StringRef LinkerName = Args.getLastArgValue(options::OPT_fuse_ld_EQ, "ld");
- if (LinkerName.equals_lower("lld")) {
- CmdArgs.push_back("-flavor");
- CmdArgs.push_back("gnu");
- } else if (!LinkerName.equals_lower("ld")) {
- D.Diag(diag::err_drv_unsupported_linker) << LinkerName;
- }
-
if (!D.SysRoot.empty())
CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
@@ -119,12 +114,24 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-s");
CmdArgs.push_back("-m");
- if (TC.getArch() == llvm::Triple::x86)
+ switch (TC.getArch()) {
+ case llvm::Triple::x86:
CmdArgs.push_back("i386pe");
- if (TC.getArch() == llvm::Triple::x86_64)
+ break;
+ case llvm::Triple::x86_64:
CmdArgs.push_back("i386pep");
- if (TC.getArch() == llvm::Triple::arm)
+ break;
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ // FIXME: this is incorrect for WinCE
CmdArgs.push_back("thumb2pe");
+ break;
+ case llvm::Triple::aarch64:
+ CmdArgs.push_back("arm64pe");
+ break;
+ default:
+ llvm_unreachable("Unsupported target architecture.");
+ }
if (Args.hasArg(options::OPT_mwindows)) {
CmdArgs.push_back("--subsystem");
@@ -185,8 +192,7 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// TODO: Add profile stuff here
- if (D.CCCIsCXX() &&
- !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
+ if (TC.ShouldLinkCXXStdlib(Args)) {
bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
!Args.hasArg(options::OPT_static);
if (OnlyLibstdcxxStatic)
@@ -230,7 +236,7 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_static))
CmdArgs.push_back("--end-group");
- else if (!LinkerName.equals_lower("lld"))
+ else
AddLibGCC(Args, CmdArgs);
}
@@ -241,7 +247,7 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o")));
}
}
- const char *Exec = Args.MakeArgString(TC.GetProgramPath(LinkerName.data()));
+ const char *Exec = Args.MakeArgString(TC.GetLinkerPath());
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
@@ -361,8 +367,11 @@ bool toolchains::MinGW::isPICDefaultForced() const {
return getArch() == llvm::Triple::x86_64;
}
-bool toolchains::MinGW::UseSEHExceptions() const {
- return getArch() == llvm::Triple::x86_64;
+llvm::ExceptionHandling
+toolchains::MinGW::GetExceptionModel(const ArgList &Args) const {
+ if (getArch() == llvm::Triple::x86_64)
+ return llvm::ExceptionHandling::WinEH;
+ return llvm::ExceptionHandling::DwarfCFI;
}
void toolchains::MinGW::AddCudaIncludeArgs(const ArgList &DriverArgs,
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/MinGW.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/MinGW.h
index 9b3d7c553f1d8..f8dbcae627565 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/MinGW.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/MinGW.h
@@ -64,7 +64,9 @@ public:
bool isPICDefault() const override;
bool isPIEDefault() const override;
bool isPICDefaultForced() const override;
- bool UseSEHExceptions() const;
+
+ llvm::ExceptionHandling GetExceptionModel(
+ const llvm::opt::ArgList &Args) const override;
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Minix.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Minix.cpp
index 2e8939c401502..39e6f90b6ef02 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Minix.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Minix.cpp
@@ -72,7 +72,8 @@ void tools::minix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
if (D.CCCIsCXX()) {
- getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (getToolChain().ShouldLinkCXXStdlib(Args))
+ getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lm");
}
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/NaCl.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/NaCl.cpp
index 5eb5c74f1310c..128478d638719 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/NaCl.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/NaCl.cpp
@@ -133,13 +133,15 @@ void nacltools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (D.CCCIsCXX() &&
!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
- bool OnlyLibstdcxxStatic =
- Args.hasArg(options::OPT_static_libstdcxx) && !IsStatic;
- if (OnlyLibstdcxxStatic)
- CmdArgs.push_back("-Bstatic");
- ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
- if (OnlyLibstdcxxStatic)
- CmdArgs.push_back("-Bdynamic");
+ if (ToolChain.ShouldLinkCXXStdlib(Args)) {
+ bool OnlyLibstdcxxStatic =
+ Args.hasArg(options::OPT_static_libstdcxx) && !IsStatic;
+ if (OnlyLibstdcxxStatic)
+ CmdArgs.push_back("-Bstatic");
+ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (OnlyLibstdcxxStatic)
+ CmdArgs.push_back("-Bdynamic");
+ }
CmdArgs.push_back("-lm");
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/NetBSD.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/NetBSD.cpp
index a1a3108cb28d7..0db6578f7407b 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/NetBSD.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/NetBSD.cpp
@@ -278,7 +278,8 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
addOpenMPRuntime(CmdArgs, getToolChain(), Args);
if (D.CCCIsCXX()) {
- getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (getToolChain().ShouldLinkCXXStdlib(Args))
+ getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lm");
}
if (NeedsSanitizerDeps)
@@ -324,7 +325,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
NetBSD::NetBSD(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
- if (getDriver().UseStdLib) {
+ if (!Args.hasArg(options::OPT_nostdlib)) {
// When targeting a 32-bit platform, try the special directory used on
// 64-bit hosts, and only fall back to the main library directory if that
// doesn't work.
@@ -415,11 +416,34 @@ void NetBSD::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
"", DriverArgs, CC1Args);
}
+llvm::ExceptionHandling NetBSD::GetExceptionModel(const ArgList &Args) const {
+ // NetBSD uses Dwarf exceptions on ARM.
+ llvm::Triple::ArchType TArch = getTriple().getArch();
+ if (TArch == llvm::Triple::arm || TArch == llvm::Triple::armeb ||
+ TArch == llvm::Triple::thumb || TArch == llvm::Triple::thumbeb)
+ return llvm::ExceptionHandling::DwarfCFI;
+ return llvm::ExceptionHandling::None;
+}
+
SanitizerMask NetBSD::getSupportedSanitizers() const {
+ const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
SanitizerMask Res = ToolChain::getSupportedSanitizers();
- if (IsX86_64) {
+ if (IsX86 || IsX86_64) {
Res |= SanitizerKind::Address;
+ Res |= SanitizerKind::Function;
+ Res |= SanitizerKind::Leak;
+ Res |= SanitizerKind::SafeStack;
+ Res |= SanitizerKind::Scudo;
+ Res |= SanitizerKind::Vptr;
+ }
+ if (IsX86_64) {
+ Res |= SanitizerKind::Efficiency;
+ Res |= SanitizerKind::Fuzzer;
+ Res |= SanitizerKind::FuzzerNoLink;
+ Res |= SanitizerKind::KernelAddress;
+ Res |= SanitizerKind::Memory;
+ Res |= SanitizerKind::Thread;
}
return Res;
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/NetBSD.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/NetBSD.h
index 5163ff72d81bb..e98df72ce65c2 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/NetBSD.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/NetBSD.h
@@ -69,6 +69,9 @@ public:
return true;
}
+ llvm::ExceptionHandling GetExceptionModel(
+ const llvm::opt::ArgList &Args) const override;
+
SanitizerMask getSupportedSanitizers() const override;
protected:
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/OpenBSD.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/OpenBSD.cpp
index 1d54a1e9cbb05..fbb84a62ca89e 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/OpenBSD.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/OpenBSD.cpp
@@ -179,7 +179,8 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
if (D.CCCIsCXX()) {
- getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (getToolChain().ShouldLinkCXXStdlib(Args))
+ getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
if (Args.hasArg(options::OPT_pg))
CmdArgs.push_back("-lm_p");
else
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/PS4CPU.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/PS4CPU.cpp
index c1b8c3d660779..b37fe7d1f9b91 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/PS4CPU.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/PS4CPU.cpp
@@ -227,7 +227,8 @@ static void ConstructGoldLinkJob(const Tool &T, Compilation &C,
// libraries for both C and C++ compilations.
CmdArgs.push_back("-lkernel");
if (D.CCCIsCXX()) {
- ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (ToolChain.ShouldLinkCXXStdlib(Args))
+ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
if (Args.hasArg(options::OPT_pg))
CmdArgs.push_back("-lm_p");
else
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Solaris.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Solaris.cpp
index de98d11b2dc7b..9fe6e9d520d09 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Solaris.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Solaris.cpp
@@ -100,7 +100,7 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
- if (getToolChain().getDriver().CCCIsCXX())
+ if (getToolChain().ShouldLinkCXXStdlib(Args))
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lgcc_s");
CmdArgs.push_back("-lc");
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/WebAssembly.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/WebAssembly.cpp
index 058bc42323e2f..8ae1b6c2f55df 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/WebAssembly.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/WebAssembly.cpp
@@ -38,46 +38,25 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const char *LinkingOutput) const {
const ToolChain &ToolChain = getToolChain();
- const Driver &D = ToolChain.getDriver();
const char *Linker = Args.MakeArgString(ToolChain.GetLinkerPath());
ArgStringList CmdArgs;
CmdArgs.push_back("-flavor");
CmdArgs.push_back("wasm");
- // Enable garbage collection of unused input sections by default, since code
- // size is of particular importance. This is significantly facilitated by
- // the enabling of -ffunction-sections and -fdata-sections in
- // Clang::ConstructJob.
- if (areOptimizationsEnabled(Args))
- CmdArgs.push_back("--gc-sections");
-
- if (Args.hasArg(options::OPT_rdynamic))
- CmdArgs.push_back("-export-dynamic");
if (Args.hasArg(options::OPT_s))
CmdArgs.push_back("--strip-all");
- if (Args.hasArg(options::OPT_shared))
- CmdArgs.push_back("-shared");
- if (Args.hasArg(options::OPT_static))
- CmdArgs.push_back("-Bstatic");
Args.AddAllArgs(CmdArgs, options::OPT_L);
+ Args.AddAllArgs(CmdArgs, options::OPT_u);
ToolChain.AddFilePathLibArgs(Args, CmdArgs);
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
- if (Args.hasArg(options::OPT_shared))
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("rcrt1.o")));
- else if (Args.hasArg(options::OPT_pie))
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("Scrt1.o")));
- else
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt1.o")));
-
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
- }
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles))
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt1.o")));
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
- if (D.CCCIsCXX())
+ if (ToolChain.ShouldLinkCXXStdlib(Args))
ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
if (Args.hasArg(options::OPT_pthread))
@@ -86,12 +65,9 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-allow-undefined-file");
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("wasm.syms")));
CmdArgs.push_back("-lc");
- CmdArgs.push_back("-lcompiler_rt");
+ AddRunTimeLibs(ToolChain, ToolChain.getDriver(), CmdArgs, Args);
}
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles))
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
-
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
@@ -123,9 +99,6 @@ bool WebAssembly::isPICDefaultForced() const { return false; }
bool WebAssembly::IsIntegratedAssemblerDefault() const { return true; }
-// TODO: Support Objective C stuff.
-bool WebAssembly::SupportsObjCGC() const { return false; }
-
bool WebAssembly::hasBlocksRuntime() const { return false; }
// TODO: Support profiling.
@@ -163,6 +136,14 @@ void WebAssembly::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
getDriver().SysRoot + "/include/c++/v1");
}
+std::string WebAssembly::getThreadModel() const {
+ // The WebAssembly MVP does not yet support threads; for now, use the
+ // "single" threading model, which lowers atomics to non-atomic operations.
+ // When threading support is standardized and implemented in popular engines,
+ // this override should be removed.
+ return "single";
+}
+
Tool *WebAssembly::buildLinker() const {
return new tools::wasm::Linker(*this);
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/WebAssembly.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/WebAssembly.h
index 2999db477f799..8784e12dfb0ec 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/WebAssembly.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/WebAssembly.h
@@ -49,7 +49,6 @@ private:
bool isPICDefaultForced() const override;
bool IsIntegratedAssemblerDefault() const override;
bool hasBlocksRuntime() const override;
- bool SupportsObjCGC() const override;
bool SupportsProfiling() const override;
bool HasNativeLLVMSupport() const override;
void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
@@ -63,6 +62,7 @@ private:
void AddClangCXXStdlibIncludeArgs(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
+ std::string getThreadModel() const override;
const char *getDefaultLinker() const override {
return "lld";
diff --git a/contrib/llvm/tools/clang/lib/Driver/XRayArgs.cpp b/contrib/llvm/tools/clang/lib/Driver/XRayArgs.cpp
index 8d68a8432d39d..232bacd5f0955 100644
--- a/contrib/llvm/tools/clang/lib/Driver/XRayArgs.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/XRayArgs.cpp
@@ -27,8 +27,6 @@ namespace {
constexpr char XRayInstrumentOption[] = "-fxray-instrument";
constexpr char XRayInstructionThresholdOption[] =
"-fxray-instruction-threshold=";
-constexpr char XRayAlwaysInstrumentOption[] = "-fxray-always-instrument=";
-constexpr char XRayNeverInstrumentOption[] = "-fxray-never-instrument=";
} // namespace
XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) {
@@ -63,6 +61,14 @@ XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) {
D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
}
+ // By default, the back-end will not emit the lowering for XRay customevent
+ // calls if the function is not instrumented. In the future we will change
+ // this default to be the reverse, but in the meantime we're going to
+ // introduce the new functionality behind a flag.
+ if (Args.hasFlag(options::OPT_fxray_always_emit_customevents,
+ options::OPT_fnoxray_always_emit_customevents, false))
+ XRayAlwaysEmitCustomEvents = true;
+
// Validate the always/never attribute files. We also make sure that they
// are treated as actual dependencies.
for (const auto &Filename :
@@ -91,17 +97,21 @@ void XRayArgs::addArgs(const ToolChain &TC, const ArgList &Args,
return;
CmdArgs.push_back(XRayInstrumentOption);
+
+ if (XRayAlwaysEmitCustomEvents)
+ CmdArgs.push_back("-fxray-always-emit-customevents");
+
CmdArgs.push_back(Args.MakeArgString(Twine(XRayInstructionThresholdOption) +
Twine(InstructionThreshold)));
for (const auto &Always : AlwaysInstrumentFiles) {
- SmallString<64> AlwaysInstrumentOpt(XRayAlwaysInstrumentOption);
+ SmallString<64> AlwaysInstrumentOpt("-fxray-always-instrument=");
AlwaysInstrumentOpt += Always;
CmdArgs.push_back(Args.MakeArgString(AlwaysInstrumentOpt));
}
for (const auto &Never : NeverInstrumentFiles) {
- SmallString<64> NeverInstrumentOpt(XRayNeverInstrumentOption);
+ SmallString<64> NeverInstrumentOpt("-fxray-never-instrument=");
NeverInstrumentOpt += Never;
CmdArgs.push_back(Args.MakeArgString(NeverInstrumentOpt));
}
diff --git a/contrib/llvm/tools/clang/lib/Format/BreakableToken.cpp b/contrib/llvm/tools/clang/lib/Format/BreakableToken.cpp
index 3c9df62f80dca..4735ab3564f0e 100644
--- a/contrib/llvm/tools/clang/lib/Format/BreakableToken.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/BreakableToken.cpp
@@ -40,9 +40,15 @@ static bool IsBlank(char C) {
}
}
-static StringRef getLineCommentIndentPrefix(StringRef Comment) {
- static const char *const KnownPrefixes[] = {
- "///<", "//!<", "///", "//", "//!"};
+static StringRef getLineCommentIndentPrefix(StringRef Comment,
+ const FormatStyle &Style) {
+ static const char *const KnownCStylePrefixes[] = {"///<", "//!<", "///", "//",
+ "//!"};
+ static const char *const KnownTextProtoPrefixes[] = {"//", "#"};
+ ArrayRef<const char *> KnownPrefixes(KnownCStylePrefixes);
+ if (Style.Language == FormatStyle::LK_TextProto)
+ KnownPrefixes = KnownTextProtoPrefixes;
+
StringRef LongestPrefix;
for (StringRef KnownPrefix : KnownPrefixes) {
if (Comment.startswith(KnownPrefix)) {
@@ -61,6 +67,8 @@ static BreakableToken::Split getCommentSplit(StringRef Text,
unsigned ColumnLimit,
unsigned TabWidth,
encoding::Encoding Encoding) {
+ DEBUG(llvm::dbgs() << "Comment split: \"" << Text << ", " << ColumnLimit
+ << "\", Content start: " << ContentStartColumn << "\n");
if (ColumnLimit <= ContentStartColumn + 1)
return BreakableToken::Split(StringRef::npos, 0);
@@ -165,7 +173,7 @@ bool switchesFormatting(const FormatToken &Token) {
}
unsigned
-BreakableToken::getLineLengthAfterCompression(unsigned RemainingTokenColumns,
+BreakableToken::getLengthAfterCompression(unsigned RemainingTokenColumns,
Split Split) const {
// Example: consider the content
// lala lala
@@ -175,58 +183,64 @@ BreakableToken::getLineLengthAfterCompression(unsigned RemainingTokenColumns,
// We compute the number of columns when the split is compressed into a single
// space, like:
// lala lala
+ //
+ // FIXME: Correctly measure the length of whitespace in Split.second so it
+ // works with tabs.
return RemainingTokenColumns + 1 - Split.second;
}
-unsigned BreakableSingleLineToken::getLineCount() const { return 1; }
+unsigned BreakableStringLiteral::getLineCount() const { return 1; }
+
+unsigned BreakableStringLiteral::getRangeLength(unsigned LineIndex,
+ unsigned Offset,
+ StringRef::size_type Length,
+ unsigned StartColumn) const {
+ llvm_unreachable("Getting the length of a part of the string literal "
+ "indicates that the code tries to reflow it.");
+}
+
+unsigned
+BreakableStringLiteral::getRemainingLength(unsigned LineIndex, unsigned Offset,
+ unsigned StartColumn) const {
+ return UnbreakableTailLength + Postfix.size() +
+ encoding::columnWidthWithTabs(Line.substr(Offset, StringRef::npos),
+ StartColumn, Style.TabWidth, Encoding);
+}
-unsigned BreakableSingleLineToken::getLineLengthAfterSplit(
- unsigned LineIndex, unsigned TailOffset,
- StringRef::size_type Length) const {
- return StartColumn + Prefix.size() + Postfix.size() +
- encoding::columnWidthWithTabs(Line.substr(TailOffset, Length),
- StartColumn + Prefix.size(),
- Style.TabWidth, Encoding);
+unsigned BreakableStringLiteral::getContentStartColumn(unsigned LineIndex,
+ bool Break) const {
+ return StartColumn + Prefix.size();
}
-BreakableSingleLineToken::BreakableSingleLineToken(
+BreakableStringLiteral::BreakableStringLiteral(
const FormatToken &Tok, unsigned StartColumn, StringRef Prefix,
StringRef Postfix, bool InPPDirective, encoding::Encoding Encoding,
const FormatStyle &Style)
: BreakableToken(Tok, InPPDirective, Encoding, Style),
- StartColumn(StartColumn), Prefix(Prefix), Postfix(Postfix) {
+ StartColumn(StartColumn), Prefix(Prefix), Postfix(Postfix),
+ UnbreakableTailLength(Tok.UnbreakableTailLength) {
assert(Tok.TokenText.startswith(Prefix) && Tok.TokenText.endswith(Postfix));
Line = Tok.TokenText.substr(
Prefix.size(), Tok.TokenText.size() - Prefix.size() - Postfix.size());
}
-BreakableStringLiteral::BreakableStringLiteral(
- const FormatToken &Tok, unsigned StartColumn, StringRef Prefix,
- StringRef Postfix, bool InPPDirective, encoding::Encoding Encoding,
- const FormatStyle &Style)
- : BreakableSingleLineToken(Tok, StartColumn, Prefix, Postfix, InPPDirective,
- Encoding, Style) {}
-
-BreakableToken::Split
-BreakableStringLiteral::getSplit(unsigned LineIndex, unsigned TailOffset,
- unsigned ColumnLimit,
- llvm::Regex &CommentPragmasRegex) const {
- return getStringSplit(Line.substr(TailOffset),
- StartColumn + Prefix.size() + Postfix.size(),
- ColumnLimit, Style.TabWidth, Encoding);
+BreakableToken::Split BreakableStringLiteral::getSplit(
+ unsigned LineIndex, unsigned TailOffset, unsigned ColumnLimit,
+ unsigned ContentStartColumn, llvm::Regex &CommentPragmasRegex) const {
+ return getStringSplit(Line.substr(TailOffset), ContentStartColumn,
+ ColumnLimit - Postfix.size(), Style.TabWidth, Encoding);
}
void BreakableStringLiteral::insertBreak(unsigned LineIndex,
unsigned TailOffset, Split Split,
- WhitespaceManager &Whitespaces) {
+ WhitespaceManager &Whitespaces) const {
Whitespaces.replaceWhitespaceInToken(
Tok, Prefix.size() + TailOffset + Split.first, Split.second, Postfix,
Prefix, InPPDirective, 1, StartColumn);
}
BreakableComment::BreakableComment(const FormatToken &Token,
- unsigned StartColumn,
- bool InPPDirective,
+ unsigned StartColumn, bool InPPDirective,
encoding::Encoding Encoding,
const FormatStyle &Style)
: BreakableToken(Token, InPPDirective, Encoding, Style),
@@ -236,19 +250,19 @@ unsigned BreakableComment::getLineCount() const { return Lines.size(); }
BreakableToken::Split
BreakableComment::getSplit(unsigned LineIndex, unsigned TailOffset,
- unsigned ColumnLimit,
+ unsigned ColumnLimit, unsigned ContentStartColumn,
llvm::Regex &CommentPragmasRegex) const {
// Don't break lines matching the comment pragmas regex.
if (CommentPragmasRegex.match(Content[LineIndex]))
return Split(StringRef::npos, 0);
return getCommentSplit(Content[LineIndex].substr(TailOffset),
- getContentStartColumn(LineIndex, TailOffset),
- ColumnLimit, Style.TabWidth, Encoding);
+ ContentStartColumn, ColumnLimit, Style.TabWidth,
+ Encoding);
}
-void BreakableComment::compressWhitespace(unsigned LineIndex,
- unsigned TailOffset, Split Split,
- WhitespaceManager &Whitespaces) {
+void BreakableComment::compressWhitespace(
+ unsigned LineIndex, unsigned TailOffset, Split Split,
+ WhitespaceManager &Whitespaces) const {
StringRef Text = Content[LineIndex].substr(TailOffset);
// Text is relative to the content line, but Whitespaces operates relative to
// the start of the corresponding token, so compute the start of the Split
@@ -262,44 +276,6 @@ void BreakableComment::compressWhitespace(unsigned LineIndex,
/*InPPDirective=*/false, /*Newlines=*/0, /*Spaces=*/1);
}
-BreakableToken::Split
-BreakableComment::getReflowSplit(StringRef Text, StringRef ReflowPrefix,
- unsigned PreviousEndColumn,
- unsigned ColumnLimit) const {
- unsigned ReflowStartColumn = PreviousEndColumn + ReflowPrefix.size();
- StringRef TrimmedText = Text.rtrim(Blanks);
- // This is the width of the resulting line in case the full line of Text gets
- // reflown up starting at ReflowStartColumn.
- unsigned FullWidth = ReflowStartColumn + encoding::columnWidthWithTabs(
- TrimmedText, ReflowStartColumn,
- Style.TabWidth, Encoding);
- // If the full line fits up, we return a reflow split after it,
- // otherwise we compute the largest piece of text that fits after
- // ReflowStartColumn.
- Split ReflowSplit =
- FullWidth <= ColumnLimit
- ? Split(TrimmedText.size(), Text.size() - TrimmedText.size())
- : getCommentSplit(Text, ReflowStartColumn, ColumnLimit,
- Style.TabWidth, Encoding);
-
- // We need to be extra careful here, because while it's OK to keep a long line
- // if it can't be broken into smaller pieces (like when the first word of a
- // long line is longer than the column limit), it's not OK to reflow that long
- // word up. So we recompute the size of the previous line after reflowing and
- // only return the reflow split if that's under the line limit.
- if (ReflowSplit.first != StringRef::npos &&
- // Check if the width of the newly reflown line is under the limit.
- PreviousEndColumn + ReflowPrefix.size() +
- encoding::columnWidthWithTabs(Text.substr(0, ReflowSplit.first),
- PreviousEndColumn +
- ReflowPrefix.size(),
- Style.TabWidth, Encoding) <=
- ColumnLimit) {
- return ReflowSplit;
- }
- return Split(StringRef::npos, 0);
-}
-
const FormatToken &BreakableComment::tokenAt(unsigned LineIndex) const {
return Tokens[LineIndex] ? *Tokens[LineIndex] : Tok;
}
@@ -309,7 +285,7 @@ static bool mayReflowContent(StringRef Content) {
// Lines starting with '@' commonly have special meaning.
// Lines starting with '-', '-#', '+' or '*' are bulleted/numbered lists.
static const SmallVector<StringRef, 8> kSpecialMeaningPrefixes = {
- "@", "TODO", "FIXME", "XXX", "-# ", "- ", "+ ", "* " };
+ "@", "TODO", "FIXME", "XXX", "-# ", "- ", "+ ", "* "};
bool hasSpecialMeaningPrefix = false;
for (StringRef Prefix : kSpecialMeaningPrefixes) {
if (Content.startswith(Prefix)) {
@@ -322,8 +298,8 @@ static bool mayReflowContent(StringRef Content) {
// To avoid issues if a line starts with a number which is actually the end
// of a previous line, we only consider numbers with up to 2 digits.
static llvm::Regex kNumberedListRegexp = llvm::Regex("^[1-9][0-9]?\\. ");
- hasSpecialMeaningPrefix = hasSpecialMeaningPrefix ||
- kNumberedListRegexp.match(Content);
+ hasSpecialMeaningPrefix =
+ hasSpecialMeaningPrefix || kNumberedListRegexp.match(Content);
// Simple heuristic for what to reflow: content should contain at least two
// characters and either the first or second character must be
@@ -339,7 +315,9 @@ BreakableBlockComment::BreakableBlockComment(
const FormatToken &Token, unsigned StartColumn,
unsigned OriginalStartColumn, bool FirstInLine, bool InPPDirective,
encoding::Encoding Encoding, const FormatStyle &Style)
- : BreakableComment(Token, StartColumn, InPPDirective, Encoding, Style) {
+ : BreakableComment(Token, StartColumn, InPPDirective, Encoding, Style),
+ DelimitersOnNewline(false),
+ UnbreakableTailLength(Token.UnbreakableTailLength) {
assert(Tok.is(TT_BlockComment) &&
"block comment section must start with a block comment");
@@ -384,8 +362,7 @@ BreakableBlockComment::BreakableBlockComment(
// If the last line is empty, the closing "*/" will have a star.
if (i + 1 == e && Content[i].empty())
break;
- if (!Content[i].empty() && i + 1 != e &&
- Decoration.startswith(Content[i]))
+ if (!Content[i].empty() && i + 1 != e && Decoration.startswith(Content[i]))
continue;
while (!Content[i].startswith(Decoration))
Decoration = Decoration.substr(0, Decoration.size() - 1);
@@ -427,11 +404,30 @@ BreakableBlockComment::BreakableBlockComment(
IndentAtLineBreak =
std::min<int>(IndentAtLineBreak, std::max(0, ContentColumn[i]));
}
- IndentAtLineBreak =
- std::max<unsigned>(IndentAtLineBreak, Decoration.size());
+ IndentAtLineBreak = std::max<unsigned>(IndentAtLineBreak, Decoration.size());
+
+ // Detect a multiline jsdoc comment and set DelimitersOnNewline in that case.
+ if (Style.Language == FormatStyle::LK_JavaScript ||
+ Style.Language == FormatStyle::LK_Java) {
+ if ((Lines[0] == "*" || Lines[0].startswith("* ")) && Lines.size() > 1) {
+ // This is a multiline jsdoc comment.
+ DelimitersOnNewline = true;
+ } else if (Lines[0].startswith("* ") && Lines.size() == 1) {
+ // Detect a long single-line comment, like:
+ // /** long long long */
+ // Below, '2' is the width of '*/'.
+ unsigned EndColumn =
+ ContentColumn[0] +
+ encoding::columnWidthWithTabs(Lines[0], ContentColumn[0],
+ Style.TabWidth, Encoding) +
+ 2;
+ DelimitersOnNewline = EndColumn > Style.ColumnLimit;
+ }
+ }
DEBUG({
llvm::dbgs() << "IndentAtLineBreak " << IndentAtLineBreak << "\n";
+ llvm::dbgs() << "DelimitersOnNewline " << DelimitersOnNewline << "\n";
for (size_t i = 0; i < Lines.size(); ++i) {
llvm::dbgs() << i << " |" << Content[i] << "| "
<< "CC=" << ContentColumn[i] << "| "
@@ -477,30 +473,45 @@ void BreakableBlockComment::adjustWhitespace(unsigned LineIndex,
IndentDelta;
}
-unsigned BreakableBlockComment::getLineLengthAfterSplit(
- unsigned LineIndex, unsigned TailOffset,
- StringRef::size_type Length) const {
- unsigned ContentStartColumn = getContentStartColumn(LineIndex, TailOffset);
+unsigned BreakableBlockComment::getRangeLength(unsigned LineIndex,
+ unsigned Offset,
+ StringRef::size_type Length,
+ unsigned StartColumn) const {
unsigned LineLength =
- ContentStartColumn + encoding::columnWidthWithTabs(
- Content[LineIndex].substr(TailOffset, Length),
- ContentStartColumn, Style.TabWidth, Encoding);
+ encoding::columnWidthWithTabs(Content[LineIndex].substr(Offset, Length),
+ StartColumn, Style.TabWidth, Encoding);
+ // FIXME: This should go into getRemainingLength instead, but we currently
+ // break tests when putting it there. Investigate how to fix those tests.
// The last line gets a "*/" postfix.
if (LineIndex + 1 == Lines.size()) {
LineLength += 2;
// We never need a decoration when breaking just the trailing "*/" postfix.
// Note that checking that Length == 0 is not enough, since Length could
// also be StringRef::npos.
- if (Content[LineIndex].substr(TailOffset, Length).empty()) {
+ if (Content[LineIndex].substr(Offset, StringRef::npos).empty()) {
LineLength -= Decoration.size();
}
}
return LineLength;
}
+unsigned BreakableBlockComment::getRemainingLength(unsigned LineIndex,
+ unsigned Offset,
+ unsigned StartColumn) const {
+ return UnbreakableTailLength +
+ getRangeLength(LineIndex, Offset, StringRef::npos, StartColumn);
+}
+
+unsigned BreakableBlockComment::getContentStartColumn(unsigned LineIndex,
+ bool Break) const {
+ if (Break)
+ return IndentAtLineBreak;
+ return std::max(0, ContentColumn[LineIndex]);
+}
+
void BreakableBlockComment::insertBreak(unsigned LineIndex, unsigned TailOffset,
Split Split,
- WhitespaceManager &Whitespaces) {
+ WhitespaceManager &Whitespaces) const {
StringRef Text = Content[LineIndex].substr(TailOffset);
StringRef Prefix = Decoration;
// We need this to account for the case when we have a decoration "* " for all
@@ -526,97 +537,55 @@ void BreakableBlockComment::insertBreak(unsigned LineIndex, unsigned TailOffset,
/*Spaces=*/LocalIndentAtLineBreak - Prefix.size());
}
-BreakableToken::Split BreakableBlockComment::getSplitBefore(
- unsigned LineIndex,
- unsigned PreviousEndColumn,
- unsigned ColumnLimit,
- llvm::Regex &CommentPragmasRegex) const {
+BreakableToken::Split
+BreakableBlockComment::getReflowSplit(unsigned LineIndex,
+ llvm::Regex &CommentPragmasRegex) const {
if (!mayReflow(LineIndex, CommentPragmasRegex))
return Split(StringRef::npos, 0);
- StringRef TrimmedContent = Content[LineIndex].ltrim(Blanks);
- return getReflowSplit(TrimmedContent, ReflowPrefix, PreviousEndColumn,
- ColumnLimit);
-}
-unsigned BreakableBlockComment::getReflownColumn(
- StringRef Content,
- unsigned LineIndex,
- unsigned PreviousEndColumn) const {
- unsigned StartColumn = PreviousEndColumn + ReflowPrefix.size();
- // If this is the last line, it will carry around its '*/' postfix.
- unsigned PostfixLength = (LineIndex + 1 == Lines.size() ? 2 : 0);
- // The line is composed of previous text, reflow prefix, reflown text and
- // postfix.
- unsigned ReflownColumn =
- StartColumn + encoding::columnWidthWithTabs(Content, StartColumn,
- Style.TabWidth, Encoding) +
- PostfixLength;
- return ReflownColumn;
+ size_t Trimmed = Content[LineIndex].find_first_not_of(Blanks);
+ return Split(0, Trimmed != StringRef::npos ? Trimmed : 0);
}
-unsigned BreakableBlockComment::getLineLengthAfterSplitBefore(
- unsigned LineIndex, unsigned TailOffset,
- unsigned PreviousEndColumn,
- unsigned ColumnLimit,
- Split SplitBefore) const {
- if (SplitBefore.first == StringRef::npos ||
- // Block comment line contents contain the trailing whitespace after the
- // decoration, so the need of left trim. Note that this behavior is
- // consistent with the breaking of block comments where the indentation of
- // a broken line is uniform across all the lines of the block comment.
- SplitBefore.first + SplitBefore.second <
- Content[LineIndex].ltrim().size()) {
- // A piece of line, not the whole, gets reflown.
- return getLineLengthAfterSplit(LineIndex, TailOffset, StringRef::npos);
- } else {
- // The whole line gets reflown, need to check if we need to insert a break
- // for the postfix or not.
- StringRef TrimmedContent = Content[LineIndex].ltrim(Blanks);
- unsigned ReflownColumn =
- getReflownColumn(TrimmedContent, LineIndex, PreviousEndColumn);
- if (ReflownColumn <= ColumnLimit) {
- return ReflownColumn;
- }
- return getLineLengthAfterSplit(LineIndex, TailOffset, StringRef::npos);
- }
+bool BreakableBlockComment::introducesBreakBeforeToken() const {
+ // A break is introduced when we want delimiters on newline.
+ return DelimitersOnNewline &&
+ Lines[0].substr(1).find_first_not_of(Blanks) != StringRef::npos;
}
-void BreakableBlockComment::replaceWhitespaceBefore(
- unsigned LineIndex, unsigned PreviousEndColumn, unsigned ColumnLimit,
- Split SplitBefore, WhitespaceManager &Whitespaces) {
- if (LineIndex == 0) return;
+
+void BreakableBlockComment::reflow(unsigned LineIndex,
+ WhitespaceManager &Whitespaces) const {
StringRef TrimmedContent = Content[LineIndex].ltrim(Blanks);
- if (SplitBefore.first != StringRef::npos) {
- // Here we need to reflow.
- assert(Tokens[LineIndex - 1] == Tokens[LineIndex] &&
- "Reflowing whitespace within a token");
- // This is the offset of the end of the last line relative to the start of
- // the token text in the token.
- unsigned WhitespaceOffsetInToken = Content[LineIndex - 1].data() +
- Content[LineIndex - 1].size() -
- tokenAt(LineIndex).TokenText.data();
- unsigned WhitespaceLength = TrimmedContent.data() -
- tokenAt(LineIndex).TokenText.data() -
- WhitespaceOffsetInToken;
- Whitespaces.replaceWhitespaceInToken(
- tokenAt(LineIndex), WhitespaceOffsetInToken,
- /*ReplaceChars=*/WhitespaceLength, /*PreviousPostfix=*/"",
- /*CurrentPrefix=*/ReflowPrefix, InPPDirective, /*Newlines=*/0,
- /*Spaces=*/0);
- // Check if we need to also insert a break at the whitespace range.
- // For this we first adapt the reflow split relative to the beginning of the
- // content.
- // Note that we don't need a penalty for this break, since it doesn't change
- // the total number of lines.
- Split BreakSplit = SplitBefore;
- BreakSplit.first += TrimmedContent.data() - Content[LineIndex].data();
- unsigned ReflownColumn =
- getReflownColumn(TrimmedContent, LineIndex, PreviousEndColumn);
- if (ReflownColumn > ColumnLimit) {
- insertBreak(LineIndex, 0, BreakSplit, Whitespaces);
+ // Here we need to reflow.
+ assert(Tokens[LineIndex - 1] == Tokens[LineIndex] &&
+ "Reflowing whitespace within a token");
+ // This is the offset of the end of the last line relative to the start of
+ // the token text in the token.
+ unsigned WhitespaceOffsetInToken = Content[LineIndex - 1].data() +
+ Content[LineIndex - 1].size() -
+ tokenAt(LineIndex).TokenText.data();
+ unsigned WhitespaceLength = TrimmedContent.data() -
+ tokenAt(LineIndex).TokenText.data() -
+ WhitespaceOffsetInToken;
+ Whitespaces.replaceWhitespaceInToken(
+ tokenAt(LineIndex), WhitespaceOffsetInToken,
+ /*ReplaceChars=*/WhitespaceLength, /*PreviousPostfix=*/"",
+ /*CurrentPrefix=*/ReflowPrefix, InPPDirective, /*Newlines=*/0,
+ /*Spaces=*/0);
+}
+
+void BreakableBlockComment::adaptStartOfLine(
+ unsigned LineIndex, WhitespaceManager &Whitespaces) const {
+ if (LineIndex == 0) {
+ if (DelimitersOnNewline) {
+ // Since we're breaking at index 1 below, the break position and the
+ // break length are the same.
+ size_t BreakLength = Lines[0].substr(1).find_first_not_of(Blanks);
+ if (BreakLength != StringRef::npos)
+ insertBreak(LineIndex, 0, Split(1, BreakLength), Whitespaces);
}
return;
}
-
// Here no reflow with the previous line will happen.
// Fix the decoration of the line at LineIndex.
StringRef Prefix = Decoration;
@@ -651,6 +620,20 @@ void BreakableBlockComment::replaceWhitespaceBefore(
InPPDirective, /*Newlines=*/1, ContentColumn[LineIndex] - Prefix.size());
}
+BreakableToken::Split
+BreakableBlockComment::getSplitAfterLastLine(unsigned TailOffset) const {
+ if (DelimitersOnNewline) {
+ // Replace the trailing whitespace of the last line with a newline.
+ // In case the last line is empty, the ending '*/' is already on its own
+ // line.
+ StringRef Line = Content.back().substr(TailOffset);
+ StringRef TrimmedLine = Line.rtrim(Blanks);
+ if (!TrimmedLine.empty())
+ return Split(TrimmedLine.size(), Line.size() - TrimmedLine.size());
+ }
+ return Split(StringRef::npos, 0);
+}
+
bool BreakableBlockComment::mayReflow(unsigned LineIndex,
llvm::Regex &CommentPragmasRegex) const {
// Content[LineIndex] may exclude the indent after the '*' decoration. In that
@@ -664,15 +647,6 @@ bool BreakableBlockComment::mayReflow(unsigned LineIndex,
!switchesFormatting(tokenAt(LineIndex));
}
-unsigned
-BreakableBlockComment::getContentStartColumn(unsigned LineIndex,
- unsigned TailOffset) const {
- // If we break, we always break at the predefined indent.
- if (TailOffset != 0)
- return IndentAtLineBreak;
- return std::max(0, ContentColumn[LineIndex]);
-}
-
BreakableLineCommentSection::BreakableLineCommentSection(
const FormatToken &Token, unsigned StartColumn,
unsigned OriginalStartColumn, bool FirstInLine, bool InPPDirective,
@@ -686,7 +660,8 @@ BreakableLineCommentSection::BreakableLineCommentSection(
CurrentTok = CurrentTok->Next) {
LastLineTok = LineTok;
StringRef TokenText(CurrentTok->TokenText);
- assert(TokenText.startswith("//"));
+ assert((TokenText.startswith("//") || TokenText.startswith("#")) &&
+ "unsupported line comment prefix, '//' and '#' are supported");
size_t FirstLineIndex = Lines.size();
TokenText.split(Lines, "\n");
Content.resize(Lines.size());
@@ -696,11 +671,13 @@ BreakableLineCommentSection::BreakableLineCommentSection(
Prefix.resize(Lines.size());
OriginalPrefix.resize(Lines.size());
for (size_t i = FirstLineIndex, e = Lines.size(); i < e; ++i) {
+ Lines[i] = Lines[i].ltrim(Blanks);
// We need to trim the blanks in case this is not the first line in a
// multiline comment. Then the indent is included in Lines[i].
StringRef IndentPrefix =
- getLineCommentIndentPrefix(Lines[i].ltrim(Blanks));
- assert(IndentPrefix.startswith("//"));
+ getLineCommentIndentPrefix(Lines[i].ltrim(Blanks), Style);
+ assert((TokenText.startswith("//") || TokenText.startswith("#")) &&
+ "unsupported line comment prefix, '//' and '#' are supported");
OriginalPrefix[i] = Prefix[i] = IndentPrefix;
if (Lines[i].size() > Prefix[i].size() &&
isAlphanumeric(Lines[i][Prefix[i].size()])) {
@@ -714,22 +691,20 @@ BreakableLineCommentSection::BreakableLineCommentSection(
Prefix[i] = "///< ";
else if (Prefix[i] == "//!<")
Prefix[i] = "//!< ";
+ else if (Prefix[i] == "#" &&
+ Style.Language == FormatStyle::LK_TextProto)
+ Prefix[i] = "# ";
}
Tokens[i] = LineTok;
Content[i] = Lines[i].substr(IndentPrefix.size());
OriginalContentColumn[i] =
- StartColumn +
- encoding::columnWidthWithTabs(OriginalPrefix[i],
- StartColumn,
- Style.TabWidth,
- Encoding);
+ StartColumn + encoding::columnWidthWithTabs(OriginalPrefix[i],
+ StartColumn,
+ Style.TabWidth, Encoding);
ContentColumn[i] =
- StartColumn +
- encoding::columnWidthWithTabs(Prefix[i],
- StartColumn,
- Style.TabWidth,
- Encoding);
+ StartColumn + encoding::columnWidthWithTabs(Prefix[i], StartColumn,
+ Style.TabWidth, Encoding);
// Calculate the end of the non-whitespace text in this line.
size_t EndOfLine = Content[i].find_last_not_of(Blanks);
@@ -760,20 +735,25 @@ BreakableLineCommentSection::BreakableLineCommentSection(
}
}
-unsigned BreakableLineCommentSection::getLineLengthAfterSplit(
- unsigned LineIndex, unsigned TailOffset,
- StringRef::size_type Length) const {
- unsigned ContentStartColumn =
- (TailOffset == 0 ? ContentColumn[LineIndex]
- : OriginalContentColumn[LineIndex]);
- return ContentStartColumn + encoding::columnWidthWithTabs(
- Content[LineIndex].substr(TailOffset, Length),
- ContentStartColumn, Style.TabWidth, Encoding);
+unsigned
+BreakableLineCommentSection::getRangeLength(unsigned LineIndex, unsigned Offset,
+ StringRef::size_type Length,
+ unsigned StartColumn) const {
+ return encoding::columnWidthWithTabs(
+ Content[LineIndex].substr(Offset, Length), StartColumn, Style.TabWidth,
+ Encoding);
+}
+
+unsigned BreakableLineCommentSection::getContentStartColumn(unsigned LineIndex,
+ bool Break) const {
+ if (Break)
+ return OriginalContentColumn[LineIndex];
+ return ContentColumn[LineIndex];
}
-void BreakableLineCommentSection::insertBreak(unsigned LineIndex,
- unsigned TailOffset, Split Split,
- WhitespaceManager &Whitespaces) {
+void BreakableLineCommentSection::insertBreak(
+ unsigned LineIndex, unsigned TailOffset, Split Split,
+ WhitespaceManager &Whitespaces) const {
StringRef Text = Content[LineIndex].substr(TailOffset);
// Compute the offset of the split relative to the beginning of the token
// text.
@@ -792,37 +772,42 @@ void BreakableLineCommentSection::insertBreak(unsigned LineIndex,
/*Spaces=*/IndentAtLineBreak - Prefix[LineIndex].size());
}
-BreakableComment::Split BreakableLineCommentSection::getSplitBefore(
- unsigned LineIndex, unsigned PreviousEndColumn, unsigned ColumnLimit,
- llvm::Regex &CommentPragmasRegex) const {
+BreakableComment::Split BreakableLineCommentSection::getReflowSplit(
+ unsigned LineIndex, llvm::Regex &CommentPragmasRegex) const {
if (!mayReflow(LineIndex, CommentPragmasRegex))
return Split(StringRef::npos, 0);
- return getReflowSplit(Content[LineIndex], ReflowPrefix, PreviousEndColumn,
- ColumnLimit);
+
+ size_t Trimmed = Content[LineIndex].find_first_not_of(Blanks);
+
+ // In a line comment section each line is a separate token; thus, after a
+ // split we replace all whitespace before the current line comment token
+ // (which does not need to be included in the split), plus the start of the
+ // line up to where the content starts.
+ return Split(0, Trimmed != StringRef::npos ? Trimmed : 0);
}
-unsigned BreakableLineCommentSection::getLineLengthAfterSplitBefore(
- unsigned LineIndex, unsigned TailOffset,
- unsigned PreviousEndColumn,
- unsigned ColumnLimit,
- Split SplitBefore) const {
- if (SplitBefore.first == StringRef::npos ||
- SplitBefore.first + SplitBefore.second < Content[LineIndex].size()) {
- // A piece of line, not the whole line, gets reflown.
- return getLineLengthAfterSplit(LineIndex, TailOffset, StringRef::npos);
- } else {
- // The whole line gets reflown.
- unsigned StartColumn = PreviousEndColumn + ReflowPrefix.size();
- return StartColumn + encoding::columnWidthWithTabs(Content[LineIndex],
- StartColumn,
- Style.TabWidth,
- Encoding);
- }
+void BreakableLineCommentSection::reflow(unsigned LineIndex,
+ WhitespaceManager &Whitespaces) const {
+ // Reflow happens between tokens. Replace the whitespace between the
+ // tokens by the empty string.
+ Whitespaces.replaceWhitespace(
+ *Tokens[LineIndex], /*Newlines=*/0, /*Spaces=*/0,
+ /*StartOfTokenColumn=*/StartColumn, /*InPPDirective=*/false);
+ // Replace the indent and prefix of the token with the reflow prefix.
+ unsigned WhitespaceLength =
+ Content[LineIndex].data() - tokenAt(LineIndex).TokenText.data();
+ Whitespaces.replaceWhitespaceInToken(*Tokens[LineIndex],
+ /*Offset=*/0,
+ /*ReplaceChars=*/WhitespaceLength,
+ /*PreviousPostfix=*/"",
+ /*CurrentPrefix=*/ReflowPrefix,
+ /*InPPDirective=*/false,
+ /*Newlines=*/0,
+ /*Spaces=*/0);
}
-void BreakableLineCommentSection::replaceWhitespaceBefore(
- unsigned LineIndex, unsigned PreviousEndColumn, unsigned ColumnLimit,
- Split SplitBefore, WhitespaceManager &Whitespaces) {
+void BreakableLineCommentSection::adaptStartOfLine(
+ unsigned LineIndex, WhitespaceManager &Whitespaces) const {
// If this is the first line of a token, we need to inform Whitespace Manager
// about it: either adapt the whitespace range preceding it, or mark it as an
// untouchable token.
@@ -830,44 +815,25 @@ void BreakableLineCommentSection::replaceWhitespaceBefore(
// // line 1 \
// // line 2
if (LineIndex > 0 && Tokens[LineIndex] != Tokens[LineIndex - 1]) {
- if (SplitBefore.first != StringRef::npos) {
- // Reflow happens between tokens. Replace the whitespace between the
- // tokens by the empty string.
- Whitespaces.replaceWhitespace(
- *Tokens[LineIndex], /*Newlines=*/0, /*Spaces=*/0,
- /*StartOfTokenColumn=*/StartColumn, /*InPPDirective=*/false);
- // Replace the indent and prefix of the token with the reflow prefix.
- unsigned WhitespaceLength =
- Content[LineIndex].data() - tokenAt(LineIndex).TokenText.data();
- Whitespaces.replaceWhitespaceInToken(*Tokens[LineIndex],
- /*Offset=*/0,
- /*ReplaceChars=*/WhitespaceLength,
- /*PreviousPostfix=*/"",
- /*CurrentPrefix=*/ReflowPrefix,
- /*InPPDirective=*/false,
- /*Newlines=*/0,
- /*Spaces=*/0);
- } else {
- // This is the first line for the current token, but no reflow with the
- // previous token is necessary. However, we still may need to adjust the
- // start column. Note that ContentColumn[LineIndex] is the expected
- // content column after a possible update to the prefix, hence the prefix
- // length change is included.
- unsigned LineColumn =
- ContentColumn[LineIndex] -
- (Content[LineIndex].data() - Lines[LineIndex].data()) +
- (OriginalPrefix[LineIndex].size() - Prefix[LineIndex].size());
+ // This is the first line for the current token, but no reflow with the
+ // previous token is necessary. However, we still may need to adjust the
+ // start column. Note that ContentColumn[LineIndex] is the expected
+ // content column after a possible update to the prefix, hence the prefix
+ // length change is included.
+ unsigned LineColumn =
+ ContentColumn[LineIndex] -
+ (Content[LineIndex].data() - Lines[LineIndex].data()) +
+ (OriginalPrefix[LineIndex].size() - Prefix[LineIndex].size());
- // We always want to create a replacement instead of adding an untouchable
- // token, even if LineColumn is the same as the original column of the
- // token. This is because WhitespaceManager doesn't align trailing
- // comments if they are untouchable.
- Whitespaces.replaceWhitespace(*Tokens[LineIndex],
- /*Newlines=*/1,
- /*Spaces=*/LineColumn,
- /*StartOfTokenColumn=*/LineColumn,
- /*InPPDirective=*/false);
- }
+ // We always want to create a replacement instead of adding an untouchable
+ // token, even if LineColumn is the same as the original column of the
+ // token. This is because WhitespaceManager doesn't align trailing
+ // comments if they are untouchable.
+ Whitespaces.replaceWhitespace(*Tokens[LineIndex],
+ /*Newlines=*/1,
+ /*Spaces=*/LineColumn,
+ /*StartOfTokenColumn=*/LineColumn,
+ /*InPPDirective=*/false);
}
if (OriginalPrefix[LineIndex] != Prefix[LineIndex]) {
// Adjust the prefix if necessary.
@@ -880,16 +846,9 @@ void BreakableLineCommentSection::replaceWhitespaceBefore(
tokenAt(LineIndex), OriginalPrefix[LineIndex].size(), 0, "", "",
/*InPPDirective=*/false, /*Newlines=*/0, /*Spaces=*/1);
}
- // Add a break after a reflow split has been introduced, if necessary.
- // Note that this break doesn't need to be penalized, since it doesn't change
- // the number of lines.
- if (SplitBefore.first != StringRef::npos &&
- SplitBefore.first + SplitBefore.second < Content[LineIndex].size()) {
- insertBreak(LineIndex, 0, SplitBefore, Whitespaces);
- }
}
-void BreakableLineCommentSection::updateNextToken(LineState& State) const {
+void BreakableLineCommentSection::updateNextToken(LineState &State) const {
if (LastLineTok) {
State.NextToken = LastLineTok->Next;
}
@@ -903,20 +862,17 @@ bool BreakableLineCommentSection::mayReflow(
if (Lines[LineIndex].startswith("//")) {
IndentContent = Lines[LineIndex].substr(2);
}
+ // FIXME: Decide whether we want to reflow non-regular indents:
+ // Currently, we only reflow when the OriginalPrefix[LineIndex] matches the
+ // OriginalPrefix[LineIndex-1]. That means we don't reflow
+ // // text that protrudes
+ // // into text with different indent
+ // We do reflow in that case in block comments.
return LineIndex > 0 && !CommentPragmasRegex.match(IndentContent) &&
mayReflowContent(Content[LineIndex]) && !Tok.Finalized &&
!switchesFormatting(tokenAt(LineIndex)) &&
OriginalPrefix[LineIndex] == OriginalPrefix[LineIndex - 1];
}
-unsigned
-BreakableLineCommentSection::getContentStartColumn(unsigned LineIndex,
- unsigned TailOffset) const {
- if (TailOffset != 0) {
- return OriginalContentColumn[LineIndex];
- }
- return ContentColumn[LineIndex];
-}
-
} // namespace format
} // namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Format/BreakableToken.h b/contrib/llvm/tools/clang/lib/Format/BreakableToken.h
index e642a538e21c3..8ef26ef464da9 100644
--- a/contrib/llvm/tools/clang/lib/Format/BreakableToken.h
+++ b/contrib/llvm/tools/clang/lib/Format/BreakableToken.h
@@ -33,19 +33,32 @@ bool switchesFormatting(const FormatToken &Token);
struct FormatStyle;
-/// \brief Base class for strategies on how to break tokens.
+/// \brief Base class for tokens / ranges of tokens that can allow breaking
+/// within the tokens - for example, to avoid whitespace beyond the column
+/// limit, or to reflow text.
///
-/// This is organised around the concept of a \c Split, which is a whitespace
-/// range that signifies a position of the content of a token where a
-/// reformatting might be done. Operating with splits is divided into 3
-/// operations:
+/// Generally, a breakable token consists of logical lines, addressed by a line
+/// index. For example, in a sequence of line comments, each line comment is its
+/// own logical line; similarly, for a block comment, each line in the block
+/// comment is on its own logical line.
+///
+/// There are two methods to compute the layout of the token:
+/// - getRangeLength measures the number of columns needed for a range of text
+/// within a logical line, and
+/// - getContentStartColumn returns the start column at which we want the
+/// content of a logical line to start (potentially after introducing a line
+/// break).
+///
+/// The mechanism to adapt the layout of the breakable token is organised
+/// around the concept of a \c Split, which is a whitespace range that signifies
+/// a position of the content of a token where a reformatting might be done.
+///
+/// Operating with splits is divided into two operations:
/// - getSplit, for finding a split starting at a position,
-/// - getLineLengthAfterSplit, for calculating the size in columns of the rest
-/// of the content after a split has been used for breaking, and
/// - insertBreak, for executing the split using a whitespace manager.
///
/// There is a pair of operations that are used to compress a long whitespace
-/// range with a single space if that will bring the line lenght under the
+/// range with a single space if that will bring the line length under the
/// column limit:
/// - getLineLengthAfterCompression, for calculating the size in columns of the
/// line after a whitespace range has been compressed, and
@@ -56,16 +69,23 @@ struct FormatStyle;
/// For tokens where the whitespace before each line needs to be also
/// reformatted, for example for tokens supporting reflow, there are analogous
/// operations that might be executed before the main line breaking occurs:
-/// - getSplitBefore, for finding a split such that the content preceding it
+/// - getReflowSplit, for finding a split such that the content preceding it
/// needs to be specially reflown,
-/// - getLineLengthAfterSplitBefore, for calculating the line length in columns
-/// of the remainder of the content after the beginning of the content has
-/// been reformatted, and
-/// - replaceWhitespaceBefore, for executing the reflow using a whitespace
+/// - reflow, for executing the split using a whitespace manager,
+/// - introducesBreakBefore, for checking if reformatting the beginning
+/// of the content introduces a line break before it,
+/// - adaptStartOfLine, for executing the reflow using a whitespace
/// manager.
///
-/// FIXME: The interface seems set in stone, so we might want to just pull the
-/// strategy into the class, instead of controlling it from the outside.
+/// For tokens that require the whitespace after the last line to be
+/// reformatted, for example in multiline jsdoc comments that require the
+/// trailing '*/' to be on a line of itself, there are analogous operations
+/// that might be executed after the last line has been reformatted:
+/// - getSplitAfterLastLine, for finding a split after the last line that needs
+/// to be reflown,
+/// - replaceWhitespaceAfterLastLine, for executing the reflow using a
+/// whitespace manager.
+///
class BreakableToken {
public:
/// \brief Contains starting character index and length of split.
@@ -76,73 +96,122 @@ public:
/// \brief Returns the number of lines in this token in the original code.
virtual unsigned getLineCount() const = 0;
- /// \brief Returns the number of columns required to format the piece of line
- /// at \p LineIndex, from byte offset \p TailOffset with length \p Length.
+ /// \brief Returns the number of columns required to format the text in the
+ /// byte range [\p Offset, \p Offset \c + \p Length).
+ ///
+ /// \p Offset is the byte offset from the start of the content of the line
+ /// at \p LineIndex.
+ ///
+ /// \p StartColumn is the column at which the text starts in the formatted
+ /// file, needed to compute tab stops correctly.
+ virtual unsigned getRangeLength(unsigned LineIndex, unsigned Offset,
+ StringRef::size_type Length,
+ unsigned StartColumn) const = 0;
+
+ /// \brief Returns the number of columns required to format the text following
+ /// the byte \p Offset in the line \p LineIndex, including potentially
+ /// unbreakable sequences of tokens following after the end of the token.
+ ///
+ /// \p Offset is the byte offset from the start of the content of the line
+ /// at \p LineIndex.
+ ///
+ /// \p StartColumn is the column at which the text starts in the formatted
+ /// file, needed to compute tab stops correctly.
+ ///
+ /// For breakable tokens that never use extra space at the end of a line, this
+ /// is equivalent to getRangeLength with a Length of StringRef::npos.
+ virtual unsigned getRemainingLength(unsigned LineIndex, unsigned Offset,
+ unsigned StartColumn) const {
+ return getRangeLength(LineIndex, Offset, StringRef::npos, StartColumn);
+ }
+
+ /// \brief Returns the column at which content in line \p LineIndex starts,
+ /// assuming no reflow.
///
- /// Note that previous breaks are not taken into account. \p TailOffset is
- /// always specified from the start of the (original) line.
- /// \p Length can be set to StringRef::npos, which means "to the end of line".
- virtual unsigned
- getLineLengthAfterSplit(unsigned LineIndex, unsigned TailOffset,
- StringRef::size_type Length) const = 0;
+ /// If \p Break is true, returns the column at which the line should start
+ /// after the line break.
+ /// If \p Break is false, returns the column at which the line itself will
+ /// start.
+ virtual unsigned getContentStartColumn(unsigned LineIndex,
+ bool Break) const = 0;
/// \brief Returns a range (offset, length) at which to break the line at
/// \p LineIndex, if previously broken at \p TailOffset. If possible, do not
- /// violate \p ColumnLimit.
+ /// violate \p ColumnLimit, assuming the text starting at \p TailOffset in
+ /// the token is formatted starting at ContentStartColumn in the reformatted
+ /// file.
virtual Split getSplit(unsigned LineIndex, unsigned TailOffset,
- unsigned ColumnLimit,
+ unsigned ColumnLimit, unsigned ContentStartColumn,
llvm::Regex &CommentPragmasRegex) const = 0;
/// \brief Emits the previously retrieved \p Split via \p Whitespaces.
virtual void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split,
- WhitespaceManager &Whitespaces) = 0;
+ WhitespaceManager &Whitespaces) const = 0;
- /// \brief Returns the number of columns required to format the piece of line
- /// at \p LineIndex, from byte offset \p TailOffset after the whitespace range
- /// \p Split has been compressed into a single space.
- unsigned getLineLengthAfterCompression(unsigned RemainingTokenColumns,
- Split Split) const;
+ /// \brief Returns the number of columns needed to format
+ /// \p RemainingTokenColumns, assuming that Split is within the range measured
+ /// by \p RemainingTokenColumns, and that the whitespace in Split is reduced
+ /// to a single space.
+ unsigned getLengthAfterCompression(unsigned RemainingTokenColumns,
+ Split Split) const;
/// \brief Replaces the whitespace range described by \p Split with a single
/// space.
virtual void compressWhitespace(unsigned LineIndex, unsigned TailOffset,
Split Split,
- WhitespaceManager &Whitespaces) = 0;
+ WhitespaceManager &Whitespaces) const = 0;
- /// \brief Returns a whitespace range (offset, length) of the content at
- /// \p LineIndex such that the content preceding this range needs to be
- /// reformatted before any breaks are made to this line.
+ /// \brief Returns whether the token supports reflowing text.
+ virtual bool supportsReflow() const { return false; }
+
+ /// \brief Returns a whitespace range (offset, length) of the content at \p
+ /// LineIndex such that the content of that line is reflown to the end of the
+ /// previous one.
///
- /// \p PreviousEndColumn is the end column of the previous line after
- /// formatting.
+ /// Returning (StringRef::npos, 0) indicates reflowing is not possible.
///
- /// A result having offset == StringRef::npos means that no piece of the line
- /// needs to be reformatted before any breaks are made.
- virtual Split getSplitBefore(unsigned LineIndex, unsigned PreviousEndColumn,
- unsigned ColumnLimit,
+ /// The range will include any whitespace preceding the specified line's
+ /// content.
+ ///
+ /// If the split is not contained within one token, for example when reflowing
+ /// line comments, returns (0, <length>).
+ virtual Split getReflowSplit(unsigned LineIndex,
llvm::Regex &CommentPragmasRegex) const {
return Split(StringRef::npos, 0);
}
- /// \brief Returns the number of columns required to format the piece of line
- /// at \p LineIndex after the content preceding the whitespace range specified
- /// \p SplitBefore has been reformatted, but before any breaks are made to
- /// this line.
- virtual unsigned getLineLengthAfterSplitBefore(unsigned LineIndex,
- unsigned TailOffset,
- unsigned PreviousEndColumn,
- unsigned ColumnLimit,
- Split SplitBefore) const {
- return getLineLengthAfterSplit(LineIndex, TailOffset, StringRef::npos);
+ /// \brief Reflows the current line into the end of the previous one.
+ virtual void reflow(unsigned LineIndex,
+ WhitespaceManager &Whitespaces) const {}
+
+ /// \brief Returns whether there will be a line break at the start of the
+ /// token.
+ virtual bool introducesBreakBeforeToken() const {
+ return false;
}
/// \brief Replaces the whitespace between \p LineIndex-1 and \p LineIndex.
- /// Performs a reformatting of the content at \p LineIndex preceding the
- /// whitespace range \p SplitBefore.
- virtual void replaceWhitespaceBefore(unsigned LineIndex,
- unsigned PreviousEndColumn,
- unsigned ColumnLimit, Split SplitBefore,
- WhitespaceManager &Whitespaces) {}
+ virtual void adaptStartOfLine(unsigned LineIndex,
+ WhitespaceManager &Whitespaces) const {}
+
+ /// \brief Returns a whitespace range (offset, length) of the content at
+ /// the last line that needs to be reformatted after the last line has been
+ /// reformatted.
+ ///
+ /// A result having offset == StringRef::npos means that no reformat is
+ /// necessary.
+ virtual Split getSplitAfterLastLine(unsigned TailOffset) const {
+ return Split(StringRef::npos, 0);
+ }
+
+ /// \brief Replaces the whitespace from \p SplitAfterLastLine on the last line
+ /// after the last line has been formatted by performing a reformatting.
+ void replaceWhitespaceAfterLastLine(unsigned TailOffset,
+ Split SplitAfterLastLine,
+ WhitespaceManager &Whitespaces) const {
+ insertBreak(getLineCount() - 1, TailOffset, SplitAfterLastLine,
+ Whitespaces);
+ }
/// \brief Updates the next token of \p State to the next token after this
/// one. This can be used when this token manages a set of underlying tokens
@@ -161,32 +230,7 @@ protected:
const FormatStyle &Style;
};
-/// \brief Base class for single line tokens that can be broken.
-///
-/// \c getSplit() needs to be implemented by child classes.
-class BreakableSingleLineToken : public BreakableToken {
-public:
- unsigned getLineCount() const override;
- unsigned getLineLengthAfterSplit(unsigned LineIndex, unsigned TailOffset,
- StringRef::size_type Length) const override;
-
-protected:
- BreakableSingleLineToken(const FormatToken &Tok, unsigned StartColumn,
- StringRef Prefix, StringRef Postfix,
- bool InPPDirective, encoding::Encoding Encoding,
- const FormatStyle &Style);
-
- // The column in which the token starts.
- unsigned StartColumn;
- // The prefix a line needs after a break in the token.
- StringRef Prefix;
- // The postfix a line needs before introducing a break.
- StringRef Postfix;
- // The token text excluding the prefix and postfix.
- StringRef Line;
-};
-
-class BreakableStringLiteral : public BreakableSingleLineToken {
+class BreakableStringLiteral : public BreakableToken {
public:
/// \brief Creates a breakable token for a single line string literal.
///
@@ -198,11 +242,32 @@ public:
const FormatStyle &Style);
Split getSplit(unsigned LineIndex, unsigned TailOffset, unsigned ColumnLimit,
+ unsigned ReflowColumn,
llvm::Regex &CommentPragmasRegex) const override;
void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split,
- WhitespaceManager &Whitespaces) override;
+ WhitespaceManager &Whitespaces) const override;
void compressWhitespace(unsigned LineIndex, unsigned TailOffset, Split Split,
- WhitespaceManager &Whitespaces) override {}
+ WhitespaceManager &Whitespaces) const override {}
+ unsigned getLineCount() const override;
+ unsigned getRangeLength(unsigned LineIndex, unsigned Offset,
+ StringRef::size_type Length,
+ unsigned StartColumn) const override;
+ unsigned getRemainingLength(unsigned LineIndex, unsigned Offset,
+ unsigned StartColumn) const override;
+ unsigned getContentStartColumn(unsigned LineIndex, bool Break) const override;
+
+protected:
+ // The column in which the token starts.
+ unsigned StartColumn;
+ // The prefix a line needs after a break in the token.
+ StringRef Prefix;
+ // The postfix a line needs before introducing a break.
+ StringRef Postfix;
+ // The token text excluding the prefix and postfix.
+ StringRef Line;
+ // Length of the sequence of tokens after this string literal that cannot
+ // contain line breaks.
+ unsigned UnbreakableTailLength;
};
class BreakableComment : public BreakableToken {
@@ -216,21 +281,15 @@ protected:
const FormatStyle &Style);
public:
+ bool supportsReflow() const override { return true; }
unsigned getLineCount() const override;
Split getSplit(unsigned LineIndex, unsigned TailOffset, unsigned ColumnLimit,
+ unsigned ReflowColumn,
llvm::Regex &CommentPragmasRegex) const override;
void compressWhitespace(unsigned LineIndex, unsigned TailOffset, Split Split,
- WhitespaceManager &Whitespaces) override;
+ WhitespaceManager &Whitespaces) const override;
protected:
- virtual unsigned getContentStartColumn(unsigned LineIndex,
- unsigned TailOffset) const = 0;
-
- // Returns a split that divides Text into a left and right parts, such that
- // the left part is suitable for reflowing after PreviousEndColumn.
- Split getReflowSplit(StringRef Text, StringRef ReflowPrefix,
- unsigned PreviousEndColumn, unsigned ColumnLimit) const;
-
// Returns the token containing the line at LineIndex.
const FormatToken &tokenAt(unsigned LineIndex) const;
@@ -289,21 +348,23 @@ public:
bool InPPDirective, encoding::Encoding Encoding,
const FormatStyle &Style);
- unsigned getLineLengthAfterSplit(unsigned LineIndex, unsigned TailOffset,
- StringRef::size_type Length) const override;
+ unsigned getRangeLength(unsigned LineIndex, unsigned Offset,
+ StringRef::size_type Length,
+ unsigned StartColumn) const override;
+ unsigned getRemainingLength(unsigned LineIndex, unsigned Offset,
+ unsigned StartColumn) const override;
+ unsigned getContentStartColumn(unsigned LineIndex, bool Break) const override;
void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split,
- WhitespaceManager &Whitespaces) override;
- Split getSplitBefore(unsigned LineIndex, unsigned PreviousEndColumn,
- unsigned ColumnLimit,
+ WhitespaceManager &Whitespaces) const override;
+ Split getReflowSplit(unsigned LineIndex,
llvm::Regex &CommentPragmasRegex) const override;
- unsigned getLineLengthAfterSplitBefore(unsigned LineIndex,
- unsigned TailOffset,
- unsigned PreviousEndColumn,
- unsigned ColumnLimit,
- Split SplitBefore) const override;
- void replaceWhitespaceBefore(unsigned LineIndex, unsigned PreviousEndColumn,
- unsigned ColumnLimit, Split SplitBefore,
- WhitespaceManager &Whitespaces) override;
+ void reflow(unsigned LineIndex,
+ WhitespaceManager &Whitespaces) const override;
+ bool introducesBreakBeforeToken() const override;
+ void adaptStartOfLine(unsigned LineIndex,
+ WhitespaceManager &Whitespaces) const override;
+ Split getSplitAfterLastLine(unsigned TailOffset) const override;
+
bool mayReflow(unsigned LineIndex,
llvm::Regex &CommentPragmasRegex) const override;
@@ -318,14 +379,6 @@ private:
// considered part of the text).
void adjustWhitespace(unsigned LineIndex, int IndentDelta);
- // Computes the end column if the full Content from LineIndex gets reflown
- // after PreviousEndColumn.
- unsigned getReflownColumn(StringRef Content, unsigned LineIndex,
- unsigned PreviousEndColumn) const;
-
- unsigned getContentStartColumn(unsigned LineIndex,
- unsigned TailOffset) const override;
-
// The column at which the text of a broken line should start.
// Note that an optional decoration would go before that column.
// IndentAtLineBreak is a uniform position for all lines in a block comment,
@@ -348,6 +401,14 @@ private:
// If this block comment has decorations, this is the column of the start of
// the decorations.
unsigned DecorationColumn;
+
+ // If true, make sure that the opening '/**' and the closing '*/' ends on a
+ // line of itself. Styles like jsdoc require this for multiline comments.
+ bool DelimitersOnNewline;
+
+ // Length of the sequence of tokens after this string literal that cannot
+ // contain line breaks.
+ unsigned UnbreakableTailLength;
};
class BreakableLineCommentSection : public BreakableComment {
@@ -357,29 +418,23 @@ public:
bool InPPDirective, encoding::Encoding Encoding,
const FormatStyle &Style);
- unsigned getLineLengthAfterSplit(unsigned LineIndex, unsigned TailOffset,
- StringRef::size_type Length) const override;
+ unsigned getRangeLength(unsigned LineIndex, unsigned Offset,
+ StringRef::size_type Length,
+ unsigned StartColumn) const override;
+ unsigned getContentStartColumn(unsigned LineIndex, bool Break) const override;
void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split,
- WhitespaceManager &Whitespaces) override;
- Split getSplitBefore(unsigned LineIndex, unsigned PreviousEndColumn,
- unsigned ColumnLimit,
+ WhitespaceManager &Whitespaces) const override;
+ Split getReflowSplit(unsigned LineIndex,
llvm::Regex &CommentPragmasRegex) const override;
- unsigned getLineLengthAfterSplitBefore(unsigned LineIndex,
- unsigned TailOffset,
- unsigned PreviousEndColumn,
- unsigned ColumnLimit,
- Split SplitBefore) const override;
- void replaceWhitespaceBefore(unsigned LineIndex, unsigned PreviousEndColumn,
- unsigned ColumnLimit, Split SplitBefore,
- WhitespaceManager &Whitespaces) override;
+ void reflow(unsigned LineIndex,
+ WhitespaceManager &Whitespaces) const override;
+ void adaptStartOfLine(unsigned LineIndex,
+ WhitespaceManager &Whitespaces) const override;
void updateNextToken(LineState &State) const override;
bool mayReflow(unsigned LineIndex,
llvm::Regex &CommentPragmasRegex) const override;
private:
- unsigned getContentStartColumn(unsigned LineIndex,
- unsigned TailOffset) const override;
-
// OriginalPrefix[i] contains the original prefix of line i, including
// trailing whitespace before the start of the content. The indentation
// preceding the prefix is not included.
diff --git a/contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.cpp b/contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.cpp
index 3bf1cd8f7c131..a3d38b244c5c1 100644
--- a/contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.cpp
@@ -12,8 +12,9 @@
///
//===----------------------------------------------------------------------===//
-#include "BreakableToken.h"
#include "ContinuationIndenter.h"
+#include "BreakableToken.h"
+#include "FormatInternal.h"
#include "WhitespaceManager.h"
#include "clang/Basic/OperatorPrecedence.h"
#include "clang/Basic/SourceManager.h"
@@ -76,6 +77,53 @@ static bool opensProtoMessageField(const FormatToken &LessTok,
(LessTok.Previous && LessTok.Previous->is(tok::equal))));
}
+// Returns the delimiter of a raw string literal, or None if TokenText is not
+// the text of a raw string literal. The delimiter could be the empty string.
+// For example, the delimiter of R"deli(cont)deli" is deli.
+static llvm::Optional<StringRef> getRawStringDelimiter(StringRef TokenText) {
+ if (TokenText.size() < 5 // The smallest raw string possible is 'R"()"'.
+ || !TokenText.startswith("R\"") || !TokenText.endswith("\""))
+ return None;
+
+ // A raw string starts with 'R"<delimiter>(' and delimiter is ascii and has
+ // size at most 16 by the standard, so the first '(' must be among the first
+ // 19 bytes.
+ size_t LParenPos = TokenText.substr(0, 19).find_first_of('(');
+ if (LParenPos == StringRef::npos)
+ return None;
+ StringRef Delimiter = TokenText.substr(2, LParenPos - 2);
+
+ // Check that the string ends in ')Delimiter"'.
+ size_t RParenPos = TokenText.size() - Delimiter.size() - 2;
+ if (TokenText[RParenPos] != ')')
+ return None;
+ if (!TokenText.substr(RParenPos + 1).startswith(Delimiter))
+ return None;
+ return Delimiter;
+}
+
+RawStringFormatStyleManager::RawStringFormatStyleManager(
+ const FormatStyle &CodeStyle) {
+ for (const auto &RawStringFormat : CodeStyle.RawStringFormats) {
+ FormatStyle Style;
+ if (!getPredefinedStyle(RawStringFormat.BasedOnStyle,
+ RawStringFormat.Language, &Style)) {
+ Style = getLLVMStyle();
+ Style.Language = RawStringFormat.Language;
+ }
+ Style.ColumnLimit = CodeStyle.ColumnLimit;
+ DelimiterStyle.insert({RawStringFormat.Delimiter, Style});
+ }
+}
+
+llvm::Optional<FormatStyle>
+RawStringFormatStyleManager::get(StringRef Delimiter) const {
+ auto It = DelimiterStyle.find(Delimiter);
+ if (It == DelimiterStyle.end())
+ return None;
+ return It->second;
+}
+
ContinuationIndenter::ContinuationIndenter(const FormatStyle &Style,
const AdditionalKeywords &Keywords,
const SourceManager &SourceMgr,
@@ -85,20 +133,32 @@ ContinuationIndenter::ContinuationIndenter(const FormatStyle &Style,
: Style(Style), Keywords(Keywords), SourceMgr(SourceMgr),
Whitespaces(Whitespaces), Encoding(Encoding),
BinPackInconclusiveFunctions(BinPackInconclusiveFunctions),
- CommentPragmasRegex(Style.CommentPragmas) {}
+ CommentPragmasRegex(Style.CommentPragmas), RawStringFormats(Style) {}
LineState ContinuationIndenter::getInitialState(unsigned FirstIndent,
+ unsigned FirstStartColumn,
const AnnotatedLine *Line,
bool DryRun) {
LineState State;
State.FirstIndent = FirstIndent;
- State.Column = FirstIndent;
+ if (FirstStartColumn && Line->First->NewlinesBefore == 0)
+ State.Column = FirstStartColumn;
+ else
+ State.Column = FirstIndent;
+ // With preprocessor directive indentation, the line starts on column 0
+ // since it's indented after the hash, but FirstIndent is set to the
+ // preprocessor indent.
+ if (Style.IndentPPDirectives == FormatStyle::PPDIS_AfterHash &&
+ (Line->Type == LT_PreprocessorDirective ||
+ Line->Type == LT_ImportStatement))
+ State.Column = 0;
State.Line = Line;
State.NextToken = Line->First;
State.Stack.push_back(ParenState(FirstIndent, FirstIndent,
/*AvoidBinPacking=*/false,
/*NoLineBreak=*/false));
State.LineContainsContinuedForLoopSection = false;
+ State.NoContinuation = false;
State.StartOfStringLiteral = 0;
State.StartOfLineLevel = 0;
State.LowestLevelOnLine = 0;
@@ -120,9 +180,8 @@ bool ContinuationIndenter::canBreak(const LineState &State) {
const FormatToken &Current = *State.NextToken;
const FormatToken &Previous = *Current.Previous;
assert(&Previous == Current.Previous);
- if (!Current.CanBreakBefore &&
- !(State.Stack.back().BreakBeforeClosingBrace &&
- Current.closesBlockOrBlockTypeList(Style)))
+ if (!Current.CanBreakBefore && !(State.Stack.back().BreakBeforeClosingBrace &&
+ Current.closesBlockOrBlockTypeList(Style)))
return false;
// The opening "{" of a braced list has to be on the same line as the first
// element if it is nested in another braced init list or function call.
@@ -264,7 +323,8 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
// We need special cases for ">>" which we have split into two ">" while
// lexing in order to make template parsing easier.
bool IsComparison = (Previous.getPrecedence() == prec::Relational ||
- Previous.getPrecedence() == prec::Equality) &&
+ Previous.getPrecedence() == prec::Equality ||
+ Previous.getPrecedence() == prec::Spaceship) &&
Previous.Previous &&
Previous.Previous->isNot(TT_BinaryOperator); // For >>.
bool LHSIsBinaryExpr =
@@ -316,6 +376,12 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
Previous.TokenText == "\'\\n\'"))))
return true;
+ if (Previous.is(TT_BlockComment) && Previous.IsMultiline)
+ return true;
+
+ if (State.NoContinuation)
+ return true;
+
return false;
}
@@ -325,6 +391,8 @@ unsigned ContinuationIndenter::addTokenToState(LineState &State, bool Newline,
const FormatToken &Current = *State.NextToken;
assert(!State.Stack.empty());
+ State.NoContinuation = false;
+
if ((Current.is(TT_ImplicitStringLiteral) &&
(Current.Previous->Tok.getIdentifierInfo() == nullptr ||
Current.Previous->Tok.getIdentifierInfo()->getPPKeywordID() ==
@@ -376,9 +444,25 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
unsigned Spaces = Current.SpacesRequiredBefore + ExtraSpaces;
+ // Indent preprocessor directives after the hash if required.
+ int PPColumnCorrection = 0;
+ if (Style.IndentPPDirectives == FormatStyle::PPDIS_AfterHash &&
+ Previous.is(tok::hash) && State.FirstIndent > 0 &&
+ (State.Line->Type == LT_PreprocessorDirective ||
+ State.Line->Type == LT_ImportStatement)) {
+ Spaces += State.FirstIndent;
+
+ // For preprocessor indent with tabs, State.Column will be 1 because of the
+ // hash. This causes second-level indents onward to have an extra space
+ // after the tabs. We avoid this misalignment by subtracting 1 from the
+ // column value passed to replaceWhitespace().
+ if (Style.UseTab != FormatStyle::UT_Never)
+ PPColumnCorrection = -1;
+ }
+
if (!DryRun)
Whitespaces.replaceWhitespace(Current, /*Newlines=*/0, Spaces,
- State.Column + Spaces);
+ State.Column + Spaces + PPColumnCorrection);
// If "BreakBeforeInheritanceComma" mode, don't break within the inheritance
// declaration unless there is multiple inheritance.
@@ -405,9 +489,8 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
if (Style.AlignAfterOpenBracket == FormatStyle::BAS_AlwaysBreak &&
Previous.isOneOf(tok::l_paren, TT_TemplateOpener, tok::l_square) &&
State.Column > getNewLineColumn(State) &&
- (!Previous.Previous ||
- !Previous.Previous->isOneOf(tok::kw_for, tok::kw_while,
- tok::kw_switch)) &&
+ (!Previous.Previous || !Previous.Previous->isOneOf(
+ tok::kw_for, tok::kw_while, tok::kw_switch)) &&
// Don't do this for simple (no expressions) one-argument function calls
// as that feels like needlessly wasting whitespace, e.g.:
//
@@ -454,7 +537,8 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
(P->is(TT_ConditionalExpr) && P->is(tok::colon))) &&
!P->isOneOf(TT_OverloadedOperator, TT_CtorInitializerComma) &&
P->getPrecedence() != prec::Assignment &&
- P->getPrecedence() != prec::Relational) {
+ P->getPrecedence() != prec::Relational &&
+ P->getPrecedence() != prec::Spaceship) {
bool BreakBeforeOperator =
P->MustBreakBefore || P->is(tok::lessless) ||
(P->is(TT_BinaryOperator) &&
@@ -619,8 +703,18 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
State.Stack.back().BreakBeforeParameter = false;
if (!DryRun) {
+ unsigned MaxEmptyLinesToKeep = Style.MaxEmptyLinesToKeep + 1;
+ if (Current.is(tok::r_brace) && Current.MatchingParen &&
+ // Only strip trailing empty lines for l_braces that have children, i.e.
+ // for function expressions (lambdas, arrows, etc).
+ !Current.MatchingParen->Children.empty()) {
+ // lambdas and arrow functions are expressions, thus their r_brace is not
+ // on its own line, and thus not covered by UnwrappedLineFormatter's logic
+ // about removing empty lines on closing blocks. Special case them here.
+ MaxEmptyLinesToKeep = 1;
+ }
unsigned Newlines = std::max(
- 1u, std::min(Current.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1));
+ 1u, std::min(Current.NewlinesBefore, MaxEmptyLinesToKeep));
bool ContinuePPDirective =
State.Line->InPPDirective && State.Line->Type != LT_ImportStatement;
Whitespaces.replaceWhitespace(Current, Newlines, State.Column, State.Column,
@@ -661,9 +755,7 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
// before the corresponding } or ].
if (PreviousNonComment &&
(PreviousNonComment->isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
- opensProtoMessageField(*PreviousNonComment, Style) ||
- (PreviousNonComment->is(TT_TemplateString) &&
- PreviousNonComment->opensScope())))
+ opensProtoMessageField(*PreviousNonComment, Style)))
State.Stack.back().BreakBeforeClosingBrace = true;
if (State.Stack.back().AvoidBinPacking) {
@@ -731,7 +823,10 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
if (NextNonComment->is(TT_TemplateString) && NextNonComment->closesScope())
return State.Stack[State.Stack.size() - 2].LastSpace;
if (Current.is(tok::identifier) && Current.Next &&
- Current.Next->is(TT_DictLiteral))
+ (Current.Next->is(TT_DictLiteral) ||
+ ((Style.Language == FormatStyle::LK_Proto ||
+ Style.Language == FormatStyle::LK_TextProto) &&
+ Current.Next->isOneOf(TT_TemplateOpener, tok::l_brace))))
return State.Stack.back().Indent;
if (NextNonComment->is(TT_ObjCStringLiteral) &&
State.StartOfStringLiteral != 0)
@@ -871,8 +966,10 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
// Next(...)
// ^ line up here.
State.Stack.back().Indent =
- State.Column + (Style.BreakConstructorInitializers ==
- FormatStyle::BCIS_BeforeComma ? 0 : 2);
+ State.Column +
+ (Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma
+ ? 0
+ : 2);
State.Stack.back().NestedBlockIndent = State.Stack.back().Indent;
if (Style.ConstructorInitializerAllOnOneLineOrOnePerLine)
State.Stack.back().AvoidBinPacking = true;
@@ -884,7 +981,7 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
State.FirstIndent + Style.ConstructorInitializerIndentWidth;
State.Stack.back().NestedBlockIndent = State.Stack.back().Indent;
if (Style.ConstructorInitializerAllOnOneLineOrOnePerLine)
- State.Stack.back().AvoidBinPacking = true;
+ State.Stack.back().AvoidBinPacking = true;
}
if (Current.is(TT_InheritanceColon))
State.Stack.back().Indent =
@@ -912,8 +1009,9 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
State.Stack[i].NoLineBreak = true;
State.Stack[State.Stack.size() - 2].NestedBlockInlined = false;
}
- if (Previous && (Previous->isOneOf(tok::l_paren, tok::comma, tok::colon) ||
- Previous->isOneOf(TT_BinaryOperator, TT_ConditionalExpr)) &&
+ if (Previous &&
+ (Previous->isOneOf(tok::l_paren, tok::comma, tok::colon) ||
+ Previous->isOneOf(TT_BinaryOperator, TT_ConditionalExpr)) &&
!Previous->isOneOf(TT_DictLiteral, TT_ObjCMethodExpr)) {
State.Stack.back().NestedBlockInlined =
!Newline &&
@@ -922,13 +1020,8 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
moveStatePastFakeLParens(State, Newline);
moveStatePastScopeCloser(State);
- if (Current.is(TT_TemplateString) && Current.opensScope())
- State.Stack.back().LastSpace =
- (Current.IsMultiline ? Current.LastLineColumnWidth
- : State.Column + Current.ColumnWidth) -
- strlen("${");
- bool CanBreakProtrudingToken = !State.Stack.back().NoLineBreak &&
- !State.Stack.back().NoLineBreakInOperand;
+ bool AllowBreak = !State.Stack.back().NoLineBreak &&
+ !State.Stack.back().NoLineBreakInOperand;
moveStatePastScopeOpener(State, Newline);
moveStatePastFakeRParens(State);
@@ -942,13 +1035,9 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
State.Column += Current.ColumnWidth;
State.NextToken = State.NextToken->Next;
- unsigned Penalty = 0;
- if (CanBreakProtrudingToken)
- Penalty = breakProtrudingToken(Current, State, DryRun);
- if (State.Column > getColumnLimit(State)) {
- unsigned ExcessCharacters = State.Column - getColumnLimit(State);
- Penalty += Style.PenaltyExcessCharacter * ExcessCharacters;
- }
+
+ unsigned Penalty =
+ handleEndOfLine(Current, State, DryRun, AllowBreak);
if (Current.Role)
Current.Role->formatFromToken(State, this, DryRun);
@@ -1072,14 +1161,13 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
bool EndsInComma = Current.MatchingParen &&
Current.MatchingParen->Previous &&
Current.MatchingParen->Previous->is(tok::comma);
- AvoidBinPacking =
- EndsInComma || Current.is(TT_DictLiteral) ||
- Style.Language == FormatStyle::LK_Proto ||
- Style.Language == FormatStyle::LK_TextProto ||
- !Style.BinPackArguments ||
- (NextNoComment &&
- NextNoComment->isOneOf(TT_DesignatedInitializerPeriod,
- TT_DesignatedInitializerLSquare));
+ AvoidBinPacking = EndsInComma || Current.is(TT_DictLiteral) ||
+ Style.Language == FormatStyle::LK_Proto ||
+ Style.Language == FormatStyle::LK_TextProto ||
+ !Style.BinPackArguments ||
+ (NextNoComment &&
+ NextNoComment->isOneOf(TT_DesignatedInitializerPeriod,
+ TT_DesignatedInitializerLSquare));
BreakBeforeParameter = EndsInComma;
if (Current.ParameterCount > 1)
NestedBlockIndent = std::max(NestedBlockIndent, State.Column + 1);
@@ -1098,18 +1186,6 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
LastSpace = std::max(LastSpace, State.Stack.back().Indent);
}
- // JavaScript template strings are special as we always want to indent
- // nested expressions relative to the ${}. Otherwise, this can create quite
- // a mess.
- if (Current.is(TT_TemplateString)) {
- unsigned Column = Current.IsMultiline
- ? Current.LastLineColumnWidth
- : State.Column + Current.ColumnWidth;
- NewIndent = Column;
- LastSpace = Column;
- NestedBlockIndent = Column;
- }
-
bool EndsInComma =
Current.MatchingParen &&
Current.MatchingParen->getPreviousNonComment() &&
@@ -1200,11 +1276,93 @@ void ContinuationIndenter::moveStateToNewBlock(LineState &State) {
State.Stack.back().BreakBeforeParameter = true;
}
-unsigned ContinuationIndenter::addMultilineToken(const FormatToken &Current,
- LineState &State) {
- if (!Current.IsMultiline)
+static unsigned getLastLineEndColumn(StringRef Text, unsigned StartColumn,
+ unsigned TabWidth,
+ encoding::Encoding Encoding) {
+ size_t LastNewlinePos = Text.find_last_of("\n");
+ if (LastNewlinePos == StringRef::npos) {
+ return StartColumn +
+ encoding::columnWidthWithTabs(Text, StartColumn, TabWidth, Encoding);
+ } else {
+ return encoding::columnWidthWithTabs(Text.substr(LastNewlinePos),
+ /*StartColumn=*/0, TabWidth, Encoding);
+ }
+}
+
+unsigned ContinuationIndenter::reformatRawStringLiteral(
+ const FormatToken &Current, LineState &State,
+ const FormatStyle &RawStringStyle, bool DryRun) {
+ unsigned StartColumn = State.Column - Current.ColumnWidth;
+ auto Delimiter = *getRawStringDelimiter(Current.TokenText);
+ // The text of a raw string is between the leading 'R"delimiter(' and the
+ // trailing 'delimiter)"'.
+ unsigned PrefixSize = 3 + Delimiter.size();
+ unsigned SuffixSize = 2 + Delimiter.size();
+
+ // The first start column is the column the raw text starts.
+ unsigned FirstStartColumn = StartColumn + PrefixSize;
+
+ // The next start column is the intended indentation a line break inside
+ // the raw string at level 0. It is determined by the following rules:
+ // - if the content starts on newline, it is one level more than the current
+ // indent, and
+ // - if the content does not start on a newline, it is the first start
+ // column.
+ // These rules have the advantage that the formatted content both does not
+ // violate the rectangle rule and visually flows within the surrounding
+ // source.
+ bool ContentStartsOnNewline = Current.TokenText[PrefixSize] == '\n';
+ unsigned NextStartColumn = ContentStartsOnNewline
+ ? State.Stack.back().Indent + Style.IndentWidth
+ : FirstStartColumn;
+
+ // The last start column is the column the raw string suffix starts if it is
+ // put on a newline.
+ // The last start column is the intended indentation of the raw string postfix
+ // if it is put on a newline. It is determined by the following rules:
+ // - if the raw string prefix starts on a newline, it is the column where
+ // that raw string prefix starts, and
+ // - if the raw string prefix does not start on a newline, it is the current
+ // indent.
+ unsigned LastStartColumn = Current.NewlinesBefore
+ ? FirstStartColumn - PrefixSize
+ : State.Stack.back().Indent;
+
+ std::string RawText =
+ Current.TokenText.substr(PrefixSize).drop_back(SuffixSize);
+
+ std::pair<tooling::Replacements, unsigned> Fixes = internal::reformat(
+ RawStringStyle, RawText, {tooling::Range(0, RawText.size())},
+ FirstStartColumn, NextStartColumn, LastStartColumn, "<stdin>",
+ /*Status=*/nullptr);
+
+ auto NewCode = applyAllReplacements(RawText, Fixes.first);
+ tooling::Replacements NoFixes;
+ if (!NewCode) {
+ State.Column += Current.ColumnWidth;
return 0;
+ }
+ if (!DryRun) {
+ SourceLocation OriginLoc =
+ Current.Tok.getLocation().getLocWithOffset(PrefixSize);
+ for (const tooling::Replacement &Fix : Fixes.first) {
+ auto Err = Whitespaces.addReplacement(tooling::Replacement(
+ SourceMgr, OriginLoc.getLocWithOffset(Fix.getOffset()),
+ Fix.getLength(), Fix.getReplacementText()));
+ if (Err) {
+ llvm::errs() << "Failed to reformat raw string: "
+ << llvm::toString(std::move(Err)) << "\n";
+ }
+ }
+ }
+ unsigned RawLastLineEndColumn = getLastLineEndColumn(
+ *NewCode, FirstStartColumn, Style.TabWidth, Encoding);
+ State.Column = RawLastLineEndColumn + SuffixSize;
+ return Fixes.second;
+}
+unsigned ContinuationIndenter::addMultilineToken(const FormatToken &Current,
+ LineState &State) {
// Break before further function parameters on all levels.
for (unsigned i = 0, e = State.Stack.size(); i != e; ++i)
State.Stack[i].BreakBeforeParameter = true;
@@ -1219,33 +1377,85 @@ unsigned ContinuationIndenter::addMultilineToken(const FormatToken &Current,
return 0;
}
-unsigned ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
- LineState &State,
- bool DryRun) {
- // Don't break multi-line tokens other than block comments. Instead, just
- // update the state.
- if (Current.isNot(TT_BlockComment) && Current.IsMultiline)
- return addMultilineToken(Current, State);
+unsigned ContinuationIndenter::handleEndOfLine(const FormatToken &Current,
+ LineState &State, bool DryRun,
+ bool AllowBreak) {
+ unsigned Penalty = 0;
+ // Compute the raw string style to use in case this is a raw string literal
+ // that can be reformatted.
+ auto RawStringStyle = getRawStringStyle(Current, State);
+ if (RawStringStyle) {
+ Penalty = reformatRawStringLiteral(Current, State, *RawStringStyle, DryRun);
+ } else if (Current.IsMultiline && Current.isNot(TT_BlockComment)) {
+ // Don't break multi-line tokens other than block comments and raw string
+ // literals. Instead, just update the state.
+ Penalty = addMultilineToken(Current, State);
+ } else if (State.Line->Type != LT_ImportStatement) {
+ // We generally don't break import statements.
+ LineState OriginalState = State;
- // Don't break implicit string literals or import statements.
- if (Current.is(TT_ImplicitStringLiteral) ||
- State.Line->Type == LT_ImportStatement)
- return 0;
+ // Whether we force the reflowing algorithm to stay strictly within the
+ // column limit.
+ bool Strict = false;
+ // Whether the first non-strict attempt at reflowing did intentionally
+ // exceed the column limit.
+ bool Exceeded = false;
+ std::tie(Penalty, Exceeded) = breakProtrudingToken(
+ Current, State, AllowBreak, /*DryRun=*/true, Strict);
+ if (Exceeded) {
+ // If non-strict reflowing exceeds the column limit, try whether strict
+ // reflowing leads to an overall lower penalty.
+ LineState StrictState = OriginalState;
+ unsigned StrictPenalty =
+ breakProtrudingToken(Current, StrictState, AllowBreak,
+ /*DryRun=*/true, /*Strict=*/true)
+ .first;
+ Strict = StrictPenalty <= Penalty;
+ if (Strict) {
+ Penalty = StrictPenalty;
+ State = StrictState;
+ }
+ }
+ if (!DryRun) {
+ // If we're not in dry-run mode, apply the changes with the decision on
+ // strictness made above.
+ breakProtrudingToken(Current, OriginalState, AllowBreak, /*DryRun=*/false,
+ Strict);
+ }
+ }
+ if (State.Column > getColumnLimit(State)) {
+ unsigned ExcessCharacters = State.Column - getColumnLimit(State);
+ Penalty += Style.PenaltyExcessCharacter * ExcessCharacters;
+ }
+ return Penalty;
+}
- if (!Current.isStringLiteral() && !Current.is(tok::comment))
- return 0;
+llvm::Optional<FormatStyle>
+ContinuationIndenter::getRawStringStyle(const FormatToken &Current,
+ const LineState &State) {
+ if (!Current.isStringLiteral())
+ return None;
+ auto Delimiter = getRawStringDelimiter(Current.TokenText);
+ if (!Delimiter)
+ return None;
+ auto RawStringStyle = RawStringFormats.get(*Delimiter);
+ if (!RawStringStyle)
+ return None;
+ RawStringStyle->ColumnLimit = getColumnLimit(State);
+ return RawStringStyle;
+}
- std::unique_ptr<BreakableToken> Token;
+std::unique_ptr<BreakableToken> ContinuationIndenter::createBreakableToken(
+ const FormatToken &Current, LineState &State, bool AllowBreak) {
unsigned StartColumn = State.Column - Current.ColumnWidth;
- unsigned ColumnLimit = getColumnLimit(State);
-
if (Current.isStringLiteral()) {
// FIXME: String literal breaking is currently disabled for Java and JS, as
// it requires strings to be merged using "+" which we don't support.
if (Style.Language == FormatStyle::LK_Java ||
Style.Language == FormatStyle::LK_JavaScript ||
- !Style.BreakStringLiterals)
- return 0;
+ !Style.BreakStringLiterals ||
+ !AllowBreak)
+ return nullptr;
// Don't break string literals inside preprocessor directives (except for
// #define directives, as their contents are stored in separate lines and
@@ -1253,11 +1463,11 @@ unsigned ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
// This way we avoid breaking code with line directives and unknown
// preprocessor directives that contain long string literals.
if (State.Line->Type == LT_PreprocessorDirective)
- return 0;
+ return nullptr;
// Exempts unterminated string literals from line breaking. The user will
// likely want to terminate the string before any line breaking is done.
if (Current.IsUnterminatedLiteral)
- return 0;
+ return nullptr;
StringRef Text = Current.TokenText;
StringRef Prefix;
@@ -1272,114 +1482,359 @@ unsigned ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
Text.startswith(Prefix = "u8\"") ||
Text.startswith(Prefix = "L\""))) ||
(Text.startswith(Prefix = "_T(\"") && Text.endswith(Postfix = "\")"))) {
- Token.reset(new BreakableStringLiteral(Current, StartColumn, Prefix,
- Postfix, State.Line->InPPDirective,
- Encoding, Style));
- } else {
- return 0;
+ return llvm::make_unique<BreakableStringLiteral>(
+ Current, StartColumn, Prefix, Postfix, State.Line->InPPDirective,
+ Encoding, Style);
}
} else if (Current.is(TT_BlockComment)) {
- if (!Current.isTrailingComment() || !Style.ReflowComments ||
+ if (!Style.ReflowComments ||
// If a comment token switches formatting, like
// /* clang-format on */, we don't want to break it further,
// but we may still want to adjust its indentation.
- switchesFormatting(Current))
- return addMultilineToken(Current, State);
- Token.reset(new BreakableBlockComment(
+ switchesFormatting(Current)) {
+ return nullptr;
+ }
+ return llvm::make_unique<BreakableBlockComment>(
Current, StartColumn, Current.OriginalColumn, !Current.Previous,
- State.Line->InPPDirective, Encoding, Style));
+ State.Line->InPPDirective, Encoding, Style);
} else if (Current.is(TT_LineComment) &&
(Current.Previous == nullptr ||
Current.Previous->isNot(TT_ImplicitStringLiteral))) {
if (!Style.ReflowComments ||
CommentPragmasRegex.match(Current.TokenText.substr(2)) ||
switchesFormatting(Current))
- return 0;
- Token.reset(new BreakableLineCommentSection(
+ return nullptr;
+ return llvm::make_unique<BreakableLineCommentSection>(
Current, StartColumn, Current.OriginalColumn, !Current.Previous,
- /*InPPDirective=*/false, Encoding, Style));
+ /*InPPDirective=*/false, Encoding, Style);
+ }
+ return nullptr;
+}
+
+std::pair<unsigned, bool>
+ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
+ LineState &State, bool AllowBreak,
+ bool DryRun, bool Strict) {
+ std::unique_ptr<const BreakableToken> Token =
+ createBreakableToken(Current, State, AllowBreak);
+ if (!Token)
+ return {0, false};
+ assert(Token->getLineCount() > 0);
+ unsigned ColumnLimit = getColumnLimit(State);
+ if (Current.is(TT_LineComment)) {
// We don't insert backslashes when breaking line comments.
ColumnLimit = Style.ColumnLimit;
- } else {
- return 0;
}
if (Current.UnbreakableTailLength >= ColumnLimit)
- return 0;
-
- unsigned RemainingSpace = ColumnLimit - Current.UnbreakableTailLength;
- bool BreakInserted = false;
+ return {0, false};
+ // ColumnWidth was already accounted into State.Column before calling
+ // breakProtrudingToken.
+ unsigned StartColumn = State.Column - Current.ColumnWidth;
+ unsigned NewBreakPenalty = Current.isStringLiteral()
+ ? Style.PenaltyBreakString
+ : Style.PenaltyBreakComment;
+ // Stores whether we intentionally decide to let a line exceed the column
+ // limit.
+ bool Exceeded = false;
+ // Stores whether we introduce a break anywhere in the token.
+ bool BreakInserted = Token->introducesBreakBeforeToken();
+ // Store whether we inserted a new line break at the end of the previous
+ // logical line.
+ bool NewBreakBefore = false;
// We use a conservative reflowing strategy. Reflow starts after a line is
// broken or the corresponding whitespace compressed. Reflow ends as soon as a
// line that doesn't get reflown with the previous line is reached.
- bool ReflowInProgress = false;
+ bool Reflow = false;
+ // Keep track of where we are in the token:
+ // Where we are in the content of the current logical line.
+ unsigned TailOffset = 0;
+ // The column number we're currently at.
+ unsigned ContentStartColumn =
+ Token->getContentStartColumn(0, /*Break=*/false);
+ // The number of columns left in the current logical line after TailOffset.
+ unsigned RemainingTokenColumns =
+ Token->getRemainingLength(0, TailOffset, ContentStartColumn);
+ // Adapt the start of the token, for example indent.
+ if (!DryRun)
+ Token->adaptStartOfLine(0, Whitespaces);
+
unsigned Penalty = 0;
- unsigned RemainingTokenColumns = 0;
+ DEBUG(llvm::dbgs() << "Breaking protruding token at column " << StartColumn
+ << ".\n");
for (unsigned LineIndex = 0, EndIndex = Token->getLineCount();
LineIndex != EndIndex; ++LineIndex) {
- BreakableToken::Split SplitBefore(StringRef::npos, 0);
- if (ReflowInProgress) {
- SplitBefore = Token->getSplitBefore(LineIndex, RemainingTokenColumns,
- RemainingSpace, CommentPragmasRegex);
- }
- ReflowInProgress = SplitBefore.first != StringRef::npos;
- unsigned TailOffset =
- ReflowInProgress ? (SplitBefore.first + SplitBefore.second) : 0;
- if (!DryRun)
- Token->replaceWhitespaceBefore(LineIndex, RemainingTokenColumns,
- RemainingSpace, SplitBefore, Whitespaces);
- RemainingTokenColumns = Token->getLineLengthAfterSplitBefore(
- LineIndex, TailOffset, RemainingTokenColumns, ColumnLimit, SplitBefore);
- while (RemainingTokenColumns > RemainingSpace) {
- BreakableToken::Split Split = Token->getSplit(
- LineIndex, TailOffset, ColumnLimit, CommentPragmasRegex);
+ DEBUG(llvm::dbgs() << " Line: " << LineIndex << " (Reflow: " << Reflow
+ << ")\n");
+ NewBreakBefore = false;
+ // If we did reflow the previous line, we'll try reflowing again. Otherwise
+ // we'll start reflowing if the current line is broken or whitespace is
+ // compressed.
+ bool TryReflow = Reflow;
+ // Break the current token until we can fit the rest of the line.
+ while (ContentStartColumn + RemainingTokenColumns > ColumnLimit) {
+ DEBUG(llvm::dbgs() << " Over limit, need: "
+ << (ContentStartColumn + RemainingTokenColumns)
+ << ", space: " << ColumnLimit
+ << ", reflown prefix: " << ContentStartColumn
+ << ", offset in line: " << TailOffset << "\n");
+ // If the current token doesn't fit, find the latest possible split in the
+ // current line so that breaking at it will be under the column limit.
+ // FIXME: Use the earliest possible split while reflowing to correctly
+ // compress whitespace within a line.
+ BreakableToken::Split Split =
+ Token->getSplit(LineIndex, TailOffset, ColumnLimit,
+ ContentStartColumn, CommentPragmasRegex);
if (Split.first == StringRef::npos) {
- // The last line's penalty is handled in addNextStateToQueue().
+ // No break opportunity - update the penalty and continue with the next
+ // logical line.
if (LineIndex < EndIndex - 1)
+ // The last line's penalty is handled in addNextStateToQueue().
Penalty += Style.PenaltyExcessCharacter *
- (RemainingTokenColumns - RemainingSpace);
+ (ContentStartColumn + RemainingTokenColumns - ColumnLimit);
+ DEBUG(llvm::dbgs() << " No break opportunity.\n");
break;
}
assert(Split.first != 0);
- // Check if compressing the whitespace range will bring the line length
- // under the limit. If that is the case, we perform whitespace compression
- // instead of inserting a line break.
- unsigned RemainingTokenColumnsAfterCompression =
- Token->getLineLengthAfterCompression(RemainingTokenColumns, Split);
- if (RemainingTokenColumnsAfterCompression <= RemainingSpace) {
- RemainingTokenColumns = RemainingTokenColumnsAfterCompression;
- ReflowInProgress = true;
- if (!DryRun)
- Token->compressWhitespace(LineIndex, TailOffset, Split, Whitespaces);
- break;
- }
+ if (Token->supportsReflow()) {
+ // Check whether the next natural split point after the current one can
+ // still fit the line, either because we can compress away whitespace,
+ // or because the penalty the excess characters introduce is lower than
+ // the break penalty.
+ // We only do this for tokens that support reflowing, and thus allow us
+ // to change the whitespace arbitrarily (e.g. comments).
+ // Other tokens, like string literals, can be broken on arbitrary
+ // positions.
- unsigned NewRemainingTokenColumns = Token->getLineLengthAfterSplit(
- LineIndex, TailOffset + Split.first + Split.second, StringRef::npos);
+ // First, compute the columns from TailOffset to the next possible split
+ // position.
+ // For example:
+ // ColumnLimit: |
+ // // Some text that breaks
+ // ^ tail offset
+ // ^-- split
+ // ^-------- to split columns
+ // ^--- next split
+ // ^--------------- to next split columns
+ unsigned ToSplitColumns = Token->getRangeLength(
+ LineIndex, TailOffset, Split.first, ContentStartColumn);
+ DEBUG(llvm::dbgs() << " ToSplit: " << ToSplitColumns << "\n");
+
+ BreakableToken::Split NextSplit = Token->getSplit(
+ LineIndex, TailOffset + Split.first + Split.second, ColumnLimit,
+ ContentStartColumn + ToSplitColumns + 1, CommentPragmasRegex);
+ // Compute the columns necessary to fit the next non-breakable sequence
+ // into the current line.
+ unsigned ToNextSplitColumns = 0;
+ if (NextSplit.first == StringRef::npos) {
+ ToNextSplitColumns = Token->getRemainingLength(LineIndex, TailOffset,
+ ContentStartColumn);
+ } else {
+ ToNextSplitColumns = Token->getRangeLength(
+ LineIndex, TailOffset,
+ Split.first + Split.second + NextSplit.first, ContentStartColumn);
+ }
+ // Compress the whitespace between the break and the start of the next
+ // unbreakable sequence.
+ ToNextSplitColumns =
+ Token->getLengthAfterCompression(ToNextSplitColumns, Split);
+ DEBUG(llvm::dbgs() << " ContentStartColumn: " << ContentStartColumn
+ << "\n");
+ DEBUG(llvm::dbgs() << " ToNextSplit: " << ToNextSplitColumns << "\n");
+ // If the whitespace compression makes us fit, continue on the current
+ // line.
+ bool ContinueOnLine =
+ ContentStartColumn + ToNextSplitColumns <= ColumnLimit;
+ unsigned ExcessCharactersPenalty = 0;
+ if (!ContinueOnLine && !Strict) {
+ // Similarly, if the excess characters' penalty is lower than the
+ // penalty of introducing a new break, continue on the current line.
+ ExcessCharactersPenalty =
+ (ContentStartColumn + ToNextSplitColumns - ColumnLimit) *
+ Style.PenaltyExcessCharacter;
+ DEBUG(llvm::dbgs()
+ << " Penalty excess: " << ExcessCharactersPenalty
+ << "\n break : " << NewBreakPenalty << "\n");
+ if (ExcessCharactersPenalty < NewBreakPenalty) {
+ Exceeded = true;
+ ContinueOnLine = true;
+ }
+ }
+ if (ContinueOnLine) {
+ DEBUG(llvm::dbgs() << " Continuing on line...\n");
+ // The current line fits after compressing the whitespace - reflow
+ // the next line into it if possible.
+ TryReflow = true;
+ if (!DryRun)
+ Token->compressWhitespace(LineIndex, TailOffset, Split,
+ Whitespaces);
+ // When we continue on the same line, leave one space between content.
+ ContentStartColumn += ToSplitColumns + 1;
+ Penalty += ExcessCharactersPenalty;
+ TailOffset += Split.first + Split.second;
+ RemainingTokenColumns = Token->getRemainingLength(
+ LineIndex, TailOffset, ContentStartColumn);
+ continue;
+ }
+ }
+ DEBUG(llvm::dbgs() << " Breaking...\n");
+ ContentStartColumn =
+ Token->getContentStartColumn(LineIndex, /*Break=*/true);
+ unsigned NewRemainingTokenColumns = Token->getRemainingLength(
+ LineIndex, TailOffset + Split.first + Split.second,
+ ContentStartColumn);
// When breaking before a tab character, it may be moved by a few columns,
// but will still be expanded to the next tab stop, so we don't save any
// columns.
- if (NewRemainingTokenColumns == RemainingTokenColumns)
+ if (NewRemainingTokenColumns == RemainingTokenColumns) {
+ // FIXME: Do we need to adjust the penalty?
break;
-
+ }
assert(NewRemainingTokenColumns < RemainingTokenColumns);
+
+ DEBUG(llvm::dbgs() << " Breaking at: " << TailOffset + Split.first
+ << ", " << Split.second << "\n");
if (!DryRun)
Token->insertBreak(LineIndex, TailOffset, Split, Whitespaces);
- Penalty += Current.SplitPenalty;
- unsigned ColumnsUsed =
- Token->getLineLengthAfterSplit(LineIndex, TailOffset, Split.first);
- if (ColumnsUsed > ColumnLimit) {
- Penalty += Style.PenaltyExcessCharacter * (ColumnsUsed - ColumnLimit);
- }
+
+ Penalty += NewBreakPenalty;
TailOffset += Split.first + Split.second;
RemainingTokenColumns = NewRemainingTokenColumns;
- ReflowInProgress = true;
BreakInserted = true;
+ NewBreakBefore = true;
+ }
+ // In case there's another line, prepare the state for the start of the next
+ // line.
+ if (LineIndex + 1 != EndIndex) {
+ unsigned NextLineIndex = LineIndex + 1;
+ if (NewBreakBefore)
+ // After breaking a line, try to reflow the next line into the current
+ // one once RemainingTokenColumns fits.
+ TryReflow = true;
+ if (TryReflow) {
+ // We decided that we want to try reflowing the next line into the
+ // current one.
+ // We will now adjust the state as if the reflow is successful (in
+ // preparation for the next line), and see whether that works. If we
+ // decide that we cannot reflow, we will later reset the state to the
+ // start of the next line.
+ Reflow = false;
+ // As we did not continue breaking the line, RemainingTokenColumns is
+ // known to fit after ContentStartColumn. Adapt ContentStartColumn to
+ // the position at which we want to format the next line if we do
+ // actually reflow.
+ // When we reflow, we need to add a space between the end of the current
+ // line and the next line's start column.
+ ContentStartColumn += RemainingTokenColumns + 1;
+ // Get the split that we need to reflow next logical line into the end
+ // of the current one; the split will include any leading whitespace of
+ // the next logical line.
+ BreakableToken::Split SplitBeforeNext =
+ Token->getReflowSplit(NextLineIndex, CommentPragmasRegex);
+ DEBUG(llvm::dbgs() << " Size of reflown text: " << ContentStartColumn
+ << "\n Potential reflow split: ");
+ if (SplitBeforeNext.first != StringRef::npos) {
+ DEBUG(llvm::dbgs() << SplitBeforeNext.first << ", "
+ << SplitBeforeNext.second << "\n");
+ TailOffset = SplitBeforeNext.first + SplitBeforeNext.second;
+ // If the rest of the next line fits into the current line below the
+ // column limit, we can safely reflow.
+ RemainingTokenColumns = Token->getRemainingLength(
+ NextLineIndex, TailOffset, ContentStartColumn);
+ Reflow = true;
+ if (ContentStartColumn + RemainingTokenColumns > ColumnLimit) {
+ DEBUG(llvm::dbgs() << " Over limit after reflow, need: "
+ << (ContentStartColumn + RemainingTokenColumns)
+ << ", space: " << ColumnLimit
+ << ", reflown prefix: " << ContentStartColumn
+ << ", offset in line: " << TailOffset << "\n");
+ // If the whole next line does not fit, try to find a point in
+ // the next line at which we can break so that attaching the part
+ // of the next line to that break point onto the current line is
+ // below the column limit.
+ BreakableToken::Split Split =
+ Token->getSplit(NextLineIndex, TailOffset, ColumnLimit,
+ ContentStartColumn, CommentPragmasRegex);
+ if (Split.first == StringRef::npos) {
+ DEBUG(llvm::dbgs() << " Did not find later break\n");
+ Reflow = false;
+ } else {
+ // Check whether the first split point gets us below the column
+ // limit. Note that we will execute this split below as part of
+ // the normal token breaking and reflow logic within the line.
+ unsigned ToSplitColumns = Token->getRangeLength(
+ NextLineIndex, TailOffset, Split.first, ContentStartColumn);
+ if (ContentStartColumn + ToSplitColumns > ColumnLimit) {
+ DEBUG(llvm::dbgs() << " Next split protrudes, need: "
+ << (ContentStartColumn + ToSplitColumns)
+ << ", space: " << ColumnLimit);
+ unsigned ExcessCharactersPenalty =
+ (ContentStartColumn + ToSplitColumns - ColumnLimit) *
+ Style.PenaltyExcessCharacter;
+ if (NewBreakPenalty < ExcessCharactersPenalty) {
+ Reflow = false;
+ }
+ }
+ }
+ }
+ } else {
+ DEBUG(llvm::dbgs() << "not found.\n");
+ }
+ }
+ if (!Reflow) {
+ // If we didn't reflow into the next line, the only space to consider is
+ // the next logical line. Reset our state to match the start of the next
+ // line.
+ TailOffset = 0;
+ ContentStartColumn =
+ Token->getContentStartColumn(NextLineIndex, /*Break=*/false);
+ RemainingTokenColumns = Token->getRemainingLength(
+ NextLineIndex, TailOffset, ContentStartColumn);
+ // Adapt the start of the token, for example indent.
+ if (!DryRun)
+ Token->adaptStartOfLine(NextLineIndex, Whitespaces);
+ } else {
+ // If we found a reflow split and have added a new break before the next
+ // line, we are going to remove the line break at the start of the next
+ // logical line. For example, here we'll add a new line break after
+ // 'text', and subsequently delete the line break between 'that' and
+ // 'reflows'.
+ // // some text that
+ // // reflows
+ // ->
+ // // some text
+ // // that reflows
+ // When adding the line break, we also added the penalty for it, so we
+ // need to subtract that penalty again when we remove the line break due
+ // to reflowing.
+ if (NewBreakBefore) {
+ assert(Penalty >= NewBreakPenalty);
+ Penalty -= NewBreakPenalty;
+ }
+ if (!DryRun)
+ Token->reflow(NextLineIndex, Whitespaces);
+ }
}
}
- State.Column = RemainingTokenColumns;
+ BreakableToken::Split SplitAfterLastLine =
+ Token->getSplitAfterLastLine(TailOffset);
+ if (SplitAfterLastLine.first != StringRef::npos) {
+ DEBUG(llvm::dbgs() << "Replacing whitespace after last line.\n");
+ if (!DryRun)
+ Token->replaceWhitespaceAfterLastLine(TailOffset, SplitAfterLastLine,
+ Whitespaces);
+ ContentStartColumn =
+ Token->getContentStartColumn(Token->getLineCount() - 1, /*Break=*/true);
+ RemainingTokenColumns = Token->getRemainingLength(
+ Token->getLineCount() - 1,
+ TailOffset + SplitAfterLastLine.first + SplitAfterLastLine.second,
+ ContentStartColumn);
+ }
+
+ State.Column = ContentStartColumn + RemainingTokenColumns -
+ Current.UnbreakableTailLength;
if (BreakInserted) {
// If we break the token inside a parameter list, we need to break before
@@ -1390,15 +1845,15 @@ unsigned ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
State.Stack[i].BreakBeforeParameter = true;
}
- Penalty += Current.isStringLiteral() ? Style.PenaltyBreakString
- : Style.PenaltyBreakComment;
+ if (Current.is(TT_BlockComment))
+ State.NoContinuation = true;
State.Stack.back().LastSpace = StartColumn;
}
Token->updateNextToken(State);
- return Penalty;
+ return {Penalty, Exceeded};
}
unsigned ContinuationIndenter::getColumnLimit(const LineState &State) const {
diff --git a/contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.h b/contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.h
index 9a06aa6f62672..ded7bfab4267c 100644
--- a/contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.h
+++ b/contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.h
@@ -20,6 +20,8 @@
#include "FormatToken.h"
#include "clang/Format/Format.h"
#include "llvm/Support/Regex.h"
+#include <map>
+#include <tuple>
namespace clang {
class SourceManager;
@@ -27,11 +29,21 @@ class SourceManager;
namespace format {
class AnnotatedLine;
+class BreakableToken;
struct FormatToken;
struct LineState;
struct ParenState;
+struct RawStringFormatStyleManager;
class WhitespaceManager;
+struct RawStringFormatStyleManager {
+ llvm::StringMap<FormatStyle> DelimiterStyle;
+
+ RawStringFormatStyleManager(const FormatStyle &CodeStyle);
+
+ llvm::Optional<FormatStyle> get(StringRef Delimiter) const;
+};
+
class ContinuationIndenter {
public:
/// \brief Constructs a \c ContinuationIndenter to format \p Line starting in
@@ -44,9 +56,11 @@ public:
bool BinPackInconclusiveFunctions);
/// \brief Get the initial state, i.e. the state after placing \p Line's
- /// first token at \p FirstIndent.
- LineState getInitialState(unsigned FirstIndent, const AnnotatedLine *Line,
- bool DryRun);
+ /// first token at \p FirstIndent. When reformatting a fragment of code, as in
+ /// the case of formatting inside raw string literals, \p FirstStartColumn is
+ /// the column at which the state of the parent formatter is.
+ LineState getInitialState(unsigned FirstIndent, unsigned FirstStartColumn,
+ const AnnotatedLine *Line, bool DryRun);
// FIXME: canBreak and mustBreak aren't strictly indentation-related. Find a
// better home.
@@ -88,17 +102,52 @@ private:
/// \brief Update 'State' with the next token opening a nested block.
void moveStateToNewBlock(LineState &State);
+ /// \brief Reformats a raw string literal.
+ ///
+ /// \returns An extra penalty induced by reformatting the token.
+ unsigned reformatRawStringLiteral(const FormatToken &Current,
+ LineState &State,
+ const FormatStyle &RawStringStyle,
+ bool DryRun);
+
+ /// \brief If the current token is at the end of the current line, handle
+ /// the transition to the next line.
+ unsigned handleEndOfLine(const FormatToken &Current, LineState &State,
+ bool DryRun, bool AllowBreak);
+
+ /// \brief If \p Current is a raw string that is configured to be reformatted,
+ /// return the style to be used.
+ llvm::Optional<FormatStyle> getRawStringStyle(const FormatToken &Current,
+ const LineState &State);
+
/// \brief If the current token sticks out over the end of the line, break
/// it if possible.
///
- /// \returns An extra penalty if a token was broken, otherwise 0.
+ /// \returns A pair (penalty, exceeded), where penalty is the extra penalty
+ /// when tokens are broken or lines exceed the column limit, and exceeded
+ /// indicates whether the algorithm purposefully left lines exceeding the
+ /// column limit.
+ ///
+ /// The returned penalty will cover the cost of the additional line breaks
+ /// and column limit violation in all lines except for the last one. The
+ /// penalty for the column limit violation in the last line (and in single
+ /// line tokens) is handled in \c addNextStateToQueue.
///
- /// The returned penalty will cover the cost of the additional line breaks and
- /// column limit violation in all lines except for the last one. The penalty
- /// for the column limit violation in the last line (and in single line
- /// tokens) is handled in \c addNextStateToQueue.
- unsigned breakProtrudingToken(const FormatToken &Current, LineState &State,
- bool DryRun);
+ /// \p Strict indicates whether reflowing is allowed to leave characters
+ /// protruding the column limit; if true, lines will be split strictly within
+ /// the column limit where possible; if false, words are allowed to protrude
+ /// over the column limit as long as the penalty is less than the penalty
+ /// of a break.
+ std::pair<unsigned, bool> breakProtrudingToken(const FormatToken &Current,
+ LineState &State,
+ bool AllowBreak, bool DryRun,
+ bool Strict);
+
+ /// \brief Returns the \c BreakableToken starting at \p Current, or nullptr
+ /// if the current token cannot be broken.
+ std::unique_ptr<BreakableToken>
+ createBreakableToken(const FormatToken &Current, LineState &State,
+ bool AllowBreak);
/// \brief Appends the next token to \p State and updates information
/// necessary for indentation.
@@ -143,6 +192,7 @@ private:
encoding::Encoding Encoding;
bool BinPackInconclusiveFunctions;
llvm::Regex CommentPragmasRegex;
+ const RawStringFormatStyleManager RawStringFormats;
};
struct ParenState {
@@ -318,6 +368,9 @@ struct LineState {
/// \brief \c true if this line contains a continued for-loop section.
bool LineContainsContinuedForLoopSection;
+ /// \brief \c true if \p NextToken should not continue this line.
+ bool NoContinuation;
+
/// \brief The \c NestingLevel at the start of this line.
unsigned StartOfLineLevel;
@@ -364,6 +417,8 @@ struct LineState {
if (LineContainsContinuedForLoopSection !=
Other.LineContainsContinuedForLoopSection)
return LineContainsContinuedForLoopSection;
+ if (NoContinuation != Other.NoContinuation)
+ return NoContinuation;
if (StartOfLineLevel != Other.StartOfLineLevel)
return StartOfLineLevel < Other.StartOfLineLevel;
if (LowestLevelOnLine != Other.LowestLevelOnLine)
diff --git a/contrib/llvm/tools/clang/lib/Format/Format.cpp b/contrib/llvm/tools/clang/lib/Format/Format.cpp
index 6fe5be2c815d4..217c6729ee397 100644
--- a/contrib/llvm/tools/clang/lib/Format/Format.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/Format.cpp
@@ -16,6 +16,7 @@
#include "clang/Format/Format.h"
#include "AffectedRangeManager.h"
#include "ContinuationIndenter.h"
+#include "FormatInternal.h"
#include "FormatTokenLexer.h"
#include "NamespaceEndCommentsFixer.h"
#include "SortJavaScriptImports.h"
@@ -45,6 +46,7 @@
using clang::format::FormatStyle;
LLVM_YAML_IS_SEQUENCE_VECTOR(clang::format::FormatStyle::IncludeCategory)
+LLVM_YAML_IS_SEQUENCE_VECTOR(clang::format::FormatStyle::RawStringFormat)
namespace llvm {
namespace yaml {
@@ -125,8 +127,10 @@ template <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> {
}
};
-template <> struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitializersStyle> {
- static void enumeration(IO &IO, FormatStyle::BreakConstructorInitializersStyle &Value) {
+template <>
+struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitializersStyle> {
+ static void
+ enumeration(IO &IO, FormatStyle::BreakConstructorInitializersStyle &Value) {
IO.enumCase(Value, "BeforeColon", FormatStyle::BCIS_BeforeColon);
IO.enumCase(Value, "BeforeComma", FormatStyle::BCIS_BeforeComma);
IO.enumCase(Value, "AfterColon", FormatStyle::BCIS_AfterColon);
@@ -134,6 +138,14 @@ template <> struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitiali
};
template <>
+struct ScalarEnumerationTraits<FormatStyle::PPDirectiveIndentStyle> {
+ static void enumeration(IO &IO, FormatStyle::PPDirectiveIndentStyle &Value) {
+ IO.enumCase(Value, "None", FormatStyle::PPDIS_None);
+ IO.enumCase(Value, "AfterHash", FormatStyle::PPDIS_AfterHash);
+ }
+};
+
+template <>
struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> {
static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) {
IO.enumCase(Value, "None", FormatStyle::RTBS_None);
@@ -181,8 +193,10 @@ template <> struct ScalarEnumerationTraits<FormatStyle::BracketAlignmentStyle> {
}
};
-template <> struct ScalarEnumerationTraits<FormatStyle::EscapedNewlineAlignmentStyle> {
- static void enumeration(IO &IO, FormatStyle::EscapedNewlineAlignmentStyle &Value) {
+template <>
+struct ScalarEnumerationTraits<FormatStyle::EscapedNewlineAlignmentStyle> {
+ static void enumeration(IO &IO,
+ FormatStyle::EscapedNewlineAlignmentStyle &Value) {
IO.enumCase(Value, "DontAlign", FormatStyle::ENAS_DontAlign);
IO.enumCase(Value, "Left", FormatStyle::ENAS_Left);
IO.enumCase(Value, "Right", FormatStyle::ENAS_Right);
@@ -347,9 +361,11 @@ template <> struct MappingTraits<FormatStyle> {
Style.ExperimentalAutoDetectBinPacking);
IO.mapOptional("FixNamespaceComments", Style.FixNamespaceComments);
IO.mapOptional("ForEachMacros", Style.ForEachMacros);
+ IO.mapOptional("IncludeBlocks", Style.IncludeBlocks);
IO.mapOptional("IncludeCategories", Style.IncludeCategories);
IO.mapOptional("IncludeIsMainRegex", Style.IncludeIsMainRegex);
IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);
+ IO.mapOptional("IndentPPDirectives", Style.IndentPPDirectives);
IO.mapOptional("IndentWidth", Style.IndentWidth);
IO.mapOptional("IndentWrappedFunctionNames",
Style.IndentWrappedFunctionNames);
@@ -365,8 +381,7 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("ObjCSpaceAfterProperty", Style.ObjCSpaceAfterProperty);
IO.mapOptional("ObjCSpaceBeforeProtocolList",
Style.ObjCSpaceBeforeProtocolList);
- IO.mapOptional("PenaltyBreakAssignment",
- Style.PenaltyBreakAssignment);
+ IO.mapOptional("PenaltyBreakAssignment", Style.PenaltyBreakAssignment);
IO.mapOptional("PenaltyBreakBeforeFirstCallParameter",
Style.PenaltyBreakBeforeFirstCallParameter);
IO.mapOptional("PenaltyBreakComment", Style.PenaltyBreakComment);
@@ -377,11 +392,13 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("PenaltyReturnTypeOnItsOwnLine",
Style.PenaltyReturnTypeOnItsOwnLine);
IO.mapOptional("PointerAlignment", Style.PointerAlignment);
+ IO.mapOptional("RawStringFormats", Style.RawStringFormats);
IO.mapOptional("ReflowComments", Style.ReflowComments);
IO.mapOptional("SortIncludes", Style.SortIncludes);
IO.mapOptional("SortUsingDeclarations", Style.SortUsingDeclarations);
IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast);
- IO.mapOptional("SpaceAfterTemplateKeyword", Style.SpaceAfterTemplateKeyword);
+ IO.mapOptional("SpaceAfterTemplateKeyword",
+ Style.SpaceAfterTemplateKeyword);
IO.mapOptional("SpaceBeforeAssignmentOperators",
Style.SpaceBeforeAssignmentOperators);
IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
@@ -411,6 +428,7 @@ template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> {
IO.mapOptional("AfterObjCDeclaration", Wrapping.AfterObjCDeclaration);
IO.mapOptional("AfterStruct", Wrapping.AfterStruct);
IO.mapOptional("AfterUnion", Wrapping.AfterUnion);
+ IO.mapOptional("AfterExternBlock", Wrapping.AfterExternBlock);
IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch);
IO.mapOptional("BeforeElse", Wrapping.BeforeElse);
IO.mapOptional("IndentBraces", Wrapping.IndentBraces);
@@ -427,6 +445,22 @@ template <> struct MappingTraits<FormatStyle::IncludeCategory> {
}
};
+template <> struct ScalarEnumerationTraits<FormatStyle::IncludeBlocksStyle> {
+ static void enumeration(IO &IO, FormatStyle::IncludeBlocksStyle &Value) {
+ IO.enumCase(Value, "Preserve", FormatStyle::IBS_Preserve);
+ IO.enumCase(Value, "Merge", FormatStyle::IBS_Merge);
+ IO.enumCase(Value, "Regroup", FormatStyle::IBS_Regroup);
+ }
+};
+
+template <> struct MappingTraits<FormatStyle::RawStringFormat> {
+ static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) {
+ IO.mapOptional("Delimiter", Format.Delimiter);
+ IO.mapOptional("Language", Format.Language);
+ IO.mapOptional("BasedOnStyle", Format.BasedOnStyle);
+ }
+};
+
// Allows to read vector<FormatStyle> while keeping default values.
// IO.getContext() should contain a pointer to the FormatStyle structure, that
// will be used to get default values for missing keys.
@@ -441,7 +475,7 @@ template <> struct DocumentListTraits<std::vector<FormatStyle>> {
if (Index >= Seq.size()) {
assert(Index == Seq.size());
FormatStyle Template;
- if (Seq.size() > 0 && Seq[0].Language == FormatStyle::LK_None) {
+ if (!Seq.empty() && Seq[0].Language == FormatStyle::LK_None) {
Template = Seq[0];
} else {
Template = *((const FormatStyle *)IO.getContext());
@@ -491,9 +525,9 @@ static FormatStyle expandPresets(const FormatStyle &Style) {
if (Style.BreakBeforeBraces == FormatStyle::BS_Custom)
return Style;
FormatStyle Expanded = Style;
- Expanded.BraceWrapping = {false, false, false, false, false, false,
- false, false, false, false, false, true,
- true, true};
+ Expanded.BraceWrapping = {false, false, false, false, false,
+ false, false, false, false, false,
+ false, false, true, true, true};
switch (Style.BreakBeforeBraces) {
case FormatStyle::BS_Linux:
Expanded.BraceWrapping.AfterClass = true;
@@ -506,6 +540,7 @@ static FormatStyle expandPresets(const FormatStyle &Style) {
Expanded.BraceWrapping.AfterFunction = true;
Expanded.BraceWrapping.AfterStruct = true;
Expanded.BraceWrapping.AfterUnion = true;
+ Expanded.BraceWrapping.AfterExternBlock = true;
Expanded.BraceWrapping.SplitEmptyFunction = true;
Expanded.BraceWrapping.SplitEmptyRecord = false;
break;
@@ -522,13 +557,13 @@ static FormatStyle expandPresets(const FormatStyle &Style) {
Expanded.BraceWrapping.AfterNamespace = true;
Expanded.BraceWrapping.AfterObjCDeclaration = true;
Expanded.BraceWrapping.AfterStruct = true;
+ Expanded.BraceWrapping.AfterExternBlock = true;
Expanded.BraceWrapping.BeforeCatch = true;
Expanded.BraceWrapping.BeforeElse = true;
break;
case FormatStyle::BS_GNU:
- Expanded.BraceWrapping = {true, true, true, true, true, true,
- true, true, true, true, true, true,
- true, true};
+ Expanded.BraceWrapping = {true, true, true, true, true, true, true, true,
+ true, true, true, true, true, true, true};
break;
case FormatStyle::BS_WebKit:
Expanded.BraceWrapping.AfterFunction = true;
@@ -564,9 +599,9 @@ FormatStyle getLLVMStyle() {
LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
LLVMStyle.BreakBeforeTernaryOperators = true;
LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
- LLVMStyle.BraceWrapping = {false, false, false, false, false, false,
- false, false, false, false, false, true,
- true, true};
+ LLVMStyle.BraceWrapping = {false, false, false, false, false,
+ false, false, false, false, false,
+ false, false, true, true, true};
LLVMStyle.BreakAfterJavaFieldAnnotations = false;
LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
LLVMStyle.BreakBeforeInheritanceComma = false;
@@ -588,7 +623,9 @@ FormatStyle getLLVMStyle() {
{"^(<|\"(gtest|gmock|isl|json)/)", 3},
{".*", 1}};
LLVMStyle.IncludeIsMainRegex = "(Test)?$";
+ LLVMStyle.IncludeBlocks = FormatStyle::IBS_Preserve;
LLVMStyle.IndentCaseLabels = false;
+ LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None;
LLVMStyle.IndentWrappedFunctionNames = false;
LLVMStyle.IndentWidth = 2;
LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave;
@@ -604,6 +641,7 @@ FormatStyle getLLVMStyle() {
LLVMStyle.SpacesBeforeTrailingComments = 1;
LLVMStyle.Standard = FormatStyle::LS_Cpp11;
LLVMStyle.UseTab = FormatStyle::UT_Never;
+ LLVMStyle.RawStringFormats = {{"pb", FormatStyle::LK_TextProto, "google"}};
LLVMStyle.ReflowComments = true;
LLVMStyle.SpacesInParentheses = false;
LLVMStyle.SpacesInSquareBrackets = false;
@@ -649,7 +687,8 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
GoogleStyle.AlwaysBreakTemplateDeclarations = true;
GoogleStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
GoogleStyle.DerivePointerAlignment = true;
- GoogleStyle.IncludeCategories = {{"^<.*\\.h>", 1}, {"^<.*", 2}, {".*", 3}};
+ GoogleStyle.IncludeCategories = {
+ {"^<ext/.*\\.h>", 2}, {"^<.*\\.h>", 1}, {"^<.*", 2}, {".*", 3}};
GoogleStyle.IncludeIsMainRegex = "([-_](test|unittest))?$";
GoogleStyle.IndentCaseLabels = true;
GoogleStyle.KeepEmptyLinesAtTheStartOfBlocks = false;
@@ -725,8 +764,7 @@ FormatStyle getMozillaStyle() {
FormatStyle MozillaStyle = getLLVMStyle();
MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false;
MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
- MozillaStyle.AlwaysBreakAfterReturnType =
- FormatStyle::RTBS_TopLevel;
+ MozillaStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_TopLevel;
MozillaStyle.AlwaysBreakAfterDefinitionReturnType =
FormatStyle::DRTBS_TopLevel;
MozillaStyle.AlwaysBreakTemplateDeclarations = true;
@@ -879,7 +917,7 @@ public:
JavaScriptRequoter(const Environment &Env, const FormatStyle &Style)
: TokenAnalyzer(Env, Style) {}
- tooling::Replacements
+ std::pair<tooling::Replacements, unsigned>
analyze(TokenAnnotator &Annotator,
SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
FormatTokenLexer &Tokens) override {
@@ -887,7 +925,7 @@ public:
AnnotatedLines.end());
tooling::Replacements Result;
requoteJSStringLiteral(AnnotatedLines, Result);
- return Result;
+ return {Result, 0};
}
private:
@@ -968,7 +1006,7 @@ public:
FormattingAttemptStatus *Status)
: TokenAnalyzer(Env, Style), Status(Status) {}
- tooling::Replacements
+ std::pair<tooling::Replacements, unsigned>
analyze(TokenAnnotator &Annotator,
SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
FormatTokenLexer &Tokens) override {
@@ -987,17 +1025,23 @@ public:
ContinuationIndenter Indenter(Style, Tokens.getKeywords(),
Env.getSourceManager(), Whitespaces, Encoding,
BinPackInconclusiveFunctions);
- UnwrappedLineFormatter(&Indenter, &Whitespaces, Style, Tokens.getKeywords(),
- Env.getSourceManager(), Status)
- .format(AnnotatedLines);
+ unsigned Penalty =
+ UnwrappedLineFormatter(&Indenter, &Whitespaces, Style,
+ Tokens.getKeywords(), Env.getSourceManager(),
+ Status)
+ .format(AnnotatedLines, /*DryRun=*/false,
+ /*AdditionalIndent=*/0,
+ /*FixBadIndentation=*/false,
+ /*FirstStartColumn=*/Env.getFirstStartColumn(),
+ /*NextStartColumn=*/Env.getNextStartColumn(),
+ /*LastStartColumn=*/Env.getLastStartColumn());
for (const auto &R : Whitespaces.generateReplacements())
if (Result.add(R))
- return Result;
- return Result;
+ return std::make_pair(Result, 0);
+ return std::make_pair(Result, Penalty);
}
private:
-
static bool inputUsesCRLF(StringRef Text) {
return Text.count('\r') * 2 > Text.count('\n');
}
@@ -1082,7 +1126,7 @@ public:
DeletedTokens(FormatTokenLess(Env.getSourceManager())) {}
// FIXME: eliminate unused parameters.
- tooling::Replacements
+ std::pair<tooling::Replacements, unsigned>
analyze(TokenAnnotator &Annotator,
SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
FormatTokenLexer &Tokens) override {
@@ -1110,7 +1154,7 @@ public:
}
}
- return generateFixes();
+ return {generateFixes(), 0};
}
private:
@@ -1386,19 +1430,27 @@ static void sortCppIncludes(const FormatStyle &Style,
}),
Indices.end());
+ int CurrentCategory = Includes.front().Category;
+
// If the #includes are out of order, we generate a single replacement fixing
// the entire block. Otherwise, no replacement is generated.
if (Indices.size() == Includes.size() &&
- std::is_sorted(Indices.begin(), Indices.end()))
+ std::is_sorted(Indices.begin(), Indices.end()) &&
+ Style.IncludeBlocks == FormatStyle::IBS_Preserve)
return;
std::string result;
for (unsigned Index : Indices) {
- if (!result.empty())
+ if (!result.empty()) {
result += "\n";
+ if (Style.IncludeBlocks == FormatStyle::IBS_Regroup &&
+ CurrentCategory != Includes[Index].Category)
+ result += "\n";
+ }
result += Includes[Index].Text;
if (Cursor && CursorIndex == Index)
*Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset;
+ CurrentCategory = Includes[Index].Category;
}
auto Err = Replaces.add(tooling::Replacement(
@@ -1506,6 +1558,10 @@ tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,
else if (Trimmed == "// clang-format on")
FormattingOff = false;
+ const bool EmptyLineSkipped =
+ Trimmed.empty() && (Style.IncludeBlocks == FormatStyle::IBS_Merge ||
+ Style.IncludeBlocks == FormatStyle::IBS_Regroup);
+
if (!FormattingOff && !Line.endswith("\\")) {
if (IncludeRegex.match(Line, &Matches)) {
StringRef IncludeName = Matches[2];
@@ -1515,7 +1571,7 @@ tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,
if (Category == 0)
MainIncludeFound = true;
IncludesInBlock.push_back({IncludeName, Line, Prev, Category});
- } else if (!IncludesInBlock.empty()) {
+ } else if (!IncludesInBlock.empty() && !EmptyLineSkipped) {
sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Replaces,
Cursor);
IncludesInBlock.clear();
@@ -1539,12 +1595,16 @@ bool isMpegTS(StringRef Code) {
return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47;
}
+bool isLikelyXml(StringRef Code) { return Code.ltrim().startswith("<"); }
+
tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code,
ArrayRef<tooling::Range> Ranges,
StringRef FileName, unsigned *Cursor) {
tooling::Replacements Replaces;
if (!Style.SortIncludes)
return Replaces;
+ if (isLikelyXml(Code))
+ return Replaces;
if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript &&
isMpegTS(Code))
return Replaces;
@@ -1887,17 +1947,22 @@ cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces,
return processReplacements(Cleanup, Code, NewReplaces, Style);
}
-tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
- ArrayRef<tooling::Range> Ranges,
- StringRef FileName,
- FormattingAttemptStatus *Status) {
+namespace internal {
+std::pair<tooling::Replacements, unsigned>
+reformat(const FormatStyle &Style, StringRef Code,
+ ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn,
+ unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName,
+ FormattingAttemptStatus *Status) {
FormatStyle Expanded = expandPresets(Style);
if (Expanded.DisableFormat)
- return tooling::Replacements();
+ return {tooling::Replacements(), 0};
+ if (isLikelyXml(Code))
+ return {tooling::Replacements(), 0};
if (Expanded.Language == FormatStyle::LK_JavaScript && isMpegTS(Code))
- return tooling::Replacements();
+ return {tooling::Replacements(), 0};
- typedef std::function<tooling::Replacements(const Environment &)>
+ typedef std::function<std::pair<tooling::Replacements, unsigned>(
+ const Environment &)>
AnalyzerPass;
SmallVector<AnalyzerPass, 4> Passes;
@@ -1923,26 +1988,42 @@ tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
return Formatter(Env, Expanded, Status).process();
});
- std::unique_ptr<Environment> Env =
- Environment::CreateVirtualEnvironment(Code, FileName, Ranges);
+ std::unique_ptr<Environment> Env = Environment::CreateVirtualEnvironment(
+ Code, FileName, Ranges, FirstStartColumn, NextStartColumn,
+ LastStartColumn);
llvm::Optional<std::string> CurrentCode = None;
tooling::Replacements Fixes;
+ unsigned Penalty = 0;
for (size_t I = 0, E = Passes.size(); I < E; ++I) {
- tooling::Replacements PassFixes = Passes[I](*Env);
+ std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env);
auto NewCode = applyAllReplacements(
- CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes);
+ CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first);
if (NewCode) {
- Fixes = Fixes.merge(PassFixes);
+ Fixes = Fixes.merge(PassFixes.first);
+ Penalty += PassFixes.second;
if (I + 1 < E) {
CurrentCode = std::move(*NewCode);
Env = Environment::CreateVirtualEnvironment(
*CurrentCode, FileName,
- tooling::calculateRangesAfterReplacements(Fixes, Ranges));
+ tooling::calculateRangesAfterReplacements(Fixes, Ranges),
+ FirstStartColumn, NextStartColumn, LastStartColumn);
}
}
}
- return Fixes;
+ return {Fixes, Penalty};
+}
+} // namespace internal
+
+tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
+ ArrayRef<tooling::Range> Ranges,
+ StringRef FileName,
+ FormattingAttemptStatus *Status) {
+ return internal::reformat(Style, Code, Ranges,
+ /*FirstStartColumn=*/0,
+ /*NextStartColumn=*/0,
+ /*LastStartColumn=*/0, FileName, Status)
+ .first;
}
tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code,
@@ -1954,7 +2035,7 @@ tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code,
std::unique_ptr<Environment> Env =
Environment::CreateVirtualEnvironment(Code, FileName, Ranges);
Cleaner Clean(*Env, Style);
- return Clean.process();
+ return Clean.process().first;
}
tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
@@ -1974,7 +2055,7 @@ tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style,
std::unique_ptr<Environment> Env =
Environment::CreateVirtualEnvironment(Code, FileName, Ranges);
NamespaceEndCommentsFixer Fix(*Env, Style);
- return Fix.process();
+ return Fix.process().first;
}
tooling::Replacements sortUsingDeclarations(const FormatStyle &Style,
@@ -1984,7 +2065,7 @@ tooling::Replacements sortUsingDeclarations(const FormatStyle &Style,
std::unique_ptr<Environment> Env =
Environment::CreateVirtualEnvironment(Code, FileName, Ranges);
UsingDeclarationsSorter Sorter(*Env, Style);
- return Sorter.process();
+ return Sorter.process().first;
}
LangOptions getFormattingLangOpts(const FormatStyle &Style) {
@@ -1992,7 +2073,8 @@ LangOptions getFormattingLangOpts(const FormatStyle &Style) {
LangOpts.CPlusPlus = 1;
LangOpts.CPlusPlus11 = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
LangOpts.CPlusPlus14 = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
- LangOpts.CPlusPlus1z = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
+ LangOpts.CPlusPlus17 = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
+ LangOpts.CPlusPlus2a = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
LangOpts.LineComment = 1;
bool AlternativeOperators = Style.isCpp();
LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0;
@@ -2025,6 +2107,11 @@ static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) {
if (FileName.endswith_lower(".proto") ||
FileName.endswith_lower(".protodevel"))
return FormatStyle::LK_Proto;
+ if (FileName.endswith_lower(".textpb") ||
+ FileName.endswith_lower(".pb.txt") ||
+ FileName.endswith_lower(".textproto") ||
+ FileName.endswith_lower(".asciipb"))
+ return FormatStyle::LK_TextProto;
if (FileName.endswith_lower(".td"))
return FormatStyle::LK_TableGen;
return FormatStyle::LK_Cpp;
@@ -2043,7 +2130,9 @@ llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
// should be improved over time and probably be done on tokens, not one the
// bare content of the file.
if (Style.Language == FormatStyle::LK_Cpp && FileName.endswith(".h") &&
- (Code.contains("\n- (") || Code.contains("\n+ (")))
+ (Code.contains("\n- (") || Code.contains("\n+ (") ||
+ Code.contains("\n@end\n") || Code.contains("\n@end ") ||
+ Code.endswith("@end")))
Style.Language = FormatStyle::LK_ObjC;
FormatStyle FallbackStyle = getNoStyle();
diff --git a/contrib/llvm/tools/clang/lib/Format/FormatInternal.h b/contrib/llvm/tools/clang/lib/Format/FormatInternal.h
new file mode 100644
index 0000000000000..3984158467b3b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Format/FormatInternal.h
@@ -0,0 +1,83 @@
+//===--- FormatInternal.h - Format C++ code ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file declares Format APIs to be used internally by the
+/// formatting library implementation.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_FORMAT_FORMATINTERNAL_H
+#define LLVM_CLANG_LIB_FORMAT_FORMATINTERNAL_H
+
+#include "BreakableToken.h"
+#include "clang/Tooling/Core/Lookup.h"
+#include <utility>
+
+namespace clang {
+namespace format {
+namespace internal {
+
+/// \brief Reformats the given \p Ranges in the code fragment \p Code.
+///
+/// A fragment of code could conceptually be surrounded by other code that might
+/// constrain how that fragment is laid out.
+/// For example, consider the fragment of code between 'R"(' and ')"',
+/// exclusive, in the following code:
+///
+/// void outer(int x) {
+/// string inner = R"(name: data
+/// ^ FirstStartColumn
+/// value: {
+/// x: 1
+/// ^ NextStartColumn
+/// }
+/// )";
+/// ^ LastStartColumn
+/// }
+///
+/// The outer code can influence the inner fragment as follows:
+/// * \p FirstStartColumn specifies the column at which \p Code starts.
+/// * \p NextStartColumn specifies the additional indent dictated by the
+/// surrounding code. It is applied to the rest of the lines of \p Code.
+/// * \p LastStartColumn specifies the column at which the last line of
+/// \p Code should end, in case the last line is an empty line.
+///
+/// In the case where the last line of the fragment contains content,
+/// the fragment ends at the end of that content and \p LastStartColumn is
+/// not taken into account, for example in:
+///
+/// void block() {
+/// string inner = R"(name: value)";
+/// }
+///
+/// Each range is extended on either end to its next bigger logic unit, i.e.
+/// everything that might influence its formatting or might be influenced by its
+/// formatting.
+///
+/// Returns a pair P, where:
+/// * P.first are the ``Replacements`` necessary to make all \p Ranges comply
+/// with \p Style.
+/// * P.second is the penalty induced by formatting the fragment \p Code.
+/// If the formatting of the fragment doesn't have a notion of penalty,
+/// returns 0.
+///
+/// If ``Status`` is non-null, its value will be populated with the status of
+/// this formatting attempt. See \c FormattingAttemptStatus.
+std::pair<tooling::Replacements, unsigned>
+reformat(const FormatStyle &Style, StringRef Code,
+ ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn,
+ unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName,
+ FormattingAttemptStatus *Status);
+
+} // namespace internal
+} // namespace format
+} // namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Format/FormatToken.cpp b/contrib/llvm/tools/clang/lib/Format/FormatToken.cpp
index ba5bf03a63464..10ac392abbf2f 100644
--- a/contrib/llvm/tools/clang/lib/Format/FormatToken.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/FormatToken.cpp
@@ -25,10 +25,9 @@ namespace format {
const char *getTokenTypeName(TokenType Type) {
static const char *const TokNames[] = {
#define TYPE(X) #X,
-LIST_TOKEN_TYPES
+ LIST_TOKEN_TYPES
#undef TYPE
- nullptr
- };
+ nullptr};
if (Type < NUM_TOKEN_TYPES)
return TokNames[Type];
@@ -52,6 +51,7 @@ bool FormatToken::isSimpleTypeSpecifier() const {
case tok::kw_half:
case tok::kw_float:
case tok::kw_double:
+ case tok::kw__Float16:
case tok::kw___float128:
case tok::kw_wchar_t:
case tok::kw_bool:
diff --git a/contrib/llvm/tools/clang/lib/Format/FormatToken.h b/contrib/llvm/tools/clang/lib/Format/FormatToken.h
index a60361a8e5fa9..3dc0ab0e7cca2 100644
--- a/contrib/llvm/tools/clang/lib/Format/FormatToken.h
+++ b/contrib/llvm/tools/clang/lib/Format/FormatToken.h
@@ -26,78 +26,79 @@
namespace clang {
namespace format {
-#define LIST_TOKEN_TYPES \
- TYPE(ArrayInitializerLSquare) \
- TYPE(ArraySubscriptLSquare) \
- TYPE(AttributeParen) \
- TYPE(BinaryOperator) \
- TYPE(BitFieldColon) \
- TYPE(BlockComment) \
- TYPE(CastRParen) \
- TYPE(ConditionalExpr) \
- TYPE(ConflictAlternative) \
- TYPE(ConflictEnd) \
- TYPE(ConflictStart) \
- TYPE(CtorInitializerColon) \
- TYPE(CtorInitializerComma) \
- TYPE(DesignatedInitializerLSquare) \
- TYPE(DesignatedInitializerPeriod) \
- TYPE(DictLiteral) \
- TYPE(ForEachMacro) \
- TYPE(FunctionAnnotationRParen) \
- TYPE(FunctionDeclarationName) \
- TYPE(FunctionLBrace) \
- TYPE(FunctionTypeLParen) \
- TYPE(ImplicitStringLiteral) \
- TYPE(InheritanceColon) \
- TYPE(InheritanceComma) \
- TYPE(InlineASMBrace) \
- TYPE(InlineASMColon) \
- TYPE(JavaAnnotation) \
- TYPE(JsComputedPropertyName) \
- TYPE(JsExponentiation) \
- TYPE(JsExponentiationEqual) \
- TYPE(JsFatArrow) \
- TYPE(JsNonNullAssertion) \
- TYPE(JsTypeColon) \
- TYPE(JsTypeOperator) \
- TYPE(JsTypeOptionalQuestion) \
- TYPE(LambdaArrow) \
- TYPE(LambdaLSquare) \
- TYPE(LeadingJavaAnnotation) \
- TYPE(LineComment) \
- TYPE(MacroBlockBegin) \
- TYPE(MacroBlockEnd) \
- TYPE(ObjCBlockLBrace) \
- TYPE(ObjCBlockLParen) \
- TYPE(ObjCDecl) \
- TYPE(ObjCForIn) \
- TYPE(ObjCMethodExpr) \
- TYPE(ObjCMethodSpecifier) \
- TYPE(ObjCProperty) \
- TYPE(ObjCStringLiteral) \
- TYPE(OverloadedOperator) \
- TYPE(OverloadedOperatorLParen) \
- TYPE(PointerOrReference) \
- TYPE(PureVirtualSpecifier) \
- TYPE(RangeBasedForLoopColon) \
- TYPE(RegexLiteral) \
- TYPE(SelectorName) \
- TYPE(StartOfName) \
- TYPE(TemplateCloser) \
- TYPE(TemplateOpener) \
- TYPE(TemplateString) \
- TYPE(TrailingAnnotation) \
- TYPE(TrailingReturnArrow) \
- TYPE(TrailingUnaryOperator) \
- TYPE(UnaryOperator) \
+#define LIST_TOKEN_TYPES \
+ TYPE(ArrayInitializerLSquare) \
+ TYPE(ArraySubscriptLSquare) \
+ TYPE(AttributeParen) \
+ TYPE(BinaryOperator) \
+ TYPE(BitFieldColon) \
+ TYPE(BlockComment) \
+ TYPE(CastRParen) \
+ TYPE(ConditionalExpr) \
+ TYPE(ConflictAlternative) \
+ TYPE(ConflictEnd) \
+ TYPE(ConflictStart) \
+ TYPE(CtorInitializerColon) \
+ TYPE(CtorInitializerComma) \
+ TYPE(DesignatedInitializerLSquare) \
+ TYPE(DesignatedInitializerPeriod) \
+ TYPE(DictLiteral) \
+ TYPE(ForEachMacro) \
+ TYPE(FunctionAnnotationRParen) \
+ TYPE(FunctionDeclarationName) \
+ TYPE(FunctionLBrace) \
+ TYPE(FunctionTypeLParen) \
+ TYPE(ImplicitStringLiteral) \
+ TYPE(InheritanceColon) \
+ TYPE(InheritanceComma) \
+ TYPE(InlineASMBrace) \
+ TYPE(InlineASMColon) \
+ TYPE(JavaAnnotation) \
+ TYPE(JsComputedPropertyName) \
+ TYPE(JsExponentiation) \
+ TYPE(JsExponentiationEqual) \
+ TYPE(JsFatArrow) \
+ TYPE(JsNonNullAssertion) \
+ TYPE(JsTypeColon) \
+ TYPE(JsTypeOperator) \
+ TYPE(JsTypeOptionalQuestion) \
+ TYPE(LambdaArrow) \
+ TYPE(LambdaLSquare) \
+ TYPE(LeadingJavaAnnotation) \
+ TYPE(LineComment) \
+ TYPE(MacroBlockBegin) \
+ TYPE(MacroBlockEnd) \
+ TYPE(ObjCBlockLBrace) \
+ TYPE(ObjCBlockLParen) \
+ TYPE(ObjCDecl) \
+ TYPE(ObjCForIn) \
+ TYPE(ObjCMethodExpr) \
+ TYPE(ObjCMethodSpecifier) \
+ TYPE(ObjCProperty) \
+ TYPE(ObjCStringLiteral) \
+ TYPE(OverloadedOperator) \
+ TYPE(OverloadedOperatorLParen) \
+ TYPE(PointerOrReference) \
+ TYPE(PureVirtualSpecifier) \
+ TYPE(RangeBasedForLoopColon) \
+ TYPE(RegexLiteral) \
+ TYPE(SelectorName) \
+ TYPE(StartOfName) \
+ TYPE(StructuredBindingLSquare) \
+ TYPE(TemplateCloser) \
+ TYPE(TemplateOpener) \
+ TYPE(TemplateString) \
+ TYPE(TrailingAnnotation) \
+ TYPE(TrailingReturnArrow) \
+ TYPE(TrailingUnaryOperator) \
+ TYPE(UnaryOperator) \
TYPE(Unknown)
enum TokenType {
#define TYPE(X) TT_##X,
-LIST_TOKEN_TYPES
+ LIST_TOKEN_TYPES
#undef TYPE
- NUM_TOKEN_TYPES
+ NUM_TOKEN_TYPES
};
/// \brief Determines the name of a token type.
@@ -340,10 +341,11 @@ struct FormatToken {
bool isSimpleTypeSpecifier() const;
bool isObjCAccessSpecifier() const {
- return is(tok::at) && Next && (Next->isObjCAtKeyword(tok::objc_public) ||
- Next->isObjCAtKeyword(tok::objc_protected) ||
- Next->isObjCAtKeyword(tok::objc_package) ||
- Next->isObjCAtKeyword(tok::objc_private));
+ return is(tok::at) && Next &&
+ (Next->isObjCAtKeyword(tok::objc_public) ||
+ Next->isObjCAtKeyword(tok::objc_protected) ||
+ Next->isObjCAtKeyword(tok::objc_package) ||
+ Next->isObjCAtKeyword(tok::objc_private));
}
/// \brief Returns whether \p Tok is ([{ or a template opening <.
@@ -471,6 +473,19 @@ struct FormatToken {
Style.Language == FormatStyle::LK_TextProto));
}
+ /// \brief Returns whether the token is the left square bracket of a C++
+ /// structured binding declaration.
+ bool isCppStructuredBinding(const FormatStyle &Style) const {
+ if (!Style.isCpp() || isNot(tok::l_square))
+ return false;
+ const FormatToken *T = this;
+ do {
+ T = T->getPreviousNonComment();
+ } while (T && T->isOneOf(tok::kw_const, tok::kw_volatile, tok::amp,
+ tok::ampamp));
+ return T && T->is(tok::kw_auto);
+ }
+
/// \brief Same as opensBlockOrBlockTypeList, but for the closing token.
bool closesBlockOrBlockTypeList(const FormatStyle &Style) const {
if (is(TT_TemplateString) && closesScope())
@@ -503,15 +518,13 @@ private:
return is(K1) && Next && Next->startsSequenceInternal(Tokens...);
}
- template <typename A>
- bool startsSequenceInternal(A K1) const {
+ template <typename A> bool startsSequenceInternal(A K1) const {
if (is(tok::comment) && Next)
return Next->startsSequenceInternal(K1);
return is(K1);
}
- template <typename A, typename... Ts>
- bool endsSequenceInternal(A K1) const {
+ template <typename A, typename... Ts> bool endsSequenceInternal(A K1) const {
if (is(tok::comment) && Previous)
return Previous->endsSequenceInternal(K1);
return is(K1);
@@ -644,6 +657,7 @@ struct AdditionalKeywords {
kw_readonly = &IdentTable.get("readonly");
kw_set = &IdentTable.get("set");
kw_type = &IdentTable.get("type");
+ kw_typeof = &IdentTable.get("typeof");
kw_var = &IdentTable.get("var");
kw_yield = &IdentTable.get("yield");
@@ -680,7 +694,7 @@ struct AdditionalKeywords {
JsExtraKeywords = std::unordered_set<IdentifierInfo *>(
{kw_as, kw_async, kw_await, kw_declare, kw_finally, kw_from,
kw_function, kw_get, kw_import, kw_is, kw_let, kw_module, kw_readonly,
- kw_set, kw_type, kw_var, kw_yield,
+ kw_set, kw_type, kw_typeof, kw_var, kw_yield,
// Keywords from the Java section.
kw_abstract, kw_extends, kw_implements, kw_instanceof, kw_interface});
}
@@ -714,6 +728,7 @@ struct AdditionalKeywords {
IdentifierInfo *kw_readonly;
IdentifierInfo *kw_set;
IdentifierInfo *kw_type;
+ IdentifierInfo *kw_typeof;
IdentifierInfo *kw_var;
IdentifierInfo *kw_yield;
diff --git a/contrib/llvm/tools/clang/lib/Format/FormatTokenLexer.cpp b/contrib/llvm/tools/clang/lib/Format/FormatTokenLexer.cpp
index 45c3ae1afe5fe..199d2974c5c74 100644
--- a/contrib/llvm/tools/clang/lib/Format/FormatTokenLexer.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/FormatTokenLexer.cpp
@@ -24,10 +24,10 @@ namespace clang {
namespace format {
FormatTokenLexer::FormatTokenLexer(const SourceManager &SourceMgr, FileID ID,
- const FormatStyle &Style,
+ unsigned Column, const FormatStyle &Style,
encoding::Encoding Encoding)
: FormatTok(nullptr), IsFirstToken(true), StateStack({LexerState::NORMAL}),
- Column(0), TrailingWhitespace(0), SourceMgr(SourceMgr), ID(ID),
+ Column(Column), TrailingWhitespace(0), SourceMgr(SourceMgr), ID(ID),
Style(Style), IdentTable(getFormattingLangOpts(Style)),
Keywords(IdentTable), Encoding(Encoding), FirstInLineIndex(0),
FormattingDisabled(false), MacroBlockBeginRegex(Style.MacroBlockBegin),
@@ -50,6 +50,8 @@ ArrayRef<FormatToken *> FormatTokenLexer::lex() {
tryParseJSRegexLiteral();
handleTemplateStrings();
}
+ if (Style.Language == FormatStyle::LK_TextProto)
+ tryParsePythonComment();
tryMergePreviousTokens();
if (Tokens.back()->NewlinesBefore > 0 || Tokens.back()->IsMultiline)
FirstInLineIndex = Tokens.size() - 1;
@@ -96,14 +98,8 @@ void FormatTokenLexer::tryMergePreviousTokens() {
}
if (Style.Language == FormatStyle::LK_Java) {
- static const tok::TokenKind JavaRightLogicalShift[] = {tok::greater,
- tok::greater,
- tok::greater};
- static const tok::TokenKind JavaRightLogicalShiftAssign[] = {tok::greater,
- tok::greater,
- tok::greaterequal};
- if (tryMergeTokens(JavaRightLogicalShift, TT_BinaryOperator))
- return;
+ static const tok::TokenKind JavaRightLogicalShiftAssign[] = {
+ tok::greater, tok::greater, tok::greaterequal};
if (tryMergeTokens(JavaRightLogicalShiftAssign, TT_BinaryOperator))
return;
}
@@ -162,9 +158,8 @@ bool FormatTokenLexer::tryMergeTokens(ArrayRef<tok::TokenKind> Kinds,
return false;
unsigned AddLength = 0;
for (unsigned i = 1; i < Kinds.size(); ++i) {
- if (!First[i]->is(Kinds[i]) ||
- First[i]->WhitespaceRange.getBegin() !=
- First[i]->WhitespaceRange.getEnd())
+ if (!First[i]->is(Kinds[i]) || First[i]->WhitespaceRange.getBegin() !=
+ First[i]->WhitespaceRange.getEnd())
return false;
AddLength += First[i]->TokenText.size();
}
@@ -337,6 +332,27 @@ void FormatTokenLexer::handleTemplateStrings() {
resetLexer(SourceMgr.getFileOffset(loc));
}
+void FormatTokenLexer::tryParsePythonComment() {
+ FormatToken *HashToken = Tokens.back();
+ if (HashToken->isNot(tok::hash))
+ return;
+ // Turn the remainder of this line into a comment.
+ const char *CommentBegin =
+ Lex->getBufferLocation() - HashToken->TokenText.size(); // at "#"
+ size_t From = CommentBegin - Lex->getBuffer().begin();
+ size_t To = Lex->getBuffer().find_first_of('\n', From);
+ if (To == StringRef::npos)
+ To = Lex->getBuffer().size();
+ size_t Len = To - From;
+ HashToken->Type = TT_LineComment;
+ HashToken->Tok.setKind(tok::comment);
+ HashToken->TokenText = Lex->getBuffer().substr(From, Len);
+ SourceLocation Loc = To < Lex->getBuffer().size()
+ ? Lex->getSourceLocation(CommentBegin + Len)
+ : SourceMgr.getLocForEndOfFile(ID);
+ resetLexer(SourceMgr.getFileOffset(Loc));
+}
+
bool FormatTokenLexer::tryMerge_TMacro() {
if (Tokens.size() < 4)
return false;
@@ -529,17 +545,53 @@ FormatToken *FormatTokenLexer::getNextToken() {
readRawToken(*FormatTok);
}
+ // JavaScript and Java do not allow to escape the end of the line with a
+ // backslash. Backslashes are syntax errors in plain source, but can occur in
+ // comments. When a single line comment ends with a \, it'll cause the next
+ // line of code to be lexed as a comment, breaking formatting. The code below
+ // finds comments that contain a backslash followed by a line break, truncates
+ // the comment token at the backslash, and resets the lexer to restart behind
+ // the backslash.
+ if ((Style.Language == FormatStyle::LK_JavaScript ||
+ Style.Language == FormatStyle::LK_Java) &&
+ FormatTok->is(tok::comment) && FormatTok->TokenText.startswith("//")) {
+ size_t BackslashPos = FormatTok->TokenText.find('\\');
+ while (BackslashPos != StringRef::npos) {
+ if (BackslashPos + 1 < FormatTok->TokenText.size() &&
+ FormatTok->TokenText[BackslashPos + 1] == '\n') {
+ const char *Offset = Lex->getBufferLocation();
+ Offset -= FormatTok->TokenText.size();
+ Offset += BackslashPos + 1;
+ resetLexer(SourceMgr.getFileOffset(Lex->getSourceLocation(Offset)));
+ FormatTok->TokenText = FormatTok->TokenText.substr(0, BackslashPos + 1);
+ FormatTok->ColumnWidth = encoding::columnWidthWithTabs(
+ FormatTok->TokenText, FormatTok->OriginalColumn, Style.TabWidth,
+ Encoding);
+ break;
+ }
+ BackslashPos = FormatTok->TokenText.find('\\', BackslashPos + 1);
+ }
+ }
+
// In case the token starts with escaped newlines, we want to
// take them into account as whitespace - this pattern is quite frequent
// in macro definitions.
// FIXME: Add a more explicit test.
- while (FormatTok->TokenText.size() > 1 && FormatTok->TokenText[0] == '\\' &&
- FormatTok->TokenText[1] == '\n') {
+ while (FormatTok->TokenText.size() > 1 && FormatTok->TokenText[0] == '\\') {
+ unsigned SkippedWhitespace = 0;
+ if (FormatTok->TokenText.size() > 2 &&
+ (FormatTok->TokenText[1] == '\r' && FormatTok->TokenText[2] == '\n'))
+ SkippedWhitespace = 3;
+ else if (FormatTok->TokenText[1] == '\n')
+ SkippedWhitespace = 2;
+ else
+ break;
+
++FormatTok->NewlinesBefore;
- WhitespaceLength += 2;
- FormatTok->LastNewlineOffset = 2;
+ WhitespaceLength += SkippedWhitespace;
+ FormatTok->LastNewlineOffset = SkippedWhitespace;
Column = 0;
- FormatTok->TokenText = FormatTok->TokenText.substr(2);
+ FormatTok->TokenText = FormatTok->TokenText.substr(SkippedWhitespace);
}
FormatTok->WhitespaceRange = SourceRange(
diff --git a/contrib/llvm/tools/clang/lib/Format/FormatTokenLexer.h b/contrib/llvm/tools/clang/lib/Format/FormatTokenLexer.h
index bf10f09cd11e1..59dc2a752f1f3 100644
--- a/contrib/llvm/tools/clang/lib/Format/FormatTokenLexer.h
+++ b/contrib/llvm/tools/clang/lib/Format/FormatTokenLexer.h
@@ -36,7 +36,7 @@ enum LexerState {
class FormatTokenLexer {
public:
- FormatTokenLexer(const SourceManager &SourceMgr, FileID ID,
+ FormatTokenLexer(const SourceManager &SourceMgr, FileID ID, unsigned Column,
const FormatStyle &Style, encoding::Encoding Encoding);
ArrayRef<FormatToken *> lex();
@@ -73,6 +73,8 @@ private:
// nested template parts by balancing curly braces.
void handleTemplateStrings();
+ void tryParsePythonComment();
+
bool tryMerge_TMacro();
bool tryMergeConflictMarkers();
diff --git a/contrib/llvm/tools/clang/lib/Format/NamespaceEndCommentsFixer.cpp b/contrib/llvm/tools/clang/lib/Format/NamespaceEndCommentsFixer.cpp
index 85b70b8c0a768..df99bb2e13819 100644
--- a/contrib/llvm/tools/clang/lib/Format/NamespaceEndCommentsFixer.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/NamespaceEndCommentsFixer.cpp
@@ -118,6 +118,12 @@ getNamespaceToken(const AnnotatedLine *line,
return nullptr;
assert(StartLineIndex < AnnotatedLines.size());
const FormatToken *NamespaceTok = AnnotatedLines[StartLineIndex]->First;
+ if (NamespaceTok->is(tok::l_brace)) {
+ // "namespace" keyword can be on the line preceding '{', e.g. in styles
+ // where BraceWrapping.AfterNamespace is true.
+ if (StartLineIndex > 0)
+ NamespaceTok = AnnotatedLines[StartLineIndex - 1]->First;
+ }
// Detect "(inline)? namespace" in the beginning of a line.
if (NamespaceTok->is(tok::kw_inline))
NamespaceTok = NamespaceTok->getNextNonComment();
@@ -131,7 +137,7 @@ NamespaceEndCommentsFixer::NamespaceEndCommentsFixer(const Environment &Env,
const FormatStyle &Style)
: TokenAnalyzer(Env, Style) {}
-tooling::Replacements NamespaceEndCommentsFixer::analyze(
+std::pair<tooling::Replacements, unsigned> NamespaceEndCommentsFixer::analyze(
TokenAnnotator &Annotator, SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
FormatTokenLexer &Tokens) {
const SourceManager &SourceMgr = Env.getSourceManager();
@@ -200,7 +206,7 @@ tooling::Replacements NamespaceEndCommentsFixer::analyze(
}
StartLineIndex = SIZE_MAX;
}
- return Fixes;
+ return {Fixes, 0};
}
} // namespace format
diff --git a/contrib/llvm/tools/clang/lib/Format/NamespaceEndCommentsFixer.h b/contrib/llvm/tools/clang/lib/Format/NamespaceEndCommentsFixer.h
index 7790668a2e829..4779f0d27c927 100644
--- a/contrib/llvm/tools/clang/lib/Format/NamespaceEndCommentsFixer.h
+++ b/contrib/llvm/tools/clang/lib/Format/NamespaceEndCommentsFixer.h
@@ -25,7 +25,7 @@ class NamespaceEndCommentsFixer : public TokenAnalyzer {
public:
NamespaceEndCommentsFixer(const Environment &Env, const FormatStyle &Style);
- tooling::Replacements
+ std::pair<tooling::Replacements, unsigned>
analyze(TokenAnnotator &Annotator,
SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
FormatTokenLexer &Tokens) override;
diff --git a/contrib/llvm/tools/clang/lib/Format/SortJavaScriptImports.cpp b/contrib/llvm/tools/clang/lib/Format/SortJavaScriptImports.cpp
index e73695ca84770..d0b979e100d5d 100644
--- a/contrib/llvm/tools/clang/lib/Format/SortJavaScriptImports.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/SortJavaScriptImports.cpp
@@ -123,7 +123,7 @@ public:
: TokenAnalyzer(Env, Style),
FileContents(Env.getSourceManager().getBufferData(Env.getFileID())) {}
- tooling::Replacements
+ std::pair<tooling::Replacements, unsigned>
analyze(TokenAnnotator &Annotator,
SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
FormatTokenLexer &Tokens) override {
@@ -138,7 +138,7 @@ public:
parseModuleReferences(Keywords, AnnotatedLines);
if (References.empty())
- return Result;
+ return {Result, 0};
SmallVector<unsigned, 16> Indices;
for (unsigned i = 0, e = References.size(); i != e; ++i)
@@ -168,7 +168,7 @@ public:
}
if (ReferencesInOrder && SymbolsInOrder)
- return Result;
+ return {Result, 0};
SourceRange InsertionPoint = References[0].Range;
InsertionPoint.setEnd(References[References.size() - 1].Range.getEnd());
@@ -202,7 +202,7 @@ public:
assert(false);
}
- return Result;
+ return {Result, 0};
}
private:
@@ -277,7 +277,7 @@ private:
// Parses module references in the given lines. Returns the module references,
// and a pointer to the first "main code" line if that is adjacent to the
// affected lines of module references, nullptr otherwise.
- std::pair<SmallVector<JsModuleReference, 16>, AnnotatedLine*>
+ std::pair<SmallVector<JsModuleReference, 16>, AnnotatedLine *>
parseModuleReferences(const AdditionalKeywords &Keywords,
SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
SmallVector<JsModuleReference, 16> References;
@@ -413,7 +413,7 @@ private:
nextToken();
if (Current->is(tok::r_brace))
break;
- if (Current->isNot(tok::identifier))
+ if (!Current->isOneOf(tok::identifier, tok::kw_default))
return false;
JsImportedSymbol Symbol;
@@ -425,7 +425,7 @@ private:
if (Current->is(Keywords.kw_as)) {
nextToken();
- if (Current->isNot(tok::identifier))
+ if (!Current->isOneOf(tok::identifier, tok::kw_default))
return false;
Symbol.Alias = Current->TokenText;
nextToken();
@@ -449,7 +449,7 @@ tooling::Replacements sortJavaScriptImports(const FormatStyle &Style,
std::unique_ptr<Environment> Env =
Environment::CreateVirtualEnvironment(Code, FileName, Ranges);
JavaScriptImportSorter Sorter(*Env, Style);
- return Sorter.process();
+ return Sorter.process().first;
}
} // end namespace format
diff --git a/contrib/llvm/tools/clang/lib/Format/TokenAnalyzer.cpp b/contrib/llvm/tools/clang/lib/Format/TokenAnalyzer.cpp
index f2e4e8ef08197..d1dfb1fea32b6 100644
--- a/contrib/llvm/tools/clang/lib/Format/TokenAnalyzer.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/TokenAnalyzer.cpp
@@ -38,7 +38,10 @@ namespace format {
// Code.
std::unique_ptr<Environment>
Environment::CreateVirtualEnvironment(StringRef Code, StringRef FileName,
- ArrayRef<tooling::Range> Ranges) {
+ ArrayRef<tooling::Range> Ranges,
+ unsigned FirstStartColumn,
+ unsigned NextStartColumn,
+ unsigned LastStartColumn) {
// This is referenced by `FileMgr` and will be released by `FileMgr` when it
// is deleted.
IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
@@ -57,8 +60,9 @@ Environment::CreateVirtualEnvironment(StringRef Code, StringRef FileName,
std::unique_ptr<SourceManager> VirtualSM(
new SourceManager(*Diagnostics, *FileMgr));
InMemoryFileSystem->addFile(
- FileName, 0, llvm::MemoryBuffer::getMemBuffer(
- Code, FileName, /*RequiresNullTerminator=*/false));
+ FileName, 0,
+ llvm::MemoryBuffer::getMemBuffer(Code, FileName,
+ /*RequiresNullTerminator=*/false));
FileID ID = VirtualSM->createFileID(FileMgr->getFile(FileName),
SourceLocation(), clang::SrcMgr::C_User);
assert(ID.isValid());
@@ -69,9 +73,9 @@ Environment::CreateVirtualEnvironment(StringRef Code, StringRef FileName,
SourceLocation End = Start.getLocWithOffset(Range.getLength());
CharRanges.push_back(CharSourceRange::getCharRange(Start, End));
}
- return llvm::make_unique<Environment>(ID, std::move(FileMgr),
- std::move(VirtualSM),
- std::move(Diagnostics), CharRanges);
+ return llvm::make_unique<Environment>(
+ ID, std::move(FileMgr), std::move(VirtualSM), std::move(Diagnostics),
+ CharRanges, FirstStartColumn, NextStartColumn, LastStartColumn);
}
TokenAnalyzer::TokenAnalyzer(const Environment &Env, const FormatStyle &Style)
@@ -88,14 +92,16 @@ TokenAnalyzer::TokenAnalyzer(const Environment &Env, const FormatStyle &Style)
<< "\n");
}
-tooling::Replacements TokenAnalyzer::process() {
+std::pair<tooling::Replacements, unsigned> TokenAnalyzer::process() {
tooling::Replacements Result;
- FormatTokenLexer Tokens(Env.getSourceManager(), Env.getFileID(), Style,
- Encoding);
+ FormatTokenLexer Tokens(Env.getSourceManager(), Env.getFileID(),
+ Env.getFirstStartColumn(), Style, Encoding);
- UnwrappedLineParser Parser(Style, Tokens.getKeywords(), Tokens.lex(), *this);
+ UnwrappedLineParser Parser(Style, Tokens.getKeywords(),
+ Env.getFirstStartColumn(), Tokens.lex(), *this);
Parser.parse();
assert(UnwrappedLines.rbegin()->empty());
+ unsigned Penalty = 0;
for (unsigned Run = 0, RunE = UnwrappedLines.size(); Run + 1 != RunE; ++Run) {
DEBUG(llvm::dbgs() << "Run " << Run << "...\n");
SmallVector<AnnotatedLine *, 16> AnnotatedLines;
@@ -106,13 +112,13 @@ tooling::Replacements TokenAnalyzer::process() {
Annotator.annotate(*AnnotatedLines.back());
}
- tooling::Replacements RunResult =
+ std::pair<tooling::Replacements, unsigned> RunResult =
analyze(Annotator, AnnotatedLines, Tokens);
DEBUG({
llvm::dbgs() << "Replacements for run " << Run << ":\n";
- for (tooling::Replacements::const_iterator I = RunResult.begin(),
- E = RunResult.end();
+ for (tooling::Replacements::const_iterator I = RunResult.first.begin(),
+ E = RunResult.first.end();
I != E; ++I) {
llvm::dbgs() << I->toString() << "\n";
}
@@ -120,17 +126,19 @@ tooling::Replacements TokenAnalyzer::process() {
for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
delete AnnotatedLines[i];
}
- for (const auto &R : RunResult) {
+
+ Penalty += RunResult.second;
+ for (const auto &R : RunResult.first) {
auto Err = Result.add(R);
// FIXME: better error handling here. For now, simply return an empty
// Replacements to indicate failure.
if (Err) {
llvm::errs() << llvm::toString(std::move(Err)) << "\n";
- return tooling::Replacements();
+ return {tooling::Replacements(), 0};
}
}
}
- return Result;
+ return {Result, Penalty};
}
void TokenAnalyzer::consumeUnwrappedLine(const UnwrappedLine &TheLine) {
diff --git a/contrib/llvm/tools/clang/lib/Format/TokenAnalyzer.h b/contrib/llvm/tools/clang/lib/Format/TokenAnalyzer.h
index 78a3d1bc8d9e5..96ea00b25ba1b 100644
--- a/contrib/llvm/tools/clang/lib/Format/TokenAnalyzer.h
+++ b/contrib/llvm/tools/clang/lib/Format/TokenAnalyzer.h
@@ -37,21 +37,37 @@ namespace format {
class Environment {
public:
Environment(SourceManager &SM, FileID ID, ArrayRef<CharSourceRange> Ranges)
- : ID(ID), CharRanges(Ranges.begin(), Ranges.end()), SM(SM) {}
+ : ID(ID), CharRanges(Ranges.begin(), Ranges.end()), SM(SM),
+ FirstStartColumn(0),
+ NextStartColumn(0),
+ LastStartColumn(0) {}
Environment(FileID ID, std::unique_ptr<FileManager> FileMgr,
std::unique_ptr<SourceManager> VirtualSM,
std::unique_ptr<DiagnosticsEngine> Diagnostics,
- const std::vector<CharSourceRange> &CharRanges)
+ const std::vector<CharSourceRange> &CharRanges,
+ unsigned FirstStartColumn,
+ unsigned NextStartColumn,
+ unsigned LastStartColumn)
: ID(ID), CharRanges(CharRanges.begin(), CharRanges.end()),
- SM(*VirtualSM), FileMgr(std::move(FileMgr)),
+ SM(*VirtualSM),
+ FirstStartColumn(FirstStartColumn),
+ NextStartColumn(NextStartColumn),
+ LastStartColumn(LastStartColumn),
+ FileMgr(std::move(FileMgr)),
VirtualSM(std::move(VirtualSM)), Diagnostics(std::move(Diagnostics)) {}
- // This sets up an virtual file system with file \p FileName containing \p
- // Code.
+ // This sets up an virtual file system with file \p FileName containing the
+ // fragment \p Code. Assumes that \p Code starts at \p FirstStartColumn,
+ // that the next lines of \p Code should start at \p NextStartColumn, and
+ // that \p Code should end at \p LastStartColumn if it ends in newline.
+ // See also the documentation of clang::format::internal::reformat.
static std::unique_ptr<Environment>
CreateVirtualEnvironment(StringRef Code, StringRef FileName,
- ArrayRef<tooling::Range> Ranges);
+ ArrayRef<tooling::Range> Ranges,
+ unsigned FirstStartColumn = 0,
+ unsigned NextStartColumn = 0,
+ unsigned LastStartColumn = 0);
FileID getFileID() const { return ID; }
@@ -59,10 +75,25 @@ public:
const SourceManager &getSourceManager() const { return SM; }
+ // Returns the column at which the fragment of code managed by this
+ // environment starts.
+ unsigned getFirstStartColumn() const { return FirstStartColumn; }
+
+ // Returns the column at which subsequent lines of the fragment of code
+ // managed by this environment should start.
+ unsigned getNextStartColumn() const { return NextStartColumn; }
+
+ // Returns the column at which the fragment of code managed by this
+ // environment should end if it ends in a newline.
+ unsigned getLastStartColumn() const { return LastStartColumn; }
+
private:
FileID ID;
SmallVector<CharSourceRange, 8> CharRanges;
SourceManager &SM;
+ unsigned FirstStartColumn;
+ unsigned NextStartColumn;
+ unsigned LastStartColumn;
// The order of these fields are important - they should be in the same order
// as they are created in `CreateVirtualEnvironment` so that they can be
@@ -76,10 +107,10 @@ class TokenAnalyzer : public UnwrappedLineConsumer {
public:
TokenAnalyzer(const Environment &Env, const FormatStyle &Style);
- tooling::Replacements process();
+ std::pair<tooling::Replacements, unsigned> process();
protected:
- virtual tooling::Replacements
+ virtual std::pair<tooling::Replacements, unsigned>
analyze(TokenAnnotator &Annotator,
SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
FormatTokenLexer &Tokens) = 0;
diff --git a/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.cpp b/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.cpp
index 46ea06b880ed2..298c72b002f8b 100644
--- a/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.cpp
@@ -47,7 +47,7 @@ private:
if (NonTemplateLess.count(CurrentToken->Previous))
return false;
- const FormatToken& Previous = *CurrentToken->Previous;
+ const FormatToken &Previous = *CurrentToken->Previous; // The '<'.
if (Previous.Previous) {
if (Previous.Previous->Tok.isLiteral())
return false;
@@ -152,11 +152,11 @@ private:
// export type X = (...);
Contexts.back().IsExpression = false;
} else if (Left->Previous &&
- (Left->Previous->isOneOf(tok::kw_static_assert, tok::kw_decltype,
- tok::kw_if, tok::kw_while, tok::l_paren,
- tok::comma) ||
- Left->Previous->endsSequence(tok::kw_constexpr, tok::kw_if) ||
- Left->Previous->is(TT_BinaryOperator))) {
+ (Left->Previous->isOneOf(tok::kw_static_assert, tok::kw_decltype,
+ tok::kw_if, tok::kw_while, tok::l_paren,
+ tok::comma) ||
+ Left->Previous->endsSequence(tok::kw_constexpr, tok::kw_if) ||
+ Left->Previous->is(TT_BinaryOperator))) {
// static_assert, if and while usually contain expressions.
Contexts.back().IsExpression = true;
} else if (Style.Language == FormatStyle::LK_JavaScript && Left->Previous &&
@@ -325,8 +325,7 @@ private:
// In C++, this can happen either in array of templates (foo<int>[10])
// or when array is a nested template type (unique_ptr<type1<type2>[]>).
bool CppArrayTemplates =
- Style.isCpp() && Parent &&
- Parent->is(TT_TemplateCloser) &&
+ Style.isCpp() && Parent && Parent->is(TT_TemplateCloser) &&
(Contexts.back().CanBeExpression || Contexts.back().IsExpression ||
Contexts.back().InTemplateArgument);
@@ -343,7 +342,9 @@ private:
bool ColonFound = false;
unsigned BindingIncrease = 1;
- if (Left->is(TT_Unknown)) {
+ if (Left->isCppStructuredBinding(Style)) {
+ Left->Type = TT_StructuredBindingLSquare;
+ } else if (Left->is(TT_Unknown)) {
if (StartsObjCMethodExpr) {
Left->Type = TT_ObjCMethodExpr;
} else if (Style.Language == FormatStyle::LK_JavaScript && Parent &&
@@ -372,6 +373,10 @@ private:
ScopedContextCreator ContextCreator(*this, tok::l_square, BindingIncrease);
Contexts.back().IsExpression = true;
+ if (Style.Language == FormatStyle::LK_JavaScript && Parent &&
+ Parent->is(TT_JsTypeColon))
+ Contexts.back().IsExpression = false;
+
Contexts.back().ColonIsObjCMethodExpr = StartsObjCMethodExpr;
while (CurrentToken) {
@@ -439,6 +444,9 @@ private:
Contexts.back().ColonIsDictLiteral = true;
if (Left->BlockKind == BK_BracedInit)
Contexts.back().IsExpression = true;
+ if (Style.Language == FormatStyle::LK_JavaScript && Left->Previous &&
+ Left->Previous->is(TT_JsTypeColon))
+ Contexts.back().IsExpression = false;
while (CurrentToken) {
if (CurrentToken->is(tok::r_brace)) {
@@ -452,6 +460,8 @@ private:
updateParameterCount(Left, CurrentToken);
if (CurrentToken->isOneOf(tok::colon, tok::l_brace, tok::less)) {
FormatToken *Previous = CurrentToken->getPreviousNonComment();
+ if (Previous->is(TT_JsTypeOptionalQuestion))
+ Previous = Previous->getPreviousNonComment();
if (((CurrentToken->is(tok::colon) &&
(!Contexts.back().ColonIsDictLiteral || !Style.isCpp())) ||
Style.Language == FormatStyle::LK_Proto ||
@@ -531,8 +541,11 @@ private:
!Line.First->isOneOf(tok::kw_enum, tok::kw_case)) ||
Contexts.back().ContextKind == tok::l_paren || // function params
Contexts.back().ContextKind == tok::l_square || // array type
+ (!Contexts.back().IsExpression &&
+ Contexts.back().ContextKind == tok::l_brace) || // object type
(Contexts.size() == 1 &&
Line.MustBeDeclaration)) { // method/property declaration
+ Contexts.back().IsExpression = false;
Tok->Type = TT_JsTypeColon;
break;
}
@@ -593,7 +606,8 @@ private:
break;
case tok::kw_if:
case tok::kw_while:
- if (Tok->is(tok::kw_if) && CurrentToken && CurrentToken->is(tok::kw_constexpr))
+ if (Tok->is(tok::kw_if) && CurrentToken &&
+ CurrentToken->is(tok::kw_constexpr))
next();
if (CurrentToken && CurrentToken->is(tok::l_paren)) {
next();
@@ -603,7 +617,9 @@ private:
break;
case tok::kw_for:
if (Style.Language == FormatStyle::LK_JavaScript) {
- if (Tok->Previous && Tok->Previous->is(tok::period))
+ // x.for and {for: ...}
+ if ((Tok->Previous && Tok->Previous->is(tok::period)) ||
+ (Tok->Next && Tok->Next->is(tok::colon)))
break;
// JS' for await ( ...
if (CurrentToken && CurrentToken->is(Keywords.kw_await))
@@ -619,8 +635,7 @@ private:
// marks the first l_paren as a OverloadedOperatorLParen. Here, we make
// the first two parens OverloadedOperators and the second l_paren an
// OverloadedOperatorLParen.
- if (Tok->Previous &&
- Tok->Previous->is(tok::r_paren) &&
+ if (Tok->Previous && Tok->Previous->is(tok::r_paren) &&
Tok->Previous->MatchingParen &&
Tok->Previous->MatchingParen->is(TT_OverloadedOperatorLParen)) {
Tok->Previous->Type = TT_OverloadedOperator;
@@ -643,7 +658,7 @@ private:
break;
case tok::l_brace:
if (Style.Language == FormatStyle::LK_TextProto) {
- FormatToken *Previous =Tok->getPreviousNonComment();
+ FormatToken *Previous = Tok->getPreviousNonComment();
if (Previous && Previous->Type != TT_DictLiteral)
Previous->Type = TT_SelectorName;
}
@@ -683,7 +698,8 @@ private:
CurrentToken->Type = TT_PointerOrReference;
consumeToken();
if (CurrentToken &&
- CurrentToken->Previous->isOneOf(TT_BinaryOperator, tok::comma))
+ CurrentToken->Previous->isOneOf(TT_BinaryOperator, TT_UnaryOperator,
+ tok::comma))
CurrentToken->Previous->Type = TT_OverloadedOperator;
}
if (CurrentToken) {
@@ -740,8 +756,8 @@ private:
void parseIncludeDirective() {
if (CurrentToken && CurrentToken->is(tok::less)) {
- next();
- while (CurrentToken) {
+ next();
+ while (CurrentToken) {
// Mark tokens up to the trailing line comments as implicit string
// literals.
if (CurrentToken->isNot(tok::comment) &&
@@ -781,9 +797,9 @@ private:
void parseHasInclude() {
if (!CurrentToken || !CurrentToken->is(tok::l_paren))
return;
- next(); // '('
+ next(); // '('
parseIncludeDirective();
- next(); // ')'
+ next(); // ')'
}
LineType parsePreprocessorDirective() {
@@ -842,7 +858,7 @@ private:
if (Tok->is(tok::l_paren))
parseParens();
else if (Tok->isOneOf(Keywords.kw___has_include,
- Keywords.kw___has_include_next))
+ Keywords.kw___has_include_next))
parseHasInclude();
}
return Type;
@@ -855,7 +871,7 @@ public:
return parsePreprocessorDirective();
// Directly allow to 'import <string-literal>' to support protocol buffer
- // definitions (code.google.com/p/protobuf) or missing "#" (either way we
+ // definitions (github.com/google/protobuf) or missing "#" (either way we
// should not break the line).
IdentifierInfo *Info = CurrentToken->Tok.getIdentifierInfo();
if ((Style.Language == FormatStyle::LK_Java &&
@@ -933,11 +949,11 @@ private:
// FIXME: Closure-library specific stuff should not be hard-coded but be
// configurable.
return Tok.TokenText == "goog" && Tok.Next && Tok.Next->is(tok::period) &&
- Tok.Next->Next && (Tok.Next->Next->TokenText == "module" ||
- Tok.Next->Next->TokenText == "provide" ||
- Tok.Next->Next->TokenText == "require" ||
- Tok.Next->Next->TokenText == "setTestOnly" ||
- Tok.Next->Next->TokenText == "forwardDeclare") &&
+ Tok.Next->Next &&
+ (Tok.Next->Next->TokenText == "module" ||
+ Tok.Next->Next->TokenText == "provide" ||
+ Tok.Next->Next->TokenText == "require" ||
+ Tok.Next->Next->TokenText == "forwardDeclare") &&
Tok.Next->Next->Next && Tok.Next->Next->Next->is(tok::l_paren);
}
@@ -1054,8 +1070,7 @@ private:
Current.Previous->is(TT_CtorInitializerColon)) {
Contexts.back().IsExpression = true;
Contexts.back().InCtorInitializer = true;
- } else if (Current.Previous &&
- Current.Previous->is(TT_InheritanceColon)) {
+ } else if (Current.Previous && Current.Previous->is(TT_InheritanceColon)) {
Contexts.back().InInheritanceList = true;
} else if (Current.isOneOf(tok::r_paren, tok::greater, tok::comma)) {
for (FormatToken *Previous = Current.Previous;
@@ -1104,6 +1119,11 @@ private:
(!Line.MightBeFunctionDecl || Current.NestingLevel != 0)) {
Contexts.back().FirstStartOfName = &Current;
Current.Type = TT_StartOfName;
+ } else if (Current.is(tok::semi)) {
+ // Reset FirstStartOfName after finding a semicolon so that a for loop
+ // with multiple increment statements is not confused with a for loop
+ // having multiple variable declarations.
+ Contexts.back().FirstStartOfName = nullptr;
} else if (Current.isOneOf(tok::kw_auto, tok::kw___auto_type)) {
AutoFound = true;
} else if (Current.is(tok::arrow) &&
@@ -1113,10 +1133,10 @@ private:
Current.NestingLevel == 0) {
Current.Type = TT_TrailingReturnArrow;
} else if (Current.isOneOf(tok::star, tok::amp, tok::ampamp)) {
- Current.Type =
- determineStarAmpUsage(Current, Contexts.back().CanBeExpression &&
- Contexts.back().IsExpression,
- Contexts.back().InTemplateArgument);
+ Current.Type = determineStarAmpUsage(Current,
+ Contexts.back().CanBeExpression &&
+ Contexts.back().IsExpression,
+ Contexts.back().InTemplateArgument);
} else if (Current.isOneOf(tok::minus, tok::plus, tok::caret)) {
Current.Type = determinePlusMinusCaretUsage(Current);
if (Current.is(TT_UnaryOperator) && Current.is(tok::caret))
@@ -1396,11 +1416,13 @@ private:
if (NextToken->isOneOf(tok::comma, tok::semi))
return TT_PointerOrReference;
- if (PrevToken->is(tok::r_paren) && PrevToken->MatchingParen &&
- PrevToken->MatchingParen->Previous &&
- PrevToken->MatchingParen->Previous->isOneOf(tok::kw_typeof,
- tok::kw_decltype))
- return TT_PointerOrReference;
+ if (PrevToken->is(tok::r_paren) && PrevToken->MatchingParen) {
+ FormatToken *TokenBeforeMatchingParen =
+ PrevToken->MatchingParen->getPreviousNonComment();
+ if (TokenBeforeMatchingParen &&
+ TokenBeforeMatchingParen->isOneOf(tok::kw_typeof, tok::kw_decltype))
+ return TT_PointerOrReference;
+ }
if (PrevToken->Tok.isLiteral() ||
PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::kw_true,
@@ -1589,7 +1611,7 @@ private:
if (Current->is(TT_ConditionalExpr))
return prec::Conditional;
if (NextNonComment && Current->is(TT_SelectorName) &&
- (NextNonComment->is(TT_DictLiteral) ||
+ (NextNonComment->isOneOf(TT_DictLiteral, TT_JsTypeColon) ||
((Style.Language == FormatStyle::LK_Proto ||
Style.Language == FormatStyle::LK_TextProto) &&
NextNonComment->is(tok::less))))
@@ -1643,17 +1665,15 @@ private:
/// \brief Parse unary operator expressions and surround them with fake
/// parentheses if appropriate.
void parseUnaryOperator() {
- if (!Current || Current->isNot(TT_UnaryOperator)) {
- parse(PrecedenceArrowAndPeriod);
- return;
+ llvm::SmallVector<FormatToken *, 2> Tokens;
+ while (Current && Current->is(TT_UnaryOperator)) {
+ Tokens.push_back(Current);
+ next();
}
-
- FormatToken *Start = Current;
- next();
- parseUnaryOperator();
-
- // The actual precedence doesn't matter.
- addFakeParenthesis(Start, prec::Unknown);
+ parse(PrecedenceArrowAndPeriod);
+ for (FormatToken *Token : llvm::reverse(Tokens))
+ // The actual precedence doesn't matter.
+ addFakeParenthesis(Token, prec::Unknown);
}
void parseConditionalExpr() {
@@ -1722,7 +1742,7 @@ void TokenAnnotator::setCommentLineLevels(
static unsigned maxNestingDepth(const AnnotatedLine &Line) {
unsigned Result = 0;
- for (const auto* Tok = Line.First; Tok != nullptr; Tok = Tok->Next)
+ for (const auto *Tok = Line.First; Tok != nullptr; Tok = Tok->Next)
Result = std::max(Result, Tok->NestingLevel);
return Result;
}
@@ -1764,7 +1784,7 @@ void TokenAnnotator::annotate(AnnotatedLine &Line) {
// function declaration.
static bool isFunctionDeclarationName(const FormatToken &Current,
const AnnotatedLine &Line) {
- auto skipOperatorName = [](const FormatToken* Next) -> const FormatToken* {
+ auto skipOperatorName = [](const FormatToken *Next) -> const FormatToken * {
for (; Next; Next = Next->Next) {
if (Next->is(TT_OverloadedOperatorLParen))
return Next;
@@ -1772,8 +1792,8 @@ static bool isFunctionDeclarationName(const FormatToken &Current,
continue;
if (Next->isOneOf(tok::kw_new, tok::kw_delete)) {
// For 'new[]' and 'delete[]'.
- if (Next->Next && Next->Next->is(tok::l_square) &&
- Next->Next->Next && Next->Next->Next->is(tok::r_square))
+ if (Next->Next && Next->Next->is(tok::l_square) && Next->Next->Next &&
+ Next->Next->Next->is(tok::r_square))
Next = Next->Next->Next;
continue;
}
@@ -1872,7 +1892,8 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) {
}
Line.First->TotalLength =
- Line.First->IsMultiline ? Style.ColumnLimit : Line.First->ColumnWidth;
+ Line.First->IsMultiline ? Style.ColumnLimit
+ : Line.FirstStartColumn + Line.First->ColumnWidth;
FormatToken *Current = Line.First->Next;
bool InFunctionDecl = Line.MightBeFunctionDecl;
while (Current) {
@@ -2005,6 +2026,9 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
if ((Left.is(TT_TemplateString) && Left.TokenText.endswith("${")) ||
(Right.is(TT_TemplateString) && Right.TokenText.startswith("}")))
return 100;
+ // Prefer breaking call chains (".foo") over empty "{}", "[]" or "()".
+ if (Left.opensScope() && Right.closesScope())
+ return 200;
}
if (Right.is(tok::identifier) && Right.Next && Right.Next->is(TT_DictLiteral))
@@ -2049,7 +2073,8 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
if (Left.is(tok::comment))
return 1000;
- if (Left.isOneOf(TT_RangeBasedForLoopColon, TT_InheritanceColon, TT_CtorInitializerColon))
+ if (Left.isOneOf(TT_RangeBasedForLoopColon, TT_InheritanceColon,
+ TT_CtorInitializerColon))
return 2;
if (Right.isMemberAccess()) {
@@ -2107,8 +2132,8 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
Style.AlignAfterOpenBracket != FormatStyle::BAS_DontAlign)
return 100;
if (Left.is(tok::l_paren) && Left.Previous &&
- (Left.Previous->isOneOf(tok::kw_if, tok::kw_for)
- || Left.Previous->endsSequence(tok::kw_constexpr, tok::kw_if)))
+ (Left.Previous->isOneOf(tok::kw_if, tok::kw_for) ||
+ Left.Previous->endsSequence(tok::kw_constexpr, tok::kw_if)))
return 1000;
if (Left.is(tok::equal) && InFunctionDecl)
return 110;
@@ -2128,7 +2153,7 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
if (Left.isOneOf(tok::plus, tok::comma) && Left.Previous &&
Left.Previous->isLabelString() &&
(Left.NextOperator || Left.OperatorIndex != 0))
- return 45;
+ return 50;
if (Right.is(tok::plus) && Left.isLabelString() &&
(Right.NextOperator || Right.OperatorIndex != 0))
return 25;
@@ -2162,6 +2187,8 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
const FormatToken &Right) {
if (Left.is(tok::kw_return) && Right.isNot(tok::semi))
return true;
+ if (Left.is(Keywords.kw_assert) && Style.Language == FormatStyle::LK_Java)
+ return true;
if (Style.ObjCSpaceAfterProperty && Line.Type == LT_ObjCProperty &&
Left.Tok.getObjCKeywordID() == tok::objc_property)
return true;
@@ -2178,8 +2205,8 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
: Style.SpacesInParentheses;
if (Right.isOneOf(tok::semi, tok::comma))
return false;
- if (Right.is(tok::less) &&
- Line.Type == LT_ObjCDecl && Style.ObjCSpaceBeforeProtocolList)
+ if (Right.is(tok::less) && Line.Type == LT_ObjCDecl &&
+ Style.ObjCSpaceBeforeProtocolList)
return true;
if (Right.is(tok::less) && Left.is(tok::kw_template))
return Style.SpaceAfterTemplateKeyword;
@@ -2201,15 +2228,23 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
Left.Previous->is(tok::kw_case));
if (Left.is(tok::l_square) && Right.is(tok::amp))
return false;
- if (Right.is(TT_PointerOrReference))
- return (Left.is(tok::r_paren) && Line.MightBeFunctionDecl) ||
- (Left.Tok.isLiteral() || (Left.is(tok::kw_const) && Left.Previous &&
- Left.Previous->is(tok::r_paren)) ||
+ if (Right.is(TT_PointerOrReference)) {
+ if (Left.is(tok::r_paren) && Line.MightBeFunctionDecl) {
+ if (!Left.MatchingParen)
+ return true;
+ FormatToken *TokenBeforeMatchingParen =
+ Left.MatchingParen->getPreviousNonComment();
+ if (!TokenBeforeMatchingParen ||
+ !TokenBeforeMatchingParen->isOneOf(tok::kw_typeof, tok::kw_decltype))
+ return true;
+ }
+ return (Left.Tok.isLiteral() ||
(!Left.isOneOf(TT_PointerOrReference, tok::l_paren) &&
(Style.PointerAlignment != FormatStyle::PAS_Left ||
(Line.IsMultiVariableDeclStmt &&
(Left.NestingLevel == 0 ||
(Left.NestingLevel == 1 && Line.First->is(tok::kw_for)))))));
+ }
if (Right.is(TT_FunctionTypeLParen) && Left.isNot(tok::l_paren) &&
(!Left.is(TT_PointerOrReference) ||
(Style.PointerAlignment != FormatStyle::PAS_Right &&
@@ -2231,17 +2266,20 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
if (Left.is(tok::l_square))
return (Left.is(TT_ArrayInitializerLSquare) &&
Style.SpacesInContainerLiterals && Right.isNot(tok::r_square)) ||
- (Left.is(TT_ArraySubscriptLSquare) && Style.SpacesInSquareBrackets &&
- Right.isNot(tok::r_square));
+ (Left.isOneOf(TT_ArraySubscriptLSquare,
+ TT_StructuredBindingLSquare) &&
+ Style.SpacesInSquareBrackets && Right.isNot(tok::r_square));
if (Right.is(tok::r_square))
return Right.MatchingParen &&
((Style.SpacesInContainerLiterals &&
Right.MatchingParen->is(TT_ArrayInitializerLSquare)) ||
(Style.SpacesInSquareBrackets &&
- Right.MatchingParen->is(TT_ArraySubscriptLSquare)));
+ Right.MatchingParen->isOneOf(TT_ArraySubscriptLSquare,
+ TT_StructuredBindingLSquare)));
if (Right.is(tok::l_square) &&
!Right.isOneOf(TT_ObjCMethodExpr, TT_LambdaLSquare,
- TT_DesignatedInitializerLSquare) &&
+ TT_DesignatedInitializerLSquare,
+ TT_StructuredBindingLSquare) &&
!Left.isOneOf(tok::numeric_constant, TT_DictLiteral))
return false;
if (Left.is(tok::l_brace) && Right.is(tok::r_brace))
@@ -2287,7 +2325,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
if (Left.is(TT_TemplateCloser) && Left.MatchingParen &&
Left.MatchingParen->Previous &&
Left.MatchingParen->Previous->is(tok::period))
- // A.<B>DoSomething();
+ // A.<B<C<...>>>DoSomething();
return false;
if (Left.is(TT_TemplateCloser) && Right.is(tok::l_square))
return false;
@@ -2317,8 +2355,8 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
if (Left.is(TT_JsFatArrow))
return true;
// for await ( ...
- if (Right.is(tok::l_paren) && Left.is(Keywords.kw_await) &&
- Left.Previous && Left.Previous->is(tok::kw_for))
+ if (Right.is(tok::l_paren) && Left.is(Keywords.kw_await) && Left.Previous &&
+ Left.Previous->is(tok::kw_for))
return true;
if (Left.is(Keywords.kw_async) && Right.is(tok::l_paren) &&
Right.MatchingParen) {
@@ -2341,18 +2379,31 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
Left.isOneOf(Keywords.kw_function, Keywords.kw_yield))
return false;
if (Right.isOneOf(tok::l_brace, tok::l_square) &&
- Left.isOneOf(Keywords.kw_function, Keywords.kw_yield))
+ Left.isOneOf(Keywords.kw_function, Keywords.kw_yield,
+ Keywords.kw_extends, Keywords.kw_implements))
return true;
- // JS methods can use some keywords as names (e.g. `delete()`).
- if (Right.is(tok::l_paren) && Line.MustBeDeclaration &&
- Left.Tok.getIdentifierInfo())
- return false;
+ if (Right.is(tok::l_paren)) {
+ // JS methods can use some keywords as names (e.g. `delete()`).
+ if (Line.MustBeDeclaration && Left.Tok.getIdentifierInfo())
+ return false;
+ // Valid JS method names can include keywords, e.g. `foo.delete()` or
+ // `bar.instanceof()`. Recognize call positions by preceding period.
+ if (Left.Previous && Left.Previous->is(tok::period) &&
+ Left.Tok.getIdentifierInfo())
+ return false;
+ // Additional unary JavaScript operators that need a space after.
+ if (Left.isOneOf(tok::kw_throw, Keywords.kw_await, Keywords.kw_typeof,
+ tok::kw_void))
+ return true;
+ }
if ((Left.isOneOf(Keywords.kw_let, Keywords.kw_var, Keywords.kw_in,
tok::kw_const) ||
// "of" is only a keyword if it appears after another identifier
- // (e.g. as "const x of y" in a for loop).
+ // (e.g. as "const x of y" in a for loop), or after a destructuring
+ // operation (const [x, y] of z, const {a, b} of c).
(Left.is(Keywords.kw_of) && Left.Previous &&
- Left.Previous->Tok.getIdentifierInfo())) &&
+ (Left.Previous->Tok.getIdentifierInfo() ||
+ Left.Previous->isOneOf(tok::r_square, tok::r_brace)))) &&
(!Left.Previous || !Left.Previous->is(tok::period)))
return true;
if (Left.isOneOf(tok::kw_for, Keywords.kw_as) && Left.Previous &&
@@ -2384,8 +2435,9 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
return false;
if (Right.is(TT_JsNonNullAssertion))
return false;
- if (Left.is(TT_JsNonNullAssertion) && Right.is(Keywords.kw_as))
- return true; // "x! as string"
+ if (Left.is(TT_JsNonNullAssertion) &&
+ Right.isOneOf(Keywords.kw_as, Keywords.kw_in))
+ return true; // "x! as string", "x! in y"
} else if (Style.Language == FormatStyle::LK_Java) {
if (Left.is(tok::r_square) && Right.is(tok::l_brace))
return true;
@@ -2464,9 +2516,18 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
return (Left.is(TT_TemplateOpener) &&
Style.Standard == FormatStyle::LS_Cpp03) ||
!(Left.isOneOf(tok::l_paren, tok::r_paren, tok::l_square,
- tok::kw___super, TT_TemplateCloser, TT_TemplateOpener));
+ tok::kw___super, TT_TemplateCloser,
+ TT_TemplateOpener));
if ((Left.is(TT_TemplateOpener)) != (Right.is(TT_TemplateCloser)))
return Style.SpacesInAngles;
+ // Space before TT_StructuredBindingLSquare.
+ if (Right.is(TT_StructuredBindingLSquare))
+ return !Left.isOneOf(tok::amp, tok::ampamp) ||
+ Style.PointerAlignment != FormatStyle::PAS_Right;
+ // Space before & or && following a TT_StructuredBindingLSquare.
+ if (Right.Next && Right.Next->is(TT_StructuredBindingLSquare) &&
+ Right.isOneOf(tok::amp, tok::ampamp))
+ return Style.PointerAlignment != FormatStyle::PAS_Left;
if ((Right.is(TT_BinaryOperator) && !Left.is(tok::l_paren)) ||
(Left.isOneOf(TT_BinaryOperator, TT_ConditionalExpr) &&
!Right.is(tok::r_paren)))
@@ -2516,7 +2577,9 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
return true;
if (Left.is(tok::l_brace) && Line.Level == 0 &&
(Line.startsWith(tok::kw_enum) ||
- Line.startsWith(tok::kw_export, tok::kw_enum)))
+ Line.startsWith(tok::kw_const, tok::kw_enum) ||
+ Line.startsWith(tok::kw_export, tok::kw_enum) ||
+ Line.startsWith(tok::kw_export, tok::kw_const, tok::kw_enum)))
// JavaScript top-level enum key/value pairs are put on separate lines
// instead of bin-packing.
return true;
@@ -2587,19 +2650,16 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
!Style.ConstructorInitializerAllOnOneLineOrOnePerLine)
return true;
// Break only if we have multiple inheritance.
- if (Style.BreakBeforeInheritanceComma &&
- Right.is(TT_InheritanceComma))
- return true;
+ if (Style.BreakBeforeInheritanceComma && Right.is(TT_InheritanceComma))
+ return true;
if (Right.is(tok::string_literal) && Right.TokenText.startswith("R\""))
// Raw string literals are special wrt. line breaks. The author has made a
// deliberate choice and might have aligned the contents of the string
// literal accordingly. Thus, we try keep existing line breaks.
return Right.NewlinesBefore > 0;
if ((Right.Previous->is(tok::l_brace) ||
- (Right.Previous->is(tok::less) &&
- Right.Previous->Previous &&
- Right.Previous->Previous->is(tok::equal))
- ) &&
+ (Right.Previous->is(tok::less) && Right.Previous->Previous &&
+ Right.Previous->Previous->is(tok::equal))) &&
Right.NestingLevel == 1 && Style.Language == FormatStyle::LK_Proto) {
// Don't put enums or option definitions onto single lines in protocol
// buffers.
@@ -2609,6 +2669,8 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
return Right.HasUnescapedNewline;
if (isAllmanBrace(Left) || isAllmanBrace(Right))
return (Line.startsWith(tok::kw_enum) && Style.BraceWrapping.AfterEnum) ||
+ (Line.startsWith(tok::kw_typedef, tok::kw_enum) &&
+ Style.BraceWrapping.AfterEnum) ||
(Line.startsWith(tok::kw_class) && Style.BraceWrapping.AfterClass) ||
(Line.startsWith(tok::kw_struct) && Style.BraceWrapping.AfterStruct);
if (Left.is(TT_ObjCBlockLBrace) && !Style.AllowShortBlocksOnASingleLine)
@@ -2639,13 +2701,16 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
} else if (Style.Language == FormatStyle::LK_JavaScript) {
const FormatToken *NonComment = Right.getPreviousNonComment();
if (NonComment &&
- NonComment->isOneOf(tok::kw_return, tok::kw_continue, tok::kw_break,
- tok::kw_throw, Keywords.kw_interface,
- Keywords.kw_type, tok::kw_static, tok::kw_public,
- tok::kw_private, tok::kw_protected,
- Keywords.kw_readonly, Keywords.kw_abstract,
- Keywords.kw_get, Keywords.kw_set))
+ NonComment->isOneOf(
+ tok::kw_return, Keywords.kw_yield, tok::kw_continue, tok::kw_break,
+ tok::kw_throw, Keywords.kw_interface, Keywords.kw_type,
+ tok::kw_static, tok::kw_public, tok::kw_private, tok::kw_protected,
+ Keywords.kw_readonly, Keywords.kw_abstract, Keywords.kw_get,
+ Keywords.kw_set, Keywords.kw_async, Keywords.kw_await))
return false; // Otherwise automatic semicolon insertion would trigger.
+ if (Left.Tok.getIdentifierInfo() &&
+ Right.startsSequence(tok::l_square, tok::r_square))
+ return false; // breaking in "foo[]" creates illegal TS type syntax.
if (Left.is(TT_JsFatArrow) && Right.is(tok::l_brace))
return false;
if (Left.is(TT_JsTypeColon))
@@ -2702,8 +2767,7 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
// list.
return Left.BlockKind == BK_BracedInit ||
(Left.is(TT_CtorInitializerColon) &&
- Style.BreakConstructorInitializers ==
- FormatStyle::BCIS_AfterColon);
+ Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon);
if (Left.is(tok::question) && Right.is(tok::colon))
return false;
if (Right.is(TT_ConditionalExpr) || Right.is(tok::question))
@@ -2820,7 +2884,7 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
}
void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) {
- llvm::errs() << "AnnotatedTokens:\n";
+ llvm::errs() << "AnnotatedTokens(L=" << Line.Level << "):\n";
const FormatToken *Tok = Line.First;
while (Tok) {
llvm::errs() << " M=" << Tok->MustBreakBefore
@@ -2828,10 +2892,9 @@ void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) {
<< " T=" << getTokenTypeName(Tok->Type)
<< " S=" << Tok->SpacesRequiredBefore
<< " B=" << Tok->BlockParameterCount
- << " BK=" << Tok->BlockKind
- << " P=" << Tok->SplitPenalty << " Name=" << Tok->Tok.getName()
- << " L=" << Tok->TotalLength << " PPK=" << Tok->PackingKind
- << " FakeLParens=";
+ << " BK=" << Tok->BlockKind << " P=" << Tok->SplitPenalty
+ << " Name=" << Tok->Tok.getName() << " L=" << Tok->TotalLength
+ << " PPK=" << Tok->PackingKind << " FakeLParens=";
for (unsigned i = 0, e = Tok->FakeLParens.size(); i != e; ++i)
llvm::errs() << Tok->FakeLParens[i] << "/";
llvm::errs() << " FakeRParens=" << Tok->FakeRParens;
diff --git a/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.h b/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.h
index 805509533bf93..04a18d45b82e5 100644
--- a/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.h
+++ b/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.h
@@ -43,7 +43,8 @@ public:
InPPDirective(Line.InPPDirective),
MustBeDeclaration(Line.MustBeDeclaration), MightBeFunctionDecl(false),
IsMultiVariableDeclStmt(false), Affected(false),
- LeadingEmptyLinesAffected(false), ChildrenAffected(false) {
+ LeadingEmptyLinesAffected(false), ChildrenAffected(false),
+ FirstStartColumn(Line.FirstStartColumn) {
assert(!Line.Tokens.empty());
// Calculate Next and Previous for all tokens. Note that we must overwrite
@@ -127,6 +128,8 @@ public:
/// \c True if one of this line's children intersects with an input range.
bool ChildrenAffected;
+ unsigned FirstStartColumn;
+
private:
// Disallow copying.
AnnotatedLine(const AnnotatedLine &) = delete;
diff --git a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.cpp b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.cpp
index 2005a2822924f..60dc1a7169d12 100644
--- a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -164,8 +164,7 @@ public:
return nullptr;
const AnnotatedLine *Current = *Next;
IndentTracker.nextLine(*Current);
- unsigned MergedLines =
- tryFitMultipleLinesInOne(IndentTracker, Next, End);
+ unsigned MergedLines = tryFitMultipleLinesInOne(IndentTracker, Next, End);
if (MergedLines > 0 && Style.ColumnLimit == 0)
// Disallow line merging if there is a break at the start of one of the
// input lines.
@@ -228,14 +227,16 @@ private:
if (Tok && Tok->getNamespaceToken())
return !Style.BraceWrapping.SplitEmptyNamespace && EmptyBlock
- ? tryMergeSimpleBlock(I, E, Limit) : 0;
+ ? tryMergeSimpleBlock(I, E, Limit)
+ : 0;
if (Tok && Tok->is(tok::kw_typedef))
Tok = Tok->getNextNonComment();
if (Tok && Tok->isOneOf(tok::kw_class, tok::kw_struct, tok::kw_union,
- Keywords.kw_interface))
+ tok::kw_extern, Keywords.kw_interface))
return !Style.BraceWrapping.SplitEmptyRecord && EmptyBlock
- ? tryMergeSimpleBlock(I, E, Limit) : 0;
+ ? tryMergeSimpleBlock(I, E, Limit)
+ : 0;
}
// FIXME: TheLine->Level != 0 might or might not be the right check to do.
@@ -279,15 +280,43 @@ private:
}
}
+ // Try to merge a function block with left brace unwrapped
if (TheLine->Last->is(TT_FunctionLBrace) &&
TheLine->First != TheLine->Last) {
return MergeShortFunctions ? tryMergeSimpleBlock(I, E, Limit) : 0;
}
+ // Try to merge a control statement block with left brace unwrapped
+ if (TheLine->Last->is(tok::l_brace) && TheLine->First != TheLine->Last &&
+ TheLine->First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for)) {
+ return Style.AllowShortBlocksOnASingleLine
+ ? tryMergeSimpleBlock(I, E, Limit)
+ : 0;
+ }
+ // Try to merge a control statement block with left brace wrapped
+ if (I[1]->First->is(tok::l_brace) &&
+ TheLine->First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for)) {
+ return Style.BraceWrapping.AfterControlStatement
+ ? tryMergeSimpleBlock(I, E, Limit)
+ : 0;
+ }
+ // Try to merge either empty or one-line block if is precedeed by control
+ // statement token
+ if (TheLine->First->is(tok::l_brace) && TheLine->First == TheLine->Last &&
+ I != AnnotatedLines.begin() &&
+ I[-1]->First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for)) {
+ return Style.AllowShortBlocksOnASingleLine
+ ? tryMergeSimpleBlock(I - 1, E, Limit)
+ : 0;
+ }
+ // Try to merge a block with left brace wrapped that wasn't yet covered
if (TheLine->Last->is(tok::l_brace)) {
- return !Style.BraceWrapping.AfterFunction
+ return !Style.BraceWrapping.AfterFunction ||
+ (I[1]->First->is(tok::r_brace) &&
+ !Style.BraceWrapping.SplitEmptyRecord)
? tryMergeSimpleBlock(I, E, Limit)
: 0;
}
+ // Try to merge a function block with left brace wrapped
if (I[1]->First->is(TT_FunctionLBrace) &&
Style.BraceWrapping.AfterFunction) {
if (I[1]->Last->is(TT_LineComment))
@@ -382,7 +411,9 @@ private:
return 0;
unsigned NumStmts = 0;
unsigned Length = 0;
+ bool EndsWithComment = false;
bool InPPDirective = I[0]->InPPDirective;
+ const unsigned Level = I[0]->Level;
for (; NumStmts < 3; ++NumStmts) {
if (I + 1 + NumStmts == E)
break;
@@ -392,9 +423,26 @@ private:
if (Line->First->isOneOf(tok::kw_case, tok::kw_default, tok::r_brace))
break;
if (Line->First->isOneOf(tok::kw_if, tok::kw_for, tok::kw_switch,
- tok::kw_while, tok::comment) ||
- Line->Last->is(tok::comment))
+ tok::kw_while) ||
+ EndsWithComment)
return 0;
+ if (Line->First->is(tok::comment)) {
+ if (Level != Line->Level)
+ return 0;
+ SmallVectorImpl<AnnotatedLine *>::const_iterator J = I + 2 + NumStmts;
+ for (; J != E; ++J) {
+ Line = *J;
+ if (Line->InPPDirective != InPPDirective)
+ break;
+ if (Line->First->isOneOf(tok::kw_case, tok::kw_default, tok::r_brace))
+ break;
+ if (Line->First->isNot(tok::comment) || Level != Line->Level)
+ return 0;
+ }
+ break;
+ }
+ if (Line->Last->is(tok::comment))
+ EndsWithComment = true;
Length += I[1 + NumStmts]->Last->TotalLength + 1; // 1 for the space.
}
if (NumStmts == 0 || NumStmts == 3 || Length > Limit)
@@ -425,11 +473,27 @@ private:
tok::kw_for, tok::r_brace, Keywords.kw___except)) {
if (!Style.AllowShortBlocksOnASingleLine)
return 0;
+ // Don't merge when we can't except the case when
+ // the control statement block is empty
if (!Style.AllowShortIfStatementsOnASingleLine &&
- Line.startsWith(tok::kw_if))
+ Line.startsWith(tok::kw_if) &&
+ !Style.BraceWrapping.AfterControlStatement &&
+ !I[1]->First->is(tok::r_brace))
+ return 0;
+ if (!Style.AllowShortIfStatementsOnASingleLine &&
+ Line.startsWith(tok::kw_if) &&
+ Style.BraceWrapping.AfterControlStatement && I + 2 != E &&
+ !I[2]->First->is(tok::r_brace))
+ return 0;
+ if (!Style.AllowShortLoopsOnASingleLine &&
+ Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for) &&
+ !Style.BraceWrapping.AfterControlStatement &&
+ !I[1]->First->is(tok::r_brace))
return 0;
if (!Style.AllowShortLoopsOnASingleLine &&
- Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for))
+ Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for) &&
+ Style.BraceWrapping.AfterControlStatement && I + 2 != E &&
+ !I[2]->First->is(tok::r_brace))
return 0;
// FIXME: Consider an option to allow short exception handling clauses on
// a single line.
@@ -441,52 +505,78 @@ private:
return 0;
}
- FormatToken *Tok = I[1]->First;
- if (Tok->is(tok::r_brace) && !Tok->MustBreakBefore &&
- (Tok->getNextNonComment() == nullptr ||
- Tok->getNextNonComment()->is(tok::semi))) {
- // We merge empty blocks even if the line exceeds the column limit.
- Tok->SpacesRequiredBefore = 0;
- Tok->CanBreakBefore = true;
- return 1;
- } else if (Limit != 0 && !Line.startsWith(tok::kw_namespace) &&
- !startsExternCBlock(Line)) {
- // We don't merge short records.
- FormatToken *RecordTok =
- Line.First->is(tok::kw_typedef) ? Line.First->Next : Line.First;
- if (RecordTok &&
- RecordTok->isOneOf(tok::kw_class, tok::kw_union, tok::kw_struct,
- Keywords.kw_interface))
- return 0;
+ if (Line.Last->is(tok::l_brace)) {
+ FormatToken *Tok = I[1]->First;
+ if (Tok->is(tok::r_brace) && !Tok->MustBreakBefore &&
+ (Tok->getNextNonComment() == nullptr ||
+ Tok->getNextNonComment()->is(tok::semi))) {
+ // We merge empty blocks even if the line exceeds the column limit.
+ Tok->SpacesRequiredBefore = 0;
+ Tok->CanBreakBefore = true;
+ return 1;
+ } else if (Limit != 0 && !Line.startsWith(tok::kw_namespace) &&
+ !startsExternCBlock(Line)) {
+ // We don't merge short records.
+ FormatToken *RecordTok = Line.First;
+ // Skip record modifiers.
+ while (RecordTok->Next &&
+ RecordTok->isOneOf(tok::kw_typedef, tok::kw_export,
+ Keywords.kw_declare, Keywords.kw_abstract,
+ tok::kw_default))
+ RecordTok = RecordTok->Next;
+ if (RecordTok &&
+ RecordTok->isOneOf(tok::kw_class, tok::kw_union, tok::kw_struct,
+ Keywords.kw_interface))
+ return 0;
- // Check that we still have three lines and they fit into the limit.
- if (I + 2 == E || I[2]->Type == LT_Invalid)
- return 0;
- Limit = limitConsideringMacros(I + 2, E, Limit);
+ // Check that we still have three lines and they fit into the limit.
+ if (I + 2 == E || I[2]->Type == LT_Invalid)
+ return 0;
+ Limit = limitConsideringMacros(I + 2, E, Limit);
- if (!nextTwoLinesFitInto(I, Limit))
- return 0;
+ if (!nextTwoLinesFitInto(I, Limit))
+ return 0;
- // Second, check that the next line does not contain any braces - if it
- // does, readability declines when putting it into a single line.
- if (I[1]->Last->is(TT_LineComment))
- return 0;
- do {
- if (Tok->is(tok::l_brace) && Tok->BlockKind != BK_BracedInit)
+ // Second, check that the next line does not contain any braces - if it
+ // does, readability declines when putting it into a single line.
+ if (I[1]->Last->is(TT_LineComment))
return 0;
- Tok = Tok->Next;
- } while (Tok);
+ do {
+ if (Tok->is(tok::l_brace) && Tok->BlockKind != BK_BracedInit)
+ return 0;
+ Tok = Tok->Next;
+ } while (Tok);
- // Last, check that the third line starts with a closing brace.
- Tok = I[2]->First;
- if (Tok->isNot(tok::r_brace))
- return 0;
+ // Last, check that the third line starts with a closing brace.
+ Tok = I[2]->First;
+ if (Tok->isNot(tok::r_brace))
+ return 0;
+
+ // Don't merge "if (a) { .. } else {".
+ if (Tok->Next && Tok->Next->is(tok::kw_else))
+ return 0;
- // Don't merge "if (a) { .. } else {".
- if (Tok->Next && Tok->Next->is(tok::kw_else))
+ return 2;
+ }
+ } else if (I[1]->First->is(tok::l_brace)) {
+ if (I[1]->Last->is(TT_LineComment))
return 0;
- return 2;
+ // Check for Limit <= 2 to account for the " {".
+ if (Limit <= 2 || (Style.ColumnLimit == 0 && containsMustBreak(*I)))
+ return 0;
+ Limit -= 2;
+ unsigned MergedLines = 0;
+ if (Style.AllowShortBlocksOnASingleLine ||
+ (I[1]->First == I[1]->Last && I + 2 != E &&
+ I[2]->First->is(tok::r_brace))) {
+ MergedLines = tryMergeSimpleBlock(I + 1, E, Limit);
+ // If we managed to merge the block, count the statement header, which
+ // is on a separate line.
+ if (MergedLines > 0)
+ ++MergedLines;
+ }
+ return MergedLines;
}
return 0;
}
@@ -574,7 +664,9 @@ public:
/// \brief Formats an \c AnnotatedLine and returns the penalty.
///
/// If \p DryRun is \c false, directly applies the changes.
- virtual unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,
+ virtual unsigned formatLine(const AnnotatedLine &Line,
+ unsigned FirstIndent,
+ unsigned FirstStartColumn,
bool DryRun) = 0;
protected:
@@ -645,7 +737,8 @@ protected:
*Child->First, /*Newlines=*/0, /*Spaces=*/1,
/*StartOfTokenColumn=*/State.Column, State.Line->InPPDirective);
}
- Penalty += formatLine(*Child, State.Column + 1, DryRun);
+ Penalty +=
+ formatLine(*Child, State.Column + 1, /*FirstStartColumn=*/0, DryRun);
State.Column += 1 + Child->Last->TotalLength;
return true;
@@ -671,10 +764,10 @@ public:
/// \brief Formats the line, simply keeping all of the input's line breaking
/// decisions.
unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,
- bool DryRun) override {
+ unsigned FirstStartColumn, bool DryRun) override {
assert(!DryRun);
- LineState State =
- Indenter->getInitialState(FirstIndent, &Line, /*DryRun=*/false);
+ LineState State = Indenter->getInitialState(FirstIndent, FirstStartColumn,
+ &Line, /*DryRun=*/false);
while (State.NextToken) {
bool Newline =
Indenter->mustBreak(State) ||
@@ -697,9 +790,10 @@ public:
/// \brief Puts all tokens into a single line.
unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,
- bool DryRun) override {
+ unsigned FirstStartColumn, bool DryRun) override {
unsigned Penalty = 0;
- LineState State = Indenter->getInitialState(FirstIndent, &Line, DryRun);
+ LineState State =
+ Indenter->getInitialState(FirstIndent, FirstStartColumn, &Line, DryRun);
while (State.NextToken) {
formatChildren(State, /*Newline=*/false, DryRun, Penalty);
Indenter->addTokenToState(
@@ -721,8 +815,9 @@ public:
/// \brief Formats the line by finding the best line breaks with line lengths
/// below the column limit.
unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,
- bool DryRun) override {
- LineState State = Indenter->getInitialState(FirstIndent, &Line, DryRun);
+ unsigned FirstStartColumn, bool DryRun) override {
+ LineState State =
+ Indenter->getInitialState(FirstIndent, FirstStartColumn, &Line, DryRun);
// If the ObjC method declaration does not fit on a line, we should format
// it with one arg per line.
@@ -763,7 +858,8 @@ private:
/// \brief The BFS queue type.
typedef std::priority_queue<QueueItem, std::vector<QueueItem>,
- std::greater<QueueItem>> QueueType;
+ std::greater<QueueItem>>
+ QueueType;
/// \brief Analyze the entire solution space starting from \p InitialState.
///
@@ -888,7 +984,10 @@ private:
unsigned
UnwrappedLineFormatter::format(const SmallVectorImpl<AnnotatedLine *> &Lines,
bool DryRun, int AdditionalIndent,
- bool FixBadIndentation) {
+ bool FixBadIndentation,
+ unsigned FirstStartColumn,
+ unsigned NextStartColumn,
+ unsigned LastStartColumn) {
LineJoiner Joiner(Style, Keywords, Lines);
// Try to look up already computed penalty in DryRun-mode.
@@ -908,9 +1007,10 @@ UnwrappedLineFormatter::format(const SmallVectorImpl<AnnotatedLine *> &Lines,
// The minimum level of consecutive lines that have been formatted.
unsigned RangeMinLevel = UINT_MAX;
+ bool FirstLine = true;
for (const AnnotatedLine *Line =
Joiner.getNextMergedLine(DryRun, IndentTracker);
- Line; Line = NextLine) {
+ Line; Line = NextLine, FirstLine = false) {
const AnnotatedLine &TheLine = *Line;
unsigned Indent = IndentTracker.getIndent();
@@ -934,8 +1034,12 @@ UnwrappedLineFormatter::format(const SmallVectorImpl<AnnotatedLine *> &Lines,
}
if (ShouldFormat && TheLine.Type != LT_Invalid) {
- if (!DryRun)
- formatFirstToken(TheLine, PreviousLine, Indent);
+ if (!DryRun) {
+ bool LastLine = Line->First->is(tok::eof);
+ formatFirstToken(TheLine, PreviousLine,
+ Indent,
+ LastLine ? LastStartColumn : NextStartColumn + Indent);
+ }
NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker);
unsigned ColumnLimit = getColumnLimit(TheLine.InPPDirective, NextLine);
@@ -944,16 +1048,18 @@ UnwrappedLineFormatter::format(const SmallVectorImpl<AnnotatedLine *> &Lines,
(TheLine.Type == LT_ImportStatement &&
(Style.Language != FormatStyle::LK_JavaScript ||
!Style.JavaScriptWrapImports));
-
if (Style.ColumnLimit == 0)
NoColumnLimitLineFormatter(Indenter, Whitespaces, Style, this)
- .formatLine(TheLine, Indent, DryRun);
+ .formatLine(TheLine, NextStartColumn + Indent,
+ FirstLine ? FirstStartColumn : 0, DryRun);
else if (FitsIntoOneLine)
Penalty += NoLineBreakFormatter(Indenter, Whitespaces, Style, this)
- .formatLine(TheLine, Indent, DryRun);
+ .formatLine(TheLine, NextStartColumn + Indent,
+ FirstLine ? FirstStartColumn : 0, DryRun);
else
Penalty += OptimizingLineFormatter(Indenter, Whitespaces, Style, this)
- .formatLine(TheLine, Indent, DryRun);
+ .formatLine(TheLine, NextStartColumn + Indent,
+ FirstLine ? FirstStartColumn : 0, DryRun);
RangeMinLevel = std::min(RangeMinLevel, TheLine.Level);
} else {
// If no token in the current line is affected, we still need to format
@@ -976,6 +1082,7 @@ UnwrappedLineFormatter::format(const SmallVectorImpl<AnnotatedLine *> &Lines,
// Format the first token.
if (ReformatLeadingWhitespace)
formatFirstToken(TheLine, PreviousLine,
+ TheLine.First->OriginalColumn,
TheLine.First->OriginalColumn);
else
Whitespaces->addUntouchableToken(*TheLine.First,
@@ -998,12 +1105,14 @@ UnwrappedLineFormatter::format(const SmallVectorImpl<AnnotatedLine *> &Lines,
void UnwrappedLineFormatter::formatFirstToken(const AnnotatedLine &Line,
const AnnotatedLine *PreviousLine,
- unsigned Indent) {
- FormatToken& RootToken = *Line.First;
+ unsigned Indent,
+ unsigned NewlineIndent) {
+ FormatToken &RootToken = *Line.First;
if (RootToken.is(tok::eof)) {
unsigned Newlines = std::min(RootToken.NewlinesBefore, 1u);
- Whitespaces->replaceWhitespace(RootToken, Newlines, /*Spaces=*/0,
- /*StartOfTokenColumn=*/0);
+ unsigned TokenIndent = Newlines ? NewlineIndent : 0;
+ Whitespaces->replaceWhitespace(RootToken, Newlines, TokenIndent,
+ TokenIndent);
return;
}
unsigned Newlines =
@@ -1013,6 +1122,9 @@ void UnwrappedLineFormatter::formatFirstToken(const AnnotatedLine &Line,
(!RootToken.Next ||
(RootToken.Next->is(tok::semi) && !RootToken.Next->Next)))
Newlines = std::min(Newlines, 1u);
+ // Remove empty lines at the start of nested blocks (lambdas/arrow functions)
+ if (PreviousLine == nullptr && Line.Level > 0)
+ Newlines = std::min(Newlines, 1u);
if (Newlines == 0 && !RootToken.IsFirst)
Newlines = 1;
if (RootToken.IsFirst && !RootToken.HasUnescapedNewline)
@@ -1035,6 +1147,13 @@ void UnwrappedLineFormatter::formatFirstToken(const AnnotatedLine &Line,
(!PreviousLine->InPPDirective || !RootToken.HasUnescapedNewline))
Newlines = std::min(1u, Newlines);
+ if (Newlines)
+ Indent = NewlineIndent;
+
+ // Preprocessor directives get indented after the hash, if indented.
+ if (Line.Type == LT_PreprocessorDirective || Line.Type == LT_ImportStatement)
+ Indent = 0;
+
Whitespaces->replaceWhitespace(RootToken, Newlines, Indent, Indent,
Line.InPPDirective &&
!RootToken.HasUnescapedNewline);
diff --git a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.h b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.h
index 55f0d1cac689f..6432ca83a4c95 100644
--- a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.h
+++ b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.h
@@ -35,19 +35,22 @@ public:
const SourceManager &SourceMgr,
FormattingAttemptStatus *Status)
: Indenter(Indenter), Whitespaces(Whitespaces), Style(Style),
- Keywords(Keywords), SourceMgr(SourceMgr),
- Status(Status) {}
+ Keywords(Keywords), SourceMgr(SourceMgr), Status(Status) {}
/// \brief Format the current block and return the penalty.
unsigned format(const SmallVectorImpl<AnnotatedLine *> &Lines,
bool DryRun = false, int AdditionalIndent = 0,
- bool FixBadIndentation = false);
+ bool FixBadIndentation = false,
+ unsigned FirstStartColumn = 0,
+ unsigned NextStartColumn = 0,
+ unsigned LastStartColumn = 0);
private:
/// \brief Add a new line and the required indent before the first Token
/// of the \c UnwrappedLine if there was no structural parsing error.
void formatFirstToken(const AnnotatedLine &Line,
- const AnnotatedLine *PreviousLine, unsigned Indent);
+ const AnnotatedLine *PreviousLine, unsigned Indent,
+ unsigned NewlineIndent);
/// \brief Returns the column limit for a line, taking into account whether we
/// need an escaped newline due to a continued preprocessor directive.
diff --git a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.cpp b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.cpp
index faac5a371c260..b8608dcac9c7e 100644
--- a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.cpp
@@ -18,6 +18,8 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+
#define DEBUG_TYPE "format-parser"
namespace clang {
@@ -56,8 +58,7 @@ private:
};
static bool isLineComment(const FormatToken &FormatTok) {
- return FormatTok.is(tok::comment) &&
- FormatTok.TokenText.startswith("//");
+ return FormatTok.is(tok::comment) && !FormatTok.TokenText.startswith("/*");
}
// Checks if \p FormatTok is a line comment that continues the line comment
@@ -226,15 +227,21 @@ private:
UnwrappedLineParser::UnwrappedLineParser(const FormatStyle &Style,
const AdditionalKeywords &Keywords,
+ unsigned FirstStartColumn,
ArrayRef<FormatToken *> Tokens,
UnwrappedLineConsumer &Callback)
: Line(new UnwrappedLine), MustBreakBeforeNextToken(false),
CurrentLines(&Lines), Style(Style), Keywords(Keywords),
CommentPragmasRegex(Style.CommentPragmas), Tokens(nullptr),
- Callback(Callback), AllTokens(Tokens), PPBranchLevel(-1) {}
+ Callback(Callback), AllTokens(Tokens), PPBranchLevel(-1),
+ IfNdefCondition(nullptr), FoundIncludeGuardStart(false),
+ IncludeGuardRejected(false), FirstStartColumn(FirstStartColumn) {}
void UnwrappedLineParser::reset() {
PPBranchLevel = -1;
+ IfNdefCondition = nullptr;
+ FoundIncludeGuardStart = false;
+ IncludeGuardRejected = false;
Line.reset(new UnwrappedLine);
CommentsBeforeNextToken.clear();
FormatTok = nullptr;
@@ -243,10 +250,12 @@ void UnwrappedLineParser::reset() {
CurrentLines = &Lines;
DeclarationScopeStack.clear();
PPStack.clear();
+ Line->FirstStartColumn = FirstStartColumn;
}
void UnwrappedLineParser::parse() {
IndexedTokenSource TokenSource(AllTokens);
+ Line->FirstStartColumn = FirstStartColumn;
do {
DEBUG(llvm::dbgs() << "----\n");
reset();
@@ -326,6 +335,12 @@ void UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
break;
case tok::kw_default:
case tok::kw_case:
+ if (Style.Language == FormatStyle::LK_JavaScript &&
+ Line->MustBeDeclaration) {
+ // A 'case: string' style field declaration.
+ parseStructuralElement();
+ break;
+ }
if (!SwitchLabelEncountered &&
(Style.IndentCaseLabels || (Line->InPPDirective && Line->Level == 1)))
++Line->Level;
@@ -346,7 +361,7 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
// definitions, too.
unsigned StoredPosition = Tokens->getPosition();
FormatToken *Tok = FormatTok;
- const FormatToken *PrevTok = getPreviousToken();
+ const FormatToken *PrevTok = Tok->Previous;
// Keep a stack of positions of lbrace tokens. We will
// update information about whether an lbrace starts a
// braced init list or a different block during the loop.
@@ -364,13 +379,16 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
switch (Tok->Tok.getKind()) {
case tok::l_brace:
if (Style.Language == FormatStyle::LK_JavaScript && PrevTok) {
- if (PrevTok->is(tok::colon))
- // A colon indicates this code is in a type, or a braced list
- // following a label in an object literal ({a: {b: 1}}). The code
- // below could be confused by semicolons between the individual
- // members in a type member list, which would normally trigger
- // BK_Block. In both cases, this must be parsed as an inline braced
- // init.
+ if (PrevTok->isOneOf(tok::colon, tok::less))
+ // A ':' indicates this code is in a type, or a braced list
+ // following a label in an object literal ({a: {b: 1}}).
+ // A '<' could be an object used in a comparison, but that is nonsense
+ // code (can never return true), so more likely it is a generic type
+ // argument (`X<{a: string; b: number}>`).
+ // The code below could be confused by semicolons between the
+ // individual members in a type member list, which would normally
+ // trigger BK_Block. In both cases, this must be parsed as an inline
+ // braced init.
Tok->BlockKind = BK_BracedInit;
else if (PrevTok->is(tok::r_paren))
// `) { }` can only occur in function or method declarations in JS.
@@ -452,6 +470,21 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
FormatTok = Tokens->setPosition(StoredPosition);
}
+template <class T>
+static inline void hash_combine(std::size_t &seed, const T &v) {
+ std::hash<T> hasher;
+ seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+}
+
+size_t UnwrappedLineParser::computePPHash() const {
+ size_t h = 0;
+ for (const auto &i : PPStack) {
+ hash_combine(h, size_t(i.Kind));
+ hash_combine(h, i.Line);
+ }
+ return h;
+}
+
void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, bool AddLevel,
bool MunchSemi) {
assert(FormatTok->isOneOf(tok::l_brace, TT_MacroBlockBegin) &&
@@ -459,16 +492,21 @@ void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, bool AddLevel,
const bool MacroBlock = FormatTok->is(TT_MacroBlockBegin);
FormatTok->BlockKind = BK_Block;
+ size_t PPStartHash = computePPHash();
+
unsigned InitialLevel = Line->Level;
- nextToken();
+ nextToken(/*LevelDifference=*/AddLevel ? 1 : 0);
if (MacroBlock && FormatTok->is(tok::l_paren))
parseParens();
+ size_t NbPreprocessorDirectives =
+ CurrentLines == &Lines ? PreprocessorDirectives.size() : 0;
addUnwrappedLine();
- size_t OpeningLineIndex = CurrentLines->empty()
- ? (UnwrappedLine::kInvalidIndex)
- : (CurrentLines->size() - 1);
+ size_t OpeningLineIndex =
+ CurrentLines->empty()
+ ? (UnwrappedLine::kInvalidIndex)
+ : (CurrentLines->size() - 1 - NbPreprocessorDirectives);
ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
MustBeDeclaration);
@@ -486,7 +524,10 @@ void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, bool AddLevel,
return;
}
- nextToken(); // Munch the closing brace.
+ size_t PPEndHash = computePPHash();
+
+ // Munch the closing brace.
+ nextToken(/*LevelDifference=*/AddLevel ? -1 : 0);
if (MacroBlock && FormatTok->is(tok::l_paren))
parseParens();
@@ -494,11 +535,14 @@ void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, bool AddLevel,
if (MunchSemi && FormatTok->Tok.is(tok::semi))
nextToken();
Line->Level = InitialLevel;
- Line->MatchingOpeningBlockLineIndex = OpeningLineIndex;
- if (OpeningLineIndex != UnwrappedLine::kInvalidIndex) {
- // Update the opening line to add the forward reference as well
- (*CurrentLines)[OpeningLineIndex].MatchingOpeningBlockLineIndex =
- CurrentLines->size() - 1;
+
+ if (PPStartHash == PPEndHash) {
+ Line->MatchingOpeningBlockLineIndex = OpeningLineIndex;
+ if (OpeningLineIndex != UnwrappedLine::kInvalidIndex) {
+ // Update the opening line to add the forward reference as well
+ (*CurrentLines)[OpeningLineIndex].MatchingOpeningBlockLineIndex =
+ CurrentLines->size() - 1;
+ }
}
}
@@ -555,9 +599,8 @@ void UnwrappedLineParser::parseChildBlock() {
FormatTok->BlockKind = BK_Block;
nextToken();
{
- bool SkipIndent =
- (Style.Language == FormatStyle::LK_JavaScript &&
- (isGoogScope(*Line) || isIIFE(*Line, Keywords)));
+ bool SkipIndent = (Style.Language == FormatStyle::LK_JavaScript &&
+ (isGoogScope(*Line) || isIIFE(*Line, Keywords)));
ScopedLineState LineState(*this);
ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
/*MustBeDeclaration=*/false);
@@ -606,10 +649,15 @@ void UnwrappedLineParser::parsePPDirective() {
}
void UnwrappedLineParser::conditionalCompilationCondition(bool Unreachable) {
- if (Unreachable || (!PPStack.empty() && PPStack.back() == PP_Unreachable))
- PPStack.push_back(PP_Unreachable);
+ size_t Line = CurrentLines->size();
+ if (CurrentLines == &PreprocessorDirectives)
+ Line += Lines.size();
+
+ if (Unreachable ||
+ (!PPStack.empty() && PPStack.back().Kind == PP_Unreachable))
+ PPStack.push_back({PP_Unreachable, Line});
else
- PPStack.push_back(PP_Conditional);
+ PPStack.push_back({PP_Conditional, Line});
}
void UnwrappedLineParser::conditionalCompilationStart(bool Unreachable) {
@@ -643,7 +691,7 @@ void UnwrappedLineParser::conditionalCompilationEnd() {
}
}
// Guard against #endif's without #if.
- if (PPBranchLevel > 0)
+ if (PPBranchLevel > -1)
--PPBranchLevel;
if (!PPChainBranchIndex.empty())
PPChainBranchIndex.pop();
@@ -660,12 +708,35 @@ void UnwrappedLineParser::parsePPIf(bool IfDef) {
if (IfDef && !IfNDef && FormatTok->TokenText == "SWIG")
Unreachable = true;
conditionalCompilationStart(Unreachable);
+ FormatToken *IfCondition = FormatTok;
+ // If there's a #ifndef on the first line, and the only lines before it are
+ // comments, it could be an include guard.
+ bool MaybeIncludeGuard = IfNDef;
+ if (!IncludeGuardRejected && !FoundIncludeGuardStart && MaybeIncludeGuard) {
+ for (auto &Line : Lines) {
+ if (!Line.Tokens.front().Tok->is(tok::comment)) {
+ MaybeIncludeGuard = false;
+ IncludeGuardRejected = true;
+ break;
+ }
+ }
+ }
+ --PPBranchLevel;
parsePPUnknown();
+ ++PPBranchLevel;
+ if (!IncludeGuardRejected && !FoundIncludeGuardStart && MaybeIncludeGuard)
+ IfNdefCondition = IfCondition;
}
void UnwrappedLineParser::parsePPElse() {
+ // If a potential include guard has an #else, it's not an include guard.
+ if (FoundIncludeGuardStart && PPBranchLevel == 0)
+ FoundIncludeGuardStart = false;
conditionalCompilationAlternative();
+ if (PPBranchLevel > -1)
+ --PPBranchLevel;
parsePPUnknown();
+ ++PPBranchLevel;
}
void UnwrappedLineParser::parsePPElIf() { parsePPElse(); }
@@ -673,6 +744,16 @@ void UnwrappedLineParser::parsePPElIf() { parsePPElse(); }
void UnwrappedLineParser::parsePPEndIf() {
conditionalCompilationEnd();
parsePPUnknown();
+ // If the #endif of a potential include guard is the last thing in the file,
+ // then we count it as a real include guard and subtract one from every
+ // preprocessor indent.
+ unsigned TokenPosition = Tokens->getPosition();
+ FormatToken *PeekNext = AllTokens[TokenPosition];
+ if (FoundIncludeGuardStart && PPBranchLevel == -1 && PeekNext->is(tok::eof) &&
+ Style.IndentPPDirectives != FormatStyle::PPDIS_None)
+ for (auto &Line : Lines)
+ if (Line.InPPDirective && Line.Level > 0)
+ --Line.Level;
}
void UnwrappedLineParser::parsePPDefine() {
@@ -682,14 +763,26 @@ void UnwrappedLineParser::parsePPDefine() {
parsePPUnknown();
return;
}
+ if (IfNdefCondition && IfNdefCondition->TokenText == FormatTok->TokenText) {
+ FoundIncludeGuardStart = true;
+ for (auto &Line : Lines) {
+ if (!Line.Tokens.front().Tok->isOneOf(tok::comment, tok::hash)) {
+ FoundIncludeGuardStart = false;
+ break;
+ }
+ }
+ }
+ IfNdefCondition = nullptr;
nextToken();
if (FormatTok->Tok.getKind() == tok::l_paren &&
FormatTok->WhitespaceRange.getBegin() ==
FormatTok->WhitespaceRange.getEnd()) {
parseParens();
}
+ if (Style.IndentPPDirectives == FormatStyle::PPDIS_AfterHash)
+ Line->Level += PPBranchLevel + 1;
addUnwrappedLine();
- Line->Level = 1;
+ ++Line->Level;
// Errors during a preprocessor directive can only affect the layout of the
// preprocessor directive, and thus we ignore them. An alternative approach
@@ -703,7 +796,10 @@ void UnwrappedLineParser::parsePPUnknown() {
do {
nextToken();
} while (!eof());
+ if (Style.IndentPPDirectives == FormatStyle::PPDIS_AfterHash)
+ Line->Level += PPBranchLevel + 1;
addUnwrappedLine();
+ IfNdefCondition = nullptr;
}
// Here we blacklist certain tokens that are not usually the first token in an
@@ -746,8 +842,8 @@ static bool mustBeJSIdent(const AdditionalKeywords &Keywords,
Keywords.kw_function, Keywords.kw_import, Keywords.kw_is,
Keywords.kw_let, Keywords.kw_var, tok::kw_const,
Keywords.kw_abstract, Keywords.kw_extends, Keywords.kw_implements,
- Keywords.kw_instanceof, Keywords.kw_interface,
- Keywords.kw_throws, Keywords.kw_from));
+ Keywords.kw_instanceof, Keywords.kw_interface, Keywords.kw_throws,
+ Keywords.kw_from));
}
static bool mustBeJSIdentOrValue(const AdditionalKeywords &Keywords,
@@ -800,11 +896,14 @@ void UnwrappedLineParser::readTokenWithJavaScriptASI() {
bool PreviousMustBeValue = mustBeJSIdentOrValue(Keywords, Previous);
bool PreviousStartsTemplateExpr =
Previous->is(TT_TemplateString) && Previous->TokenText.endswith("${");
- if (PreviousMustBeValue && Line && Line->Tokens.size() > 1) {
- // If the token before the previous one is an '@', the previous token is an
- // annotation and can precede another identifier/value.
- const FormatToken *PrePrevious = std::prev(Line->Tokens.end(), 2)->Tok;
- if (PrePrevious->is(tok::at))
+ if (PreviousMustBeValue || Previous->is(tok::r_paren)) {
+ // If the line contains an '@' sign, the previous token might be an
+ // annotation, which can precede another identifier/value.
+ bool HasAt = std::find_if(Line->Tokens.begin(), Line->Tokens.end(),
+ [](UnwrappedLineNode &LineNode) {
+ return LineNode.Tok->is(tok::at);
+ }) != Line->Tokens.end();
+ if (HasAt)
return;
}
if (Next->is(tok::exclaim) && PreviousMustBeValue)
@@ -817,7 +916,8 @@ void UnwrappedLineParser::readTokenWithJavaScriptASI() {
Previous->isOneOf(tok::r_square, tok::r_paren, tok::plusplus,
tok::minusminus)))
return addUnwrappedLine();
- if (PreviousMustBeValue && isJSDeclOrStmt(Keywords, Next))
+ if ((PreviousMustBeValue || Previous->is(tok::r_paren)) &&
+ isJSDeclOrStmt(Keywords, Next))
return addUnwrappedLine();
}
@@ -922,13 +1022,22 @@ void UnwrappedLineParser::parseStructuralElement() {
parseDoWhile();
return;
case tok::kw_switch:
+ if (Style.Language == FormatStyle::LK_JavaScript && Line->MustBeDeclaration)
+ // 'switch: string' field declaration.
+ break;
parseSwitch();
return;
case tok::kw_default:
+ if (Style.Language == FormatStyle::LK_JavaScript && Line->MustBeDeclaration)
+ // 'default: string' field declaration.
+ break;
nextToken();
parseLabel();
return;
case tok::kw_case:
+ if (Style.Language == FormatStyle::LK_JavaScript && Line->MustBeDeclaration)
+ // 'case: string' field declaration.
+ break;
parseCaseLabel();
return;
case tok::kw_try:
@@ -940,7 +1049,12 @@ void UnwrappedLineParser::parseStructuralElement() {
if (FormatTok->Tok.is(tok::string_literal)) {
nextToken();
if (FormatTok->Tok.is(tok::l_brace)) {
- parseBlock(/*MustBeDeclaration=*/true, /*AddLevel=*/false);
+ if (Style.BraceWrapping.AfterExternBlock) {
+ addUnwrappedLine();
+ parseBlock(/*MustBeDeclaration=*/true);
+ } else {
+ parseBlock(/*MustBeDeclaration=*/true, /*AddLevel=*/false);
+ }
addUnwrappedLine();
return;
}
@@ -996,7 +1110,7 @@ void UnwrappedLineParser::parseStructuralElement() {
break;
}
do {
- const FormatToken *Previous = getPreviousToken();
+ const FormatToken *Previous = FormatTok->Previous;
switch (FormatTok->Tok.getKind()) {
case tok::at:
nextToken();
@@ -1186,7 +1300,7 @@ void UnwrappedLineParser::parseStructuralElement() {
nextToken();
parseBracedList();
} else if (Style.Language == FormatStyle::LK_Proto &&
- FormatTok->Tok.is(tok::less)) {
+ FormatTok->Tok.is(tok::less)) {
nextToken();
parseBracedList(/*ContinueOnSemicolons=*/false,
/*ClosingBraceKind=*/tok::greater);
@@ -1210,14 +1324,6 @@ bool UnwrappedLineParser::tryToParseLambda() {
nextToken();
return false;
}
- const FormatToken* Previous = getPreviousToken();
- if (Previous &&
- (Previous->isOneOf(tok::identifier, tok::kw_operator, tok::kw_new,
- tok::kw_delete) ||
- Previous->closesScope() || Previous->isSimpleTypeSpecifier())) {
- nextToken();
- return false;
- }
assert(FormatTok->is(tok::l_square));
FormatToken &LSquare = *FormatTok;
if (!tryToParseLambdaIntroducer())
@@ -1260,49 +1366,18 @@ bool UnwrappedLineParser::tryToParseLambda() {
}
bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
- nextToken();
- if (FormatTok->is(tok::equal)) {
- nextToken();
- if (FormatTok->is(tok::r_square)) {
- nextToken();
- return true;
- }
- if (FormatTok->isNot(tok::comma))
- return false;
- nextToken();
- } else if (FormatTok->is(tok::amp)) {
- nextToken();
- if (FormatTok->is(tok::r_square)) {
- nextToken();
- return true;
- }
- if (!FormatTok->isOneOf(tok::comma, tok::identifier)) {
- return false;
- }
- if (FormatTok->is(tok::comma))
- nextToken();
- } else if (FormatTok->is(tok::r_square)) {
+ const FormatToken *Previous = FormatTok->Previous;
+ if (Previous &&
+ (Previous->isOneOf(tok::identifier, tok::kw_operator, tok::kw_new,
+ tok::kw_delete) ||
+ FormatTok->isCppStructuredBinding(Style) || Previous->closesScope() ||
+ Previous->isSimpleTypeSpecifier())) {
nextToken();
- return true;
+ return false;
}
- do {
- if (FormatTok->is(tok::amp))
- nextToken();
- if (!FormatTok->isOneOf(tok::identifier, tok::kw_this))
- return false;
- nextToken();
- if (FormatTok->is(tok::ellipsis))
- nextToken();
- if (FormatTok->is(tok::comma)) {
- nextToken();
- } else if (FormatTok->is(tok::r_square)) {
- nextToken();
- return true;
- } else {
- return false;
- }
- } while (!eof());
- return false;
+ nextToken();
+ parseSquare(/*LambdaIntroducer=*/true);
+ return true;
}
void UnwrappedLineParser::tryToParseJSFunction() {
@@ -1419,6 +1494,15 @@ bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons,
nextToken();
parseBracedList();
break;
+ case tok::less:
+ if (Style.Language == FormatStyle::LK_Proto) {
+ nextToken();
+ parseBracedList(/*ContinueOnSemicolons=*/false,
+ /*ClosingBraceKind=*/tok::greater);
+ } else {
+ nextToken();
+ }
+ break;
case tok::semi:
// JavaScript (or more precisely TypeScript) can have semicolons in braced
// lists (in so-called TypeMemberLists). Thus, the semicolon cannot be
@@ -1495,10 +1579,12 @@ void UnwrappedLineParser::parseParens() {
} while (!eof());
}
-void UnwrappedLineParser::parseSquare() {
- assert(FormatTok->Tok.is(tok::l_square) && "'[' expected.");
- if (tryToParseLambda())
- return;
+void UnwrappedLineParser::parseSquare(bool LambdaIntroducer) {
+ if (!LambdaIntroducer) {
+ assert(FormatTok->Tok.is(tok::l_square) && "'[' expected.");
+ if (tryToParseLambda())
+ return;
+ }
do {
switch (FormatTok->Tok.getKind()) {
case tok::l_paren:
@@ -1939,6 +2025,17 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
((Style.Language == FormatStyle::LK_Java ||
Style.Language == FormatStyle::LK_JavaScript) &&
FormatTok->isOneOf(tok::period, tok::comma))) {
+ if (Style.Language == FormatStyle::LK_JavaScript &&
+ FormatTok->isOneOf(Keywords.kw_extends, Keywords.kw_implements)) {
+ // JavaScript/TypeScript supports inline object types in
+ // extends/implements positions:
+ // class Foo implements {bar: number} { }
+ nextToken();
+ if (FormatTok->is(tok::l_brace)) {
+ tryToParseBracedList();
+ continue;
+ }
+ }
bool IsNonMacroIdentifier =
FormatTok->is(tok::identifier) &&
FormatTok->TokenText != FormatTok->TokenText.upper();
@@ -2090,7 +2187,7 @@ void UnwrappedLineParser::parseJavaScriptEs6ImportExport() {
while (!eof()) {
if (FormatTok->is(tok::semi))
return;
- if (Line->Tokens.size() == 0) {
+ if (Line->Tokens.empty()) {
// Common issue: Automatic Semicolon Insertion wrapped the line, so the
// import statement should terminate.
return;
@@ -2107,14 +2204,15 @@ void UnwrappedLineParser::parseJavaScriptEs6ImportExport() {
LLVM_ATTRIBUTE_UNUSED static void printDebugInfo(const UnwrappedLine &Line,
StringRef Prefix = "") {
- llvm::dbgs() << Prefix << "Line(" << Line.Level << ")"
+ llvm::dbgs() << Prefix << "Line(" << Line.Level
+ << ", FSC=" << Line.FirstStartColumn << ")"
<< (Line.InPPDirective ? " MACRO" : "") << ": ";
for (std::list<UnwrappedLineNode>::const_iterator I = Line.Tokens.begin(),
E = Line.Tokens.end();
I != E; ++I) {
llvm::dbgs() << I->Tok->Tok.getName() << "["
- << "T=" << I->Tok->Type
- << ", OC=" << I->Tok->OriginalColumn << "] ";
+ << "T=" << I->Tok->Type << ", OC=" << I->Tok->OriginalColumn
+ << "] ";
}
for (std::list<UnwrappedLineNode>::const_iterator I = Line.Tokens.begin(),
E = Line.Tokens.end();
@@ -2140,12 +2238,15 @@ void UnwrappedLineParser::addUnwrappedLine() {
CurrentLines->push_back(std::move(*Line));
Line->Tokens.clear();
Line->MatchingOpeningBlockLineIndex = UnwrappedLine::kInvalidIndex;
+ Line->FirstStartColumn = 0;
if (CurrentLines == &Lines && !PreprocessorDirectives.empty()) {
CurrentLines->append(
std::make_move_iterator(PreprocessorDirectives.begin()),
std::make_move_iterator(PreprocessorDirectives.end()));
PreprocessorDirectives.clear();
}
+ // Disconnect the current token from the last token on the previous line.
+ FormatTok->Previous = nullptr;
}
bool UnwrappedLineParser::eof() const { return FormatTok->Tok.is(tok::eof); }
@@ -2287,23 +2388,17 @@ void UnwrappedLineParser::flushComments(bool NewlineBeforeNext) {
CommentsBeforeNextToken.clear();
}
-void UnwrappedLineParser::nextToken() {
+void UnwrappedLineParser::nextToken(int LevelDifference) {
if (eof())
return;
flushComments(isOnNewLine(*FormatTok));
pushToken(FormatTok);
+ FormatToken *Previous = FormatTok;
if (Style.Language != FormatStyle::LK_JavaScript)
- readToken();
+ readToken(LevelDifference);
else
readTokenWithJavaScriptASI();
-}
-
-const FormatToken *UnwrappedLineParser::getPreviousToken() {
- // FIXME: This is a dirty way to access the previous token. Find a better
- // solution.
- if (!Line || Line->Tokens.empty())
- return nullptr;
- return Line->Tokens.back().Tok;
+ FormatTok->Previous = Previous;
}
void UnwrappedLineParser::distributeComments(
@@ -2343,8 +2438,7 @@ void UnwrappedLineParser::distributeComments(
}
for (unsigned i = 0, e = Comments.size(); i < e; ++i) {
FormatToken *FormatTok = Comments[i];
- if (HasTrailAlignedWithNextToken &&
- i == StartOfTrailAlignedWithNextToken) {
+ if (HasTrailAlignedWithNextToken && i == StartOfTrailAlignedWithNextToken) {
FormatTok->ContinuesLineCommentSection = false;
} else {
FormatTok->ContinuesLineCommentSection =
@@ -2362,7 +2456,7 @@ void UnwrappedLineParser::distributeComments(
}
}
-void UnwrappedLineParser::readToken() {
+void UnwrappedLineParser::readToken(int LevelDifference) {
SmallVector<FormatToken *, 1> Comments;
do {
FormatTok = Tokens->getNextToken();
@@ -2375,6 +2469,10 @@ void UnwrappedLineParser::readToken() {
// directives only after that unwrapped line was finished later.
bool SwitchToPreprocessorLines = !Line->Tokens.empty();
ScopedLineState BlockState(*this, SwitchToPreprocessorLines);
+ assert((LevelDifference >= 0 ||
+ static_cast<unsigned>(-LevelDifference) <= Line->Level) &&
+ "LevelDifference makes Line->Level negative");
+ Line->Level += LevelDifference;
// Comments stored before the preprocessor directive need to be output
// before the preprocessor directive, at the same level as the
// preprocessor directive, as we consider them to apply to the directive.
@@ -2395,7 +2493,7 @@ void UnwrappedLineParser::readToken() {
FormatTok->MustBreakBefore = true;
}
- if (!PPStack.empty() && (PPStack.back() == PP_Unreachable) &&
+ if (!PPStack.empty() && (PPStack.back().Kind == PP_Unreachable) &&
!Line->InPPDirective) {
continue;
}
diff --git a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.h b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.h
index a2aa2f006728e..1d8ccabbd0f8e 100644
--- a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.h
+++ b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.h
@@ -56,6 +56,8 @@ struct UnwrappedLine {
size_t MatchingOpeningBlockLineIndex;
static const size_t kInvalidIndex = -1;
+
+ unsigned FirstStartColumn = 0;
};
class UnwrappedLineConsumer {
@@ -71,6 +73,7 @@ class UnwrappedLineParser {
public:
UnwrappedLineParser(const FormatStyle &Style,
const AdditionalKeywords &Keywords,
+ unsigned FirstStartColumn,
ArrayRef<FormatToken *> Tokens,
UnwrappedLineConsumer &Callback);
@@ -96,7 +99,7 @@ private:
bool parseBracedList(bool ContinueOnSemicolons = false,
tok::TokenKind ClosingBraceKind = tok::r_brace);
void parseParens();
- void parseSquare();
+ void parseSquare(bool LambdaIntroducer = false);
void parseIfThenElse();
void parseTryCatch();
void parseForOrWhileLoop();
@@ -123,9 +126,12 @@ private:
void tryToParseJSFunction();
void addUnwrappedLine();
bool eof() const;
- void nextToken();
- const FormatToken *getPreviousToken();
- void readToken();
+ // LevelDifference is the difference of levels after and before the current
+ // token. For example:
+ // - if the token is '{' and opens a block, LevelDifference is 1.
+ // - if the token is '}' and closes a block, LevelDifference is -1.
+ void nextToken(int LevelDifference = 0);
+ void readToken(int LevelDifference = 0);
// Decides which comment tokens should be added to the current line and which
// should be added as comments before the next token.
@@ -156,6 +162,11 @@ private:
bool isOnNewLine(const FormatToken &FormatTok);
+ // Compute hash of the current preprocessor branch.
+ // This is used to identify the different branches, and thus track if block
+ // open and close in the same branch.
+ size_t computePPHash() const;
+
// FIXME: We are constantly running into bugs where Line.Level is incorrectly
// subtracted from beyond 0. Introduce a method to subtract from Line.Level
// and use that everywhere in the Parser.
@@ -174,7 +185,7 @@ private:
// Preprocessor directives are parsed out-of-order from other unwrapped lines.
// Thus, we need to keep a list of preprocessor directives to be reported
- // after an unwarpped line that has been started was finished.
+ // after an unwrapped line that has been started was finished.
SmallVector<UnwrappedLine, 4> PreprocessorDirectives;
// New unwrapped lines are added via CurrentLines.
@@ -207,8 +218,14 @@ private:
PP_Unreachable // #if 0 or a conditional preprocessor block inside #if 0
};
+ struct PPBranch {
+ PPBranch(PPBranchKind Kind, size_t Line) : Kind(Kind), Line(Line) {}
+ PPBranchKind Kind;
+ size_t Line;
+ };
+
// Keeps a stack of currently active preprocessor branching directives.
- SmallVector<PPBranchKind, 16> PPStack;
+ SmallVector<PPBranch, 16> PPStack;
// The \c UnwrappedLineParser re-parses the code for each combination
// of preprocessor branches that can be taken.
@@ -231,6 +248,15 @@ private:
// sequence.
std::stack<int> PPChainBranchIndex;
+ // Contains the #ifndef condition for a potential include guard.
+ FormatToken *IfNdefCondition;
+ bool FoundIncludeGuardStart;
+ bool IncludeGuardRejected;
+ // Contains the first start column where the source begins. This is zero for
+ // normal source code and may be nonzero when formatting a code fragment that
+ // does not start at the beginning of the file.
+ unsigned FirstStartColumn;
+
friend class ScopedLineState;
friend class CompoundStatementIndenter;
};
@@ -243,8 +269,9 @@ struct UnwrappedLineNode {
SmallVector<UnwrappedLine, 0> Children;
};
-inline UnwrappedLine::UnwrappedLine() : Level(0), InPPDirective(false),
- MustBeDeclaration(false), MatchingOpeningBlockLineIndex(kInvalidIndex) {}
+inline UnwrappedLine::UnwrappedLine()
+ : Level(0), InPPDirective(false), MustBeDeclaration(false),
+ MatchingOpeningBlockLineIndex(kInvalidIndex) {}
} // end namespace format
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Format/UsingDeclarationsSorter.cpp b/contrib/llvm/tools/clang/lib/Format/UsingDeclarationsSorter.cpp
index fb4f59fbc9bcf..ef0c7a7d5a45e 100644
--- a/contrib/llvm/tools/clang/lib/Format/UsingDeclarationsSorter.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/UsingDeclarationsSorter.cpp
@@ -26,6 +26,45 @@ namespace format {
namespace {
+// The order of using declaration is defined as follows:
+// Split the strings by "::" and discard any initial empty strings. The last
+// element of each list is a non-namespace name; all others are namespace
+// names. Sort the lists of names lexicographically, where the sort order of
+// individual names is that all non-namespace names come before all namespace
+// names, and within those groups, names are in case-insensitive lexicographic
+// order.
+int compareLabels(StringRef A, StringRef B) {
+ SmallVector<StringRef, 2> NamesA;
+ A.split(NamesA, "::", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+ SmallVector<StringRef, 2> NamesB;
+ B.split(NamesB, "::", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+ size_t SizeA = NamesA.size();
+ size_t SizeB = NamesB.size();
+ for (size_t I = 0, E = std::min(SizeA, SizeB); I < E; ++I) {
+ if (I + 1 == SizeA) {
+ // I is the last index of NamesA and NamesA[I] is a non-namespace name.
+
+ // Non-namespace names come before all namespace names.
+ if (SizeB > SizeA)
+ return -1;
+
+ // Two names within a group compare case-insensitively.
+ return NamesA[I].compare_lower(NamesB[I]);
+ }
+
+ // I is the last index of NamesB and NamesB[I] is a non-namespace name.
+ // Non-namespace names come before all namespace names.
+ if (I + 1 == SizeB)
+ return 1;
+
+ // Two namespaces names within a group compare case-insensitively.
+ int C = NamesA[I].compare_lower(NamesB[I]);
+ if (C != 0)
+ return C;
+ }
+ return 0;
+}
+
struct UsingDeclaration {
const AnnotatedLine *Line;
std::string Label;
@@ -34,7 +73,7 @@ struct UsingDeclaration {
: Line(Line), Label(Label) {}
bool operator<(const UsingDeclaration &Other) const {
- return Label < Other.Label;
+ return compareLabels(Label, Other.Label) < 0;
}
};
@@ -76,10 +115,42 @@ std::string computeUsingDeclarationLabel(const FormatToken *UsingTok) {
void endUsingDeclarationBlock(
SmallVectorImpl<UsingDeclaration> *UsingDeclarations,
const SourceManager &SourceMgr, tooling::Replacements *Fixes) {
+ bool BlockAffected = false;
+ for (const UsingDeclaration &Declaration : *UsingDeclarations) {
+ if (Declaration.Line->Affected) {
+ BlockAffected = true;
+ break;
+ }
+ }
+ if (!BlockAffected) {
+ UsingDeclarations->clear();
+ return;
+ }
SmallVector<UsingDeclaration, 4> SortedUsingDeclarations(
UsingDeclarations->begin(), UsingDeclarations->end());
- std::sort(SortedUsingDeclarations.begin(), SortedUsingDeclarations.end());
+ std::stable_sort(SortedUsingDeclarations.begin(),
+ SortedUsingDeclarations.end());
+ SortedUsingDeclarations.erase(
+ std::unique(SortedUsingDeclarations.begin(),
+ SortedUsingDeclarations.end(),
+ [](const UsingDeclaration &a, const UsingDeclaration &b) {
+ return a.Label == b.Label;
+ }),
+ SortedUsingDeclarations.end());
for (size_t I = 0, E = UsingDeclarations->size(); I < E; ++I) {
+ if (I >= SortedUsingDeclarations.size()) {
+ // This using declaration has been deduplicated, delete it.
+ auto Begin =
+ (*UsingDeclarations)[I].Line->First->WhitespaceRange.getBegin();
+ auto End = (*UsingDeclarations)[I].Line->Last->Tok.getEndLoc();
+ auto Range = CharSourceRange::getCharRange(Begin, End);
+ auto Err = Fixes->add(tooling::Replacement(SourceMgr, Range, ""));
+ if (Err) {
+ llvm::errs() << "Error while sorting using declarations: "
+ << llvm::toString(std::move(Err)) << "\n";
+ }
+ continue;
+ }
if ((*UsingDeclarations)[I].Line == SortedUsingDeclarations[I].Line)
continue;
auto Begin = (*UsingDeclarations)[I].Line->First->Tok.getLocation();
@@ -112,7 +183,7 @@ UsingDeclarationsSorter::UsingDeclarationsSorter(const Environment &Env,
const FormatStyle &Style)
: TokenAnalyzer(Env, Style) {}
-tooling::Replacements UsingDeclarationsSorter::analyze(
+std::pair<tooling::Replacements, unsigned> UsingDeclarationsSorter::analyze(
TokenAnnotator &Annotator, SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
FormatTokenLexer &Tokens) {
const SourceManager &SourceMgr = Env.getSourceManager();
@@ -121,15 +192,17 @@ tooling::Replacements UsingDeclarationsSorter::analyze(
tooling::Replacements Fixes;
SmallVector<UsingDeclaration, 4> UsingDeclarations;
for (size_t I = 0, E = AnnotatedLines.size(); I != E; ++I) {
- if (!AnnotatedLines[I]->Affected || AnnotatedLines[I]->InPPDirective ||
- !AnnotatedLines[I]->startsWith(tok::kw_using) ||
- AnnotatedLines[I]->First->Finalized) {
+ const auto *FirstTok = AnnotatedLines[I]->First;
+ if (AnnotatedLines[I]->InPPDirective ||
+ !AnnotatedLines[I]->startsWith(tok::kw_using) || FirstTok->Finalized) {
endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes);
continue;
}
- if (AnnotatedLines[I]->First->NewlinesBefore > 1)
+ if (FirstTok->NewlinesBefore > 1)
endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes);
- std::string Label = computeUsingDeclarationLabel(AnnotatedLines[I]->First);
+ const auto *UsingTok =
+ FirstTok->is(tok::comment) ? FirstTok->getNextNonComment() : FirstTok;
+ std::string Label = computeUsingDeclarationLabel(UsingTok);
if (Label.empty()) {
endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes);
continue;
@@ -137,7 +210,7 @@ tooling::Replacements UsingDeclarationsSorter::analyze(
UsingDeclarations.push_back(UsingDeclaration(AnnotatedLines[I], Label));
}
endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes);
- return Fixes;
+ return {Fixes, 0};
}
} // namespace format
diff --git a/contrib/llvm/tools/clang/lib/Format/UsingDeclarationsSorter.h b/contrib/llvm/tools/clang/lib/Format/UsingDeclarationsSorter.h
index f7d5f97e3a2af..6f137712d8416 100644
--- a/contrib/llvm/tools/clang/lib/Format/UsingDeclarationsSorter.h
+++ b/contrib/llvm/tools/clang/lib/Format/UsingDeclarationsSorter.h
@@ -25,7 +25,7 @@ class UsingDeclarationsSorter : public TokenAnalyzer {
public:
UsingDeclarationsSorter(const Environment &Env, const FormatStyle &Style);
- tooling::Replacements
+ std::pair<tooling::Replacements, unsigned>
analyze(TokenAnnotator &Annotator,
SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
FormatTokenLexer &Tokens) override;
diff --git a/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.cpp b/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.cpp
index 377ec3a681b63..a5477a996327b 100644
--- a/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.cpp
@@ -67,6 +67,11 @@ void WhitespaceManager::addUntouchableToken(const FormatToken &Tok,
/*IsInsideToken=*/false));
}
+llvm::Error
+WhitespaceManager::addReplacement(const tooling::Replacement &Replacement) {
+ return Replaces.add(Replacement);
+}
+
void WhitespaceManager::replaceWhitespaceInToken(
const FormatToken &Tok, unsigned Offset, unsigned ReplaceChars,
StringRef PreviousPostfix, StringRef CurrentPrefix, bool InPPDirective,
@@ -166,15 +171,15 @@ void WhitespaceManager::calculateLineBreakInformation() {
// BreakableLineCommentSection does comment reflow changes and here is
// the aligning of trailing comments. Consider the case where we reflow
// the second line up in this example:
- //
+ //
// // line 1
// // line 2
- //
+ //
// That amounts to 2 changes by BreakableLineCommentSection:
// - the first, delimited by (), for the whitespace between the tokens,
// - and second, delimited by [], for the whitespace at the beginning
// of the second token:
- //
+ //
// // line 1(
// )[// ]line 2
//
@@ -608,8 +613,9 @@ void WhitespaceManager::generateChanges() {
if (C.CreateReplacement) {
std::string ReplacementText = C.PreviousLinePostfix;
if (C.ContinuesPPDirective)
- appendNewlineText(ReplacementText, C.NewlinesBefore,
- C.PreviousEndOfTokenColumn, C.EscapedNewlineColumn);
+ appendEscapedNewlineText(ReplacementText, C.NewlinesBefore,
+ C.PreviousEndOfTokenColumn,
+ C.EscapedNewlineColumn);
else
appendNewlineText(ReplacementText, C.NewlinesBefore);
appendIndentText(ReplacementText, C.Tok->IndentLevel,
@@ -621,8 +627,7 @@ void WhitespaceManager::generateChanges() {
}
}
-void WhitespaceManager::storeReplacement(SourceRange Range,
- StringRef Text) {
+void WhitespaceManager::storeReplacement(SourceRange Range, StringRef Text) {
unsigned WhitespaceLength = SourceMgr.getFileOffset(Range.getEnd()) -
SourceMgr.getFileOffset(Range.getBegin());
// Don't create a replacement, if it does not change anything.
@@ -645,16 +650,16 @@ void WhitespaceManager::appendNewlineText(std::string &Text,
Text.append(UseCRLF ? "\r\n" : "\n");
}
-void WhitespaceManager::appendNewlineText(std::string &Text, unsigned Newlines,
- unsigned PreviousEndOfTokenColumn,
- unsigned EscapedNewlineColumn) {
+void WhitespaceManager::appendEscapedNewlineText(
+ std::string &Text, unsigned Newlines, unsigned PreviousEndOfTokenColumn,
+ unsigned EscapedNewlineColumn) {
if (Newlines > 0) {
- unsigned Offset =
- std::min<int>(EscapedNewlineColumn - 2, PreviousEndOfTokenColumn);
+ unsigned Spaces =
+ std::max<int>(1, EscapedNewlineColumn - PreviousEndOfTokenColumn - 1);
for (unsigned i = 0; i < Newlines; ++i) {
- Text.append(EscapedNewlineColumn - Offset - 1, ' ');
+ Text.append(Spaces, ' ');
Text.append(UseCRLF ? "\\\r\n" : "\\\n");
- Offset = 0;
+ Spaces = std::max<int>(0, EscapedNewlineColumn - 1);
}
}
}
diff --git a/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.h b/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.h
index 4e78ab43abaf7..af20dc5616a70 100644
--- a/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.h
+++ b/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.h
@@ -57,6 +57,8 @@ public:
/// was not called.
void addUntouchableToken(const FormatToken &Tok, bool InPPDirective);
+ llvm::Error addReplacement(const tooling::Replacement &Replacement);
+
/// \brief Inserts or replaces whitespace in the middle of a token.
///
/// Inserts \p PreviousPostfix, \p Newlines, \p Spaces and \p CurrentPrefix
@@ -194,9 +196,9 @@ private:
/// \brief Stores \p Text as the replacement for the whitespace in \p Range.
void storeReplacement(SourceRange Range, StringRef Text);
void appendNewlineText(std::string &Text, unsigned Newlines);
- void appendNewlineText(std::string &Text, unsigned Newlines,
- unsigned PreviousEndOfTokenColumn,
- unsigned EscapedNewlineColumn);
+ void appendEscapedNewlineText(std::string &Text, unsigned Newlines,
+ unsigned PreviousEndOfTokenColumn,
+ unsigned EscapedNewlineColumn);
void appendIndentText(std::string &Text, unsigned IndentLevel,
unsigned Spaces, unsigned WhitespaceStartColumn);
diff --git a/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp b/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp
index 1094e6d089a65..1160df15a9201 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp
@@ -243,7 +243,8 @@ static unsigned getDeclShowContexts(const NamedDecl *ND,
uint64_t Contexts = 0;
if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND) ||
- isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND)) {
+ isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND) ||
+ isa<TypeAliasTemplateDecl>(ND)) {
// Types can appear in these contexts.
if (LangOpts.CPlusPlus || !isa<TagDecl>(ND))
Contexts |= (1LL << CodeCompletionContext::CCC_TopLevel)
@@ -263,8 +264,12 @@ static unsigned getDeclShowContexts(const NamedDecl *ND,
Contexts |= (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver);
// In Objective-C, you can only be a subclass of another Objective-C class
- if (isa<ObjCInterfaceDecl>(ND))
+ if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {
+ // Objective-C interfaces can be used in a class property expression.
+ if (ID->getDefinition())
+ Contexts |= (1LL << CodeCompletionContext::CCC_Expression);
Contexts |= (1LL << CodeCompletionContext::CCC_ObjCInterfaceName);
+ }
// Deal with tag names.
if (isa<EnumDecl>(ND)) {
@@ -542,6 +547,9 @@ private:
// Initialize the ASTContext
Context->InitBuiltinTypes(*Target);
+ // Adjust printing policy based on language options.
+ Context->setPrintingPolicy(PrintingPolicy(LangOpt));
+
// We didn't have access to the comment options when the ASTContext was
// constructed, so register them now.
Context->getCommentCommandTraits().registerCommentOptions(
@@ -962,9 +970,8 @@ public:
}
}
- void HandleMacroDefined(const Token &MacroNameTok,
- const MacroDirective *MD) override {
- AddDefinedMacroToHash(MacroNameTok, Hash);
+ std::unique_ptr<PPCallbacks> createPPCallbacks() override {
+ return llvm::make_unique<MacroDefinitionTrackerPPCallbacks>(Hash);
}
private:
@@ -1016,6 +1023,19 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
if (!Invocation)
return true;
+ auto CCInvocation = std::make_shared<CompilerInvocation>(*Invocation);
+ if (OverrideMainBuffer) {
+ assert(Preamble &&
+ "No preamble was built, but OverrideMainBuffer is not null");
+ IntrusiveRefCntPtr<vfs::FileSystem> OldVFS = VFS;
+ Preamble->AddImplicitPreamble(*CCInvocation, VFS, OverrideMainBuffer.get());
+ if (OldVFS != VFS && FileMgr) {
+ assert(OldVFS == FileMgr->getVirtualFileSystem() &&
+ "VFS passed to Parse and VFS in FileMgr are different");
+ FileMgr = new FileManager(FileMgr->getFileSystemOpts(), VFS);
+ }
+ }
+
// Create the compiler instance to use for building the AST.
std::unique_ptr<CompilerInstance> Clang(
new CompilerInstance(std::move(PCHContainerOps)));
@@ -1030,7 +1050,7 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
CICleanup(Clang.get());
- Clang->setInvocation(std::make_shared<CompilerInvocation>(*Invocation));
+ Clang->setInvocation(CCInvocation);
OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].getFile();
// Set up diagnostics, capturing any diagnostics that would
@@ -1084,9 +1104,6 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
// If the main file has been overridden due to the use of a preamble,
// make that override happen and introduce the preamble.
if (OverrideMainBuffer) {
- assert(Preamble && "No preamble was built, but OverrideMainBuffer is not null");
- Preamble->AddImplicitPreamble(Clang->getInvocation(), OverrideMainBuffer.get());
-
// The stored diagnostic has the old source manager in it; update
// the locations to refer into the new source manager. Since we've
// been careful to make sure that the source manager's state
@@ -1275,7 +1292,7 @@ ASTUnit::getMainBufferWithPrecompiledPreamble(
llvm::ErrorOr<PrecompiledPreamble> NewPreamble = PrecompiledPreamble::Build(
PreambleInvocationIn, MainFileBuffer.get(), Bounds, *Diagnostics, VFS,
- PCHContainerOps, Callbacks);
+ PCHContainerOps, /*StoreInMemory=*/false, Callbacks);
if (NewPreamble) {
Preamble = std::move(*NewPreamble);
PreambleRebuildCounter = 1;
@@ -1658,7 +1675,6 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
PreprocessorOptions &PPOpts = CI->getPreprocessorOpts();
PPOpts.RemappedFilesKeepOriginalName = RemappedFilesKeepOriginalName;
PPOpts.AllowPCHWithCompilerErrors = AllowPCHWithCompilerErrors;
- PPOpts.GeneratePreamble = PrecompilePreambleAfterNParses != 0;
PPOpts.SingleFileParseMode = SingleFileParse;
// Override the resources path.
@@ -2152,8 +2168,16 @@ void ASTUnit::CodeComplete(
// If the main file has been overridden due to the use of a preamble,
// make that override happen and introduce the preamble.
if (OverrideMainBuffer) {
- assert(Preamble && "No preamble was built, but OverrideMainBuffer is not null");
- Preamble->AddImplicitPreamble(Clang->getInvocation(), OverrideMainBuffer.get());
+ assert(Preamble &&
+ "No preamble was built, but OverrideMainBuffer is not null");
+
+ auto VFS = FileMgr.getVirtualFileSystem();
+ Preamble->AddImplicitPreamble(Clang->getInvocation(), VFS,
+ OverrideMainBuffer.get());
+ // FIXME: there is no way to update VFS if it was changed by
+ // AddImplicitPreamble as FileMgr is accepted as a parameter by this method.
+ // We use on-disk preambles instead and rely on FileMgr's VFS to ensure the
+ // PCH files are always readable.
OwnedBuffers.push_back(OverrideMainBuffer.release());
} else {
PreprocessorOpts.PrecompiledPreambleBytes.first = 0;
@@ -2395,7 +2419,7 @@ SourceLocation ASTUnit::getLocation(const FileEntry *File,
/// \brief If \arg Loc is a loaded location from the preamble, returns
/// the corresponding local location of the main file, otherwise it returns
/// \arg Loc.
-SourceLocation ASTUnit::mapLocationFromPreamble(SourceLocation Loc) {
+SourceLocation ASTUnit::mapLocationFromPreamble(SourceLocation Loc) const {
FileID PreambleID;
if (SourceMgr)
PreambleID = SourceMgr->getPreambleFileID();
@@ -2416,7 +2440,7 @@ SourceLocation ASTUnit::mapLocationFromPreamble(SourceLocation Loc) {
/// \brief If \arg Loc is a local location of the main file but inside the
/// preamble chunk, returns the corresponding loaded location from the
/// preamble, otherwise it returns \arg Loc.
-SourceLocation ASTUnit::mapLocationToPreamble(SourceLocation Loc) {
+SourceLocation ASTUnit::mapLocationToPreamble(SourceLocation Loc) const {
FileID PreambleID;
if (SourceMgr)
PreambleID = SourceMgr->getPreambleFileID();
@@ -2434,7 +2458,7 @@ SourceLocation ASTUnit::mapLocationToPreamble(SourceLocation Loc) {
return Loc;
}
-bool ASTUnit::isInPreambleFileID(SourceLocation Loc) {
+bool ASTUnit::isInPreambleFileID(SourceLocation Loc) const {
FileID FID;
if (SourceMgr)
FID = SourceMgr->getPreambleFileID();
@@ -2445,7 +2469,7 @@ bool ASTUnit::isInPreambleFileID(SourceLocation Loc) {
return SourceMgr->isInFileID(Loc, FID);
}
-bool ASTUnit::isInMainFileID(SourceLocation Loc) {
+bool ASTUnit::isInMainFileID(SourceLocation Loc) const {
FileID FID;
if (SourceMgr)
FID = SourceMgr->getMainFileID();
@@ -2456,7 +2480,7 @@ bool ASTUnit::isInMainFileID(SourceLocation Loc) {
return SourceMgr->isInFileID(Loc, FID);
}
-SourceLocation ASTUnit::getEndOfPreambleFileID() {
+SourceLocation ASTUnit::getEndOfPreambleFileID() const {
FileID FID;
if (SourceMgr)
FID = SourceMgr->getPreambleFileID();
@@ -2467,7 +2491,7 @@ SourceLocation ASTUnit::getEndOfPreambleFileID() {
return SourceMgr->getLocForEndOfFile(FID);
}
-SourceLocation ASTUnit::getStartOfMainFileID() {
+SourceLocation ASTUnit::getStartOfMainFileID() const {
FileID FID;
if (SourceMgr)
FID = SourceMgr->getMainFileID();
@@ -2543,7 +2567,7 @@ const FileEntry *ASTUnit::getPCHFile() {
return nullptr;
}
-bool ASTUnit::isModuleFile() {
+bool ASTUnit::isModuleFile() const {
return isMainFileAST() && getLangOpts().isCompilingModule();
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp b/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp
index bb6a665cb4565..32f1232bbe246 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp
@@ -300,12 +300,16 @@ CompilerInstance::createDiagnostics(DiagnosticOptions *Opts,
// File Manager
-void CompilerInstance::createFileManager() {
+FileManager *CompilerInstance::createFileManager() {
if (!hasVirtualFileSystem()) {
- // TODO: choose the virtual file system based on the CompilerInvocation.
- setVirtualFileSystem(vfs::getRealFileSystem());
+ if (IntrusiveRefCntPtr<vfs::FileSystem> VFS =
+ createVFSFromCompilerInvocation(getInvocation(), getDiagnostics()))
+ setVirtualFileSystem(VFS);
+ else
+ return nullptr;
}
FileMgr = new FileManager(getFileSystemOpts(), VirtualFileSystem);
+ return FileMgr.get();
}
// Source Manager
@@ -382,6 +386,7 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
Invocation->getPreprocessorOptsPtr(), getDiagnostics(), getLangOpts(),
getSourceManager(), getPCMCache(), *HeaderInfo, *this, PTHMgr,
/*OwnsHeaderSearch=*/true, TUKind);
+ getTarget().adjust(getLangOpts());
PP->Initialize(getTarget(), getAuxTarget());
// Note that this is different then passing PTHMgr to Preprocessor's ctor.
@@ -759,9 +764,15 @@ std::unique_ptr<llvm::raw_pwrite_stream> CompilerInstance::createOutputFile(
if (UseTemporary) {
// Create a temporary file.
- SmallString<128> TempPath;
- TempPath = OutFile;
+ // Insert -%%%%%%%% before the extension (if any), and because some tools
+ // (noticeable, clang's own GlobalModuleIndex.cpp) glob for build
+ // artifacts, also append .tmp.
+ StringRef OutputExtension = llvm::sys::path::extension(OutFile);
+ SmallString<128> TempPath =
+ StringRef(OutFile).drop_back(OutputExtension.size());
TempPath += "-%%%%%%%%";
+ TempPath += OutputExtension;
+ TempPath += ".tmp";
int fd;
std::error_code EC =
llvm::sys::fs::createUniqueFile(TempPath, fd, TempPath);
@@ -832,8 +843,8 @@ bool CompilerInstance::InitializeSourceManager(
: Input.isSystem() ? SrcMgr::C_System : SrcMgr::C_User;
if (Input.isBuffer()) {
- SourceMgr.setMainFileID(SourceMgr.createFileID(
- std::unique_ptr<llvm::MemoryBuffer>(Input.getBuffer()), Kind));
+ SourceMgr.setMainFileID(SourceMgr.createFileID(SourceManager::Unowned,
+ Input.getBuffer(), Kind));
assert(SourceMgr.getMainFileID().isValid() &&
"Couldn't establish MainFileID!");
return true;
@@ -997,8 +1008,17 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
OS << " and ";
if (NumErrors)
OS << NumErrors << " error" << (NumErrors == 1 ? "" : "s");
- if (NumWarnings || NumErrors)
- OS << " generated.\n";
+ if (NumWarnings || NumErrors) {
+ OS << " generated";
+ if (getLangOpts().CUDA) {
+ if (!getLangOpts().CUDAIsDevice) {
+ OS << " when compiling for host";
+ } else {
+ OS << " when compiling for " << getTargetOpts().CPU;
+ }
+ }
+ OS << ".\n";
+ }
}
if (getFrontendOpts().ShowStats) {
@@ -1595,7 +1615,22 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
Module::NameVisibilityKind Visibility,
bool IsInclusionDirective) {
// Determine what file we're searching from.
- StringRef ModuleName = Path[0].first->getName();
+ // FIXME: Should we be deciding whether this is a submodule (here and
+ // below) based on -fmodules-ts or should we pass a flag and make the
+ // caller decide?
+ std::string ModuleName;
+ if (getLangOpts().ModulesTS) {
+ // FIXME: Same code as Sema::ActOnModuleDecl() so there is probably a
+ // better place/way to do this.
+ for (auto &Piece : Path) {
+ if (!ModuleName.empty())
+ ModuleName += ".";
+ ModuleName += Piece.first->getName();
+ }
+ }
+ else
+ ModuleName = Path[0].first->getName();
+
SourceLocation ModuleNameLoc = Path[0].second;
// If we've already handled this import, just return the cached result.
@@ -1620,6 +1655,14 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
} else if (ModuleName == getLangOpts().CurrentModule) {
// This is the module we're building.
Module = PP->getHeaderSearchInfo().lookupModule(ModuleName);
+ /// FIXME: perhaps we should (a) look for a module using the module name
+ // to file map (PrebuiltModuleFiles) and (b) diagnose if still not found?
+ //if (Module == nullptr) {
+ // getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_found)
+ // << ModuleName;
+ // ModuleBuildFailed = true;
+ // return ModuleLoadResult();
+ //}
Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first;
} else {
// Search for a module with the given name.
@@ -1641,16 +1684,17 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
}
// Try to load the module from the prebuilt module path.
- if (Source == ModuleNotFound && !HSOpts.PrebuiltModulePaths.empty()) {
- ModuleFileName = PP->getHeaderSearchInfo().getModuleFileName(
- ModuleName, "", /*UsePrebuiltPath*/ true);
+ if (Source == ModuleNotFound && (!HSOpts.PrebuiltModuleFiles.empty() ||
+ !HSOpts.PrebuiltModulePaths.empty())) {
+ ModuleFileName =
+ PP->getHeaderSearchInfo().getPrebuiltModuleFileName(ModuleName);
if (!ModuleFileName.empty())
Source = PrebuiltModulePath;
}
// Try to load the module from the module cache.
if (Source == ModuleNotFound && Module) {
- ModuleFileName = PP->getHeaderSearchInfo().getModuleFileName(Module);
+ ModuleFileName = PP->getHeaderSearchInfo().getCachedModuleFileName(Module);
Source = ModuleCache;
}
@@ -1810,7 +1854,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
// Verify that the rest of the module path actually corresponds to
// a submodule.
- if (Path.size() > 1) {
+ if (!getLangOpts().ModulesTS && Path.size() > 1) {
for (unsigned I = 1, N = Path.size(); I != N; ++I) {
StringRef Name = Path[I].first->getName();
clang::Module *Sub = Module->findSubmodule(Name);
diff --git a/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp b/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
index 0d0869c815d3b..2e8a737de4e42 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
@@ -527,7 +527,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file);
Opts.SplitDwarfInlining = !Args.hasArg(OPT_fno_split_dwarf_inlining);
Opts.DebugTypeExtRefs = Args.hasArg(OPT_dwarf_ext_refs);
- Opts.DebugExplicitImport = Triple.isPS4CPU();
+ Opts.DebugExplicitImport = Args.hasArg(OPT_dwarf_explicit_import);
+ Opts.DebugFwdTemplateParams = Args.hasArg(OPT_debug_forward_template_params);
for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ))
Opts.DebugPrefixMap.insert(StringRef(Arg).split('='));
@@ -545,6 +546,11 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
OPT_fuse_register_sized_bitfield_access);
Opts.RelaxedAliasing = Args.hasArg(OPT_relaxed_aliasing);
Opts.StructPathTBAA = !Args.hasArg(OPT_no_struct_path_tbaa);
+ Opts.NewStructPathTBAA = !Args.hasArg(OPT_no_struct_path_tbaa) &&
+ Args.hasArg(OPT_new_struct_path_tbaa);
+ Opts.FineGrainedBitfieldAccesses =
+ Args.hasFlag(OPT_ffine_grained_bitfield_accesses,
+ OPT_fno_fine_grained_bitfield_accesses, false);
Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags);
Opts.MergeAllConstants = !Args.hasArg(OPT_fno_merge_all_constants);
Opts.NoCommon = Args.hasArg(OPT_fno_common);
@@ -564,6 +570,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.SampleProfileFile = Args.getLastArgValue(OPT_fprofile_sample_use_EQ);
Opts.DebugInfoForProfiling = Args.hasFlag(
OPT_fdebug_info_for_profiling, OPT_fno_debug_info_for_profiling, false);
+ Opts.GnuPubnames = Args.hasArg(OPT_ggnu_pubnames);
setPGOInstrumentor(Opts, Args, Diags);
Opts.InstrProfileOutput =
@@ -632,9 +639,11 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Args.hasArg(OPT_cl_no_signed_zeros) ||
Args.hasArg(OPT_cl_unsafe_math_optimizations) ||
Args.hasArg(OPT_cl_fast_relaxed_math));
+ Opts.Reassociate = Args.hasArg(OPT_mreassociate);
Opts.FlushDenorm = Args.hasArg(OPT_cl_denorms_are_zero);
Opts.CorrectlyRoundedDivSqrt =
Args.hasArg(OPT_cl_fp32_correctly_rounded_divide_sqrt);
+ Opts.Reciprocals = Args.getAllArgValues(OPT_mrecip_EQ);
Opts.ReciprocalMath = Args.hasArg(OPT_freciprocal_math);
Opts.NoTrappingMath = Args.hasArg(OPT_fno_trapping_math);
Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss);
@@ -648,6 +657,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Args.hasArg(OPT_mincremental_linker_compatible);
Opts.PIECopyRelocations =
Args.hasArg(OPT_mpie_copy_relocations);
+ Opts.NoPLT = Args.hasArg(OPT_fno_plt);
Opts.OmitLeafFramePointer = Args.hasArg(OPT_momit_leaf_frame_pointer);
Opts.SaveTempLabels = Args.hasArg(OPT_msave_temp_labels);
Opts.NoDwarfDirectoryAsm = Args.hasArg(OPT_fno_dwarf_directory_asm);
@@ -679,6 +689,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.NoUseJumpTables = Args.hasArg(OPT_fno_jump_tables);
+ Opts.ProfileSampleAccurate = Args.hasArg(OPT_fprofile_sample_accurate);
+
Opts.PrepareForLTO = Args.hasArg(OPT_flto, OPT_flto_EQ);
Opts.EmitSummaryIndex = false;
if (Arg *A = Args.getLastArg(OPT_flto_EQ)) {
@@ -702,6 +714,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.VectorizeLoop = Args.hasArg(OPT_vectorize_loops);
Opts.VectorizeSLP = Args.hasArg(OPT_vectorize_slp);
+ Opts.PreferVectorWidth = Args.getLastArgValue(OPT_mprefer_vector_width_EQ);
+
Opts.MainFileName = Args.getLastArgValue(OPT_main_file_name);
Opts.VerifyModule = !Args.hasArg(OPT_disable_llvm_verifier);
@@ -769,7 +783,13 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.PreserveVec3Type = Args.hasArg(OPT_fpreserve_vec3_type);
Opts.InstrumentFunctions = Args.hasArg(OPT_finstrument_functions);
+ Opts.InstrumentFunctionsAfterInlining =
+ Args.hasArg(OPT_finstrument_functions_after_inlining);
+ Opts.InstrumentFunctionEntryBare =
+ Args.hasArg(OPT_finstrument_function_entry_bare);
Opts.XRayInstrumentFunctions = Args.hasArg(OPT_fxray_instrument);
+ Opts.XRayAlwaysEmitCustomEvents =
+ Args.hasArg(OPT_fxray_always_emit_customevents);
Opts.XRayInstructionThreshold =
getLastArgIntValue(Args, OPT_fxray_instruction_threshold_EQ, 200, Diags);
Opts.InstrumentForProfiling = Args.hasArg(OPT_pg);
@@ -821,11 +841,19 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.SanitizeCoverageNoPrune = Args.hasArg(OPT_fsanitize_coverage_no_prune);
Opts.SanitizeCoverageInline8bitCounters =
Args.hasArg(OPT_fsanitize_coverage_inline_8bit_counters);
+ Opts.SanitizeCoveragePCTable = Args.hasArg(OPT_fsanitize_coverage_pc_table);
+ Opts.SanitizeCoverageStackDepth =
+ Args.hasArg(OPT_fsanitize_coverage_stack_depth);
Opts.SanitizeMemoryTrackOrigins =
getLastArgIntValue(Args, OPT_fsanitize_memory_track_origins_EQ, 0, Diags);
Opts.SanitizeMemoryUseAfterDtor =
- Args.hasArg(OPT_fsanitize_memory_use_after_dtor);
+ Args.hasFlag(OPT_fsanitize_memory_use_after_dtor,
+ OPT_fno_sanitize_memory_use_after_dtor,
+ false);
+ Opts.SanitizeMinimalRuntime = Args.hasArg(OPT_fsanitize_minimal_runtime);
Opts.SanitizeCfiCrossDso = Args.hasArg(OPT_fsanitize_cfi_cross_dso);
+ Opts.SanitizeCfiICallGeneralizePointers =
+ Args.hasArg(OPT_fsanitize_cfi_icall_generalize_pointers);
Opts.SanitizeStats = Args.hasArg(OPT_fsanitize_stats);
if (Arg *A = Args.getLastArg(OPT_fsanitize_address_use_after_scope,
OPT_fno_sanitize_address_use_after_scope)) {
@@ -1003,9 +1031,12 @@ static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
// They won't be discovered by the regular preprocessor, so
// we let make / ninja to know about this implicit dependency.
Opts.ExtraDeps = Args.getAllArgValues(OPT_fdepfile_entry);
- auto ModuleFiles = Args.getAllArgValues(OPT_fmodule_file);
- Opts.ExtraDeps.insert(Opts.ExtraDeps.end(), ModuleFiles.begin(),
- ModuleFiles.end());
+ // Only the -fmodule-file=<file> form.
+ for (const Arg *A : Args.filtered(OPT_fmodule_file)) {
+ StringRef Val = A->getValue();
+ if (Val.find('=') == StringRef::npos)
+ Opts.ExtraDeps.push_back(Val);
+ }
}
static bool parseShowColorsArgs(const ArgList &Args, bool DefaultColor) {
@@ -1041,6 +1072,26 @@ static bool parseShowColorsArgs(const ArgList &Args, bool DefaultColor) {
llvm::sys::Process::StandardErrHasColors());
}
+static bool checkVerifyPrefixes(const std::vector<std::string> &VerifyPrefixes,
+ DiagnosticsEngine *Diags) {
+ bool Success = true;
+ for (const auto &Prefix : VerifyPrefixes) {
+ // Every prefix must start with a letter and contain only alphanumeric
+ // characters, hyphens, and underscores.
+ auto BadChar = std::find_if(Prefix.begin(), Prefix.end(),
+ [](char C){return !isAlphanumeric(C)
+ && C != '-' && C != '_';});
+ if (BadChar != Prefix.end() || !isLetter(Prefix[0])) {
+ Success = false;
+ if (Diags) {
+ Diags->Report(diag::err_drv_invalid_value) << "-verify=" << Prefix;
+ Diags->Report(diag::note_drv_verify_prefix_spelling);
+ }
+ }
+ }
+ return Success;
+}
+
bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
DiagnosticsEngine *Diags,
bool DefaultDiagColor, bool DefaultShowOpt) {
@@ -1128,7 +1179,18 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info);
Opts.ShowParseableFixits = Args.hasArg(OPT_fdiagnostics_parseable_fixits);
Opts.ShowPresumedLoc = !Args.hasArg(OPT_fno_diagnostics_use_presumed_location);
- Opts.VerifyDiagnostics = Args.hasArg(OPT_verify);
+ Opts.VerifyDiagnostics = Args.hasArg(OPT_verify) || Args.hasArg(OPT_verify_EQ);
+ Opts.VerifyPrefixes = Args.getAllArgValues(OPT_verify_EQ);
+ if (Args.hasArg(OPT_verify))
+ Opts.VerifyPrefixes.push_back("expected");
+ // Keep VerifyPrefixes in its original order for the sake of diagnostics, and
+ // then sort it to prepare for fast lookup using std::binary_search.
+ if (!checkVerifyPrefixes(Opts.VerifyPrefixes, Diags)) {
+ Opts.VerifyDiagnostics = false;
+ Success = false;
+ }
+ else
+ std::sort(Opts.VerifyPrefixes.begin(), Opts.VerifyPrefixes.end());
DiagnosticLevelMask DiagMask = DiagnosticLevelMask::None;
Success &= parseDiagnosticLevelMask("-verify-ignore-unexpected=",
Args.getAllArgValues(OPT_verify_ignore_unexpected_EQ),
@@ -1334,7 +1396,12 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Opts.UseGlobalModuleIndex = !Args.hasArg(OPT_fno_modules_global_index);
Opts.GenerateGlobalModuleIndex = Opts.UseGlobalModuleIndex;
Opts.ModuleMapFiles = Args.getAllArgValues(OPT_fmodule_map_file);
- Opts.ModuleFiles = Args.getAllArgValues(OPT_fmodule_file);
+ // Only the -fmodule-file=<file> form.
+ for (const Arg *A : Args.filtered(OPT_fmodule_file)) {
+ StringRef Val = A->getValue();
+ if (Val.find('=') == StringRef::npos)
+ Opts.ModuleFiles.push_back(Val);
+ }
Opts.ModulesEmbedFiles = Args.getAllArgValues(OPT_fmodules_embed_file_EQ);
Opts.ModulesEmbedAllFiles = Args.hasArg(OPT_fmodules_embed_all_files);
Opts.IncludeTimestamps = !Args.hasArg(OPT_fno_pch_timestamp);
@@ -1345,6 +1412,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
= Args.hasArg(OPT_code_completion_patterns);
Opts.CodeCompleteOpts.IncludeGlobals
= !Args.hasArg(OPT_no_code_completion_globals);
+ Opts.CodeCompleteOpts.IncludeNamespaceLevelDecls
+ = !Args.hasArg(OPT_no_code_completion_ns_level_decls);
Opts.CodeCompleteOpts.IncludeBriefComments
= Args.hasArg(OPT_code_completion_brief_comments);
@@ -1538,6 +1607,12 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,
Opts.ModuleCachePath = P.str();
Opts.ModuleUserBuildPath = Args.getLastArgValue(OPT_fmodules_user_build_path);
+ // Only the -fmodule-file=<name>=<file> form.
+ for (const Arg *A : Args.filtered(OPT_fmodule_file)) {
+ StringRef Val = A->getValue();
+ if (Val.find('=') != StringRef::npos)
+ Opts.PrebuiltModuleFiles.insert(Val.split('='));
+ }
for (const Arg *A : Args.filtered(OPT_fprebuilt_module_path))
Opts.AddPrebuiltModulePath(A->getValue());
Opts.DisableModuleHash = Args.hasArg(OPT_fdisable_module_hash);
@@ -1690,11 +1765,7 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
break;
case InputKind::CXX:
case InputKind::ObjCXX:
- // The PS4 uses C++11 as the default C++ standard.
- if (T.isPS4())
- LangStd = LangStandard::lang_gnucxx11;
- else
- LangStd = LangStandard::lang_gnucxx98;
+ LangStd = LangStandard::lang_gnucxx14;
break;
case InputKind::RenderScript:
LangStd = LangStandard::lang_c99;
@@ -1706,10 +1777,11 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
Opts.LineComment = Std.hasLineComments();
Opts.C99 = Std.isC99();
Opts.C11 = Std.isC11();
+ Opts.C17 = Std.isC17();
Opts.CPlusPlus = Std.isCPlusPlus();
Opts.CPlusPlus11 = Std.isCPlusPlus11();
Opts.CPlusPlus14 = Std.isCPlusPlus14();
- Opts.CPlusPlus1z = Std.isCPlusPlus1z();
+ Opts.CPlusPlus17 = Std.isCPlusPlus17();
Opts.CPlusPlus2a = Std.isCPlusPlus2a();
Opts.Digraphs = Std.hasDigraphs();
Opts.GNUMode = Std.isGNUMode();
@@ -1765,7 +1837,7 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
Opts.GNUKeywords = Opts.GNUMode;
Opts.CXXOperatorNames = Opts.CPlusPlus;
- Opts.AlignedAllocation = Opts.CPlusPlus1z;
+ Opts.AlignedAllocation = Opts.CPlusPlus17;
Opts.DollarIdents = !Opts.AsmPreprocessor;
}
@@ -2084,7 +2156,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
// Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs
// is specified, or -std is set to a conforming mode.
// Trigraphs are disabled by default in c++1z onwards.
- Opts.Trigraphs = !Opts.GNUMode && !Opts.MSVCCompat && !Opts.CPlusPlus1z;
+ Opts.Trigraphs = !Opts.GNUMode && !Opts.MSVCCompat && !Opts.CPlusPlus17;
Opts.Trigraphs =
Args.hasFlag(OPT_ftrigraphs, OPT_fno_trigraphs, Opts.Trigraphs);
@@ -2104,7 +2176,18 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.Exceptions = Args.hasArg(OPT_fexceptions);
Opts.ObjCExceptions = Args.hasArg(OPT_fobjc_exceptions);
Opts.CXXExceptions = Args.hasArg(OPT_fcxx_exceptions);
- Opts.SjLjExceptions = Args.hasArg(OPT_fsjlj_exceptions);
+
+ // Handle exception personalities
+ Arg *A = Args.getLastArg(options::OPT_fsjlj_exceptions,
+ options::OPT_fseh_exceptions,
+ options::OPT_fdwarf_exceptions);
+ if (A) {
+ const Option &Opt = A->getOption();
+ Opts.SjLjExceptions = Opt.matches(options::OPT_fsjlj_exceptions);
+ Opts.SEHExceptions = Opt.matches(options::OPT_fseh_exceptions);
+ Opts.DWARFExceptions = Opt.matches(options::OPT_fdwarf_exceptions);
+ }
+
Opts.ExternCNoUnwind = Args.hasArg(OPT_fexternc_nounwind);
Opts.TraditionalCPP = Args.hasArg(OPT_traditional_cpp);
@@ -2114,6 +2197,12 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
&& Opts.OpenCLVersion >= 200);
Opts.BlocksRuntimeOptional = Args.hasArg(OPT_fblocks_runtime_optional);
Opts.CoroutinesTS = Args.hasArg(OPT_fcoroutines_ts);
+
+ // Enable [[]] attributes in C++11 by default.
+ Opts.DoubleSquareBracketAttributes =
+ Args.hasFlag(OPT_fdouble_square_bracket_attributes,
+ OPT_fno_double_square_bracket_attributes, Opts.CPlusPlus11);
+
Opts.ModulesTS = Args.hasArg(OPT_fmodules_ts);
Opts.Modules = Args.hasArg(OPT_fmodules) || Opts.ModulesTS;
Opts.ModulesStrictDeclUse = Args.hasArg(OPT_fmodules_strict_decluse);
@@ -2130,7 +2219,16 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.ImplicitModules = !Args.hasArg(OPT_fno_implicit_modules);
Opts.CharIsSigned = Opts.OpenCL || !Args.hasArg(OPT_fno_signed_char);
Opts.WChar = Opts.CPlusPlus && !Args.hasArg(OPT_fno_wchar);
- Opts.ShortWChar = Args.hasFlag(OPT_fshort_wchar, OPT_fno_short_wchar, false);
+ if (const Arg *A = Args.getLastArg(OPT_fwchar_type_EQ)) {
+ Opts.WCharSize = llvm::StringSwitch<unsigned>(A->getValue())
+ .Case("char", 1)
+ .Case("short", 2)
+ .Case("int", 4)
+ .Default(0);
+ if (Opts.WCharSize == 0)
+ Diags.Report(diag::err_fe_invalid_wchar_type) << A->getValue();
+ }
+ Opts.WCharIsSigned = Args.hasFlag(OPT_fsigned_wchar, OPT_fno_signed_wchar, true);
Opts.ShortEnums = Args.hasArg(OPT_fshort_enums);
Opts.Freestanding = Args.hasArg(OPT_ffreestanding);
Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding;
@@ -2266,12 +2364,12 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
// Check for MS default calling conventions being specified.
if (Arg *A = Args.getLastArg(OPT_fdefault_calling_conv_EQ)) {
LangOptions::DefaultCallingConvention DefaultCC =
- llvm::StringSwitch<LangOptions::DefaultCallingConvention>(
- A->getValue())
+ llvm::StringSwitch<LangOptions::DefaultCallingConvention>(A->getValue())
.Case("cdecl", LangOptions::DCC_CDecl)
.Case("fastcall", LangOptions::DCC_FastCall)
.Case("stdcall", LangOptions::DCC_StdCall)
.Case("vectorcall", LangOptions::DCC_VectorCall)
+ .Case("regcall", LangOptions::DCC_RegCall)
.Default(LangOptions::DCC_None);
if (DefaultCC == LangOptions::DCC_None)
Diags.Report(diag::err_drv_invalid_value)
@@ -2282,7 +2380,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
bool emitError = (DefaultCC == LangOptions::DCC_FastCall ||
DefaultCC == LangOptions::DCC_StdCall) &&
Arch != llvm::Triple::x86;
- emitError |= DefaultCC == LangOptions::DCC_VectorCall &&
+ emitError |= (DefaultCC == LangOptions::DCC_VectorCall ||
+ DefaultCC == LangOptions::DCC_RegCall) &&
!(Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64);
if (emitError)
Diags.Report(diag::err_drv_argument_not_allowed_with)
@@ -2334,13 +2433,27 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
}
}
+ // Set the flag to prevent the implementation from emitting device exception
+ // handling code for those requiring so.
+ if (Opts.OpenMPIsDevice && T.isNVPTX()) {
+ Opts.Exceptions = 0;
+ Opts.CXXExceptions = 0;
+ }
+
// Get the OpenMP target triples if any.
if (Arg *A = Args.getLastArg(options::OPT_fopenmp_targets_EQ)) {
for (unsigned i = 0; i < A->getNumValues(); ++i) {
llvm::Triple TT(A->getValue(i));
- if (TT.getArch() == llvm::Triple::UnknownArch)
+ if (TT.getArch() == llvm::Triple::UnknownArch ||
+ !(TT.getArch() == llvm::Triple::ppc ||
+ TT.getArch() == llvm::Triple::ppc64 ||
+ TT.getArch() == llvm::Triple::ppc64le ||
+ TT.getArch() == llvm::Triple::nvptx ||
+ TT.getArch() == llvm::Triple::nvptx64 ||
+ TT.getArch() == llvm::Triple::x86 ||
+ TT.getArch() == llvm::Triple::x86_64))
Diags.Report(clang::diag::err_drv_invalid_omp_target) << A->getValue(i);
else
Opts.OMPTargetTriples.push_back(TT);
@@ -2425,6 +2538,11 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.XRayInstrument =
Args.hasFlag(OPT_fxray_instrument, OPT_fnoxray_instrument, false);
+ // -fxray-always-emit-customevents
+ Opts.XRayAlwaysEmitCustomEvents =
+ Args.hasFlag(OPT_fxray_always_emit_customevents,
+ OPT_fnoxray_always_emit_customevents, false);
+
// -fxray-{always,never}-instrument= filenames.
Opts.XRayAlwaysInstrumentFiles =
Args.getAllArgValues(OPT_fxray_always_instrument);
@@ -2603,7 +2721,6 @@ static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args,
Opts.FeaturesAsWritten = Args.getAllArgValues(OPT_target_feature);
Opts.LinkerVersion = Args.getLastArgValue(OPT_target_linker_version);
Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple));
- Opts.Reciprocals = Args.getAllArgValues(OPT_mrecip_EQ);
// Use the default target triple if unspecified.
if (Opts.Triple.empty())
Opts.Triple = llvm::sys::getDefaultTargetTriple();
@@ -2710,6 +2827,13 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
if (Arch == llvm::Triple::spir || Arch == llvm::Triple::spir64) {
Res.getDiagnosticOpts().Warnings.push_back("spir-compat");
}
+
+ // If sanitizer is enabled, disable OPT_ffine_grained_bitfield_accesses.
+ if (Res.getCodeGenOpts().FineGrainedBitfieldAccesses &&
+ !Res.getLangOpts()->Sanitize.empty()) {
+ Res.getCodeGenOpts().FineGrainedBitfieldAccesses = false;
+ Diags.Report(diag::warn_drv_fine_grained_bitfield_accesses_ignored);
+ }
return Success;
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp b/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp
index 704d51509851f..12226b2314175 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp
@@ -633,18 +633,12 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
return true;
}
- if (!CI.hasVirtualFileSystem()) {
- if (IntrusiveRefCntPtr<vfs::FileSystem> VFS =
- createVFSFromCompilerInvocation(CI.getInvocation(),
- CI.getDiagnostics()))
- CI.setVirtualFileSystem(VFS);
- else
+ // Set up the file and source managers, if needed.
+ if (!CI.hasFileManager()) {
+ if (!CI.createFileManager()) {
goto failure;
+ }
}
-
- // Set up the file and source managers, if needed.
- if (!CI.hasFileManager())
- CI.createFileManager();
if (!CI.hasSourceManager())
CI.createSourceManager(CI.getFileManager());
@@ -754,10 +748,11 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
goto failure;
// Reinitialize the main file entry to refer to the new input.
- if (!CI.InitializeSourceManager(FrontendInputFile(
- Buffer.release(), Input.getKind().withFormat(InputKind::Source),
- CurrentModule->IsSystem)))
- goto failure;
+ auto Kind = CurrentModule->IsSystem ? SrcMgr::C_System : SrcMgr::C_User;
+ auto &SourceMgr = CI.getSourceManager();
+ auto BufferID = SourceMgr.createFileID(std::move(Buffer), Kind);
+ assert(BufferID.isValid() && "couldn't creaate module buffer ID");
+ SourceMgr.setMainFileID(BufferID);
}
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp b/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp
index d42400183a433..ffa5b410d2d8f 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp
@@ -80,9 +80,12 @@ DeclContextPrintAction::CreateASTConsumer(CompilerInstance &CI,
std::unique_ptr<ASTConsumer>
GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
std::string Sysroot;
+ if (!ComputeASTConsumerArguments(CI, /*ref*/ Sysroot))
+ return nullptr;
+
std::string OutputFile;
std::unique_ptr<raw_pwrite_stream> OS =
- ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile);
+ CreateOutputFile(CI, InFile, /*ref*/ OutputFile);
if (!OS)
return nullptr;
@@ -103,17 +106,20 @@ GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
}
-std::unique_ptr<raw_pwrite_stream>
-GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI,
- StringRef InFile,
- std::string &Sysroot,
- std::string &OutputFile) {
+bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI,
+ std::string &Sysroot) {
Sysroot = CI.getHeaderSearchOpts().Sysroot;
if (CI.getFrontendOpts().RelocatablePCH && Sysroot.empty()) {
CI.getDiagnostics().Report(diag::err_relocatable_without_isysroot);
- return nullptr;
+ return false;
}
+ return true;
+}
+
+std::unique_ptr<llvm::raw_pwrite_stream>
+GeneratePCHAction::CreateOutputFile(CompilerInstance &CI, StringRef InFile,
+ std::string &OutputFile) {
// We use createOutputFile here because this is exposed via libclang, and we
// must disable the RemoveFileOnSignal behavior.
// We use a temporary to avoid race conditions.
@@ -185,8 +191,8 @@ GenerateModuleFromModuleMapAction::CreateOutputFile(CompilerInstance &CI,
HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
CI.getFrontendOpts().OutputFile =
- HS.getModuleFileName(CI.getLangOpts().CurrentModule, ModuleMapFile,
- /*UsePrebuiltPath=*/false);
+ HS.getCachedModuleFileName(CI.getLangOpts().CurrentModule,
+ ModuleMapFile);
}
// We use createOutputFile here because this is exposed via libclang, and we
@@ -591,7 +597,7 @@ void PrintPreambleAction::ExecuteAction() {
auto Buffer = CI.getFileManager().getBufferForFile(getCurrentFile());
if (Buffer) {
unsigned Preamble =
- Lexer::ComputePreamble((*Buffer)->getBuffer(), CI.getLangOpts()).first;
+ Lexer::ComputePreamble((*Buffer)->getBuffer(), CI.getLangOpts()).Size;
llvm::outs().write((*Buffer)->getBufferStart(), Preamble);
}
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp b/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp
index 1d7c8a0c871bd..8c6faced76ac0 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp
@@ -213,7 +213,6 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple,
case llvm::Triple::FreeBSD:
case llvm::Triple::NetBSD:
case llvm::Triple::OpenBSD:
- case llvm::Triple::Bitrig:
case llvm::Triple::NaCl:
case llvm::Triple::PS4:
case llvm::Triple::ELFIAMCU:
diff --git a/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp b/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp
index 92d61369b40f0..d39890494323d 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp
@@ -14,6 +14,7 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/MacroBuilder.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/SyncScope.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Version.h"
#include "clang/Frontend/FrontendDiagnostic.h"
@@ -109,9 +110,11 @@ static void AddImplicitIncludePCH(MacroBuilder &Builder, Preprocessor &PP,
/// PickFP - This is used to pick a value based on the FP semantics of the
/// specified FP model.
template <typename T>
-static T PickFP(const llvm::fltSemantics *Sem, T IEEESingleVal,
+static T PickFP(const llvm::fltSemantics *Sem, T IEEEHalfVal, T IEEESingleVal,
T IEEEDoubleVal, T X87DoubleExtendedVal, T PPCDoubleDoubleVal,
T IEEEQuadVal) {
+ if (Sem == (const llvm::fltSemantics*)&llvm::APFloat::IEEEhalf())
+ return IEEEHalfVal;
if (Sem == (const llvm::fltSemantics*)&llvm::APFloat::IEEEsingle())
return IEEESingleVal;
if (Sem == (const llvm::fltSemantics*)&llvm::APFloat::IEEEdouble())
@@ -127,26 +130,26 @@ static T PickFP(const llvm::fltSemantics *Sem, T IEEESingleVal,
static void DefineFloatMacros(MacroBuilder &Builder, StringRef Prefix,
const llvm::fltSemantics *Sem, StringRef Ext) {
const char *DenormMin, *Epsilon, *Max, *Min;
- DenormMin = PickFP(Sem, "1.40129846e-45", "4.9406564584124654e-324",
- "3.64519953188247460253e-4951",
+ DenormMin = PickFP(Sem, "5.9604644775390625e-8", "1.40129846e-45",
+ "4.9406564584124654e-324", "3.64519953188247460253e-4951",
"4.94065645841246544176568792868221e-324",
"6.47517511943802511092443895822764655e-4966");
- int Digits = PickFP(Sem, 6, 15, 18, 31, 33);
- int DecimalDigits = PickFP(Sem, 9, 17, 21, 33, 36);
- Epsilon = PickFP(Sem, "1.19209290e-7", "2.2204460492503131e-16",
- "1.08420217248550443401e-19",
+ int Digits = PickFP(Sem, 3, 6, 15, 18, 31, 33);
+ int DecimalDigits = PickFP(Sem, 5, 9, 17, 21, 33, 36);
+ Epsilon = PickFP(Sem, "9.765625e-4", "1.19209290e-7",
+ "2.2204460492503131e-16", "1.08420217248550443401e-19",
"4.94065645841246544176568792868221e-324",
"1.92592994438723585305597794258492732e-34");
- int MantissaDigits = PickFP(Sem, 24, 53, 64, 106, 113);
- int Min10Exp = PickFP(Sem, -37, -307, -4931, -291, -4931);
- int Max10Exp = PickFP(Sem, 38, 308, 4932, 308, 4932);
- int MinExp = PickFP(Sem, -125, -1021, -16381, -968, -16381);
- int MaxExp = PickFP(Sem, 128, 1024, 16384, 1024, 16384);
- Min = PickFP(Sem, "1.17549435e-38", "2.2250738585072014e-308",
+ int MantissaDigits = PickFP(Sem, 11, 24, 53, 64, 106, 113);
+ int Min10Exp = PickFP(Sem, -13, -37, -307, -4931, -291, -4931);
+ int Max10Exp = PickFP(Sem, 4, 38, 308, 4932, 308, 4932);
+ int MinExp = PickFP(Sem, -14, -125, -1021, -16381, -968, -16381);
+ int MaxExp = PickFP(Sem, 15, 128, 1024, 16384, 1024, 16384);
+ Min = PickFP(Sem, "6.103515625e-5", "1.17549435e-38", "2.2250738585072014e-308",
"3.36210314311209350626e-4932",
"2.00416836000897277799610805135016e-292",
"3.36210314311209350626267781732175260e-4932");
- Max = PickFP(Sem, "3.40282347e+38", "1.7976931348623157e+308",
+ Max = PickFP(Sem, "6.5504e+4", "3.40282347e+38", "1.7976931348623157e+308",
"1.18973149535723176502e+4932",
"1.79769313486231580793728971405301e+308",
"1.18973149535723176508575932662800702e+4932");
@@ -190,7 +193,7 @@ static void DefineTypeSize(const Twine &MacroName, unsigned TypeWidth,
/// the width, suffix, and signedness of the given type
static void DefineTypeSize(const Twine &MacroName, TargetInfo::IntType Ty,
const TargetInfo &TI, MacroBuilder &Builder) {
- DefineTypeSize(MacroName, TI.getTypeWidth(Ty), TI.getTypeConstantSuffix(Ty),
+ DefineTypeSize(MacroName, TI.getTypeWidth(Ty), TI.getTypeConstantSuffix(Ty),
TI.isTypeSigned(Ty), Builder);
}
@@ -300,25 +303,25 @@ static const char *getLockFreeValue(unsigned TypeWidth, unsigned TypeAlign,
/// \brief Add definitions required for a smooth interaction between
/// Objective-C++ automated reference counting and libstdc++ (4.2).
-static void AddObjCXXARCLibstdcxxDefines(const LangOptions &LangOpts,
+static void AddObjCXXARCLibstdcxxDefines(const LangOptions &LangOpts,
MacroBuilder &Builder) {
Builder.defineMacro("_GLIBCXX_PREDEFINED_OBJC_ARC_IS_SCALAR");
-
+
std::string Result;
{
- // Provide specializations for the __is_scalar type trait so that
+ // Provide specializations for the __is_scalar type trait so that
// lifetime-qualified objects are not considered "scalar" types, which
// libstdc++ uses as an indicator of the presence of trivial copy, assign,
// default-construct, and destruct semantics (none of which hold for
// lifetime-qualified objects in ARC).
llvm::raw_string_ostream Out(Result);
-
+
Out << "namespace std {\n"
<< "\n"
<< "struct __true_type;\n"
<< "struct __false_type;\n"
<< "\n";
-
+
Out << "template<typename _Tp> struct __is_scalar;\n"
<< "\n";
@@ -330,7 +333,7 @@ static void AddObjCXXARCLibstdcxxDefines(const LangOptions &LangOpts,
<< "};\n"
<< "\n";
}
-
+
if (LangOpts.ObjCWeak) {
Out << "template<typename _Tp>\n"
<< "struct __is_scalar<__attribute__((objc_ownership(weak))) _Tp> {\n"
@@ -339,7 +342,7 @@ static void AddObjCXXARCLibstdcxxDefines(const LangOptions &LangOpts,
<< "};\n"
<< "\n";
}
-
+
if (LangOpts.ObjCAutoRefCount) {
Out << "template<typename _Tp>\n"
<< "struct __is_scalar<__attribute__((objc_ownership(autoreleasing)))"
@@ -349,7 +352,7 @@ static void AddObjCXXARCLibstdcxxDefines(const LangOptions &LangOpts,
<< "};\n"
<< "\n";
}
-
+
Out << "}\n";
}
Builder.append(Result);
@@ -367,7 +370,9 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI,
Builder.defineMacro("__STDC_HOSTED__");
if (!LangOpts.CPlusPlus) {
- if (LangOpts.C11)
+ if (LangOpts.C17)
+ Builder.defineMacro("__STDC_VERSION__", "201710L");
+ else if (LangOpts.C11)
Builder.defineMacro("__STDC_VERSION__", "201112L");
else if (LangOpts.C99)
Builder.defineMacro("__STDC_VERSION__", "199901L");
@@ -380,7 +385,7 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI,
// C++17 [cpp.predefined]p1:
// The name __cplusplus is defined to the value 201703L when compiling a
// C++ translation unit.
- else if (LangOpts.CPlusPlus1z)
+ else if (LangOpts.CPlusPlus17)
Builder.defineMacro("__cplusplus", "201703L");
// C++1y [cpp.predefined]p1:
// The name __cplusplus is defined to the value 201402L when compiling a
@@ -480,12 +485,12 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts,
Builder.defineMacro("__cpp_user_defined_literals", "200809");
Builder.defineMacro("__cpp_lambdas", "200907");
Builder.defineMacro("__cpp_constexpr",
- LangOpts.CPlusPlus1z ? "201603" :
+ LangOpts.CPlusPlus17 ? "201603" :
LangOpts.CPlusPlus14 ? "201304" : "200704");
Builder.defineMacro("__cpp_range_based_for",
- LangOpts.CPlusPlus1z ? "201603" : "200907");
+ LangOpts.CPlusPlus17 ? "201603" : "200907");
Builder.defineMacro("__cpp_static_assert",
- LangOpts.CPlusPlus1z ? "201411" : "200410");
+ LangOpts.CPlusPlus17 ? "201411" : "200410");
Builder.defineMacro("__cpp_decltype", "200707");
Builder.defineMacro("__cpp_attributes", "200809");
Builder.defineMacro("__cpp_rvalue_references", "200610");
@@ -515,7 +520,7 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts,
Builder.defineMacro("__cpp_sized_deallocation", "201309");
// C++17 features.
- if (LangOpts.CPlusPlus1z) {
+ if (LangOpts.CPlusPlus17) {
Builder.defineMacro("__cpp_hex_float", "201603");
Builder.defineMacro("__cpp_inline_variables", "201606");
Builder.defineMacro("__cpp_noexcept_function_type", "201510");
@@ -556,7 +561,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
Builder.defineMacro("__clang_patchlevel__", TOSTR(CLANG_VERSION_PATCHLEVEL));
#undef TOSTR
#undef TOSTR2
- Builder.defineMacro("__clang_version__",
+ Builder.defineMacro("__clang_version__",
"\"" CLANG_VERSION_STRING " "
+ getClangFullRepositoryVersion() + "\"");
if (!LangOpts.MSVCCompat) {
@@ -576,13 +581,27 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
Builder.defineMacro("__ATOMIC_ACQ_REL", "4");
Builder.defineMacro("__ATOMIC_SEQ_CST", "5");
+ // Define macros for the OpenCL memory scope.
+ // The values should match AtomicScopeOpenCLModel::ID enum.
+ static_assert(
+ static_cast<unsigned>(AtomicScopeOpenCLModel::WorkGroup) == 1 &&
+ static_cast<unsigned>(AtomicScopeOpenCLModel::Device) == 2 &&
+ static_cast<unsigned>(AtomicScopeOpenCLModel::AllSVMDevices) == 3 &&
+ static_cast<unsigned>(AtomicScopeOpenCLModel::SubGroup) == 4,
+ "Invalid OpenCL memory scope enum definition");
+ Builder.defineMacro("__OPENCL_MEMORY_SCOPE_WORK_ITEM", "0");
+ Builder.defineMacro("__OPENCL_MEMORY_SCOPE_WORK_GROUP", "1");
+ Builder.defineMacro("__OPENCL_MEMORY_SCOPE_DEVICE", "2");
+ Builder.defineMacro("__OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES", "3");
+ Builder.defineMacro("__OPENCL_MEMORY_SCOPE_SUB_GROUP", "4");
+
// Support for #pragma redefine_extname (Sun compatibility)
Builder.defineMacro("__PRAGMA_REDEFINE_EXTNAME", "1");
// As sad as it is, enough software depends on the __VERSION__ for version
// checks that it is necessary to report 4.2.1 (the base GCC version we claim
// compatibility with) first.
- Builder.defineMacro("__VERSION__", "\"4.2.1 Compatible " +
+ Builder.defineMacro("__VERSION__", "\"4.2.1 Compatible " +
Twine(getClangFullCPPVersion()) + "\"");
// Initialize language-specific preprocessor defines.
@@ -597,7 +616,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
if (LangOpts.ObjC1) {
if (LangOpts.ObjCRuntime.isNonFragile()) {
Builder.defineMacro("__OBJC2__");
-
+
if (LangOpts.ObjCExceptions)
Builder.defineMacro("OBJC_ZEROCOST_EXCEPTIONS");
}
@@ -660,8 +679,14 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
Builder.defineMacro("__EXCEPTIONS");
if (!LangOpts.MSVCCompat && LangOpts.RTTI)
Builder.defineMacro("__GXX_RTTI");
+
if (LangOpts.SjLjExceptions)
Builder.defineMacro("__USING_SJLJ_EXCEPTIONS__");
+ else if (LangOpts.SEHExceptions)
+ Builder.defineMacro("__SEH__");
+ else if (LangOpts.DWARFExceptions &&
+ (TI.getTriple().isThumb() || TI.getTriple().isARM()))
+ Builder.defineMacro("__ARM_DWARF_EH__");
if (LangOpts.Deprecated)
Builder.defineMacro("__DEPRECATED");
@@ -728,6 +753,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
DefineTypeSize("__LONG_MAX__", TargetInfo::SignedLong, TI, Builder);
DefineTypeSize("__LONG_LONG_MAX__", TargetInfo::SignedLongLong, TI, Builder);
DefineTypeSize("__WCHAR_MAX__", TI.getWCharType(), TI, Builder);
+ DefineTypeSize("__WINT_MAX__", TI.getWIntType(), TI, Builder);
DefineTypeSize("__INTMAX_MAX__", TI.getIntMaxType(), TI, Builder);
DefineTypeSize("__SIZE_MAX__", TI.getSizeType(), TI, Builder);
@@ -787,9 +813,14 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
DefineFmt("__UINTPTR", TI.getUIntPtrType(), TI, Builder);
DefineTypeWidth("__UINTPTR_WIDTH__", TI.getUIntPtrType(), TI, Builder);
+ DefineFloatMacros(Builder, "FLT16", &TI.getHalfFormat(), "F16");
DefineFloatMacros(Builder, "FLT", &TI.getFloatFormat(), "F");
DefineFloatMacros(Builder, "DBL", &TI.getDoubleFormat(), "");
DefineFloatMacros(Builder, "LDBL", &TI.getLongDoubleFormat(), "L");
+ if (TI.hasFloat128Type())
+ // FIXME: Switch away from the non-standard "Q" when we can
+ DefineFloatMacros(Builder, "FLT128", &TI.getFloat128Format(), "Q");
+
// Define a __POINTER_WIDTH__ macro for stdint.h.
Builder.defineMacro("__POINTER_WIDTH__",
@@ -969,6 +1000,11 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
Builder.defineMacro("__nullable", "_Nullable");
}
+ // Add a macro to differentiate between regular iOS/tvOS/watchOS targets and
+ // the corresponding simulator targets.
+ if (TI.getTriple().isOSDarwin() && TI.getTriple().isSimulatorEnvironment())
+ Builder.defineMacro("__APPLE_EMBEDDED_SIMULATOR__", "1");
+
// OpenMP definition
// OpenMP 2.2:
// In implementations that support a preprocessor, the _OPENMP
@@ -1010,6 +1046,10 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
LangOpts.OpenCLVersion)) \
Builder.defineMacro(#Ext);
#include "clang/Basic/OpenCLExtensions.def"
+
+ auto Arch = TI.getTriple().getArch();
+ if (Arch == llvm::Triple::spir || Arch == llvm::Triple::spir64)
+ Builder.defineMacro("__IMAGE_SUPPORT__");
}
if (TI.hasInt128Type() && LangOpts.CPlusPlus && LangOpts.GNUMode) {
@@ -1068,7 +1108,7 @@ void clang::InitializePreprocessor(
}
}
}
-
+
// Even with predefines off, some macros are still predefined.
// These should all be defined in the preprocessor according to the
// current language configuration.
@@ -1114,7 +1154,7 @@ void clang::InitializePreprocessor(
// Instruct the preprocessor to skip the preamble.
PP.setSkipMainFilePreamble(InitOpts.PrecompiledPreambleBytes.first,
InitOpts.PrecompiledPreambleBytes.second);
-
+
// Copy PredefinedBuffer into the Preprocessor.
PP.setPredefines(Predefines.str());
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/MultiplexConsumer.cpp b/contrib/llvm/tools/clang/lib/Frontend/MultiplexConsumer.cpp
index 8ef6df5e740da..04a8f6c1cdfbc 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/MultiplexConsumer.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/MultiplexConsumer.cpp
@@ -116,14 +116,16 @@ public:
void ResolvedExceptionSpec(const FunctionDecl *FD) override;
void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) override;
void ResolvedOperatorDelete(const CXXDestructorDecl *DD,
- const FunctionDecl *Delete) override;
+ const FunctionDecl *Delete,
+ Expr *ThisArg) override;
void CompletedImplicitDefinition(const FunctionDecl *D) override;
- void StaticDataMemberInstantiated(const VarDecl *D) override;
+ void InstantiationRequested(const ValueDecl *D) override;
+ void VariableDefinitionInstantiated(const VarDecl *D) override;
+ void FunctionDefinitionInstantiated(const FunctionDecl *D) override;
void DefaultArgumentInstantiated(const ParmVarDecl *D) override;
void DefaultMemberInitializerInstantiated(const FieldDecl *D) override;
void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
const ObjCInterfaceDecl *IFD) override;
- void FunctionDefinitionInstantiated(const FunctionDecl *D) override;
void DeclarationMarkedUsed(const Decl *D) override;
void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) override;
void DeclarationMarkedOpenMPDeclareTarget(const Decl *D,
@@ -183,19 +185,28 @@ void MultiplexASTMutationListener::DeducedReturnType(const FunctionDecl *FD,
Listeners[i]->DeducedReturnType(FD, ReturnType);
}
void MultiplexASTMutationListener::ResolvedOperatorDelete(
- const CXXDestructorDecl *DD, const FunctionDecl *Delete) {
+ const CXXDestructorDecl *DD, const FunctionDecl *Delete, Expr *ThisArg) {
for (auto *L : Listeners)
- L->ResolvedOperatorDelete(DD, Delete);
+ L->ResolvedOperatorDelete(DD, Delete, ThisArg);
}
void MultiplexASTMutationListener::CompletedImplicitDefinition(
const FunctionDecl *D) {
for (size_t i = 0, e = Listeners.size(); i != e; ++i)
Listeners[i]->CompletedImplicitDefinition(D);
}
-void MultiplexASTMutationListener::StaticDataMemberInstantiated(
- const VarDecl *D) {
+void MultiplexASTMutationListener::InstantiationRequested(const ValueDecl *D) {
+ for (size_t i = 0, e = Listeners.size(); i != e; ++i)
+ Listeners[i]->InstantiationRequested(D);
+}
+void MultiplexASTMutationListener::VariableDefinitionInstantiated(
+ const VarDecl *D) {
for (size_t i = 0, e = Listeners.size(); i != e; ++i)
- Listeners[i]->StaticDataMemberInstantiated(D);
+ Listeners[i]->VariableDefinitionInstantiated(D);
+}
+void MultiplexASTMutationListener::FunctionDefinitionInstantiated(
+ const FunctionDecl *D) {
+ for (auto &Listener : Listeners)
+ Listener->FunctionDefinitionInstantiated(D);
}
void MultiplexASTMutationListener::DefaultArgumentInstantiated(
const ParmVarDecl *D) {
@@ -213,11 +224,6 @@ void MultiplexASTMutationListener::AddedObjCCategoryToInterface(
for (size_t i = 0, e = Listeners.size(); i != e; ++i)
Listeners[i]->AddedObjCCategoryToInterface(CatD, IFD);
}
-void MultiplexASTMutationListener::FunctionDefinitionInstantiated(
- const FunctionDecl *D) {
- for (auto &Listener : Listeners)
- Listener->FunctionDefinitionInstantiated(D);
-}
void MultiplexASTMutationListener::DeclarationMarkedUsed(const Decl *D) {
for (size_t i = 0, e = Listeners.size(); i != e; ++i)
Listeners[i]->DeclarationMarkedUsed(D);
diff --git a/contrib/llvm/tools/clang/lib/Frontend/PrecompiledPreamble.cpp b/contrib/llvm/tools/clang/lib/Frontend/PrecompiledPreamble.cpp
index 15b24cbed4841..f6964d02b2373 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/PrecompiledPreamble.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/PrecompiledPreamble.cpp
@@ -24,15 +24,45 @@
#include "clang/Serialization/ASTWriter.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Support/MutexGuard.h"
+#include "llvm/Support/Process.h"
+
+#include <utility>
using namespace clang;
namespace {
+StringRef getInMemoryPreamblePath() {
+#if defined(LLVM_ON_UNIX)
+ return "/__clang_tmp/___clang_inmemory_preamble___";
+#elif defined(LLVM_ON_WIN32)
+ return "C:\\__clang_tmp\\___clang_inmemory_preamble___";
+#else
+#warning "Unknown platform. Defaulting to UNIX-style paths for in-memory PCHs"
+ return "/__clang_tmp/___clang_inmemory_preamble___";
+#endif
+}
+
+IntrusiveRefCntPtr<vfs::FileSystem>
+createVFSOverlayForPreamblePCH(StringRef PCHFilename,
+ std::unique_ptr<llvm::MemoryBuffer> PCHBuffer,
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
+ // We want only the PCH file from the real filesystem to be available,
+ // so we create an in-memory VFS with just that and overlay it on top.
+ IntrusiveRefCntPtr<vfs::InMemoryFileSystem> PCHFS(
+ new vfs::InMemoryFileSystem());
+ PCHFS->addFile(PCHFilename, 0, std::move(PCHBuffer));
+ IntrusiveRefCntPtr<vfs::OverlayFileSystem> Overlay(
+ new vfs::OverlayFileSystem(VFS));
+ Overlay->pushOverlay(PCHFS);
+ return Overlay;
+}
+
/// Keeps a track of files to be deleted in destructor.
class TemporaryFiles {
public:
@@ -85,23 +115,11 @@ void TemporaryFiles::removeFile(StringRef File) {
llvm::sys::fs::remove(File);
}
-class PreambleMacroCallbacks : public PPCallbacks {
-public:
- PreambleMacroCallbacks(PreambleCallbacks &Callbacks) : Callbacks(Callbacks) {}
-
- void MacroDefined(const Token &MacroNameTok,
- const MacroDirective *MD) override {
- Callbacks.HandleMacroDefined(MacroNameTok, MD);
- }
-
-private:
- PreambleCallbacks &Callbacks;
-};
-
class PrecompilePreambleAction : public ASTFrontendAction {
public:
- PrecompilePreambleAction(PreambleCallbacks &Callbacks)
- : Callbacks(Callbacks) {}
+ PrecompilePreambleAction(std::string *InMemStorage,
+ PreambleCallbacks &Callbacks)
+ : InMemStorage(InMemStorage), Callbacks(Callbacks) {}
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) override;
@@ -122,6 +140,7 @@ private:
friend class PrecompilePreambleConsumer;
bool HasEmittedPreamblePCH = false;
+ std::string *InMemStorage;
PreambleCallbacks &Callbacks;
};
@@ -163,21 +182,24 @@ private:
std::unique_ptr<ASTConsumer>
PrecompilePreambleAction::CreateASTConsumer(CompilerInstance &CI,
-
StringRef InFile) {
std::string Sysroot;
- std::string OutputFile;
- std::unique_ptr<raw_ostream> OS =
- GeneratePCHAction::ComputeASTConsumerArguments(CI, InFile, Sysroot,
- OutputFile);
+ if (!GeneratePCHAction::ComputeASTConsumerArguments(CI, Sysroot))
+ return nullptr;
+
+ std::unique_ptr<llvm::raw_ostream> OS;
+ if (InMemStorage) {
+ OS = llvm::make_unique<llvm::raw_string_ostream>(*InMemStorage);
+ } else {
+ std::string OutputFile;
+ OS = GeneratePCHAction::CreateOutputFile(CI, InFile, OutputFile);
+ }
if (!OS)
return nullptr;
if (!CI.getFrontendOpts().RelocatablePCH)
Sysroot.clear();
- CI.getPreprocessor().addPPCallbacks(
- llvm::make_unique<PreambleMacroCallbacks>(Callbacks));
return llvm::make_unique<PrecompilePreambleConsumer>(
*this, CI.getPreprocessor(), Sysroot, std::move(OS));
}
@@ -194,15 +216,14 @@ template <class T> bool moveOnNoError(llvm::ErrorOr<T> Val, T &Output) {
PreambleBounds clang::ComputePreambleBounds(const LangOptions &LangOpts,
llvm::MemoryBuffer *Buffer,
unsigned MaxLines) {
- auto Pre = Lexer::ComputePreamble(Buffer->getBuffer(), LangOpts, MaxLines);
- return PreambleBounds(Pre.first, Pre.second);
+ return Lexer::ComputePreamble(Buffer->getBuffer(), LangOpts, MaxLines);
}
llvm::ErrorOr<PrecompiledPreamble> PrecompiledPreamble::Build(
const CompilerInvocation &Invocation,
const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds,
DiagnosticsEngine &Diagnostics, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
- std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps, bool StoreInMemory,
PreambleCallbacks &Callbacks) {
assert(VFS && "VFS is null");
@@ -214,12 +235,19 @@ llvm::ErrorOr<PrecompiledPreamble> PrecompiledPreamble::Build(
PreprocessorOptions &PreprocessorOpts =
PreambleInvocation->getPreprocessorOpts();
- // Create a temporary file for the precompiled preamble. In rare
- // circumstances, this can fail.
- llvm::ErrorOr<PrecompiledPreamble::TempPCHFile> PreamblePCHFile =
- PrecompiledPreamble::TempPCHFile::CreateNewPreamblePCHFile();
- if (!PreamblePCHFile)
- return BuildPreambleError::CouldntCreateTempFile;
+ llvm::Optional<TempPCHFile> TempFile;
+ if (!StoreInMemory) {
+ // Create a temporary file for the precompiled preamble. In rare
+ // circumstances, this can fail.
+ llvm::ErrorOr<PrecompiledPreamble::TempPCHFile> PreamblePCHFile =
+ PrecompiledPreamble::TempPCHFile::CreateNewPreamblePCHFile();
+ if (!PreamblePCHFile)
+ return BuildPreambleError::CouldntCreateTempFile;
+ TempFile = std::move(*PreamblePCHFile);
+ }
+
+ PCHStorage Storage = StoreInMemory ? PCHStorage(InMemoryPreamble())
+ : PCHStorage(std::move(*TempFile));
// Save the preamble text for later; we'll need to compare against it for
// subsequent reparses.
@@ -230,10 +258,12 @@ llvm::ErrorOr<PrecompiledPreamble> PrecompiledPreamble::Build(
// Tell the compiler invocation to generate a temporary precompiled header.
FrontendOpts.ProgramAction = frontend::GeneratePCH;
- // FIXME: Generate the precompiled header into memory?
- FrontendOpts.OutputFile = PreamblePCHFile->getFilePath();
+ FrontendOpts.OutputFile = StoreInMemory ? getInMemoryPreamblePath()
+ : Storage.asFile().getFilePath();
PreprocessorOpts.PrecompiledPreambleBytes.first = 0;
PreprocessorOpts.PrecompiledPreambleBytes.second = false;
+ // Inform preprocessor to record conditional stack when building the preamble.
+ PreprocessorOpts.GeneratePreamble = true;
// Create the compiler instance to use for building the precompiled preamble.
std::unique_ptr<CompilerInstance> Clang(
@@ -301,10 +331,16 @@ llvm::ErrorOr<PrecompiledPreamble> PrecompiledPreamble::Build(
}
std::unique_ptr<PrecompilePreambleAction> Act;
- Act.reset(new PrecompilePreambleAction(Callbacks));
+ Act.reset(new PrecompilePreambleAction(
+ StoreInMemory ? &Storage.asMemory().Data : nullptr, Callbacks));
if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0]))
return BuildPreambleError::BeginSourceFileFailed;
+ std::unique_ptr<PPCallbacks> DelegatedPPCallbacks =
+ Callbacks.createPPCallbacks();
+ if (DelegatedPPCallbacks)
+ Clang->getPreprocessor().addPPCallbacks(std::move(DelegatedPPCallbacks));
+
Act->Execute();
// Run the callbacks.
@@ -335,9 +371,9 @@ llvm::ErrorOr<PrecompiledPreamble> PrecompiledPreamble::Build(
}
}
- return PrecompiledPreamble(
- std::move(*PreamblePCHFile), std::move(PreambleBytes),
- PreambleEndsAtStartOfLine, std::move(FilesInPreamble));
+ return PrecompiledPreamble(std::move(Storage), std::move(PreambleBytes),
+ PreambleEndsAtStartOfLine,
+ std::move(FilesInPreamble));
}
PreambleBounds PrecompiledPreamble::getBounds() const {
@@ -425,27 +461,33 @@ bool PrecompiledPreamble::CanReuse(const CompilerInvocation &Invocation,
}
void PrecompiledPreamble::AddImplicitPreamble(
- CompilerInvocation &CI, llvm::MemoryBuffer *MainFileBuffer) const {
+ CompilerInvocation &CI, IntrusiveRefCntPtr<vfs::FileSystem> &VFS,
+ llvm::MemoryBuffer *MainFileBuffer) const {
+ assert(VFS && "VFS must not be null");
+
auto &PreprocessorOpts = CI.getPreprocessorOpts();
+ // Remap main file to point to MainFileBuffer.
+ auto MainFilePath = CI.getFrontendOpts().Inputs[0].getFile();
+ PreprocessorOpts.addRemappedFile(MainFilePath, MainFileBuffer);
+
// Configure ImpicitPCHInclude.
PreprocessorOpts.PrecompiledPreambleBytes.first = PreambleBytes.size();
PreprocessorOpts.PrecompiledPreambleBytes.second = PreambleEndsAtStartOfLine;
- PreprocessorOpts.ImplicitPCHInclude = PCHFile.getFilePath();
PreprocessorOpts.DisablePCHValidation = true;
- // Remap main file to point to MainFileBuffer.
- auto MainFilePath = CI.getFrontendOpts().Inputs[0].getFile();
- PreprocessorOpts.addRemappedFile(MainFilePath, MainFileBuffer);
+ setupPreambleStorage(Storage, PreprocessorOpts, VFS);
}
PrecompiledPreamble::PrecompiledPreamble(
- TempPCHFile PCHFile, std::vector<char> PreambleBytes,
+ PCHStorage Storage, std::vector<char> PreambleBytes,
bool PreambleEndsAtStartOfLine,
llvm::StringMap<PreambleFileHash> FilesInPreamble)
- : PCHFile(std::move(PCHFile)), FilesInPreamble(FilesInPreamble),
+ : Storage(std::move(Storage)), FilesInPreamble(std::move(FilesInPreamble)),
PreambleBytes(std::move(PreambleBytes)),
- PreambleEndsAtStartOfLine(PreambleEndsAtStartOfLine) {}
+ PreambleEndsAtStartOfLine(PreambleEndsAtStartOfLine) {
+ assert(this->Storage.getKind() != PCHStorage::Kind::Empty);
+}
llvm::ErrorOr<PrecompiledPreamble::TempPCHFile>
PrecompiledPreamble::TempPCHFile::CreateNewPreamblePCHFile() {
@@ -462,9 +504,15 @@ llvm::ErrorOr<PrecompiledPreamble::TempPCHFile>
PrecompiledPreamble::TempPCHFile::createInSystemTempDir(const Twine &Prefix,
StringRef Suffix) {
llvm::SmallString<64> File;
- auto EC = llvm::sys::fs::createTemporaryFile(Prefix, Suffix, /*ref*/ File);
+ // Using a version of createTemporaryFile with a file descriptor guarantees
+ // that we would never get a race condition in a multi-threaded setting (i.e.,
+ // multiple threads getting the same temporary path).
+ int FD;
+ auto EC = llvm::sys::fs::createTemporaryFile(Prefix, Suffix, FD, File);
if (EC)
return EC;
+ // We only needed to make sure the file exists, close the file right away.
+ llvm::sys::Process::SafelyCloseFileDescriptor(FD);
return TempPCHFile(std::move(File).str());
}
@@ -506,6 +554,87 @@ llvm::StringRef PrecompiledPreamble::TempPCHFile::getFilePath() const {
return *FilePath;
}
+PrecompiledPreamble::PCHStorage::PCHStorage(TempPCHFile File)
+ : StorageKind(Kind::TempFile) {
+ new (&asFile()) TempPCHFile(std::move(File));
+}
+
+PrecompiledPreamble::PCHStorage::PCHStorage(InMemoryPreamble Memory)
+ : StorageKind(Kind::InMemory) {
+ new (&asMemory()) InMemoryPreamble(std::move(Memory));
+}
+
+PrecompiledPreamble::PCHStorage::PCHStorage(PCHStorage &&Other) : PCHStorage() {
+ *this = std::move(Other);
+}
+
+PrecompiledPreamble::PCHStorage &PrecompiledPreamble::PCHStorage::
+operator=(PCHStorage &&Other) {
+ destroy();
+
+ StorageKind = Other.StorageKind;
+ switch (StorageKind) {
+ case Kind::Empty:
+ // do nothing;
+ break;
+ case Kind::TempFile:
+ new (&asFile()) TempPCHFile(std::move(Other.asFile()));
+ break;
+ case Kind::InMemory:
+ new (&asMemory()) InMemoryPreamble(std::move(Other.asMemory()));
+ break;
+ }
+
+ Other.setEmpty();
+ return *this;
+}
+
+PrecompiledPreamble::PCHStorage::~PCHStorage() { destroy(); }
+
+PrecompiledPreamble::PCHStorage::Kind
+PrecompiledPreamble::PCHStorage::getKind() const {
+ return StorageKind;
+}
+
+PrecompiledPreamble::TempPCHFile &PrecompiledPreamble::PCHStorage::asFile() {
+ assert(getKind() == Kind::TempFile);
+ return *reinterpret_cast<TempPCHFile *>(Storage.buffer);
+}
+
+const PrecompiledPreamble::TempPCHFile &
+PrecompiledPreamble::PCHStorage::asFile() const {
+ return const_cast<PCHStorage *>(this)->asFile();
+}
+
+PrecompiledPreamble::InMemoryPreamble &
+PrecompiledPreamble::PCHStorage::asMemory() {
+ assert(getKind() == Kind::InMemory);
+ return *reinterpret_cast<InMemoryPreamble *>(Storage.buffer);
+}
+
+const PrecompiledPreamble::InMemoryPreamble &
+PrecompiledPreamble::PCHStorage::asMemory() const {
+ return const_cast<PCHStorage *>(this)->asMemory();
+}
+
+void PrecompiledPreamble::PCHStorage::destroy() {
+ switch (StorageKind) {
+ case Kind::Empty:
+ return;
+ case Kind::TempFile:
+ asFile().~TempPCHFile();
+ return;
+ case Kind::InMemory:
+ asMemory().~InMemoryPreamble();
+ return;
+ }
+}
+
+void PrecompiledPreamble::PCHStorage::setEmpty() {
+ destroy();
+ StorageKind = Kind::Empty;
+}
+
PrecompiledPreamble::PreambleFileHash
PrecompiledPreamble::PreambleFileHash::createForFile(off_t Size,
time_t ModTime) {
@@ -530,11 +659,47 @@ PrecompiledPreamble::PreambleFileHash::createForMemoryBuffer(
return Result;
}
+void PrecompiledPreamble::setupPreambleStorage(
+ const PCHStorage &Storage, PreprocessorOptions &PreprocessorOpts,
+ IntrusiveRefCntPtr<vfs::FileSystem> &VFS) {
+ if (Storage.getKind() == PCHStorage::Kind::TempFile) {
+ const TempPCHFile &PCHFile = Storage.asFile();
+ PreprocessorOpts.ImplicitPCHInclude = PCHFile.getFilePath();
+
+ // Make sure we can access the PCH file even if we're using a VFS
+ IntrusiveRefCntPtr<vfs::FileSystem> RealFS = vfs::getRealFileSystem();
+ auto PCHPath = PCHFile.getFilePath();
+ if (VFS == RealFS || VFS->exists(PCHPath))
+ return;
+ auto Buf = RealFS->getBufferForFile(PCHPath);
+ if (!Buf) {
+ // We can't read the file even from RealFS, this is clearly an error,
+ // but we'll just leave the current VFS as is and let clang's code
+ // figure out what to do with missing PCH.
+ return;
+ }
+
+ // We have a slight inconsistency here -- we're using the VFS to
+ // read files, but the PCH was generated in the real file system.
+ VFS = createVFSOverlayForPreamblePCH(PCHPath, std::move(*Buf), VFS);
+ } else {
+ assert(Storage.getKind() == PCHStorage::Kind::InMemory);
+ // For in-memory preamble, we have to provide a VFS overlay that makes it
+ // accessible.
+ StringRef PCHPath = getInMemoryPreamblePath();
+ PreprocessorOpts.ImplicitPCHInclude = PCHPath;
+
+ auto Buf = llvm::MemoryBuffer::getMemBuffer(Storage.asMemory().Data);
+ VFS = createVFSOverlayForPreamblePCH(PCHPath, std::move(Buf), VFS);
+ }
+}
+
void PreambleCallbacks::AfterExecute(CompilerInstance &CI) {}
void PreambleCallbacks::AfterPCHEmitted(ASTWriter &Writer) {}
void PreambleCallbacks::HandleTopLevelDecl(DeclGroupRef DG) {}
-void PreambleCallbacks::HandleMacroDefined(const Token &MacroNameTok,
- const MacroDirective *MD) {}
+std::unique_ptr<PPCallbacks> PreambleCallbacks::createPPCallbacks() {
+ return nullptr;
+}
std::error_code clang::make_error_code(BuildPreambleError Error) {
return std::error_code(static_cast<int>(Error), BuildPreambleErrorCategory());
diff --git a/contrib/llvm/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp b/contrib/llvm/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp
index 914039ad5bb1d..2e023294f1e8e 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -143,6 +143,8 @@ public:
ArrayRef<int> Ids) override;
void PragmaWarningPush(SourceLocation Loc, int Level) override;
void PragmaWarningPop(SourceLocation Loc) override;
+ void PragmaAssumeNonNullBegin(SourceLocation Loc) override;
+ void PragmaAssumeNonNullEnd(SourceLocation Loc) override;
bool HandleFirstTokOnLine(Token &Tok);
@@ -549,6 +551,22 @@ void PrintPPOutputPPCallbacks::PragmaWarningPop(SourceLocation Loc) {
setEmittedDirectiveOnThisLine();
}
+void PrintPPOutputPPCallbacks::
+PragmaAssumeNonNullBegin(SourceLocation Loc) {
+ startNewLineIfNeeded();
+ MoveToLine(Loc);
+ OS << "#pragma clang assume_nonnull begin";
+ setEmittedDirectiveOnThisLine();
+}
+
+void PrintPPOutputPPCallbacks::
+PragmaAssumeNonNullEnd(SourceLocation Loc) {
+ startNewLineIfNeeded();
+ MoveToLine(Loc);
+ OS << "#pragma clang assume_nonnull end";
+ setEmittedDirectiveOnThisLine();
+}
+
/// HandleFirstTokOnLine - When emitting a preprocessed file in -E mode, this
/// is called for the first token on each new line. If this really is the start
/// of a new logical line, handle it and return true, otherwise return false.
@@ -702,6 +720,12 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok,
// -traditional-cpp the lexer keeps /all/ whitespace, including comments.
SourceLocation StartLoc = Tok.getLocation();
Callbacks->MoveToLine(StartLoc.getLocWithOffset(Tok.getLength()));
+ } else if (Tok.is(tok::eod)) {
+ // Don't print end of directive tokens, since they are typically newlines
+ // that mess up our line tracking. These come from unknown pre-processor
+ // directives or hash-prefixed comments in standalone assembly files.
+ PP.Lex(Tok);
+ continue;
} else if (Tok.is(tok::annot_module_include)) {
// PrintPPOutputPPCallbacks::InclusionDirective handles producing
// appropriate output here. Ignore this token entirely.
diff --git a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FrontendActions.cpp b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FrontendActions.cpp
index 5efa6aeaf760a..4d587048f62d7 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FrontendActions.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FrontendActions.cpp
@@ -154,7 +154,7 @@ bool FixItRecompile::BeginInvocation(CompilerInstance &CI) {
return true;
}
-#ifdef CLANG_ENABLE_OBJC_REWRITER
+#if CLANG_ENABLE_OBJC_REWRITER
std::unique_ptr<ASTConsumer>
RewriteObjCAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
diff --git a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
index 21686b8c78ea5..1954b24aedad3 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
@@ -31,7 +31,7 @@
#include "llvm/Support/raw_ostream.h"
#include <memory>
-#ifdef CLANG_ENABLE_OBJC_REWRITER
+#if CLANG_ENABLE_OBJC_REWRITER
using namespace clang;
using llvm::utostr;
diff --git a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteObjC.cpp b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
index e0d813df70f8a..096b81bc3f08c 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
@@ -30,7 +30,7 @@
#include "llvm/Support/raw_ostream.h"
#include <memory>
-#ifdef CLANG_ENABLE_OBJC_REWRITER
+#if CLANG_ENABLE_OBJC_REWRITER
using namespace clang;
using llvm::utostr;
diff --git a/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticBuffer.cpp b/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticBuffer.cpp
index d49e983fcd377..288507310baab 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticBuffer.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticBuffer.cpp
@@ -30,34 +30,45 @@ void TextDiagnosticBuffer::HandleDiagnostic(DiagnosticsEngine::Level Level,
default: llvm_unreachable(
"Diagnostic not handled during diagnostic buffering!");
case DiagnosticsEngine::Note:
+ All.emplace_back(Level, Notes.size());
Notes.emplace_back(Info.getLocation(), Buf.str());
break;
case DiagnosticsEngine::Warning:
+ All.emplace_back(Level, Warnings.size());
Warnings.emplace_back(Info.getLocation(), Buf.str());
break;
case DiagnosticsEngine::Remark:
+ All.emplace_back(Level, Remarks.size());
Remarks.emplace_back(Info.getLocation(), Buf.str());
break;
case DiagnosticsEngine::Error:
case DiagnosticsEngine::Fatal:
+ All.emplace_back(Level, Errors.size());
Errors.emplace_back(Info.getLocation(), Buf.str());
break;
}
}
void TextDiagnosticBuffer::FlushDiagnostics(DiagnosticsEngine &Diags) const {
- // FIXME: Flush the diagnostics in order.
- for (const_iterator it = err_begin(), ie = err_end(); it != ie; ++it)
- Diags.Report(Diags.getCustomDiagID(DiagnosticsEngine::Error, "%0"))
- << it->second;
- for (const_iterator it = warn_begin(), ie = warn_end(); it != ie; ++it)
- Diags.Report(Diags.getCustomDiagID(DiagnosticsEngine::Warning, "%0"))
- << it->second;
- for (const_iterator it = remark_begin(), ie = remark_end(); it != ie; ++it)
- Diags.Report(Diags.getCustomDiagID(DiagnosticsEngine::Remark, "%0"))
- << it->second;
- for (const_iterator it = note_begin(), ie = note_end(); it != ie; ++it)
- Diags.Report(Diags.getCustomDiagID(DiagnosticsEngine::Note, "%0"))
- << it->second;
+ for (auto it = All.begin(), ie = All.end(); it != ie; ++it) {
+ auto Diag = Diags.Report(Diags.getCustomDiagID(it->first, "%0"));
+ switch (it->first) {
+ default: llvm_unreachable(
+ "Diagnostic not handled during diagnostic flushing!");
+ case DiagnosticsEngine::Note:
+ Diag << Notes[it->second].second;
+ break;
+ case DiagnosticsEngine::Warning:
+ Diag << Warnings[it->second].second;
+ break;
+ case DiagnosticsEngine::Remark:
+ Diag << Remarks[it->second].second;
+ break;
+ case DiagnosticsEngine::Error:
+ case DiagnosticsEngine::Fatal:
+ Diag << Errors[it->second].second;
+ break;
+ }
+ }
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp b/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
index 427d15ed703ae..0df5393a309bf 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
@@ -229,22 +229,52 @@ public:
return true;
}
- // Return true if string literal is found.
- // When true, P marks begin-position of S in content.
- bool Search(StringRef S, bool EnsureStartOfWord = false) {
+ // Return true if string literal S is matched in content.
+ // When true, P marks begin-position of the match, and calling Advance sets C
+ // to end-position of the match.
+ // If S is the empty string, then search for any letter instead (makes sense
+ // with FinishDirectiveToken=true).
+ // If EnsureStartOfWord, then skip matches that don't start a new word.
+ // If FinishDirectiveToken, then assume the match is the start of a comment
+ // directive for -verify, and extend the match to include the entire first
+ // token of that directive.
+ bool Search(StringRef S, bool EnsureStartOfWord = false,
+ bool FinishDirectiveToken = false) {
do {
- P = std::search(C, End, S.begin(), S.end());
- PEnd = P + S.size();
+ if (!S.empty()) {
+ P = std::search(C, End, S.begin(), S.end());
+ PEnd = P + S.size();
+ }
+ else {
+ P = C;
+ while (P != End && !isLetter(*P))
+ ++P;
+ PEnd = P + 1;
+ }
if (P == End)
break;
- if (!EnsureStartOfWord
- // Check if string literal starts a new word.
- || P == Begin || isWhitespace(P[-1])
- // Or it could be preceded by the start of a comment.
- || (P > (Begin + 1) && (P[-1] == '/' || P[-1] == '*')
- && P[-2] == '/'))
- return true;
- // Otherwise, skip and search again.
+ // If not start of word but required, skip and search again.
+ if (EnsureStartOfWord
+ // Check if string literal starts a new word.
+ && !(P == Begin || isWhitespace(P[-1])
+ // Or it could be preceded by the start of a comment.
+ || (P > (Begin + 1) && (P[-1] == '/' || P[-1] == '*')
+ && P[-2] == '/')))
+ continue;
+ if (FinishDirectiveToken) {
+ while (PEnd != End && (isAlphanumeric(*PEnd)
+ || *PEnd == '-' || *PEnd == '_'))
+ ++PEnd;
+ // Put back trailing digits and hyphens to be parsed later as a count
+ // or count range. Because -verify prefixes must start with letters,
+ // we know the actual directive we found starts with a letter, so
+ // we won't put back the entire directive word and thus record an empty
+ // string.
+ assert(isLetter(*P) && "-verify prefix must start with a letter");
+ while (isDigit(PEnd[-1]) || PEnd[-1] == '-')
+ --PEnd;
+ }
+ return true;
} while (Advance());
return false;
}
@@ -314,37 +344,68 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
// A single comment may contain multiple directives.
bool FoundDirective = false;
for (ParseHelper PH(S); !PH.Done();) {
- // Search for token: expected
- if (!PH.Search("expected", true))
+ // Search for the initial directive token.
+ // If one prefix, save time by searching only for its directives.
+ // Otherwise, search for any potential directive token and check it later.
+ const auto &Prefixes = Diags.getDiagnosticOptions().VerifyPrefixes;
+ if (!(Prefixes.size() == 1 ? PH.Search(*Prefixes.begin(), true, true)
+ : PH.Search("", true, true)))
break;
PH.Advance();
- // Next token: -
- if (!PH.Next("-"))
- continue;
- PH.Advance();
+ // Default directive kind.
+ bool RegexKind = false;
+ const char* KindStr = "string";
+
+ // Parse the initial directive token in reverse so we can easily determine
+ // its exact actual prefix. If we were to parse it from the front instead,
+ // it would be harder to determine where the prefix ends because there
+ // might be multiple matching -verify prefixes because some might prefix
+ // others.
+ StringRef DToken(PH.P, PH.C - PH.P);
- // Next token: { error | warning | note }
+ // Regex in initial directive token: -re
+ if (DToken.endswith("-re")) {
+ RegexKind = true;
+ KindStr = "regex";
+ DToken = DToken.substr(0, DToken.size()-3);
+ }
+
+ // Type in initial directive token: -{error|warning|note|no-diagnostics}
DirectiveList *DL = nullptr;
- if (PH.Next("error"))
+ bool NoDiag = false;
+ StringRef DType;
+ if (DToken.endswith(DType="-error"))
DL = ED ? &ED->Errors : nullptr;
- else if (PH.Next("warning"))
+ else if (DToken.endswith(DType="-warning"))
DL = ED ? &ED->Warnings : nullptr;
- else if (PH.Next("remark"))
+ else if (DToken.endswith(DType="-remark"))
DL = ED ? &ED->Remarks : nullptr;
- else if (PH.Next("note"))
+ else if (DToken.endswith(DType="-note"))
DL = ED ? &ED->Notes : nullptr;
- else if (PH.Next("no-diagnostics")) {
+ else if (DToken.endswith(DType="-no-diagnostics")) {
+ NoDiag = true;
+ if (RegexKind)
+ continue;
+ }
+ else
+ continue;
+ DToken = DToken.substr(0, DToken.size()-DType.size());
+
+ // What's left in DToken is the actual prefix. That might not be a -verify
+ // prefix even if there is only one -verify prefix (for example, the full
+ // DToken is foo-bar-warning, but foo is the only -verify prefix).
+ if (!std::binary_search(Prefixes.begin(), Prefixes.end(), DToken))
+ continue;
+
+ if (NoDiag) {
if (Status == VerifyDiagnosticConsumer::HasOtherExpectedDirectives)
Diags.Report(Pos, diag::err_verify_invalid_no_diags)
<< /*IsExpectedNoDiagnostics=*/true;
else
Status = VerifyDiagnosticConsumer::HasExpectedNoDiagnostics;
continue;
- } else
- continue;
- PH.Advance();
-
+ }
if (Status == VerifyDiagnosticConsumer::HasExpectedNoDiagnostics) {
Diags.Report(Pos, diag::err_verify_invalid_no_diags)
<< /*IsExpectedNoDiagnostics=*/false;
@@ -357,17 +418,6 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
if (!DL)
return true;
- // Default directive kind.
- bool RegexKind = false;
- const char* KindStr = "string";
-
- // Next optional token: -
- if (PH.Next("-re")) {
- PH.Advance();
- RegexKind = true;
- KindStr = "regex";
- }
-
// Next optional token: @
SourceLocation ExpectedLoc;
bool MatchAnyLine = false;
@@ -416,9 +466,12 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
MatchAnyLine = true;
ExpectedLoc = SM.translateFileLineCol(FE, 1, 1);
}
+ } else if (PH.Next("*")) {
+ MatchAnyLine = true;
+ ExpectedLoc = SourceLocation();
}
- if (ExpectedLoc.isInvalid()) {
+ if (ExpectedLoc.isInvalid() && !MatchAnyLine) {
Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
diag::err_verify_missing_line) << KindStr;
continue;
@@ -650,7 +703,10 @@ static unsigned PrintExpected(DiagnosticsEngine &Diags,
llvm::raw_svector_ostream OS(Fmt);
for (auto *DirPtr : DL) {
Directive &D = *DirPtr;
- OS << "\n File " << SourceMgr.getFilename(D.DiagnosticLoc);
+ if (D.DiagnosticLoc.isInvalid())
+ OS << "\n File *";
+ else
+ OS << "\n File " << SourceMgr.getFilename(D.DiagnosticLoc);
if (D.MatchAnyLine)
OS << " Line *";
else
@@ -708,7 +764,8 @@ static unsigned CheckLists(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
continue;
}
- if (!IsFromSameFile(SourceMgr, D.DiagnosticLoc, II->first))
+ if (!D.DiagnosticLoc.isInvalid() &&
+ !IsFromSameFile(SourceMgr, D.DiagnosticLoc, II->first))
continue;
const std::string &RightText = II->second;
diff --git a/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 1666315588065..4167e1fe20b81 100644
--- a/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -94,18 +94,18 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
case RewriteMacros: return llvm::make_unique<RewriteMacrosAction>();
case RewriteTest: return llvm::make_unique<RewriteTestAction>();
-#ifdef CLANG_ENABLE_OBJC_REWRITER
+#if CLANG_ENABLE_OBJC_REWRITER
case RewriteObjC: return llvm::make_unique<RewriteObjCAction>();
#else
case RewriteObjC: Action = "RewriteObjC"; break;
#endif
-#ifdef CLANG_ENABLE_ARCMT
+#if CLANG_ENABLE_ARCMT
case MigrateSource:
return llvm::make_unique<arcmt::MigrateSourceAction>();
#else
case MigrateSource: Action = "MigrateSource"; break;
#endif
-#ifdef CLANG_ENABLE_STATIC_ANALYZER
+#if CLANG_ENABLE_STATIC_ANALYZER
case RunAnalysis: return llvm::make_unique<ento::AnalysisAction>();
#else
case RunAnalysis: Action = "RunAnalysis"; break;
@@ -113,8 +113,8 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
case RunPreprocessorOnly: return llvm::make_unique<PreprocessOnlyAction>();
}
-#if !defined(CLANG_ENABLE_ARCMT) || !defined(CLANG_ENABLE_STATIC_ANALYZER) \
- || !defined(CLANG_ENABLE_OBJC_REWRITER)
+#if !CLANG_ENABLE_ARCMT || !CLANG_ENABLE_STATIC_ANALYZER \
+ || !CLANG_ENABLE_OBJC_REWRITER
CI.getDiagnostics().Report(diag::err_fe_action_not_available) << Action;
return 0;
#else
@@ -135,7 +135,7 @@ CreateFrontendAction(CompilerInstance &CI) {
Act = llvm::make_unique<FixItRecompile>(std::move(Act));
}
-#ifdef CLANG_ENABLE_ARCMT
+#if CLANG_ENABLE_ARCMT
if (CI.getFrontendOpts().ProgramAction != frontend::MigrateSource &&
CI.getFrontendOpts().ProgramAction != frontend::GeneratePCH) {
// Potentially wrap the base FE action in an ARC Migrate Tool action.
@@ -179,7 +179,8 @@ bool clang::ExecuteCompilerInvocation(CompilerInstance *Clang) {
std::unique_ptr<OptTable> Opts = driver::createDriverOptTable();
Opts->PrintHelp(llvm::outs(), "clang -cc1",
"LLVM 'Clang' Compiler: http://clang.llvm.org",
- /*Include=*/ driver::options::CC1Option, /*Exclude=*/ 0);
+ /*Include=*/driver::options::CC1Option,
+ /*Exclude=*/0, /*ShowAllAliases=*/false);
return true;
}
@@ -227,7 +228,7 @@ bool clang::ExecuteCompilerInvocation(CompilerInstance *Clang) {
llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get());
}
-#ifdef CLANG_ENABLE_STATIC_ANALYZER
+#if CLANG_ENABLE_STATIC_ANALYZER
// Honor -analyzer-checker-help.
// This should happen AFTER plugins have been loaded!
if (Clang->getAnalyzerOpts()->ShowCheckerHelp) {
diff --git a/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_cmath.h b/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_cmath.h
index 9bef82611aa42..5331ba401a954 100644
--- a/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_cmath.h
+++ b/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_cmath.h
@@ -131,15 +131,6 @@ __DEVICE__ float ldexp(float __arg, int __exp) {
__DEVICE__ float log(float __x) { return ::logf(__x); }
__DEVICE__ float log10(float __x) { return ::log10f(__x); }
__DEVICE__ float modf(float __x, float *__iptr) { return ::modff(__x, __iptr); }
-__DEVICE__ float nexttoward(float __from, double __to) {
- return __builtin_nexttowardf(__from, __to);
-}
-__DEVICE__ double nexttoward(double __from, double __to) {
- return __builtin_nexttoward(__from, __to);
-}
-__DEVICE__ float nexttowardf(float __from, double __to) {
- return __builtin_nexttowardf(__from, __to);
-}
__DEVICE__ float pow(float __base, float __exp) {
return ::powf(__base, __exp);
}
@@ -157,6 +148,10 @@ __DEVICE__ float sqrt(float __x) { return ::sqrtf(__x); }
__DEVICE__ float tan(float __x) { return ::tanf(__x); }
__DEVICE__ float tanh(float __x) { return ::tanhf(__x); }
+// Notably missing above is nexttoward. We omit it because
+// libdevice doesn't provide an implementation, and we don't want to be in the
+// business of implementing tricky libm functions in this header.
+
// Now we've defined everything we promised we'd define in
// __clang_cuda_math_forward_declares.h. We need to do two additional things to
// fix up our math functions.
@@ -295,13 +290,6 @@ ldexp(__T __x, int __exp) {
return std::ldexp((double)__x, __exp);
}
-template <typename __T>
-__DEVICE__ typename __clang_cuda_enable_if<std::numeric_limits<__T>::is_integer,
- double>::type
-nexttoward(__T __from, double __to) {
- return std::nexttoward((double)__from, __to);
-}
-
template <typename __T1, typename __T2>
__DEVICE__ typename __clang_cuda_enable_if<
std::numeric_limits<__T1>::is_specialized &&
@@ -388,7 +376,6 @@ using ::lrint;
using ::lround;
using ::nearbyint;
using ::nextafter;
-using ::nexttoward;
using ::pow;
using ::remainder;
using ::remquo;
@@ -456,8 +443,6 @@ using ::lroundf;
using ::modff;
using ::nearbyintf;
using ::nextafterf;
-using ::nexttowardf;
-using ::nexttowardf;
using ::powf;
using ::remainderf;
using ::remquof;
diff --git a/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_intrinsics.h b/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_intrinsics.h
index b43ce21d0bb32..02d68a2e618ed 100644
--- a/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_intrinsics.h
+++ b/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_intrinsics.h
@@ -92,6 +92,152 @@ __MAKE_SHUFFLES(__shfl_xor, __nvvm_shfl_bfly_i32, __nvvm_shfl_bfly_f32, 0x1f);
#endif // !defined(__CUDA_ARCH__) || __CUDA_ARCH__ >= 300
+#if CUDA_VERSION >= 9000
+#if (!defined(__CUDA_ARCH__) || __CUDA_ARCH__ >= 300)
+// __shfl_sync_* variants available in CUDA-9
+#pragma push_macro("__MAKE_SYNC_SHUFFLES")
+#define __MAKE_SYNC_SHUFFLES(__FnName, __IntIntrinsic, __FloatIntrinsic, \
+ __Mask) \
+ inline __device__ int __FnName(unsigned int __mask, int __val, int __offset, \
+ int __width = warpSize) { \
+ return __IntIntrinsic(__mask, __val, __offset, \
+ ((warpSize - __width) << 8) | (__Mask)); \
+ } \
+ inline __device__ float __FnName(unsigned int __mask, float __val, \
+ int __offset, int __width = warpSize) { \
+ return __FloatIntrinsic(__mask, __val, __offset, \
+ ((warpSize - __width) << 8) | (__Mask)); \
+ } \
+ inline __device__ unsigned int __FnName(unsigned int __mask, \
+ unsigned int __val, int __offset, \
+ int __width = warpSize) { \
+ return static_cast<unsigned int>( \
+ ::__FnName(__mask, static_cast<int>(__val), __offset, __width)); \
+ } \
+ inline __device__ long long __FnName(unsigned int __mask, long long __val, \
+ int __offset, int __width = warpSize) { \
+ struct __Bits { \
+ int __a, __b; \
+ }; \
+ _Static_assert(sizeof(__val) == sizeof(__Bits)); \
+ _Static_assert(sizeof(__Bits) == 2 * sizeof(int)); \
+ __Bits __tmp; \
+ memcpy(&__val, &__tmp, sizeof(__val)); \
+ __tmp.__a = ::__FnName(__mask, __tmp.__a, __offset, __width); \
+ __tmp.__b = ::__FnName(__mask, __tmp.__b, __offset, __width); \
+ long long __ret; \
+ memcpy(&__ret, &__tmp, sizeof(__tmp)); \
+ return __ret; \
+ } \
+ inline __device__ unsigned long long __FnName( \
+ unsigned int __mask, unsigned long long __val, int __offset, \
+ int __width = warpSize) { \
+ return static_cast<unsigned long long>(::__FnName( \
+ __mask, static_cast<unsigned long long>(__val), __offset, __width)); \
+ } \
+ inline __device__ long __FnName(unsigned int __mask, long __val, \
+ int __offset, int __width = warpSize) { \
+ _Static_assert(sizeof(long) == sizeof(long long) || \
+ sizeof(long) == sizeof(int)); \
+ if (sizeof(long) == sizeof(long long)) { \
+ return static_cast<long>(::__FnName( \
+ __mask, static_cast<long long>(__val), __offset, __width)); \
+ } else if (sizeof(long) == sizeof(int)) { \
+ return static_cast<long>( \
+ ::__FnName(__mask, static_cast<int>(__val), __offset, __width)); \
+ } \
+ } \
+ inline __device__ unsigned long __FnName(unsigned int __mask, \
+ unsigned long __val, int __offset, \
+ int __width = warpSize) { \
+ return static_cast<unsigned long>( \
+ ::__FnName(__mask, static_cast<long>(__val), __offset, __width)); \
+ } \
+ inline __device__ double __FnName(unsigned int __mask, double __val, \
+ int __offset, int __width = warpSize) { \
+ long long __tmp; \
+ _Static_assert(sizeof(__tmp) == sizeof(__val)); \
+ memcpy(&__tmp, &__val, sizeof(__val)); \
+ __tmp = ::__FnName(__mask, __tmp, __offset, __width); \
+ double __ret; \
+ memcpy(&__ret, &__tmp, sizeof(__ret)); \
+ return __ret; \
+ }
+__MAKE_SYNC_SHUFFLES(__shfl_sync, __nvvm_shfl_sync_idx_i32,
+ __nvvm_shfl_sync_idx_f32, 0x1f);
+// We use 0 rather than 31 as our mask, because shfl.up applies to lanes >=
+// maxLane.
+__MAKE_SYNC_SHUFFLES(__shfl_up_sync, __nvvm_shfl_sync_up_i32,
+ __nvvm_shfl_sync_up_f32, 0);
+__MAKE_SYNC_SHUFFLES(__shfl_down_sync, __nvvm_shfl_sync_down_i32,
+ __nvvm_shfl_sync_down_f32, 0x1f);
+__MAKE_SYNC_SHUFFLES(__shfl_xor_sync, __nvvm_shfl_sync_bfly_i32,
+ __nvvm_shfl_sync_bfly_f32, 0x1f);
+#pragma pop_macro("__MAKE_SYNC_SHUFFLES")
+
+inline __device__ void __syncwarp(unsigned int mask = 0xffffffff) {
+ return __nvvm_bar_warp_sync(mask);
+}
+
+inline __device__ void __barrier_sync(unsigned int id) {
+ __nvvm_barrier_sync(id);
+}
+
+inline __device__ void __barrier_sync_count(unsigned int id,
+ unsigned int count) {
+ __nvvm_barrier_sync_cnt(id, count);
+}
+
+inline __device__ int __all_sync(unsigned int mask, int pred) {
+ return __nvvm_vote_all_sync(mask, pred);
+}
+
+inline __device__ int __any_sync(unsigned int mask, int pred) {
+ return __nvvm_vote_any_sync(mask, pred);
+}
+
+inline __device__ int __uni_sync(unsigned int mask, int pred) {
+ return __nvvm_vote_uni_sync(mask, pred);
+}
+
+inline __device__ unsigned int __ballot_sync(unsigned int mask, int pred) {
+ return __nvvm_vote_ballot_sync(mask, pred);
+}
+
+inline __device__ unsigned int __activemask() { return __nvvm_vote_ballot(1); }
+
+inline __device__ unsigned int __fns(unsigned mask, unsigned base, int offset) {
+ return __nvvm_fns(mask, base, offset);
+}
+
+#endif // !defined(__CUDA_ARCH__) || __CUDA_ARCH__ >= 300
+
+// Define __match* builtins CUDA-9 headers expect to see.
+#if !defined(__CUDA_ARCH__) || __CUDA_ARCH__ >= 700
+inline __device__ unsigned int __match32_any_sync(unsigned int mask,
+ unsigned int value) {
+ return __nvvm_match_any_sync_i32(mask, value);
+}
+
+inline __device__ unsigned long long
+__match64_any_sync(unsigned int mask, unsigned long long value) {
+ return __nvvm_match_any_sync_i64(mask, value);
+}
+
+inline __device__ unsigned int
+__match32_all_sync(unsigned int mask, unsigned int value, int *pred) {
+ return __nvvm_match_all_sync_i32p(mask, value, pred);
+}
+
+inline __device__ unsigned long long
+__match64_all_sync(unsigned int mask, unsigned long long value, int *pred) {
+ return __nvvm_match_all_sync_i64p(mask, value, pred);
+}
+#include "crt/sm_70_rt.hpp"
+
+#endif // !defined(__CUDA_ARCH__) || __CUDA_ARCH__ >= 700
+#endif // __CUDA_VERSION >= 9000
+
// sm_32 intrinsics: __ldg and __funnelshift_{l,lc,r,rc}.
// Prevent the vanilla sm_32 intrinsics header from being included.
diff --git a/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_math_forward_declares.h b/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_math_forward_declares.h
index 49c805151d65f..c31b1f4cda355 100644
--- a/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_math_forward_declares.h
+++ b/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_math_forward_declares.h
@@ -149,9 +149,6 @@ __DEVICE__ double nearbyint(double);
__DEVICE__ float nearbyint(float);
__DEVICE__ double nextafter(double, double);
__DEVICE__ float nextafter(float, float);
-__DEVICE__ double nexttoward(double, double);
-__DEVICE__ float nexttoward(float, double);
-__DEVICE__ float nexttowardf(float, double);
__DEVICE__ double pow(double, double);
__DEVICE__ double pow(double, int);
__DEVICE__ float pow(float, float);
@@ -185,6 +182,10 @@ __DEVICE__ float tgamma(float);
__DEVICE__ double trunc(double);
__DEVICE__ float trunc(float);
+// Notably missing above is nexttoward, which we don't define on
+// the device side because libdevice doesn't give us an implementation, and we
+// don't want to be in the business of writing one ourselves.
+
// We need to define these overloads in exactly the namespace our standard
// library uses (including the right inline namespace), otherwise they won't be
// picked up by other functions in the standard library (e.g. functions in
@@ -255,7 +256,6 @@ using ::nan;
using ::nanf;
using ::nearbyint;
using ::nextafter;
-using ::nexttoward;
using ::pow;
using ::remainder;
using ::remquo;
diff --git a/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_runtime_wrapper.h b/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_runtime_wrapper.h
index 931d44b6965b7..a82a8490f3670 100644
--- a/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_runtime_wrapper.h
+++ b/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_runtime_wrapper.h
@@ -62,7 +62,7 @@
#include "cuda.h"
#if !defined(CUDA_VERSION)
#error "cuda.h did not define CUDA_VERSION"
-#elif CUDA_VERSION < 7000 || CUDA_VERSION > 8000
+#elif CUDA_VERSION < 7000 || CUDA_VERSION > 9000
#error "Unsupported CUDA version!"
#endif
@@ -86,7 +86,11 @@
#define __COMMON_FUNCTIONS_H__
#undef __CUDACC__
+#if CUDA_VERSION < 9000
#define __CUDABE__
+#else
+#define __CUDA_LIBDEVICE__
+#endif
// Disables definitions of device-side runtime support stubs in
// cuda_device_runtime_api.h
#include "driver_types.h"
@@ -94,6 +98,7 @@
#include "host_defines.h"
#undef __CUDABE__
+#undef __CUDA_LIBDEVICE__
#define __CUDACC__
#include "cuda_runtime.h"
@@ -105,7 +110,9 @@
#define __nvvm_memcpy(s, d, n, a) __builtin_memcpy(s, d, n)
#define __nvvm_memset(d, c, n, a) __builtin_memset(d, c, n)
+#if CUDA_VERSION < 9000
#include "crt/device_runtime.h"
+#endif
#include "crt/host_runtime.h"
// device_runtime.h defines __cxa_* macros that will conflict with
// cxxabi.h.
@@ -166,7 +173,18 @@ inline __host__ double __signbitd(double x) {
// __device__.
#pragma push_macro("__forceinline__")
#define __forceinline__ __device__ __inline__ __attribute__((always_inline))
+
+#pragma push_macro("__float2half_rn")
+#if CUDA_VERSION >= 9000
+// CUDA-9 has conflicting prototypes for __float2half_rn(float f) in
+// cuda_fp16.h[pp] and device_functions.hpp. We need to get the one in
+// device_functions.hpp out of the way.
+#define __float2half_rn __float2half_rn_disabled
+#endif
+
#include "device_functions.hpp"
+#pragma pop_macro("__float2half_rn")
+
// math_function.hpp uses the __USE_FAST_MATH__ macro to determine whether we
// get the slow-but-accurate or fast-but-inaccurate versions of functions like
@@ -247,7 +265,23 @@ static inline __device__ void __brkpt(int __c) { __brkpt(); }
#pragma push_macro("__GNUC__")
#undef __GNUC__
#define signbit __ignored_cuda_signbit
+
+// CUDA-9 omits device-side definitions of some math functions if it sees
+// include guard from math.h wrapper from libstdc++. We have to undo the header
+// guard temporarily to get the definitions we need.
+#pragma push_macro("_GLIBCXX_MATH_H")
+#pragma push_macro("_LIBCPP_VERSION")
+#if CUDA_VERSION >= 9000
+#undef _GLIBCXX_MATH_H
+// We also need to undo another guard that checks for libc++ 3.8+
+#ifdef _LIBCPP_VERSION
+#define _LIBCPP_VERSION 3700
+#endif
+#endif
+
#include "math_functions.hpp"
+#pragma pop_macro("_GLIBCXX_MATH_H")
+#pragma pop_macro("_LIBCPP_VERSION")
#pragma pop_macro("__GNUC__")
#pragma pop_macro("signbit")
diff --git a/contrib/llvm/tools/clang/lib/Headers/arm64intr.h b/contrib/llvm/tools/clang/lib/Headers/arm64intr.h
new file mode 100644
index 0000000000000..be5228361895c
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/arm64intr.h
@@ -0,0 +1,49 @@
+/*===---- arm64intr.h - ARM64 Windows intrinsics -------------------------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+/* Only include this if we're compiling for the windows platform. */
+#ifndef _MSC_VER
+#include_next <arm64intr.h>
+#else
+
+#ifndef __ARM64INTR_H
+#define __ARM64INTR_H
+
+typedef enum
+{
+ _ARM64_BARRIER_SY = 0xF,
+ _ARM64_BARRIER_ST = 0xE,
+ _ARM64_BARRIER_LD = 0xD,
+ _ARM64_BARRIER_ISH = 0xB,
+ _ARM64_BARRIER_ISHST = 0xA,
+ _ARM64_BARRIER_ISHLD = 0x9,
+ _ARM64_BARRIER_NSH = 0x7,
+ _ARM64_BARRIER_NSHST = 0x6,
+ _ARM64_BARRIER_NSHLD = 0x5,
+ _ARM64_BARRIER_OSH = 0x3,
+ _ARM64_BARRIER_OSHST = 0x2,
+ _ARM64_BARRIER_OSHLD = 0x1
+} _ARM64INTR_BARRIER_TYPE;
+
+#endif /* __ARM64INTR_H */
+#endif /* _MSC_VER */
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx2intrin.h b/contrib/llvm/tools/clang/lib/Headers/avx2intrin.h
index 576f761b25426..caf4ced920545 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx2intrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx2intrin.h
@@ -145,13 +145,21 @@ _mm256_andnot_si256(__m256i __a, __m256i __b)
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_avg_epu8(__m256i __a, __m256i __b)
{
- return (__m256i)__builtin_ia32_pavgb256((__v32qi)__a, (__v32qi)__b);
+ typedef unsigned short __v32hu __attribute__((__vector_size__(64)));
+ return (__m256i)__builtin_convertvector(
+ ((__builtin_convertvector((__v32qu)__a, __v32hu) +
+ __builtin_convertvector((__v32qu)__b, __v32hu)) + 1)
+ >> 1, __v32qu);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_avg_epu16(__m256i __a, __m256i __b)
{
- return (__m256i)__builtin_ia32_pavgw256((__v16hi)__a, (__v16hi)__b);
+ typedef unsigned int __v16su __attribute__((__vector_size__(64)));
+ return (__m256i)__builtin_convertvector(
+ ((__builtin_convertvector((__v16hu)__a, __v16su) +
+ __builtin_convertvector((__v16hu)__b, __v16su)) + 1)
+ >> 1, __v16hu);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512bwintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512bwintrin.h
index 41958b7214e2f..3ff0e3aafdcc2 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512bwintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512bwintrin.h
@@ -56,293 +56,145 @@ _mm512_setzero_hi(void) {
/* Integer compare */
-static __inline__ __mmask64 __DEFAULT_FN_ATTRS
-_mm512_cmpeq_epi8_mask(__m512i __a, __m512i __b) {
- return (__mmask64)__builtin_ia32_pcmpeqb512_mask((__v64qi)__a, (__v64qi)__b,
- (__mmask64)-1);
-}
-
-static __inline__ __mmask64 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpeq_epi8_mask(__mmask64 __u, __m512i __a, __m512i __b) {
- return (__mmask64)__builtin_ia32_pcmpeqb512_mask((__v64qi)__a, (__v64qi)__b,
- __u);
-}
-
-static __inline__ __mmask64 __DEFAULT_FN_ATTRS
-_mm512_cmpeq_epu8_mask(__m512i __a, __m512i __b) {
- return (__mmask64)__builtin_ia32_ucmpb512_mask((__v64qi)__a, (__v64qi)__b, 0,
- (__mmask64)-1);
-}
-
-static __inline__ __mmask64 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpeq_epu8_mask(__mmask64 __u, __m512i __a, __m512i __b) {
- return (__mmask64)__builtin_ia32_ucmpb512_mask((__v64qi)__a, (__v64qi)__b, 0,
- __u);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm512_cmpeq_epi16_mask(__m512i __a, __m512i __b) {
- return (__mmask32)__builtin_ia32_pcmpeqw512_mask((__v32hi)__a, (__v32hi)__b,
- (__mmask32)-1);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpeq_epi16_mask(__mmask32 __u, __m512i __a, __m512i __b) {
- return (__mmask32)__builtin_ia32_pcmpeqw512_mask((__v32hi)__a, (__v32hi)__b,
- __u);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm512_cmpeq_epu16_mask(__m512i __a, __m512i __b) {
- return (__mmask32)__builtin_ia32_ucmpw512_mask((__v32hi)__a, (__v32hi)__b, 0,
- (__mmask32)-1);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpeq_epu16_mask(__mmask32 __u, __m512i __a, __m512i __b) {
- return (__mmask32)__builtin_ia32_ucmpw512_mask((__v32hi)__a, (__v32hi)__b, 0,
- __u);
-}
-
-static __inline__ __mmask64 __DEFAULT_FN_ATTRS
-_mm512_cmpge_epi8_mask(__m512i __a, __m512i __b) {
- return (__mmask64)__builtin_ia32_cmpb512_mask((__v64qi)__a, (__v64qi)__b, 5,
- (__mmask64)-1);
-}
-
-static __inline__ __mmask64 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpge_epi8_mask(__mmask64 __u, __m512i __a, __m512i __b) {
- return (__mmask64)__builtin_ia32_cmpb512_mask((__v64qi)__a, (__v64qi)__b, 5,
- __u);
-}
-
-static __inline__ __mmask64 __DEFAULT_FN_ATTRS
-_mm512_cmpge_epu8_mask(__m512i __a, __m512i __b) {
- return (__mmask64)__builtin_ia32_ucmpb512_mask((__v64qi)__a, (__v64qi)__b, 5,
- (__mmask64)-1);
-}
-
-static __inline__ __mmask64 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpge_epu8_mask(__mmask64 __u, __m512i __a, __m512i __b) {
- return (__mmask64)__builtin_ia32_ucmpb512_mask((__v64qi)__a, (__v64qi)__b, 5,
- __u);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm512_cmpge_epi16_mask(__m512i __a, __m512i __b) {
- return (__mmask32)__builtin_ia32_cmpw512_mask((__v32hi)__a, (__v32hi)__b, 5,
- (__mmask32)-1);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpge_epi16_mask(__mmask32 __u, __m512i __a, __m512i __b) {
- return (__mmask32)__builtin_ia32_cmpw512_mask((__v32hi)__a, (__v32hi)__b, 5,
- __u);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm512_cmpge_epu16_mask(__m512i __a, __m512i __b) {
- return (__mmask32)__builtin_ia32_ucmpw512_mask((__v32hi)__a, (__v32hi)__b, 5,
- (__mmask32)-1);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpge_epu16_mask(__mmask32 __u, __m512i __a, __m512i __b) {
- return (__mmask32)__builtin_ia32_ucmpw512_mask((__v32hi)__a, (__v32hi)__b, 5,
- __u);
-}
-
-static __inline__ __mmask64 __DEFAULT_FN_ATTRS
-_mm512_cmpgt_epi8_mask(__m512i __a, __m512i __b) {
- return (__mmask64)__builtin_ia32_pcmpgtb512_mask((__v64qi)__a, (__v64qi)__b,
- (__mmask64)-1);
-}
-
-static __inline__ __mmask64 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpgt_epi8_mask(__mmask64 __u, __m512i __a, __m512i __b) {
- return (__mmask64)__builtin_ia32_pcmpgtb512_mask((__v64qi)__a, (__v64qi)__b,
- __u);
-}
-
-static __inline__ __mmask64 __DEFAULT_FN_ATTRS
-_mm512_cmpgt_epu8_mask(__m512i __a, __m512i __b) {
- return (__mmask64)__builtin_ia32_ucmpb512_mask((__v64qi)__a, (__v64qi)__b, 6,
- (__mmask64)-1);
-}
-
-static __inline__ __mmask64 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpgt_epu8_mask(__mmask64 __u, __m512i __a, __m512i __b) {
- return (__mmask64)__builtin_ia32_ucmpb512_mask((__v64qi)__a, (__v64qi)__b, 6,
- __u);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm512_cmpgt_epi16_mask(__m512i __a, __m512i __b) {
- return (__mmask32)__builtin_ia32_pcmpgtw512_mask((__v32hi)__a, (__v32hi)__b,
- (__mmask32)-1);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpgt_epi16_mask(__mmask32 __u, __m512i __a, __m512i __b) {
- return (__mmask32)__builtin_ia32_pcmpgtw512_mask((__v32hi)__a, (__v32hi)__b,
- __u);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm512_cmpgt_epu16_mask(__m512i __a, __m512i __b) {
- return (__mmask32)__builtin_ia32_ucmpw512_mask((__v32hi)__a, (__v32hi)__b, 6,
- (__mmask32)-1);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpgt_epu16_mask(__mmask32 __u, __m512i __a, __m512i __b) {
- return (__mmask32)__builtin_ia32_ucmpw512_mask((__v32hi)__a, (__v32hi)__b, 6,
- __u);
-}
-
-static __inline__ __mmask64 __DEFAULT_FN_ATTRS
-_mm512_cmple_epi8_mask(__m512i __a, __m512i __b) {
- return (__mmask64)__builtin_ia32_cmpb512_mask((__v64qi)__a, (__v64qi)__b, 2,
- (__mmask64)-1);
-}
-
-static __inline__ __mmask64 __DEFAULT_FN_ATTRS
-_mm512_mask_cmple_epi8_mask(__mmask64 __u, __m512i __a, __m512i __b) {
- return (__mmask64)__builtin_ia32_cmpb512_mask((__v64qi)__a, (__v64qi)__b, 2,
- __u);
-}
-
-static __inline__ __mmask64 __DEFAULT_FN_ATTRS
-_mm512_cmple_epu8_mask(__m512i __a, __m512i __b) {
- return (__mmask64)__builtin_ia32_ucmpb512_mask((__v64qi)__a, (__v64qi)__b, 2,
- (__mmask64)-1);
-}
-
-static __inline__ __mmask64 __DEFAULT_FN_ATTRS
-_mm512_mask_cmple_epu8_mask(__mmask64 __u, __m512i __a, __m512i __b) {
- return (__mmask64)__builtin_ia32_ucmpb512_mask((__v64qi)__a, (__v64qi)__b, 2,
- __u);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm512_cmple_epi16_mask(__m512i __a, __m512i __b) {
- return (__mmask32)__builtin_ia32_cmpw512_mask((__v32hi)__a, (__v32hi)__b, 2,
- (__mmask32)-1);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm512_mask_cmple_epi16_mask(__mmask32 __u, __m512i __a, __m512i __b) {
- return (__mmask32)__builtin_ia32_cmpw512_mask((__v32hi)__a, (__v32hi)__b, 2,
- __u);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm512_cmple_epu16_mask(__m512i __a, __m512i __b) {
- return (__mmask32)__builtin_ia32_ucmpw512_mask((__v32hi)__a, (__v32hi)__b, 2,
- (__mmask32)-1);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm512_mask_cmple_epu16_mask(__mmask32 __u, __m512i __a, __m512i __b) {
- return (__mmask32)__builtin_ia32_ucmpw512_mask((__v32hi)__a, (__v32hi)__b, 2,
- __u);
-}
-
-static __inline__ __mmask64 __DEFAULT_FN_ATTRS
-_mm512_cmplt_epi8_mask(__m512i __a, __m512i __b) {
- return (__mmask64)__builtin_ia32_cmpb512_mask((__v64qi)__a, (__v64qi)__b, 1,
- (__mmask64)-1);
-}
-
-static __inline__ __mmask64 __DEFAULT_FN_ATTRS
-_mm512_mask_cmplt_epi8_mask(__mmask64 __u, __m512i __a, __m512i __b) {
- return (__mmask64)__builtin_ia32_cmpb512_mask((__v64qi)__a, (__v64qi)__b, 1,
- __u);
-}
-
-static __inline__ __mmask64 __DEFAULT_FN_ATTRS
-_mm512_cmplt_epu8_mask(__m512i __a, __m512i __b) {
- return (__mmask64)__builtin_ia32_ucmpb512_mask((__v64qi)__a, (__v64qi)__b, 1,
- (__mmask64)-1);
-}
-
-static __inline__ __mmask64 __DEFAULT_FN_ATTRS
-_mm512_mask_cmplt_epu8_mask(__mmask64 __u, __m512i __a, __m512i __b) {
- return (__mmask64)__builtin_ia32_ucmpb512_mask((__v64qi)__a, (__v64qi)__b, 1,
- __u);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm512_cmplt_epi16_mask(__m512i __a, __m512i __b) {
- return (__mmask32)__builtin_ia32_cmpw512_mask((__v32hi)__a, (__v32hi)__b, 1,
- (__mmask32)-1);
-}
+#define _mm512_cmp_epi8_mask(a, b, p) __extension__ ({ \
+ (__mmask64)__builtin_ia32_cmpb512_mask((__v64qi)(__m512i)(a), \
+ (__v64qi)(__m512i)(b), (int)(p), \
+ (__mmask64)-1); })
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm512_mask_cmplt_epi16_mask(__mmask32 __u, __m512i __a, __m512i __b) {
- return (__mmask32)__builtin_ia32_cmpw512_mask((__v32hi)__a, (__v32hi)__b, 1,
- __u);
-}
+#define _mm512_mask_cmp_epi8_mask(m, a, b, p) __extension__ ({ \
+ (__mmask64)__builtin_ia32_cmpb512_mask((__v64qi)(__m512i)(a), \
+ (__v64qi)(__m512i)(b), (int)(p), \
+ (__mmask64)(m)); })
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm512_cmplt_epu16_mask(__m512i __a, __m512i __b) {
- return (__mmask32)__builtin_ia32_ucmpw512_mask((__v32hi)__a, (__v32hi)__b, 1,
- (__mmask32)-1);
-}
+#define _mm512_cmp_epu8_mask(a, b, p) __extension__ ({ \
+ (__mmask64)__builtin_ia32_ucmpb512_mask((__v64qi)(__m512i)(a), \
+ (__v64qi)(__m512i)(b), (int)(p), \
+ (__mmask64)-1); })
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm512_mask_cmplt_epu16_mask(__mmask32 __u, __m512i __a, __m512i __b) {
- return (__mmask32)__builtin_ia32_ucmpw512_mask((__v32hi)__a, (__v32hi)__b, 1,
- __u);
-}
+#define _mm512_mask_cmp_epu8_mask(m, a, b, p) __extension__ ({ \
+ (__mmask64)__builtin_ia32_ucmpb512_mask((__v64qi)(__m512i)(a), \
+ (__v64qi)(__m512i)(b), (int)(p), \
+ (__mmask64)(m)); })
-static __inline__ __mmask64 __DEFAULT_FN_ATTRS
-_mm512_cmpneq_epi8_mask(__m512i __a, __m512i __b) {
- return (__mmask64)__builtin_ia32_cmpb512_mask((__v64qi)__a, (__v64qi)__b, 4,
- (__mmask64)-1);
-}
+#define _mm512_cmp_epi16_mask(a, b, p) __extension__ ({ \
+ (__mmask32)__builtin_ia32_cmpw512_mask((__v32hi)(__m512i)(a), \
+ (__v32hi)(__m512i)(b), (int)(p), \
+ (__mmask32)-1); })
-static __inline__ __mmask64 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpneq_epi8_mask(__mmask64 __u, __m512i __a, __m512i __b) {
- return (__mmask64)__builtin_ia32_cmpb512_mask((__v64qi)__a, (__v64qi)__b, 4,
- __u);
-}
+#define _mm512_mask_cmp_epi16_mask(m, a, b, p) __extension__ ({ \
+ (__mmask32)__builtin_ia32_cmpw512_mask((__v32hi)(__m512i)(a), \
+ (__v32hi)(__m512i)(b), (int)(p), \
+ (__mmask32)(m)); })
-static __inline__ __mmask64 __DEFAULT_FN_ATTRS
-_mm512_cmpneq_epu8_mask(__m512i __a, __m512i __b) {
- return (__mmask64)__builtin_ia32_ucmpb512_mask((__v64qi)__a, (__v64qi)__b, 4,
- (__mmask64)-1);
-}
+#define _mm512_cmp_epu16_mask(a, b, p) __extension__ ({ \
+ (__mmask32)__builtin_ia32_ucmpw512_mask((__v32hi)(__m512i)(a), \
+ (__v32hi)(__m512i)(b), (int)(p), \
+ (__mmask32)-1); })
-static __inline__ __mmask64 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpneq_epu8_mask(__mmask64 __u, __m512i __a, __m512i __b) {
- return (__mmask64)__builtin_ia32_ucmpb512_mask((__v64qi)__a, (__v64qi)__b, 4,
- __u);
-}
+#define _mm512_mask_cmp_epu16_mask(m, a, b, p) __extension__ ({ \
+ (__mmask32)__builtin_ia32_ucmpw512_mask((__v32hi)(__m512i)(a), \
+ (__v32hi)(__m512i)(b), (int)(p), \
+ (__mmask32)(m)); })
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm512_cmpneq_epi16_mask(__m512i __a, __m512i __b) {
- return (__mmask32)__builtin_ia32_cmpw512_mask((__v32hi)__a, (__v32hi)__b, 4,
- (__mmask32)-1);
-}
+#define _mm512_cmpeq_epi8_mask(A, B) \
+ _mm512_cmp_epi8_mask((A), (B), _MM_CMPINT_EQ)
+#define _mm512_mask_cmpeq_epi8_mask(k, A, B) \
+ _mm512_mask_cmp_epi8_mask((k), (A), (B), _MM_CMPINT_EQ)
+#define _mm512_cmpge_epi8_mask(A, B) \
+ _mm512_cmp_epi8_mask((A), (B), _MM_CMPINT_GE)
+#define _mm512_mask_cmpge_epi8_mask(k, A, B) \
+ _mm512_mask_cmp_epi8_mask((k), (A), (B), _MM_CMPINT_GE)
+#define _mm512_cmpgt_epi8_mask(A, B) \
+ _mm512_cmp_epi8_mask((A), (B), _MM_CMPINT_GT)
+#define _mm512_mask_cmpgt_epi8_mask(k, A, B) \
+ _mm512_mask_cmp_epi8_mask((k), (A), (B), _MM_CMPINT_GT)
+#define _mm512_cmple_epi8_mask(A, B) \
+ _mm512_cmp_epi8_mask((A), (B), _MM_CMPINT_LE)
+#define _mm512_mask_cmple_epi8_mask(k, A, B) \
+ _mm512_mask_cmp_epi8_mask((k), (A), (B), _MM_CMPINT_LE)
+#define _mm512_cmplt_epi8_mask(A, B) \
+ _mm512_cmp_epi8_mask((A), (B), _MM_CMPINT_LT)
+#define _mm512_mask_cmplt_epi8_mask(k, A, B) \
+ _mm512_mask_cmp_epi8_mask((k), (A), (B), _MM_CMPINT_LT)
+#define _mm512_cmpneq_epi8_mask(A, B) \
+ _mm512_cmp_epi8_mask((A), (B), _MM_CMPINT_NE)
+#define _mm512_mask_cmpneq_epi8_mask(k, A, B) \
+ _mm512_mask_cmp_epi8_mask((k), (A), (B), _MM_CMPINT_NE)
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpneq_epi16_mask(__mmask32 __u, __m512i __a, __m512i __b) {
- return (__mmask32)__builtin_ia32_cmpw512_mask((__v32hi)__a, (__v32hi)__b, 4,
- __u);
-}
+#define _mm512_cmpeq_epu8_mask(A, B) \
+ _mm512_cmp_epu8_mask((A), (B), _MM_CMPINT_EQ)
+#define _mm512_mask_cmpeq_epu8_mask(k, A, B) \
+ _mm512_mask_cmp_epu8_mask((k), (A), (B), _MM_CMPINT_EQ)
+#define _mm512_cmpge_epu8_mask(A, B) \
+ _mm512_cmp_epu8_mask((A), (B), _MM_CMPINT_GE)
+#define _mm512_mask_cmpge_epu8_mask(k, A, B) \
+ _mm512_mask_cmp_epu8_mask((k), (A), (B), _MM_CMPINT_GE)
+#define _mm512_cmpgt_epu8_mask(A, B) \
+ _mm512_cmp_epu8_mask((A), (B), _MM_CMPINT_GT)
+#define _mm512_mask_cmpgt_epu8_mask(k, A, B) \
+ _mm512_mask_cmp_epu8_mask((k), (A), (B), _MM_CMPINT_GT)
+#define _mm512_cmple_epu8_mask(A, B) \
+ _mm512_cmp_epu8_mask((A), (B), _MM_CMPINT_LE)
+#define _mm512_mask_cmple_epu8_mask(k, A, B) \
+ _mm512_mask_cmp_epu8_mask((k), (A), (B), _MM_CMPINT_LE)
+#define _mm512_cmplt_epu8_mask(A, B) \
+ _mm512_cmp_epu8_mask((A), (B), _MM_CMPINT_LT)
+#define _mm512_mask_cmplt_epu8_mask(k, A, B) \
+ _mm512_mask_cmp_epu8_mask((k), (A), (B), _MM_CMPINT_LT)
+#define _mm512_cmpneq_epu8_mask(A, B) \
+ _mm512_cmp_epu8_mask((A), (B), _MM_CMPINT_NE)
+#define _mm512_mask_cmpneq_epu8_mask(k, A, B) \
+ _mm512_mask_cmp_epu8_mask((k), (A), (B), _MM_CMPINT_NE)
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm512_cmpneq_epu16_mask(__m512i __a, __m512i __b) {
- return (__mmask32)__builtin_ia32_ucmpw512_mask((__v32hi)__a, (__v32hi)__b, 4,
- (__mmask32)-1);
-}
+#define _mm512_cmpeq_epi16_mask(A, B) \
+ _mm512_cmp_epi16_mask((A), (B), _MM_CMPINT_EQ)
+#define _mm512_mask_cmpeq_epi16_mask(k, A, B) \
+ _mm512_mask_cmp_epi16_mask((k), (A), (B), _MM_CMPINT_EQ)
+#define _mm512_cmpge_epi16_mask(A, B) \
+ _mm512_cmp_epi16_mask((A), (B), _MM_CMPINT_GE)
+#define _mm512_mask_cmpge_epi16_mask(k, A, B) \
+ _mm512_mask_cmp_epi16_mask((k), (A), (B), _MM_CMPINT_GE)
+#define _mm512_cmpgt_epi16_mask(A, B) \
+ _mm512_cmp_epi16_mask((A), (B), _MM_CMPINT_GT)
+#define _mm512_mask_cmpgt_epi16_mask(k, A, B) \
+ _mm512_mask_cmp_epi16_mask((k), (A), (B), _MM_CMPINT_GT)
+#define _mm512_cmple_epi16_mask(A, B) \
+ _mm512_cmp_epi16_mask((A), (B), _MM_CMPINT_LE)
+#define _mm512_mask_cmple_epi16_mask(k, A, B) \
+ _mm512_mask_cmp_epi16_mask((k), (A), (B), _MM_CMPINT_LE)
+#define _mm512_cmplt_epi16_mask(A, B) \
+ _mm512_cmp_epi16_mask((A), (B), _MM_CMPINT_LT)
+#define _mm512_mask_cmplt_epi16_mask(k, A, B) \
+ _mm512_mask_cmp_epi16_mask((k), (A), (B), _MM_CMPINT_LT)
+#define _mm512_cmpneq_epi16_mask(A, B) \
+ _mm512_cmp_epi16_mask((A), (B), _MM_CMPINT_NE)
+#define _mm512_mask_cmpneq_epi16_mask(k, A, B) \
+ _mm512_mask_cmp_epi16_mask((k), (A), (B), _MM_CMPINT_NE)
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpneq_epu16_mask(__mmask32 __u, __m512i __a, __m512i __b) {
- return (__mmask32)__builtin_ia32_ucmpw512_mask((__v32hi)__a, (__v32hi)__b, 4,
- __u);
-}
+#define _mm512_cmpeq_epu16_mask(A, B) \
+ _mm512_cmp_epu16_mask((A), (B), _MM_CMPINT_EQ)
+#define _mm512_mask_cmpeq_epu16_mask(k, A, B) \
+ _mm512_mask_cmp_epu16_mask((k), (A), (B), _MM_CMPINT_EQ)
+#define _mm512_cmpge_epu16_mask(A, B) \
+ _mm512_cmp_epu16_mask((A), (B), _MM_CMPINT_GE)
+#define _mm512_mask_cmpge_epu16_mask(k, A, B) \
+ _mm512_mask_cmp_epu16_mask((k), (A), (B), _MM_CMPINT_GE)
+#define _mm512_cmpgt_epu16_mask(A, B) \
+ _mm512_cmp_epu16_mask((A), (B), _MM_CMPINT_GT)
+#define _mm512_mask_cmpgt_epu16_mask(k, A, B) \
+ _mm512_mask_cmp_epu16_mask((k), (A), (B), _MM_CMPINT_GT)
+#define _mm512_cmple_epu16_mask(A, B) \
+ _mm512_cmp_epu16_mask((A), (B), _MM_CMPINT_LE)
+#define _mm512_mask_cmple_epu16_mask(k, A, B) \
+ _mm512_mask_cmp_epu16_mask((k), (A), (B), _MM_CMPINT_LE)
+#define _mm512_cmplt_epu16_mask(A, B) \
+ _mm512_cmp_epu16_mask((A), (B), _MM_CMPINT_LT)
+#define _mm512_mask_cmplt_epu16_mask(k, A, B) \
+ _mm512_mask_cmp_epu16_mask((k), (A), (B), _MM_CMPINT_LT)
+#define _mm512_cmpneq_epu16_mask(A, B) \
+ _mm512_cmp_epu16_mask((A), (B), _MM_CMPINT_NE)
+#define _mm512_mask_cmpneq_epu16_mask(k, A, B) \
+ _mm512_mask_cmp_epu16_mask((k), (A), (B), _MM_CMPINT_NE)
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_add_epi8 (__m512i __A, __m512i __B) {
@@ -706,57 +558,55 @@ _mm512_maskz_adds_epu16 (__mmask32 __U, __m512i __A, __m512i __B)
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_avg_epu8 (__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pavgb512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) _mm512_setzero_qi(),
- (__mmask64) -1);
+ typedef unsigned short __v64hu __attribute__((__vector_size__(128)));
+ return (__m512i)__builtin_convertvector(
+ ((__builtin_convertvector((__v64qu) __A, __v64hu) +
+ __builtin_convertvector((__v64qu) __B, __v64hu)) + 1)
+ >> 1, __v64qu);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mask_avg_epu8 (__m512i __W, __mmask64 __U, __m512i __A,
__m512i __B)
{
- return (__m512i) __builtin_ia32_pavgb512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) __W,
- (__mmask64) __U);
+ return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
+ (__v64qi)_mm512_avg_epu8(__A, __B),
+ (__v64qi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_avg_epu8 (__mmask64 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pavgb512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) _mm512_setzero_qi(),
- (__mmask64) __U);
+ return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
+ (__v64qi)_mm512_avg_epu8(__A, __B),
+ (__v64qi)_mm512_setzero_qi());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_avg_epu16 (__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pavgw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) _mm512_setzero_hi(),
- (__mmask32) -1);
+ typedef unsigned int __v32su __attribute__((__vector_size__(128)));
+ return (__m512i)__builtin_convertvector(
+ ((__builtin_convertvector((__v32hu) __A, __v32su) +
+ __builtin_convertvector((__v32hu) __B, __v32su)) + 1)
+ >> 1, __v32hu);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mask_avg_epu16 (__m512i __W, __mmask32 __U, __m512i __A,
__m512i __B)
{
- return (__m512i) __builtin_ia32_pavgw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) __W,
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_avg_epu16(__A, __B),
+ (__v32hi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_avg_epu16 (__mmask32 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pavgw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) _mm512_setzero_hi(),
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_avg_epu16(__A, __B),
+ (__v32hi) _mm512_setzero_hi());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -1543,46 +1393,6 @@ _mm512_maskz_cvtepu8_epi16(__mmask32 __U, __m256i __A)
}
-#define _mm512_cmp_epi8_mask(a, b, p) __extension__ ({ \
- (__mmask64)__builtin_ia32_cmpb512_mask((__v64qi)(__m512i)(a), \
- (__v64qi)(__m512i)(b), (int)(p), \
- (__mmask64)-1); })
-
-#define _mm512_mask_cmp_epi8_mask(m, a, b, p) __extension__ ({ \
- (__mmask64)__builtin_ia32_cmpb512_mask((__v64qi)(__m512i)(a), \
- (__v64qi)(__m512i)(b), (int)(p), \
- (__mmask64)(m)); })
-
-#define _mm512_cmp_epu8_mask(a, b, p) __extension__ ({ \
- (__mmask64)__builtin_ia32_ucmpb512_mask((__v64qi)(__m512i)(a), \
- (__v64qi)(__m512i)(b), (int)(p), \
- (__mmask64)-1); })
-
-#define _mm512_mask_cmp_epu8_mask(m, a, b, p) __extension__ ({ \
- (__mmask64)__builtin_ia32_ucmpb512_mask((__v64qi)(__m512i)(a), \
- (__v64qi)(__m512i)(b), (int)(p), \
- (__mmask64)(m)); })
-
-#define _mm512_cmp_epi16_mask(a, b, p) __extension__ ({ \
- (__mmask32)__builtin_ia32_cmpw512_mask((__v32hi)(__m512i)(a), \
- (__v32hi)(__m512i)(b), (int)(p), \
- (__mmask32)-1); })
-
-#define _mm512_mask_cmp_epi16_mask(m, a, b, p) __extension__ ({ \
- (__mmask32)__builtin_ia32_cmpw512_mask((__v32hi)(__m512i)(a), \
- (__v32hi)(__m512i)(b), (int)(p), \
- (__mmask32)(m)); })
-
-#define _mm512_cmp_epu16_mask(a, b, p) __extension__ ({ \
- (__mmask32)__builtin_ia32_ucmpw512_mask((__v32hi)(__m512i)(a), \
- (__v32hi)(__m512i)(b), (int)(p), \
- (__mmask32)-1); })
-
-#define _mm512_mask_cmp_epu16_mask(m, a, b, p) __extension__ ({ \
- (__mmask32)__builtin_ia32_ucmpw512_mask((__v32hi)(__m512i)(a), \
- (__v32hi)(__m512i)(b), (int)(p), \
- (__mmask32)(m)); })
-
#define _mm512_shufflehi_epi16(A, imm) __extension__ ({ \
(__m512i)__builtin_shufflevector((__v32hi)(__m512i)(A), \
(__v32hi)_mm512_undefined_epi32(), \
@@ -2028,32 +1838,29 @@ _mm512_maskz_mov_epi8 (__mmask64 __U, __m512i __A)
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mask_set1_epi8 (__m512i __O, __mmask64 __M, char __A)
{
- return (__m512i) __builtin_ia32_pbroadcastb512_gpr_mask (__A,
- (__v64qi) __O,
- __M);
+ return (__m512i) __builtin_ia32_selectb_512(__M,
+ (__v64qi)_mm512_set1_epi8(__A),
+ (__v64qi) __O);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_set1_epi8 (__mmask64 __M, char __A)
{
- return (__m512i) __builtin_ia32_pbroadcastb512_gpr_mask (__A,
- (__v64qi)
- _mm512_setzero_qi(),
- __M);
+ return (__m512i) __builtin_ia32_selectb_512(__M,
+ (__v64qi) _mm512_set1_epi8(__A),
+ (__v64qi) _mm512_setzero_si512());
}
static __inline__ __mmask64 __DEFAULT_FN_ATTRS
_mm512_kunpackd (__mmask64 __A, __mmask64 __B)
{
- return (__mmask64) __builtin_ia32_kunpckdi ((__mmask64) __A,
- (__mmask64) __B);
+ return (__mmask64) (( __A & 0xFFFFFFFF) | ( __B << 32));
}
static __inline__ __mmask32 __DEFAULT_FN_ATTRS
_mm512_kunpackw (__mmask32 __A, __mmask32 __B)
{
- return (__mmask32) __builtin_ia32_kunpcksi ((__mmask32) __A,
- (__mmask32) __B);
+return (__mmask32) (( __A & 0xFFFF) | ( __B << 16));
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -2108,61 +1915,56 @@ _mm512_mask_storeu_epi8 (void *__P, __mmask64 __U, __m512i __A)
static __inline__ __mmask64 __DEFAULT_FN_ATTRS
_mm512_test_epi8_mask (__m512i __A, __m512i __B)
{
- return (__mmask64) __builtin_ia32_ptestmb512 ((__v64qi) __A,
- (__v64qi) __B,
- (__mmask64) -1);
+ return _mm512_cmpneq_epi8_mask (_mm512_and_epi32 (__A, __B),
+ _mm512_setzero_qi());
}
static __inline__ __mmask64 __DEFAULT_FN_ATTRS
_mm512_mask_test_epi8_mask (__mmask64 __U, __m512i __A, __m512i __B)
{
- return (__mmask64) __builtin_ia32_ptestmb512 ((__v64qi) __A,
- (__v64qi) __B, __U);
+ return _mm512_mask_cmpneq_epi8_mask (__U, _mm512_and_epi32 (__A, __B),
+ _mm512_setzero_qi());
}
static __inline__ __mmask32 __DEFAULT_FN_ATTRS
_mm512_test_epi16_mask (__m512i __A, __m512i __B)
{
- return (__mmask32) __builtin_ia32_ptestmw512 ((__v32hi) __A,
- (__v32hi) __B,
- (__mmask32) -1);
+ return _mm512_cmpneq_epi16_mask (_mm512_and_epi32 (__A, __B),
+ _mm512_setzero_qi());
}
static __inline__ __mmask32 __DEFAULT_FN_ATTRS
_mm512_mask_test_epi16_mask (__mmask32 __U, __m512i __A, __m512i __B)
{
- return (__mmask32) __builtin_ia32_ptestmw512 ((__v32hi) __A,
- (__v32hi) __B, __U);
+ return _mm512_mask_cmpneq_epi16_mask (__U, _mm512_and_epi32 (__A, __B),
+ _mm512_setzero_qi());
}
static __inline__ __mmask64 __DEFAULT_FN_ATTRS
_mm512_testn_epi8_mask (__m512i __A, __m512i __B)
{
- return (__mmask64) __builtin_ia32_ptestnmb512 ((__v64qi) __A,
- (__v64qi) __B,
- (__mmask64) -1);
+ return _mm512_cmpeq_epi8_mask (_mm512_and_epi32 (__A, __B), _mm512_setzero_qi());
}
static __inline__ __mmask64 __DEFAULT_FN_ATTRS
_mm512_mask_testn_epi8_mask (__mmask64 __U, __m512i __A, __m512i __B)
{
- return (__mmask64) __builtin_ia32_ptestnmb512 ((__v64qi) __A,
- (__v64qi) __B, __U);
+ return _mm512_mask_cmpeq_epi8_mask (__U, _mm512_and_epi32 (__A, __B),
+ _mm512_setzero_qi());
}
static __inline__ __mmask32 __DEFAULT_FN_ATTRS
_mm512_testn_epi16_mask (__m512i __A, __m512i __B)
{
- return (__mmask32) __builtin_ia32_ptestnmw512 ((__v32hi) __A,
- (__v32hi) __B,
- (__mmask32) -1);
+ return _mm512_cmpeq_epi16_mask (_mm512_and_epi32 (__A, __B),
+ _mm512_setzero_qi());
}
static __inline__ __mmask32 __DEFAULT_FN_ATTRS
_mm512_mask_testn_epi16_mask (__mmask32 __U, __m512i __A, __m512i __B)
{
- return (__mmask32) __builtin_ia32_ptestnmw512 ((__v32hi) __A,
- (__v32hi) __B, __U);
+ return _mm512_mask_cmpeq_epi16_mask (__U, _mm512_and_epi32 (__A, __B),
+ _mm512_setzero_qi());
}
static __inline__ __mmask64 __DEFAULT_FN_ATTRS
@@ -2219,17 +2021,17 @@ _mm512_maskz_broadcastb_epi8 (__mmask64 __M, __m128i __A)
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mask_set1_epi16 (__m512i __O, __mmask32 __M, short __A)
{
- return (__m512i) __builtin_ia32_pbroadcastw512_gpr_mask (__A,
- (__v32hi) __O,
- __M);
+ return (__m512i) __builtin_ia32_selectw_512(__M,
+ (__v32hi) _mm512_set1_epi16(__A),
+ (__v32hi) __O);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_set1_epi16 (__mmask32 __M, short __A)
{
- return (__m512i) __builtin_ia32_pbroadcastw512_gpr_mask (__A,
- (__v32hi) _mm512_setzero_hi(),
- __M);
+ return (__m512i) __builtin_ia32_selectw_512(__M,
+ (__v32hi) _mm512_set1_epi16(__A),
+ (__v32hi) _mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512cdintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512cdintrin.h
index 23c423584a7a4..ec7e0cd443b4d 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512cdintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512cdintrin.h
@@ -130,13 +130,14 @@ _mm512_maskz_lzcnt_epi64 (__mmask8 __U, __m512i __A)
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_broadcastmb_epi64 (__mmask8 __A)
{
- return (__m512i) __builtin_ia32_broadcastmb512 (__A);
+ return (__m512i) _mm512_set1_epi64((long long) __A);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_broadcastmw_epi32 (__mmask16 __A)
{
- return (__m512i) __builtin_ia32_broadcastmw512 (__A);
+ return (__m512i) _mm512_set1_epi32((int) __A);
+
}
#undef __DEFAULT_FN_ATTRS
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512dqintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512dqintrin.h
index 4fd1add7735b9..2c431d9740cd1 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512dqintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512dqintrin.h
@@ -973,25 +973,26 @@ _mm512_movepi64_mask (__m512i __A)
static __inline__ __m512 __DEFAULT_FN_ATTRS
_mm512_broadcast_f32x2 (__m128 __A)
{
- return (__m512) __builtin_ia32_broadcastf32x2_512_mask ((__v4sf) __A,
- (__v16sf)_mm512_undefined_ps(),
- (__mmask16) -1);
+ return (__m512)__builtin_shufflevector((__v4sf)__A,
+ (__v4sf)_mm_undefined_ps(),
+ 0, 1, 0, 1, 0, 1, 0, 1,
+ 0, 1, 0, 1, 0, 1, 0, 1);
}
static __inline__ __m512 __DEFAULT_FN_ATTRS
_mm512_mask_broadcast_f32x2 (__m512 __O, __mmask16 __M, __m128 __A)
{
- return (__m512) __builtin_ia32_broadcastf32x2_512_mask ((__v4sf) __A,
- (__v16sf)
- __O, __M);
+ return (__m512)__builtin_ia32_selectps_512((__mmask16)__M,
+ (__v16sf)_mm512_broadcast_f32x2(__A),
+ (__v16sf)__O);
}
static __inline__ __m512 __DEFAULT_FN_ATTRS
_mm512_maskz_broadcast_f32x2 (__mmask16 __M, __m128 __A)
{
- return (__m512) __builtin_ia32_broadcastf32x2_512_mask ((__v4sf) __A,
- (__v16sf)_mm512_setzero_ps (),
- __M);
+ return (__m512)__builtin_ia32_selectps_512((__mmask16)__M,
+ (__v16sf)_mm512_broadcast_f32x2(__A),
+ (__v16sf)_mm512_setzero_ps());
}
static __inline__ __m512 __DEFAULT_FN_ATTRS
@@ -1044,25 +1045,26 @@ _mm512_maskz_broadcast_f64x2(__mmask8 __M, __m128d __A)
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_broadcast_i32x2 (__m128i __A)
{
- return (__m512i) __builtin_ia32_broadcasti32x2_512_mask ((__v4si) __A,
- (__v16si)_mm512_setzero_si512(),
- (__mmask16) -1);
+ return (__m512i)__builtin_shufflevector((__v4si)__A,
+ (__v4si)_mm_undefined_si128(),
+ 0, 1, 0, 1, 0, 1, 0, 1,
+ 0, 1, 0, 1, 0, 1, 0, 1);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mask_broadcast_i32x2 (__m512i __O, __mmask16 __M, __m128i __A)
{
- return (__m512i) __builtin_ia32_broadcasti32x2_512_mask ((__v4si) __A,
- (__v16si)
- __O, __M);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M,
+ (__v16si)_mm512_broadcast_i32x2(__A),
+ (__v16si)__O);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_broadcast_i32x2 (__mmask16 __M, __m128i __A)
{
- return (__m512i) __builtin_ia32_broadcasti32x2_512_mask ((__v4si) __A,
- (__v16si)_mm512_setzero_si512 (),
- __M);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M,
+ (__v16si)_mm512_broadcast_i32x2(__A),
+ (__v16si)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512fintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512fintrin.h
index 4b66acc02fa98..d34f0b1327ae7 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512fintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512fintrin.h
@@ -258,25 +258,6 @@ _mm512_maskz_broadcastq_epi64 (__mmask8 __M, __m128i __A)
(__v8di) _mm512_setzero_si512());
}
-static __inline __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_set1_epi32(__mmask16 __M, int __A)
-{
- return (__m512i) __builtin_ia32_pbroadcastd512_gpr_mask (__A,
- (__v16si)
- _mm512_setzero_si512 (),
- __M);
-}
-
-#ifdef __x86_64__
-static __inline __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_set1_epi64(__mmask8 __M, long long __A)
-{
- return (__m512i) __builtin_ia32_pbroadcastq512_gpr_mask (__A,
- (__v8di)
- _mm512_setzero_si512 (),
- __M);
-}
-#endif
static __inline __m512 __DEFAULT_FN_ATTRS
_mm512_setzero_ps(void)
@@ -336,11 +317,29 @@ _mm512_set1_epi32(int __s)
}
static __inline __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_set1_epi32(__mmask16 __M, int __A)
+{
+ return (__m512i)__builtin_ia32_selectd_512(__M,
+ (__v16si)_mm512_set1_epi32(__A),
+ (__v16si)_mm512_setzero_si512());
+}
+
+static __inline __m512i __DEFAULT_FN_ATTRS
_mm512_set1_epi64(long long __d)
{
return (__m512i)(__v8di){ __d, __d, __d, __d, __d, __d, __d, __d };
}
+#ifdef __x86_64__
+static __inline __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_set1_epi64(__mmask8 __M, long long __A)
+{
+ return (__m512i)__builtin_ia32_selectq_512(__M,
+ (__v8di)_mm512_set1_epi64(__A),
+ (__v8di)_mm512_setzero_si512());
+}
+#endif
+
static __inline__ __m512 __DEFAULT_FN_ATTRS
_mm512_broadcastss_ps(__m128 __A)
{
@@ -4544,37 +4543,6 @@ _mm512_maskz_unpacklo_epi64 (__mmask8 __U, __m512i __A, __m512i __B)
(__v8di)_mm512_setzero_si512());
}
-/* Bit Test */
-
-static __inline __mmask16 __DEFAULT_FN_ATTRS
-_mm512_test_epi32_mask(__m512i __A, __m512i __B)
-{
- return (__mmask16) __builtin_ia32_ptestmd512 ((__v16si) __A,
- (__v16si) __B,
- (__mmask16) -1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm512_mask_test_epi32_mask (__mmask16 __U, __m512i __A, __m512i __B)
-{
- return (__mmask16) __builtin_ia32_ptestmd512 ((__v16si) __A,
- (__v16si) __B, __U);
-}
-
-static __inline __mmask8 __DEFAULT_FN_ATTRS
-_mm512_test_epi64_mask(__m512i __A, __m512i __B)
-{
- return (__mmask8) __builtin_ia32_ptestmq512 ((__v8di) __A,
- (__v8di) __B,
- (__mmask8) -1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm512_mask_test_epi64_mask (__mmask8 __U, __m512i __A, __m512i __B)
-{
- return (__mmask8) __builtin_ia32_ptestmq512 ((__v8di) __A, (__v8di) __B, __U);
-}
-
/* SIMD load ops */
@@ -4845,293 +4813,105 @@ _mm512_knot(__mmask16 __M)
/* Integer compare */
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm512_cmpeq_epi32_mask(__m512i __a, __m512i __b) {
- return (__mmask16)__builtin_ia32_pcmpeqd512_mask((__v16si)__a, (__v16si)__b,
- (__mmask16)-1);
-}
+#define _mm512_cmpeq_epi32_mask(A, B) \
+ _mm512_cmp_epi32_mask((A), (B), _MM_CMPINT_EQ)
+#define _mm512_mask_cmpeq_epi32_mask(k, A, B) \
+ _mm512_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_EQ)
+#define _mm512_cmpge_epi32_mask(A, B) \
+ _mm512_cmp_epi32_mask((A), (B), _MM_CMPINT_GE)
+#define _mm512_mask_cmpge_epi32_mask(k, A, B) \
+ _mm512_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_GE)
+#define _mm512_cmpgt_epi32_mask(A, B) \
+ _mm512_cmp_epi32_mask((A), (B), _MM_CMPINT_GT)
+#define _mm512_mask_cmpgt_epi32_mask(k, A, B) \
+ _mm512_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_GT)
+#define _mm512_cmple_epi32_mask(A, B) \
+ _mm512_cmp_epi32_mask((A), (B), _MM_CMPINT_LE)
+#define _mm512_mask_cmple_epi32_mask(k, A, B) \
+ _mm512_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_LE)
+#define _mm512_cmplt_epi32_mask(A, B) \
+ _mm512_cmp_epi32_mask((A), (B), _MM_CMPINT_LT)
+#define _mm512_mask_cmplt_epi32_mask(k, A, B) \
+ _mm512_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_LT)
+#define _mm512_cmpneq_epi32_mask(A, B) \
+ _mm512_cmp_epi32_mask((A), (B), _MM_CMPINT_NE)
+#define _mm512_mask_cmpneq_epi32_mask(k, A, B) \
+ _mm512_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_NE)
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpeq_epi32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
- return (__mmask16)__builtin_ia32_pcmpeqd512_mask((__v16si)__a, (__v16si)__b,
- __u);
-}
+#define _mm512_cmpeq_epu32_mask(A, B) \
+ _mm512_cmp_epu32_mask((A), (B), _MM_CMPINT_EQ)
+#define _mm512_mask_cmpeq_epu32_mask(k, A, B) \
+ _mm512_mask_cmp_epu32_mask((k), (A), (B), _MM_CMPINT_EQ)
+#define _mm512_cmpge_epu32_mask(A, B) \
+ _mm512_cmp_epu32_mask((A), (B), _MM_CMPINT_GE)
+#define _mm512_mask_cmpge_epu32_mask(k, A, B) \
+ _mm512_mask_cmp_epu32_mask((k), (A), (B), _MM_CMPINT_GE)
+#define _mm512_cmpgt_epu32_mask(A, B) \
+ _mm512_cmp_epu32_mask((A), (B), _MM_CMPINT_GT)
+#define _mm512_mask_cmpgt_epu32_mask(k, A, B) \
+ _mm512_mask_cmp_epu32_mask((k), (A), (B), _MM_CMPINT_GT)
+#define _mm512_cmple_epu32_mask(A, B) \
+ _mm512_cmp_epu32_mask((A), (B), _MM_CMPINT_LE)
+#define _mm512_mask_cmple_epu32_mask(k, A, B) \
+ _mm512_mask_cmp_epu32_mask((k), (A), (B), _MM_CMPINT_LE)
+#define _mm512_cmplt_epu32_mask(A, B) \
+ _mm512_cmp_epu32_mask((A), (B), _MM_CMPINT_LT)
+#define _mm512_mask_cmplt_epu32_mask(k, A, B) \
+ _mm512_mask_cmp_epu32_mask((k), (A), (B), _MM_CMPINT_LT)
+#define _mm512_cmpneq_epu32_mask(A, B) \
+ _mm512_cmp_epu32_mask((A), (B), _MM_CMPINT_NE)
+#define _mm512_mask_cmpneq_epu32_mask(k, A, B) \
+ _mm512_mask_cmp_epu32_mask((k), (A), (B), _MM_CMPINT_NE)
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm512_cmpeq_epu32_mask(__m512i __a, __m512i __b) {
- return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 0,
- (__mmask16)-1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpeq_epu32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
- return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 0,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpeq_epi64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
- return (__mmask8)__builtin_ia32_pcmpeqq512_mask((__v8di)__a, (__v8di)__b,
- __u);
-}
+#define _mm512_cmpeq_epi64_mask(A, B) \
+ _mm512_cmp_epi64_mask((A), (B), _MM_CMPINT_EQ)
+#define _mm512_mask_cmpeq_epi64_mask(k, A, B) \
+ _mm512_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_EQ)
+#define _mm512_cmpge_epi64_mask(A, B) \
+ _mm512_cmp_epi64_mask((A), (B), _MM_CMPINT_GE)
+#define _mm512_mask_cmpge_epi64_mask(k, A, B) \
+ _mm512_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_GE)
+#define _mm512_cmpgt_epi64_mask(A, B) \
+ _mm512_cmp_epi64_mask((A), (B), _MM_CMPINT_GT)
+#define _mm512_mask_cmpgt_epi64_mask(k, A, B) \
+ _mm512_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_GT)
+#define _mm512_cmple_epi64_mask(A, B) \
+ _mm512_cmp_epi64_mask((A), (B), _MM_CMPINT_LE)
+#define _mm512_mask_cmple_epi64_mask(k, A, B) \
+ _mm512_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_LE)
+#define _mm512_cmplt_epi64_mask(A, B) \
+ _mm512_cmp_epi64_mask((A), (B), _MM_CMPINT_LT)
+#define _mm512_mask_cmplt_epi64_mask(k, A, B) \
+ _mm512_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_LT)
+#define _mm512_cmpneq_epi64_mask(A, B) \
+ _mm512_cmp_epi64_mask((A), (B), _MM_CMPINT_NE)
+#define _mm512_mask_cmpneq_epi64_mask(k, A, B) \
+ _mm512_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_NE)
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm512_cmpeq_epi64_mask(__m512i __a, __m512i __b) {
- return (__mmask8)__builtin_ia32_pcmpeqq512_mask((__v8di)__a, (__v8di)__b,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm512_cmpeq_epu64_mask(__m512i __a, __m512i __b) {
- return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 0,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpeq_epu64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
- return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 0,
- __u);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm512_cmpge_epi32_mask(__m512i __a, __m512i __b) {
- return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 5,
- (__mmask16)-1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpge_epi32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
- return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 5,
- __u);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm512_cmpge_epu32_mask(__m512i __a, __m512i __b) {
- return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 5,
- (__mmask16)-1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpge_epu32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
- return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 5,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm512_cmpge_epi64_mask(__m512i __a, __m512i __b) {
- return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 5,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpge_epi64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
- return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 5,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm512_cmpge_epu64_mask(__m512i __a, __m512i __b) {
- return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 5,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpge_epu64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
- return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 5,
- __u);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm512_cmpgt_epi32_mask(__m512i __a, __m512i __b) {
- return (__mmask16)__builtin_ia32_pcmpgtd512_mask((__v16si)__a, (__v16si)__b,
- (__mmask16)-1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpgt_epi32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
- return (__mmask16)__builtin_ia32_pcmpgtd512_mask((__v16si)__a, (__v16si)__b,
- __u);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm512_cmpgt_epu32_mask(__m512i __a, __m512i __b) {
- return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 6,
- (__mmask16)-1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpgt_epu32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
- return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 6,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpgt_epi64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
- return (__mmask8)__builtin_ia32_pcmpgtq512_mask((__v8di)__a, (__v8di)__b,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm512_cmpgt_epi64_mask(__m512i __a, __m512i __b) {
- return (__mmask8)__builtin_ia32_pcmpgtq512_mask((__v8di)__a, (__v8di)__b,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm512_cmpgt_epu64_mask(__m512i __a, __m512i __b) {
- return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 6,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpgt_epu64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
- return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 6,
- __u);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm512_cmple_epi32_mask(__m512i __a, __m512i __b) {
- return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 2,
- (__mmask16)-1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm512_mask_cmple_epi32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
- return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 2,
- __u);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm512_cmple_epu32_mask(__m512i __a, __m512i __b) {
- return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 2,
- (__mmask16)-1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm512_mask_cmple_epu32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
- return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 2,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm512_cmple_epi64_mask(__m512i __a, __m512i __b) {
- return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 2,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm512_mask_cmple_epi64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
- return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 2,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm512_cmple_epu64_mask(__m512i __a, __m512i __b) {
- return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 2,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm512_mask_cmple_epu64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
- return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 2,
- __u);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm512_cmplt_epi32_mask(__m512i __a, __m512i __b) {
- return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 1,
- (__mmask16)-1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm512_mask_cmplt_epi32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
- return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 1,
- __u);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm512_cmplt_epu32_mask(__m512i __a, __m512i __b) {
- return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 1,
- (__mmask16)-1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm512_mask_cmplt_epu32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
- return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 1,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm512_cmplt_epi64_mask(__m512i __a, __m512i __b) {
- return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 1,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm512_mask_cmplt_epi64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
- return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 1,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm512_cmplt_epu64_mask(__m512i __a, __m512i __b) {
- return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 1,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm512_mask_cmplt_epu64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
- return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 1,
- __u);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm512_cmpneq_epi32_mask(__m512i __a, __m512i __b) {
- return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 4,
- (__mmask16)-1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpneq_epi32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
- return (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, 4,
- __u);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm512_cmpneq_epu32_mask(__m512i __a, __m512i __b) {
- return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 4,
- (__mmask16)-1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpneq_epu32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
- return (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, 4,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm512_cmpneq_epi64_mask(__m512i __a, __m512i __b) {
- return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 4,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpneq_epi64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
- return (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, 4,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm512_cmpneq_epu64_mask(__m512i __a, __m512i __b) {
- return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 4,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm512_mask_cmpneq_epu64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
- return (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, 4,
- __u);
-}
+#define _mm512_cmpeq_epu64_mask(A, B) \
+ _mm512_cmp_epu64_mask((A), (B), _MM_CMPINT_EQ)
+#define _mm512_mask_cmpeq_epu64_mask(k, A, B) \
+ _mm512_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_EQ)
+#define _mm512_cmpge_epu64_mask(A, B) \
+ _mm512_cmp_epu64_mask((A), (B), _MM_CMPINT_GE)
+#define _mm512_mask_cmpge_epu64_mask(k, A, B) \
+ _mm512_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_GE)
+#define _mm512_cmpgt_epu64_mask(A, B) \
+ _mm512_cmp_epu64_mask((A), (B), _MM_CMPINT_GT)
+#define _mm512_mask_cmpgt_epu64_mask(k, A, B) \
+ _mm512_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_GT)
+#define _mm512_cmple_epu64_mask(A, B) \
+ _mm512_cmp_epu64_mask((A), (B), _MM_CMPINT_LE)
+#define _mm512_mask_cmple_epu64_mask(k, A, B) \
+ _mm512_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_LE)
+#define _mm512_cmplt_epu64_mask(A, B) \
+ _mm512_cmp_epu64_mask((A), (B), _MM_CMPINT_LT)
+#define _mm512_mask_cmplt_epu64_mask(k, A, B) \
+ _mm512_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_LT)
+#define _mm512_cmpneq_epu64_mask(A, B) \
+ _mm512_cmp_epu64_mask((A), (B), _MM_CMPINT_NE)
+#define _mm512_mask_cmpneq_epu64_mask(k, A, B) \
+ _mm512_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_NE)
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_cvtepi8_epi32(__m128i __A)
@@ -6798,35 +6578,6 @@ _mm512_maskz_permutex2var_ps (__mmask16 __U, __m512 __A, __m512i __I,
(__mmask16) __U);
}
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm512_testn_epi32_mask (__m512i __A, __m512i __B)
-{
- return (__mmask16) __builtin_ia32_ptestnmd512 ((__v16si) __A,
- (__v16si) __B,
- (__mmask16) -1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm512_mask_testn_epi32_mask (__mmask16 __U, __m512i __A, __m512i __B)
-{
- return (__mmask16) __builtin_ia32_ptestnmd512 ((__v16si) __A,
- (__v16si) __B, __U);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm512_testn_epi64_mask (__m512i __A, __m512i __B)
-{
- return (__mmask8) __builtin_ia32_ptestnmq512 ((__v8di) __A,
- (__v8di) __B,
- (__mmask8) -1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm512_mask_testn_epi64_mask (__mmask8 __U, __m512i __A, __m512i __B)
-{
- return (__mmask8) __builtin_ia32_ptestnmq512 ((__v8di) __A,
- (__v8di) __B, __U);
-}
#define _mm512_cvtt_roundpd_epu32(A, R) __extension__ ({ \
(__m256i)__builtin_ia32_cvttpd2udq512_mask((__v8df)(__m512d)(A), \
@@ -7195,76 +6946,100 @@ _mm512_maskz_srai_epi64(__mmask8 __U, __m512i __A, int __B)
}
#define _mm512_shuffle_f32x4(A, B, imm) __extension__ ({ \
- (__m512)__builtin_ia32_shuf_f32x4_mask((__v16sf)(__m512)(A), \
- (__v16sf)(__m512)(B), (int)(imm), \
- (__v16sf)_mm512_undefined_ps(), \
- (__mmask16)-1); })
+ (__m512)__builtin_shufflevector((__v16sf)(__m512)(A), \
+ (__v16sf)(__m512)(B), \
+ 0 + ((((imm) >> 0) & 0x3) * 4), \
+ 1 + ((((imm) >> 0) & 0x3) * 4), \
+ 2 + ((((imm) >> 0) & 0x3) * 4), \
+ 3 + ((((imm) >> 0) & 0x3) * 4), \
+ 0 + ((((imm) >> 2) & 0x3) * 4), \
+ 1 + ((((imm) >> 2) & 0x3) * 4), \
+ 2 + ((((imm) >> 2) & 0x3) * 4), \
+ 3 + ((((imm) >> 2) & 0x3) * 4), \
+ 16 + ((((imm) >> 4) & 0x3) * 4), \
+ 17 + ((((imm) >> 4) & 0x3) * 4), \
+ 18 + ((((imm) >> 4) & 0x3) * 4), \
+ 19 + ((((imm) >> 4) & 0x3) * 4), \
+ 16 + ((((imm) >> 6) & 0x3) * 4), \
+ 17 + ((((imm) >> 6) & 0x3) * 4), \
+ 18 + ((((imm) >> 6) & 0x3) * 4), \
+ 19 + ((((imm) >> 6) & 0x3) * 4)); })
#define _mm512_mask_shuffle_f32x4(W, U, A, B, imm) __extension__ ({ \
- (__m512)__builtin_ia32_shuf_f32x4_mask((__v16sf)(__m512)(A), \
- (__v16sf)(__m512)(B), (int)(imm), \
- (__v16sf)(__m512)(W), \
- (__mmask16)(U)); })
+ (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \
+ (__v16sf)_mm512_shuffle_f32x4((A), (B), (imm)), \
+ (__v16sf)(__m512)(W)); })
#define _mm512_maskz_shuffle_f32x4(U, A, B, imm) __extension__ ({ \
- (__m512)__builtin_ia32_shuf_f32x4_mask((__v16sf)(__m512)(A), \
- (__v16sf)(__m512)(B), (int)(imm), \
- (__v16sf)_mm512_setzero_ps(), \
- (__mmask16)(U)); })
+ (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \
+ (__v16sf)_mm512_shuffle_f32x4((A), (B), (imm)), \
+ (__v16sf)_mm512_setzero_ps()); })
#define _mm512_shuffle_f64x2(A, B, imm) __extension__ ({ \
- (__m512d)__builtin_ia32_shuf_f64x2_mask((__v8df)(__m512d)(A), \
- (__v8df)(__m512d)(B), (int)(imm), \
- (__v8df)_mm512_undefined_pd(), \
- (__mmask8)-1); })
+ (__m512d)__builtin_shufflevector((__v8df)(__m512d)(A), \
+ (__v8df)(__m512d)(B), \
+ 0 + ((((imm) >> 0) & 0x3) * 2), \
+ 1 + ((((imm) >> 0) & 0x3) * 2), \
+ 0 + ((((imm) >> 2) & 0x3) * 2), \
+ 1 + ((((imm) >> 2) & 0x3) * 2), \
+ 8 + ((((imm) >> 4) & 0x3) * 2), \
+ 9 + ((((imm) >> 4) & 0x3) * 2), \
+ 8 + ((((imm) >> 6) & 0x3) * 2), \
+ 9 + ((((imm) >> 6) & 0x3) * 2)); })
#define _mm512_mask_shuffle_f64x2(W, U, A, B, imm) __extension__ ({ \
- (__m512d)__builtin_ia32_shuf_f64x2_mask((__v8df)(__m512d)(A), \
- (__v8df)(__m512d)(B), (int)(imm), \
- (__v8df)(__m512d)(W), \
- (__mmask8)(U)); })
+ (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
+ (__v8df)_mm512_shuffle_f64x2((A), (B), (imm)), \
+ (__v8df)(__m512d)(W)); })
#define _mm512_maskz_shuffle_f64x2(U, A, B, imm) __extension__ ({ \
- (__m512d)__builtin_ia32_shuf_f64x2_mask((__v8df)(__m512d)(A), \
- (__v8df)(__m512d)(B), (int)(imm), \
- (__v8df)_mm512_setzero_pd(), \
- (__mmask8)(U)); })
+ (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
+ (__v8df)_mm512_shuffle_f64x2((A), (B), (imm)), \
+ (__v8df)_mm512_setzero_pd()); })
#define _mm512_shuffle_i32x4(A, B, imm) __extension__ ({ \
- (__m512i)__builtin_ia32_shuf_i32x4_mask((__v16si)(__m512i)(A), \
- (__v16si)(__m512i)(B), (int)(imm), \
- (__v16si)_mm512_setzero_si512(), \
- (__mmask16)-1); })
+ (__m512i)__builtin_shufflevector((__v8di)(__m512i)(A), \
+ (__v8di)(__m512i)(B), \
+ 0 + ((((imm) >> 0) & 0x3) * 2), \
+ 1 + ((((imm) >> 0) & 0x3) * 2), \
+ 0 + ((((imm) >> 2) & 0x3) * 2), \
+ 1 + ((((imm) >> 2) & 0x3) * 2), \
+ 8 + ((((imm) >> 4) & 0x3) * 2), \
+ 9 + ((((imm) >> 4) & 0x3) * 2), \
+ 8 + ((((imm) >> 6) & 0x3) * 2), \
+ 9 + ((((imm) >> 6) & 0x3) * 2)); })
#define _mm512_mask_shuffle_i32x4(W, U, A, B, imm) __extension__ ({ \
- (__m512i)__builtin_ia32_shuf_i32x4_mask((__v16si)(__m512i)(A), \
- (__v16si)(__m512i)(B), (int)(imm), \
- (__v16si)(__m512i)(W), \
- (__mmask16)(U)); })
+ (__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \
+ (__v16si)_mm512_shuffle_i32x4((A), (B), (imm)), \
+ (__v16si)(__m512i)(W)); })
#define _mm512_maskz_shuffle_i32x4(U, A, B, imm) __extension__ ({ \
- (__m512i)__builtin_ia32_shuf_i32x4_mask((__v16si)(__m512i)(A), \
- (__v16si)(__m512i)(B), (int)(imm), \
- (__v16si)_mm512_setzero_si512(), \
- (__mmask16)(U)); })
+ (__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \
+ (__v16si)_mm512_shuffle_i32x4((A), (B), (imm)), \
+ (__v16si)_mm512_setzero_si512()); })
#define _mm512_shuffle_i64x2(A, B, imm) __extension__ ({ \
- (__m512i)__builtin_ia32_shuf_i64x2_mask((__v8di)(__m512i)(A), \
- (__v8di)(__m512i)(B), (int)(imm), \
- (__v8di)_mm512_setzero_si512(), \
- (__mmask8)-1); })
+ (__m512i)__builtin_shufflevector((__v8di)(__m512i)(A), \
+ (__v8di)(__m512i)(B), \
+ 0 + ((((imm) >> 0) & 0x3) * 2), \
+ 1 + ((((imm) >> 0) & 0x3) * 2), \
+ 0 + ((((imm) >> 2) & 0x3) * 2), \
+ 1 + ((((imm) >> 2) & 0x3) * 2), \
+ 8 + ((((imm) >> 4) & 0x3) * 2), \
+ 9 + ((((imm) >> 4) & 0x3) * 2), \
+ 8 + ((((imm) >> 6) & 0x3) * 2), \
+ 9 + ((((imm) >> 6) & 0x3) * 2)); })
#define _mm512_mask_shuffle_i64x2(W, U, A, B, imm) __extension__ ({ \
- (__m512i)__builtin_ia32_shuf_i64x2_mask((__v8di)(__m512i)(A), \
- (__v8di)(__m512i)(B), (int)(imm), \
- (__v8di)(__m512i)(W), \
- (__mmask8)(U)); })
+ (__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \
+ (__v8di)_mm512_shuffle_i64x2((A), (B), (imm)), \
+ (__v8di)(__m512i)(W)); })
#define _mm512_maskz_shuffle_i64x2(U, A, B, imm) __extension__ ({ \
- (__m512i)__builtin_ia32_shuf_i64x2_mask((__v8di)(__m512i)(A), \
- (__v8di)(__m512i)(B), (int)(imm), \
- (__v8di)_mm512_setzero_si512(), \
- (__mmask8)(U)); })
+ (__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \
+ (__v8di)_mm512_shuffle_i64x2((A), (B), (imm)), \
+ (__v8di)_mm512_setzero_si512()); })
#define _mm512_shuffle_pd(A, B, M) __extension__ ({ \
(__m512d)__builtin_shufflevector((__v8df)(__m512d)(A), \
@@ -9012,7 +8787,7 @@ _mm512_kortestz (__mmask16 __A, __mmask16 __B)
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
_mm512_kunpackb (__mmask16 __A, __mmask16 __B)
{
- return (__mmask16) __builtin_ia32_kunpckhi ((__mmask16) __A, (__mmask16) __B);
+ return (__mmask16) (( __A & 0xFF) | ( __B << 8));
}
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
@@ -9035,7 +8810,7 @@ _mm512_stream_si512 (__m512i * __P, __m512i __A)
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_stream_load_si512 (void *__P)
+_mm512_stream_load_si512 (void const *__P)
{
typedef __v8di __v8di_aligned __attribute__((aligned(64)));
return (__m512i) __builtin_nontemporal_load((const __v8di_aligned *)__P);
@@ -9167,6 +8942,64 @@ _mm512_maskz_compress_epi32 (__mmask16 __U, __m512i __A)
(__mmask8)(M), \
_MM_FROUND_CUR_DIRECTION); })
+/* Bit Test */
+
+static __inline __mmask16 __DEFAULT_FN_ATTRS
+_mm512_test_epi32_mask (__m512i __A, __m512i __B)
+{
+ return _mm512_cmpneq_epi32_mask (_mm512_and_epi32(__A, __B),
+ _mm512_setzero_epi32());
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm512_mask_test_epi32_mask (__mmask16 __U, __m512i __A, __m512i __B)
+{
+ return _mm512_mask_cmpneq_epi32_mask (__U, _mm512_and_epi32 (__A, __B),
+ _mm512_setzero_epi32());
+}
+
+static __inline __mmask8 __DEFAULT_FN_ATTRS
+_mm512_test_epi64_mask (__m512i __A, __m512i __B)
+{
+ return _mm512_cmpneq_epi64_mask (_mm512_and_epi32 (__A, __B),
+ _mm512_setzero_epi32());
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm512_mask_test_epi64_mask (__mmask8 __U, __m512i __A, __m512i __B)
+{
+ return _mm512_mask_cmpneq_epi64_mask (__U, _mm512_and_epi32 (__A, __B),
+ _mm512_setzero_epi32());
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm512_testn_epi32_mask (__m512i __A, __m512i __B)
+{
+ return _mm512_cmpeq_epi32_mask (_mm512_and_epi32 (__A, __B),
+ _mm512_setzero_epi32());
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm512_mask_testn_epi32_mask (__mmask16 __U, __m512i __A, __m512i __B)
+{
+ return _mm512_mask_cmpeq_epi32_mask (__U, _mm512_and_epi32 (__A, __B),
+ _mm512_setzero_epi32());
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm512_testn_epi64_mask (__m512i __A, __m512i __B)
+{
+ return _mm512_cmpeq_epi64_mask (_mm512_and_epi32 (__A, __B),
+ _mm512_setzero_epi32());
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_mm512_mask_testn_epi64_mask (__mmask8 __U, __m512i __A, __m512i __B)
+{
+ return _mm512_mask_cmpeq_epi64_mask (__U, _mm512_and_epi32 (__A, __B),
+ _mm512_setzero_epi32());
+}
+
static __inline__ __m512 __DEFAULT_FN_ATTRS
_mm512_movehdup_ps (__m512 __A)
{
@@ -9737,16 +9570,18 @@ _mm_cvtu64_ss (__m128 __A, unsigned long long __B)
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mask_set1_epi32 (__m512i __O, __mmask16 __M, int __A)
{
- return (__m512i) __builtin_ia32_pbroadcastd512_gpr_mask (__A, (__v16si) __O,
- __M);
+ return (__m512i) __builtin_ia32_selectd_512(__M,
+ (__v16si) _mm512_set1_epi32(__A),
+ (__v16si) __O);
}
#ifdef __x86_64__
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mask_set1_epi64 (__m512i __O, __mmask8 __M, long long __A)
{
- return (__m512i) __builtin_ia32_pbroadcastq512_gpr_mask (__A, (__v8di) __O,
- __M);
+ return (__m512i) __builtin_ia32_selectq_512(__M,
+ (__v8di) _mm512_set1_epi64(__A),
+ (__v8di) __O);
}
#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512vlbwintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512vlbwintrin.h
index 3b58d043395a7..e940e2b68533d 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512vlbwintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512vlbwintrin.h
@@ -38,581 +38,285 @@ _mm_setzero_hi(void){
/* Integer compare */
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm_cmpeq_epi8_mask(__m128i __a, __m128i __b) {
- return (__mmask16)__builtin_ia32_pcmpeqb128_mask((__v16qi)__a, (__v16qi)__b,
- (__mmask16)-1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm_mask_cmpeq_epi8_mask(__mmask16 __u, __m128i __a, __m128i __b) {
- return (__mmask16)__builtin_ia32_pcmpeqb128_mask((__v16qi)__a, (__v16qi)__b,
- __u);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm_cmpeq_epu8_mask(__m128i __a, __m128i __b) {
- return (__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)__a, (__v16qi)__b, 0,
- (__mmask16)-1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm_mask_cmpeq_epu8_mask(__mmask16 __u, __m128i __a, __m128i __b) {
- return (__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)__a, (__v16qi)__b, 0,
- __u);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm256_cmpeq_epi8_mask(__m256i __a, __m256i __b) {
- return (__mmask32)__builtin_ia32_pcmpeqb256_mask((__v32qi)__a, (__v32qi)__b,
- (__mmask32)-1);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpeq_epi8_mask(__mmask32 __u, __m256i __a, __m256i __b) {
- return (__mmask32)__builtin_ia32_pcmpeqb256_mask((__v32qi)__a, (__v32qi)__b,
- __u);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm256_cmpeq_epu8_mask(__m256i __a, __m256i __b) {
- return (__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)__a, (__v32qi)__b, 0,
- (__mmask32)-1);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpeq_epu8_mask(__mmask32 __u, __m256i __a, __m256i __b) {
- return (__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)__a, (__v32qi)__b, 0,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmpeq_epi16_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_pcmpeqw128_mask((__v8hi)__a, (__v8hi)__b,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmpeq_epi16_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_pcmpeqw128_mask((__v8hi)__a, (__v8hi)__b,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmpeq_epu16_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)__a, (__v8hi)__b, 0,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmpeq_epu16_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)__a, (__v8hi)__b, 0,
- __u);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm256_cmpeq_epi16_mask(__m256i __a, __m256i __b) {
- return (__mmask16)__builtin_ia32_pcmpeqw256_mask((__v16hi)__a, (__v16hi)__b,
- (__mmask16)-1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpeq_epi16_mask(__mmask16 __u, __m256i __a, __m256i __b) {
- return (__mmask16)__builtin_ia32_pcmpeqw256_mask((__v16hi)__a, (__v16hi)__b,
- __u);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm256_cmpeq_epu16_mask(__m256i __a, __m256i __b) {
- return (__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)__a, (__v16hi)__b, 0,
- (__mmask16)-1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpeq_epu16_mask(__mmask16 __u, __m256i __a, __m256i __b) {
- return (__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)__a, (__v16hi)__b, 0,
- __u);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm_cmpge_epi8_mask(__m128i __a, __m128i __b) {
- return (__mmask16)__builtin_ia32_cmpb128_mask((__v16qi)__a, (__v16qi)__b, 5,
- (__mmask16)-1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm_mask_cmpge_epi8_mask(__mmask16 __u, __m128i __a, __m128i __b) {
- return (__mmask16)__builtin_ia32_cmpb128_mask((__v16qi)__a, (__v16qi)__b, 5,
- __u);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm_cmpge_epu8_mask(__m128i __a, __m128i __b) {
- return (__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)__a, (__v16qi)__b, 5,
- (__mmask16)-1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm_mask_cmpge_epu8_mask(__mmask16 __u, __m128i __a, __m128i __b) {
- return (__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)__a, (__v16qi)__b, 5,
- __u);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm256_cmpge_epi8_mask(__m256i __a, __m256i __b) {
- return (__mmask32)__builtin_ia32_cmpb256_mask((__v32qi)__a, (__v32qi)__b, 5,
- (__mmask32)-1);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpge_epi8_mask(__mmask32 __u, __m256i __a, __m256i __b) {
- return (__mmask32)__builtin_ia32_cmpb256_mask((__v32qi)__a, (__v32qi)__b, 5,
- __u);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm256_cmpge_epu8_mask(__m256i __a, __m256i __b) {
- return (__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)__a, (__v32qi)__b, 5,
- (__mmask32)-1);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpge_epu8_mask(__mmask32 __u, __m256i __a, __m256i __b) {
- return (__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)__a, (__v32qi)__b, 5,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmpge_epi16_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_cmpw128_mask((__v8hi)__a, (__v8hi)__b, 5,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmpge_epi16_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_cmpw128_mask((__v8hi)__a, (__v8hi)__b, 5,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmpge_epu16_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)__a, (__v8hi)__b, 5,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmpge_epu16_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)__a, (__v8hi)__b, 5,
- __u);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm256_cmpge_epi16_mask(__m256i __a, __m256i __b) {
- return (__mmask16)__builtin_ia32_cmpw256_mask((__v16hi)__a, (__v16hi)__b, 5,
- (__mmask16)-1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpge_epi16_mask(__mmask16 __u, __m256i __a, __m256i __b) {
- return (__mmask16)__builtin_ia32_cmpw256_mask((__v16hi)__a, (__v16hi)__b, 5,
- __u);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm256_cmpge_epu16_mask(__m256i __a, __m256i __b) {
- return (__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)__a, (__v16hi)__b, 5,
- (__mmask16)-1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpge_epu16_mask(__mmask16 __u, __m256i __a, __m256i __b) {
- return (__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)__a, (__v16hi)__b, 5,
- __u);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm_cmpgt_epi8_mask(__m128i __a, __m128i __b) {
- return (__mmask16)__builtin_ia32_pcmpgtb128_mask((__v16qi)__a, (__v16qi)__b,
- (__mmask16)-1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm_mask_cmpgt_epi8_mask(__mmask16 __u, __m128i __a, __m128i __b) {
- return (__mmask16)__builtin_ia32_pcmpgtb128_mask((__v16qi)__a, (__v16qi)__b,
- __u);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm_cmpgt_epu8_mask(__m128i __a, __m128i __b) {
- return (__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)__a, (__v16qi)__b, 6,
- (__mmask16)-1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm_mask_cmpgt_epu8_mask(__mmask16 __u, __m128i __a, __m128i __b) {
- return (__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)__a, (__v16qi)__b, 6,
- __u);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm256_cmpgt_epi8_mask(__m256i __a, __m256i __b) {
- return (__mmask32)__builtin_ia32_pcmpgtb256_mask((__v32qi)__a, (__v32qi)__b,
- (__mmask32)-1);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpgt_epi8_mask(__mmask32 __u, __m256i __a, __m256i __b) {
- return (__mmask32)__builtin_ia32_pcmpgtb256_mask((__v32qi)__a, (__v32qi)__b,
- __u);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm256_cmpgt_epu8_mask(__m256i __a, __m256i __b) {
- return (__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)__a, (__v32qi)__b, 6,
- (__mmask32)-1);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpgt_epu8_mask(__mmask32 __u, __m256i __a, __m256i __b) {
- return (__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)__a, (__v32qi)__b, 6,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmpgt_epi16_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_pcmpgtw128_mask((__v8hi)__a, (__v8hi)__b,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmpgt_epi16_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_pcmpgtw128_mask((__v8hi)__a, (__v8hi)__b,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmpgt_epu16_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)__a, (__v8hi)__b, 6,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmpgt_epu16_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)__a, (__v8hi)__b, 6,
- __u);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm256_cmpgt_epi16_mask(__m256i __a, __m256i __b) {
- return (__mmask16)__builtin_ia32_pcmpgtw256_mask((__v16hi)__a, (__v16hi)__b,
- (__mmask16)-1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpgt_epi16_mask(__mmask16 __u, __m256i __a, __m256i __b) {
- return (__mmask16)__builtin_ia32_pcmpgtw256_mask((__v16hi)__a, (__v16hi)__b,
- __u);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm256_cmpgt_epu16_mask(__m256i __a, __m256i __b) {
- return (__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)__a, (__v16hi)__b, 6,
- (__mmask16)-1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpgt_epu16_mask(__mmask16 __u, __m256i __a, __m256i __b) {
- return (__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)__a, (__v16hi)__b, 6,
- __u);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm_cmple_epi8_mask(__m128i __a, __m128i __b) {
- return (__mmask16)__builtin_ia32_cmpb128_mask((__v16qi)__a, (__v16qi)__b, 2,
- (__mmask16)-1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm_mask_cmple_epi8_mask(__mmask16 __u, __m128i __a, __m128i __b) {
- return (__mmask16)__builtin_ia32_cmpb128_mask((__v16qi)__a, (__v16qi)__b, 2,
- __u);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm_cmple_epu8_mask(__m128i __a, __m128i __b) {
- return (__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)__a, (__v16qi)__b, 2,
- (__mmask16)-1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm_mask_cmple_epu8_mask(__mmask16 __u, __m128i __a, __m128i __b) {
- return (__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)__a, (__v16qi)__b, 2,
- __u);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm256_cmple_epi8_mask(__m256i __a, __m256i __b) {
- return (__mmask32)__builtin_ia32_cmpb256_mask((__v32qi)__a, (__v32qi)__b, 2,
- (__mmask32)-1);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm256_mask_cmple_epi8_mask(__mmask32 __u, __m256i __a, __m256i __b) {
- return (__mmask32)__builtin_ia32_cmpb256_mask((__v32qi)__a, (__v32qi)__b, 2,
- __u);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm256_cmple_epu8_mask(__m256i __a, __m256i __b) {
- return (__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)__a, (__v32qi)__b, 2,
- (__mmask32)-1);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm256_mask_cmple_epu8_mask(__mmask32 __u, __m256i __a, __m256i __b) {
- return (__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)__a, (__v32qi)__b, 2,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmple_epi16_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_cmpw128_mask((__v8hi)__a, (__v8hi)__b, 2,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmple_epi16_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_cmpw128_mask((__v8hi)__a, (__v8hi)__b, 2,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmple_epu16_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)__a, (__v8hi)__b, 2,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmple_epu16_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)__a, (__v8hi)__b, 2,
- __u);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm256_cmple_epi16_mask(__m256i __a, __m256i __b) {
- return (__mmask16)__builtin_ia32_cmpw256_mask((__v16hi)__a, (__v16hi)__b, 2,
- (__mmask16)-1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm256_mask_cmple_epi16_mask(__mmask16 __u, __m256i __a, __m256i __b) {
- return (__mmask16)__builtin_ia32_cmpw256_mask((__v16hi)__a, (__v16hi)__b, 2,
- __u);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm256_cmple_epu16_mask(__m256i __a, __m256i __b) {
- return (__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)__a, (__v16hi)__b, 2,
- (__mmask16)-1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm256_mask_cmple_epu16_mask(__mmask16 __u, __m256i __a, __m256i __b) {
- return (__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)__a, (__v16hi)__b, 2,
- __u);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm_cmplt_epi8_mask(__m128i __a, __m128i __b) {
- return (__mmask16)__builtin_ia32_cmpb128_mask((__v16qi)__a, (__v16qi)__b, 1,
- (__mmask16)-1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm_mask_cmplt_epi8_mask(__mmask16 __u, __m128i __a, __m128i __b) {
- return (__mmask16)__builtin_ia32_cmpb128_mask((__v16qi)__a, (__v16qi)__b, 1,
- __u);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm_cmplt_epu8_mask(__m128i __a, __m128i __b) {
- return (__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)__a, (__v16qi)__b, 1,
- (__mmask16)-1);
-}
-
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm_mask_cmplt_epu8_mask(__mmask16 __u, __m128i __a, __m128i __b) {
- return (__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)__a, (__v16qi)__b, 1,
- __u);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm256_cmplt_epi8_mask(__m256i __a, __m256i __b) {
- return (__mmask32)__builtin_ia32_cmpb256_mask((__v32qi)__a, (__v32qi)__b, 1,
- (__mmask32)-1);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm256_mask_cmplt_epi8_mask(__mmask32 __u, __m256i __a, __m256i __b) {
- return (__mmask32)__builtin_ia32_cmpb256_mask((__v32qi)__a, (__v32qi)__b, 1,
- __u);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm256_cmplt_epu8_mask(__m256i __a, __m256i __b) {
- return (__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)__a, (__v32qi)__b, 1,
- (__mmask32)-1);
-}
-
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm256_mask_cmplt_epu8_mask(__mmask32 __u, __m256i __a, __m256i __b) {
- return (__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)__a, (__v32qi)__b, 1,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmplt_epi16_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_cmpw128_mask((__v8hi)__a, (__v8hi)__b, 1,
- (__mmask8)-1);
-}
+#define _mm_cmp_epi8_mask(a, b, p) __extension__ ({ \
+ (__mmask16)__builtin_ia32_cmpb128_mask((__v16qi)(__m128i)(a), \
+ (__v16qi)(__m128i)(b), (int)(p), \
+ (__mmask16)-1); })
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmplt_epi16_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_cmpw128_mask((__v8hi)__a, (__v8hi)__b, 1,
- __u);
-}
+#define _mm_mask_cmp_epi8_mask(m, a, b, p) __extension__ ({ \
+ (__mmask16)__builtin_ia32_cmpb128_mask((__v16qi)(__m128i)(a), \
+ (__v16qi)(__m128i)(b), (int)(p), \
+ (__mmask16)(m)); })
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmplt_epu16_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)__a, (__v8hi)__b, 1,
- (__mmask8)-1);
-}
+#define _mm_cmp_epu8_mask(a, b, p) __extension__ ({ \
+ (__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)(__m128i)(a), \
+ (__v16qi)(__m128i)(b), (int)(p), \
+ (__mmask16)-1); })
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmplt_epu16_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)__a, (__v8hi)__b, 1,
- __u);
-}
+#define _mm_mask_cmp_epu8_mask(m, a, b, p) __extension__ ({ \
+ (__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)(__m128i)(a), \
+ (__v16qi)(__m128i)(b), (int)(p), \
+ (__mmask16)(m)); })
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm256_cmplt_epi16_mask(__m256i __a, __m256i __b) {
- return (__mmask16)__builtin_ia32_cmpw256_mask((__v16hi)__a, (__v16hi)__b, 1,
- (__mmask16)-1);
-}
+#define _mm256_cmp_epi8_mask(a, b, p) __extension__ ({ \
+ (__mmask32)__builtin_ia32_cmpb256_mask((__v32qi)(__m256i)(a), \
+ (__v32qi)(__m256i)(b), (int)(p), \
+ (__mmask32)-1); })
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm256_mask_cmplt_epi16_mask(__mmask16 __u, __m256i __a, __m256i __b) {
- return (__mmask16)__builtin_ia32_cmpw256_mask((__v16hi)__a, (__v16hi)__b, 1,
- __u);
-}
+#define _mm256_mask_cmp_epi8_mask(m, a, b, p) __extension__ ({ \
+ (__mmask32)__builtin_ia32_cmpb256_mask((__v32qi)(__m256i)(a), \
+ (__v32qi)(__m256i)(b), (int)(p), \
+ (__mmask32)(m)); })
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm256_cmplt_epu16_mask(__m256i __a, __m256i __b) {
- return (__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)__a, (__v16hi)__b, 1,
- (__mmask16)-1);
-}
+#define _mm256_cmp_epu8_mask(a, b, p) __extension__ ({ \
+ (__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)(__m256i)(a), \
+ (__v32qi)(__m256i)(b), (int)(p), \
+ (__mmask32)-1); })
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm256_mask_cmplt_epu16_mask(__mmask16 __u, __m256i __a, __m256i __b) {
- return (__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)__a, (__v16hi)__b, 1,
- __u);
-}
+#define _mm256_mask_cmp_epu8_mask(m, a, b, p) __extension__ ({ \
+ (__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)(__m256i)(a), \
+ (__v32qi)(__m256i)(b), (int)(p), \
+ (__mmask32)(m)); })
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm_cmpneq_epi8_mask(__m128i __a, __m128i __b) {
- return (__mmask16)__builtin_ia32_cmpb128_mask((__v16qi)__a, (__v16qi)__b, 4,
- (__mmask16)-1);
-}
+#define _mm_cmp_epi16_mask(a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_cmpw128_mask((__v8hi)(__m128i)(a), \
+ (__v8hi)(__m128i)(b), (int)(p), \
+ (__mmask8)-1); })
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm_mask_cmpneq_epi8_mask(__mmask16 __u, __m128i __a, __m128i __b) {
- return (__mmask16)__builtin_ia32_cmpb128_mask((__v16qi)__a, (__v16qi)__b, 4,
- __u);
-}
+#define _mm_mask_cmp_epi16_mask(m, a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_cmpw128_mask((__v8hi)(__m128i)(a), \
+ (__v8hi)(__m128i)(b), (int)(p), \
+ (__mmask8)(m)); })
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm_cmpneq_epu8_mask(__m128i __a, __m128i __b) {
- return (__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)__a, (__v16qi)__b, 4,
- (__mmask16)-1);
-}
+#define _mm_cmp_epu16_mask(a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)(__m128i)(a), \
+ (__v8hi)(__m128i)(b), (int)(p), \
+ (__mmask8)-1); })
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm_mask_cmpneq_epu8_mask(__mmask16 __u, __m128i __a, __m128i __b) {
- return (__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)__a, (__v16qi)__b, 4,
- __u);
-}
+#define _mm_mask_cmp_epu16_mask(m, a, b, p) __extension__ ({ \
+ (__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)(__m128i)(a), \
+ (__v8hi)(__m128i)(b), (int)(p), \
+ (__mmask8)(m)); })
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm256_cmpneq_epi8_mask(__m256i __a, __m256i __b) {
- return (__mmask32)__builtin_ia32_cmpb256_mask((__v32qi)__a, (__v32qi)__b, 4,
- (__mmask32)-1);
-}
+#define _mm256_cmp_epi16_mask(a, b, p) __extension__ ({ \
+ (__mmask16)__builtin_ia32_cmpw256_mask((__v16hi)(__m256i)(a), \
+ (__v16hi)(__m256i)(b), (int)(p), \
+ (__mmask16)-1); })
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpneq_epi8_mask(__mmask32 __u, __m256i __a, __m256i __b) {
- return (__mmask32)__builtin_ia32_cmpb256_mask((__v32qi)__a, (__v32qi)__b, 4,
- __u);
-}
+#define _mm256_mask_cmp_epi16_mask(m, a, b, p) __extension__ ({ \
+ (__mmask16)__builtin_ia32_cmpw256_mask((__v16hi)(__m256i)(a), \
+ (__v16hi)(__m256i)(b), (int)(p), \
+ (__mmask16)(m)); })
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm256_cmpneq_epu8_mask(__m256i __a, __m256i __b) {
- return (__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)__a, (__v32qi)__b, 4,
- (__mmask32)-1);
-}
+#define _mm256_cmp_epu16_mask(a, b, p) __extension__ ({ \
+ (__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)(__m256i)(a), \
+ (__v16hi)(__m256i)(b), (int)(p), \
+ (__mmask16)-1); })
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpneq_epu8_mask(__mmask32 __u, __m256i __a, __m256i __b) {
- return (__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)__a, (__v32qi)__b, 4,
- __u);
-}
+#define _mm256_mask_cmp_epu16_mask(m, a, b, p) __extension__ ({ \
+ (__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)(__m256i)(a), \
+ (__v16hi)(__m256i)(b), (int)(p), \
+ (__mmask16)(m)); })
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmpneq_epi16_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_cmpw128_mask((__v8hi)__a, (__v8hi)__b, 4,
- (__mmask8)-1);
-}
+#define _mm_cmpeq_epi8_mask(A, B) \
+ _mm_cmp_epi8_mask((A), (B), _MM_CMPINT_EQ)
+#define _mm_mask_cmpeq_epi8_mask(k, A, B) \
+ _mm_mask_cmp_epi8_mask((k), (A), (B), _MM_CMPINT_EQ)
+#define _mm_cmpge_epi8_mask(A, B) \
+ _mm_cmp_epi8_mask((A), (B), _MM_CMPINT_GE)
+#define _mm_mask_cmpge_epi8_mask(k, A, B) \
+ _mm_mask_cmp_epi8_mask((k), (A), (B), _MM_CMPINT_GE)
+#define _mm_cmpgt_epi8_mask(A, B) \
+ _mm_cmp_epi8_mask((A), (B), _MM_CMPINT_GT)
+#define _mm_mask_cmpgt_epi8_mask(k, A, B) \
+ _mm_mask_cmp_epi8_mask((k), (A), (B), _MM_CMPINT_GT)
+#define _mm_cmple_epi8_mask(A, B) \
+ _mm_cmp_epi8_mask((A), (B), _MM_CMPINT_LE)
+#define _mm_mask_cmple_epi8_mask(k, A, B) \
+ _mm_mask_cmp_epi8_mask((k), (A), (B), _MM_CMPINT_LE)
+#define _mm_cmplt_epi8_mask(A, B) \
+ _mm_cmp_epi8_mask((A), (B), _MM_CMPINT_LT)
+#define _mm_mask_cmplt_epi8_mask(k, A, B) \
+ _mm_mask_cmp_epi8_mask((k), (A), (B), _MM_CMPINT_LT)
+#define _mm_cmpneq_epi8_mask(A, B) \
+ _mm_cmp_epi8_mask((A), (B), _MM_CMPINT_NE)
+#define _mm_mask_cmpneq_epi8_mask(k, A, B) \
+ _mm_mask_cmp_epi8_mask((k), (A), (B), _MM_CMPINT_NE)
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmpneq_epi16_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_cmpw128_mask((__v8hi)__a, (__v8hi)__b, 4,
- __u);
-}
+#define _mm256_cmpeq_epi8_mask(A, B) \
+ _mm256_cmp_epi8_mask((A), (B), _MM_CMPINT_EQ)
+#define _mm256_mask_cmpeq_epi8_mask(k, A, B) \
+ _mm256_mask_cmp_epi8_mask((k), (A), (B), _MM_CMPINT_EQ)
+#define _mm256_cmpge_epi8_mask(A, B) \
+ _mm256_cmp_epi8_mask((A), (B), _MM_CMPINT_GE)
+#define _mm256_mask_cmpge_epi8_mask(k, A, B) \
+ _mm256_mask_cmp_epi8_mask((k), (A), (B), _MM_CMPINT_GE)
+#define _mm256_cmpgt_epi8_mask(A, B) \
+ _mm256_cmp_epi8_mask((A), (B), _MM_CMPINT_GT)
+#define _mm256_mask_cmpgt_epi8_mask(k, A, B) \
+ _mm256_mask_cmp_epi8_mask((k), (A), (B), _MM_CMPINT_GT)
+#define _mm256_cmple_epi8_mask(A, B) \
+ _mm256_cmp_epi8_mask((A), (B), _MM_CMPINT_LE)
+#define _mm256_mask_cmple_epi8_mask(k, A, B) \
+ _mm256_mask_cmp_epi8_mask((k), (A), (B), _MM_CMPINT_LE)
+#define _mm256_cmplt_epi8_mask(A, B) \
+ _mm256_cmp_epi8_mask((A), (B), _MM_CMPINT_LT)
+#define _mm256_mask_cmplt_epi8_mask(k, A, B) \
+ _mm256_mask_cmp_epi8_mask((k), (A), (B), _MM_CMPINT_LT)
+#define _mm256_cmpneq_epi8_mask(A, B) \
+ _mm256_cmp_epi8_mask((A), (B), _MM_CMPINT_NE)
+#define _mm256_mask_cmpneq_epi8_mask(k, A, B) \
+ _mm256_mask_cmp_epi8_mask((k), (A), (B), _MM_CMPINT_NE)
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmpneq_epu16_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)__a, (__v8hi)__b, 4,
- (__mmask8)-1);
-}
+#define _mm_cmpeq_epu8_mask(A, B) \
+ _mm_cmp_epu8_mask((A), (B), _MM_CMPINT_EQ)
+#define _mm_mask_cmpeq_epu8_mask(k, A, B) \
+ _mm_mask_cmp_epu8_mask((k), (A), (B), _MM_CMPINT_EQ)
+#define _mm_cmpge_epu8_mask(A, B) \
+ _mm_cmp_epu8_mask((A), (B), _MM_CMPINT_GE)
+#define _mm_mask_cmpge_epu8_mask(k, A, B) \
+ _mm_mask_cmp_epu8_mask((k), (A), (B), _MM_CMPINT_GE)
+#define _mm_cmpgt_epu8_mask(A, B) \
+ _mm_cmp_epu8_mask((A), (B), _MM_CMPINT_GT)
+#define _mm_mask_cmpgt_epu8_mask(k, A, B) \
+ _mm_mask_cmp_epu8_mask((k), (A), (B), _MM_CMPINT_GT)
+#define _mm_cmple_epu8_mask(A, B) \
+ _mm_cmp_epu8_mask((A), (B), _MM_CMPINT_LE)
+#define _mm_mask_cmple_epu8_mask(k, A, B) \
+ _mm_mask_cmp_epu8_mask((k), (A), (B), _MM_CMPINT_LE)
+#define _mm_cmplt_epu8_mask(A, B) \
+ _mm_cmp_epu8_mask((A), (B), _MM_CMPINT_LT)
+#define _mm_mask_cmplt_epu8_mask(k, A, B) \
+ _mm_mask_cmp_epu8_mask((k), (A), (B), _MM_CMPINT_LT)
+#define _mm_cmpneq_epu8_mask(A, B) \
+ _mm_cmp_epu8_mask((A), (B), _MM_CMPINT_NE)
+#define _mm_mask_cmpneq_epu8_mask(k, A, B) \
+ _mm_mask_cmp_epu8_mask((k), (A), (B), _MM_CMPINT_NE)
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmpneq_epu16_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)__a, (__v8hi)__b, 4,
- __u);
-}
+#define _mm256_cmpeq_epu8_mask(A, B) \
+ _mm256_cmp_epu8_mask((A), (B), _MM_CMPINT_EQ)
+#define _mm256_mask_cmpeq_epu8_mask(k, A, B) \
+ _mm256_mask_cmp_epu8_mask((k), (A), (B), _MM_CMPINT_EQ)
+#define _mm256_cmpge_epu8_mask(A, B) \
+ _mm256_cmp_epu8_mask((A), (B), _MM_CMPINT_GE)
+#define _mm256_mask_cmpge_epu8_mask(k, A, B) \
+ _mm256_mask_cmp_epu8_mask((k), (A), (B), _MM_CMPINT_GE)
+#define _mm256_cmpgt_epu8_mask(A, B) \
+ _mm256_cmp_epu8_mask((A), (B), _MM_CMPINT_GT)
+#define _mm256_mask_cmpgt_epu8_mask(k, A, B) \
+ _mm256_mask_cmp_epu8_mask((k), (A), (B), _MM_CMPINT_GT)
+#define _mm256_cmple_epu8_mask(A, B) \
+ _mm256_cmp_epu8_mask((A), (B), _MM_CMPINT_LE)
+#define _mm256_mask_cmple_epu8_mask(k, A, B) \
+ _mm256_mask_cmp_epu8_mask((k), (A), (B), _MM_CMPINT_LE)
+#define _mm256_cmplt_epu8_mask(A, B) \
+ _mm256_cmp_epu8_mask((A), (B), _MM_CMPINT_LT)
+#define _mm256_mask_cmplt_epu8_mask(k, A, B) \
+ _mm256_mask_cmp_epu8_mask((k), (A), (B), _MM_CMPINT_LT)
+#define _mm256_cmpneq_epu8_mask(A, B) \
+ _mm256_cmp_epu8_mask((A), (B), _MM_CMPINT_NE)
+#define _mm256_mask_cmpneq_epu8_mask(k, A, B) \
+ _mm256_mask_cmp_epu8_mask((k), (A), (B), _MM_CMPINT_NE)
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm256_cmpneq_epi16_mask(__m256i __a, __m256i __b) {
- return (__mmask16)__builtin_ia32_cmpw256_mask((__v16hi)__a, (__v16hi)__b, 4,
- (__mmask16)-1);
-}
+#define _mm_cmpeq_epi16_mask(A, B) \
+ _mm_cmp_epi16_mask((A), (B), _MM_CMPINT_EQ)
+#define _mm_mask_cmpeq_epi16_mask(k, A, B) \
+ _mm_mask_cmp_epi16_mask((k), (A), (B), _MM_CMPINT_EQ)
+#define _mm_cmpge_epi16_mask(A, B) \
+ _mm_cmp_epi16_mask((A), (B), _MM_CMPINT_GE)
+#define _mm_mask_cmpge_epi16_mask(k, A, B) \
+ _mm_mask_cmp_epi16_mask((k), (A), (B), _MM_CMPINT_GE)
+#define _mm_cmpgt_epi16_mask(A, B) \
+ _mm_cmp_epi16_mask((A), (B), _MM_CMPINT_GT)
+#define _mm_mask_cmpgt_epi16_mask(k, A, B) \
+ _mm_mask_cmp_epi16_mask((k), (A), (B), _MM_CMPINT_GT)
+#define _mm_cmple_epi16_mask(A, B) \
+ _mm_cmp_epi16_mask((A), (B), _MM_CMPINT_LE)
+#define _mm_mask_cmple_epi16_mask(k, A, B) \
+ _mm_mask_cmp_epi16_mask((k), (A), (B), _MM_CMPINT_LE)
+#define _mm_cmplt_epi16_mask(A, B) \
+ _mm_cmp_epi16_mask((A), (B), _MM_CMPINT_LT)
+#define _mm_mask_cmplt_epi16_mask(k, A, B) \
+ _mm_mask_cmp_epi16_mask((k), (A), (B), _MM_CMPINT_LT)
+#define _mm_cmpneq_epi16_mask(A, B) \
+ _mm_cmp_epi16_mask((A), (B), _MM_CMPINT_NE)
+#define _mm_mask_cmpneq_epi16_mask(k, A, B) \
+ _mm_mask_cmp_epi16_mask((k), (A), (B), _MM_CMPINT_NE)
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpneq_epi16_mask(__mmask16 __u, __m256i __a, __m256i __b) {
- return (__mmask16)__builtin_ia32_cmpw256_mask((__v16hi)__a, (__v16hi)__b, 4,
- __u);
-}
+#define _mm256_cmpeq_epi16_mask(A, B) \
+ _mm256_cmp_epi16_mask((A), (B), _MM_CMPINT_EQ)
+#define _mm256_mask_cmpeq_epi16_mask(k, A, B) \
+ _mm256_mask_cmp_epi16_mask((k), (A), (B), _MM_CMPINT_EQ)
+#define _mm256_cmpge_epi16_mask(A, B) \
+ _mm256_cmp_epi16_mask((A), (B), _MM_CMPINT_GE)
+#define _mm256_mask_cmpge_epi16_mask(k, A, B) \
+ _mm256_mask_cmp_epi16_mask((k), (A), (B), _MM_CMPINT_GE)
+#define _mm256_cmpgt_epi16_mask(A, B) \
+ _mm256_cmp_epi16_mask((A), (B), _MM_CMPINT_GT)
+#define _mm256_mask_cmpgt_epi16_mask(k, A, B) \
+ _mm256_mask_cmp_epi16_mask((k), (A), (B), _MM_CMPINT_GT)
+#define _mm256_cmple_epi16_mask(A, B) \
+ _mm256_cmp_epi16_mask((A), (B), _MM_CMPINT_LE)
+#define _mm256_mask_cmple_epi16_mask(k, A, B) \
+ _mm256_mask_cmp_epi16_mask((k), (A), (B), _MM_CMPINT_LE)
+#define _mm256_cmplt_epi16_mask(A, B) \
+ _mm256_cmp_epi16_mask((A), (B), _MM_CMPINT_LT)
+#define _mm256_mask_cmplt_epi16_mask(k, A, B) \
+ _mm256_mask_cmp_epi16_mask((k), (A), (B), _MM_CMPINT_LT)
+#define _mm256_cmpneq_epi16_mask(A, B) \
+ _mm256_cmp_epi16_mask((A), (B), _MM_CMPINT_NE)
+#define _mm256_mask_cmpneq_epi16_mask(k, A, B) \
+ _mm256_mask_cmp_epi16_mask((k), (A), (B), _MM_CMPINT_NE)
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm256_cmpneq_epu16_mask(__m256i __a, __m256i __b) {
- return (__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)__a, (__v16hi)__b, 4,
- (__mmask16)-1);
-}
+#define _mm_cmpeq_epu16_mask(A, B) \
+ _mm_cmp_epu16_mask((A), (B), _MM_CMPINT_EQ)
+#define _mm_mask_cmpeq_epu16_mask(k, A, B) \
+ _mm_mask_cmp_epu16_mask((k), (A), (B), _MM_CMPINT_EQ)
+#define _mm_cmpge_epu16_mask(A, B) \
+ _mm_cmp_epu16_mask((A), (B), _MM_CMPINT_GE)
+#define _mm_mask_cmpge_epu16_mask(k, A, B) \
+ _mm_mask_cmp_epu16_mask((k), (A), (B), _MM_CMPINT_GE)
+#define _mm_cmpgt_epu16_mask(A, B) \
+ _mm_cmp_epu16_mask((A), (B), _MM_CMPINT_GT)
+#define _mm_mask_cmpgt_epu16_mask(k, A, B) \
+ _mm_mask_cmp_epu16_mask((k), (A), (B), _MM_CMPINT_GT)
+#define _mm_cmple_epu16_mask(A, B) \
+ _mm_cmp_epu16_mask((A), (B), _MM_CMPINT_LE)
+#define _mm_mask_cmple_epu16_mask(k, A, B) \
+ _mm_mask_cmp_epu16_mask((k), (A), (B), _MM_CMPINT_LE)
+#define _mm_cmplt_epu16_mask(A, B) \
+ _mm_cmp_epu16_mask((A), (B), _MM_CMPINT_LT)
+#define _mm_mask_cmplt_epu16_mask(k, A, B) \
+ _mm_mask_cmp_epu16_mask((k), (A), (B), _MM_CMPINT_LT)
+#define _mm_cmpneq_epu16_mask(A, B) \
+ _mm_cmp_epu16_mask((A), (B), _MM_CMPINT_NE)
+#define _mm_mask_cmpneq_epu16_mask(k, A, B) \
+ _mm_mask_cmp_epu16_mask((k), (A), (B), _MM_CMPINT_NE)
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpneq_epu16_mask(__mmask16 __u, __m256i __a, __m256i __b) {
- return (__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)__a, (__v16hi)__b, 4,
- __u);
-}
+#define _mm256_cmpeq_epu16_mask(A, B) \
+ _mm256_cmp_epu16_mask((A), (B), _MM_CMPINT_EQ)
+#define _mm256_mask_cmpeq_epu16_mask(k, A, B) \
+ _mm256_mask_cmp_epu16_mask((k), (A), (B), _MM_CMPINT_EQ)
+#define _mm256_cmpge_epu16_mask(A, B) \
+ _mm256_cmp_epu16_mask((A), (B), _MM_CMPINT_GE)
+#define _mm256_mask_cmpge_epu16_mask(k, A, B) \
+ _mm256_mask_cmp_epu16_mask((k), (A), (B), _MM_CMPINT_GE)
+#define _mm256_cmpgt_epu16_mask(A, B) \
+ _mm256_cmp_epu16_mask((A), (B), _MM_CMPINT_GT)
+#define _mm256_mask_cmpgt_epu16_mask(k, A, B) \
+ _mm256_mask_cmp_epu16_mask((k), (A), (B), _MM_CMPINT_GT)
+#define _mm256_cmple_epu16_mask(A, B) \
+ _mm256_cmp_epu16_mask((A), (B), _MM_CMPINT_LE)
+#define _mm256_mask_cmple_epu16_mask(k, A, B) \
+ _mm256_mask_cmp_epu16_mask((k), (A), (B), _MM_CMPINT_LE)
+#define _mm256_cmplt_epu16_mask(A, B) \
+ _mm256_cmp_epu16_mask((A), (B), _MM_CMPINT_LT)
+#define _mm256_mask_cmplt_epu16_mask(k, A, B) \
+ _mm256_mask_cmp_epu16_mask((k), (A), (B), _MM_CMPINT_LT)
+#define _mm256_cmpneq_epu16_mask(A, B) \
+ _mm256_cmp_epu16_mask((A), (B), _MM_CMPINT_NE)
+#define _mm256_mask_cmpneq_epu16_mask(k, A, B) \
+ _mm256_mask_cmp_epu16_mask((k), (A), (B), _MM_CMPINT_NE)
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_mask_add_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B){
@@ -2146,86 +1850,6 @@ _mm256_maskz_cvtepu8_epi16 (__mmask16 __U, __m128i __A)
}
-#define _mm_cmp_epi8_mask(a, b, p) __extension__ ({ \
- (__mmask16)__builtin_ia32_cmpb128_mask((__v16qi)(__m128i)(a), \
- (__v16qi)(__m128i)(b), (int)(p), \
- (__mmask16)-1); })
-
-#define _mm_mask_cmp_epi8_mask(m, a, b, p) __extension__ ({ \
- (__mmask16)__builtin_ia32_cmpb128_mask((__v16qi)(__m128i)(a), \
- (__v16qi)(__m128i)(b), (int)(p), \
- (__mmask16)(m)); })
-
-#define _mm_cmp_epu8_mask(a, b, p) __extension__ ({ \
- (__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)(__m128i)(a), \
- (__v16qi)(__m128i)(b), (int)(p), \
- (__mmask16)-1); })
-
-#define _mm_mask_cmp_epu8_mask(m, a, b, p) __extension__ ({ \
- (__mmask16)__builtin_ia32_ucmpb128_mask((__v16qi)(__m128i)(a), \
- (__v16qi)(__m128i)(b), (int)(p), \
- (__mmask16)(m)); })
-
-#define _mm256_cmp_epi8_mask(a, b, p) __extension__ ({ \
- (__mmask32)__builtin_ia32_cmpb256_mask((__v32qi)(__m256i)(a), \
- (__v32qi)(__m256i)(b), (int)(p), \
- (__mmask32)-1); })
-
-#define _mm256_mask_cmp_epi8_mask(m, a, b, p) __extension__ ({ \
- (__mmask32)__builtin_ia32_cmpb256_mask((__v32qi)(__m256i)(a), \
- (__v32qi)(__m256i)(b), (int)(p), \
- (__mmask32)(m)); })
-
-#define _mm256_cmp_epu8_mask(a, b, p) __extension__ ({ \
- (__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)(__m256i)(a), \
- (__v32qi)(__m256i)(b), (int)(p), \
- (__mmask32)-1); })
-
-#define _mm256_mask_cmp_epu8_mask(m, a, b, p) __extension__ ({ \
- (__mmask32)__builtin_ia32_ucmpb256_mask((__v32qi)(__m256i)(a), \
- (__v32qi)(__m256i)(b), (int)(p), \
- (__mmask32)(m)); })
-
-#define _mm_cmp_epi16_mask(a, b, p) __extension__ ({ \
- (__mmask8)__builtin_ia32_cmpw128_mask((__v8hi)(__m128i)(a), \
- (__v8hi)(__m128i)(b), (int)(p), \
- (__mmask8)-1); })
-
-#define _mm_mask_cmp_epi16_mask(m, a, b, p) __extension__ ({ \
- (__mmask8)__builtin_ia32_cmpw128_mask((__v8hi)(__m128i)(a), \
- (__v8hi)(__m128i)(b), (int)(p), \
- (__mmask8)(m)); })
-
-#define _mm_cmp_epu16_mask(a, b, p) __extension__ ({ \
- (__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)(__m128i)(a), \
- (__v8hi)(__m128i)(b), (int)(p), \
- (__mmask8)-1); })
-
-#define _mm_mask_cmp_epu16_mask(m, a, b, p) __extension__ ({ \
- (__mmask8)__builtin_ia32_ucmpw128_mask((__v8hi)(__m128i)(a), \
- (__v8hi)(__m128i)(b), (int)(p), \
- (__mmask8)(m)); })
-
-#define _mm256_cmp_epi16_mask(a, b, p) __extension__ ({ \
- (__mmask16)__builtin_ia32_cmpw256_mask((__v16hi)(__m256i)(a), \
- (__v16hi)(__m256i)(b), (int)(p), \
- (__mmask16)-1); })
-
-#define _mm256_mask_cmp_epi16_mask(m, a, b, p) __extension__ ({ \
- (__mmask16)__builtin_ia32_cmpw256_mask((__v16hi)(__m256i)(a), \
- (__v16hi)(__m256i)(b), (int)(p), \
- (__mmask16)(m)); })
-
-#define _mm256_cmp_epu16_mask(a, b, p) __extension__ ({ \
- (__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)(__m256i)(a), \
- (__v16hi)(__m256i)(b), (int)(p), \
- (__mmask16)-1); })
-
-#define _mm256_mask_cmp_epu16_mask(m, a, b, p) __extension__ ({ \
- (__mmask16)__builtin_ia32_ucmpw256_mask((__v16hi)(__m256i)(a), \
- (__v16hi)(__m256i)(b), (int)(p), \
- (__mmask16)(m)); })
-
#define _mm_mask_shufflehi_epi16(W, U, A, imm) __extension__ ({ \
(__m128i)__builtin_ia32_selectw_128((__mmask8)(U), \
(__v8hi)_mm_shufflehi_epi16((A), (imm)), \
@@ -2660,35 +2284,33 @@ _mm256_maskz_mov_epi8 (__mmask32 __U, __m256i __A)
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_mask_set1_epi8 (__m128i __O, __mmask16 __M, char __A)
{
- return (__m128i) __builtin_ia32_pbroadcastb128_gpr_mask (__A,
- (__v16qi) __O,
- __M);
+ return (__m128i) __builtin_ia32_selectb_128(__M,
+ (__v16qi) _mm_set1_epi8(__A),
+ (__v16qi) __O);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_maskz_set1_epi8 (__mmask16 __M, char __A)
{
- return (__m128i) __builtin_ia32_pbroadcastb128_gpr_mask (__A,
- (__v16qi)
- _mm_setzero_si128 (),
- __M);
+ return (__m128i) __builtin_ia32_selectb_128(__M,
+ (__v16qi) _mm_set1_epi8(__A),
+ (__v16qi) _mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_mask_set1_epi8 (__m256i __O, __mmask32 __M, char __A)
{
- return (__m256i) __builtin_ia32_pbroadcastb256_gpr_mask (__A,
- (__v32qi) __O,
- __M);
+ return (__m256i) __builtin_ia32_selectb_256(__M,
+ (__v32qi) _mm256_set1_epi8(__A),
+ (__v32qi) __O);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_maskz_set1_epi8 (__mmask32 __M, char __A)
{
- return (__m256i) __builtin_ia32_pbroadcastb256_gpr_mask (__A,
- (__v32qi)
- _mm256_setzero_si256 (),
- __M);
+ return (__m256i) __builtin_ia32_selectb_256(__M,
+ (__v32qi) _mm256_set1_epi8(__A),
+ (__v32qi) _mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
@@ -2793,121 +2415,108 @@ _mm256_mask_storeu_epi8 (void *__P, __mmask32 __U, __m256i __A)
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
_mm_test_epi8_mask (__m128i __A, __m128i __B)
{
- return (__mmask16) __builtin_ia32_ptestmb128 ((__v16qi) __A,
- (__v16qi) __B,
- (__mmask16) -1);
+ return _mm_cmpneq_epi8_mask (_mm_and_si128(__A, __B), _mm_setzero_hi());
}
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
_mm_mask_test_epi8_mask (__mmask16 __U, __m128i __A, __m128i __B)
{
- return (__mmask16) __builtin_ia32_ptestmb128 ((__v16qi) __A,
- (__v16qi) __B, __U);
+ return _mm_mask_cmpneq_epi8_mask (__U, _mm_and_si128 (__A, __B),
+ _mm_setzero_hi());
}
static __inline__ __mmask32 __DEFAULT_FN_ATTRS
_mm256_test_epi8_mask (__m256i __A, __m256i __B)
{
- return (__mmask32) __builtin_ia32_ptestmb256 ((__v32qi) __A,
- (__v32qi) __B,
- (__mmask32) -1);
+ return _mm256_cmpneq_epi8_mask (_mm256_and_si256(__A, __B),
+ _mm256_setzero_si256());
}
static __inline__ __mmask32 __DEFAULT_FN_ATTRS
_mm256_mask_test_epi8_mask (__mmask32 __U, __m256i __A, __m256i __B)
{
- return (__mmask32) __builtin_ia32_ptestmb256 ((__v32qi) __A,
- (__v32qi) __B, __U);
+ return _mm256_mask_cmpneq_epi8_mask (__U, _mm256_and_si256(__A, __B),
+ _mm256_setzero_si256());
}
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm_test_epi16_mask (__m128i __A, __m128i __B)
{
- return (__mmask8) __builtin_ia32_ptestmw128 ((__v8hi) __A,
- (__v8hi) __B,
- (__mmask8) -1);
+ return _mm_cmpneq_epi16_mask (_mm_and_si128 (__A, __B), _mm_setzero_hi());
}
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm_mask_test_epi16_mask (__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__mmask8) __builtin_ia32_ptestmw128 ((__v8hi) __A,
- (__v8hi) __B, __U);
+ return _mm_mask_cmpneq_epi16_mask (__U, _mm_and_si128 (__A, __B),
+ _mm_setzero_hi());
}
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
_mm256_test_epi16_mask (__m256i __A, __m256i __B)
{
- return (__mmask16) __builtin_ia32_ptestmw256 ((__v16hi) __A,
- (__v16hi) __B,
- (__mmask16) -1);
+ return _mm256_cmpneq_epi16_mask (_mm256_and_si256 (__A, __B),
+ _mm256_setzero_si256 ());
}
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
_mm256_mask_test_epi16_mask (__mmask16 __U, __m256i __A, __m256i __B)
{
- return (__mmask16) __builtin_ia32_ptestmw256 ((__v16hi) __A,
- (__v16hi) __B, __U);
+ return _mm256_mask_cmpneq_epi16_mask (__U, _mm256_and_si256(__A, __B),
+ _mm256_setzero_si256());
}
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
_mm_testn_epi8_mask (__m128i __A, __m128i __B)
{
- return (__mmask16) __builtin_ia32_ptestnmb128 ((__v16qi) __A,
- (__v16qi) __B,
- (__mmask16) -1);
+ return _mm_cmpeq_epi8_mask (_mm_and_si128 (__A, __B), _mm_setzero_hi());
}
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
_mm_mask_testn_epi8_mask (__mmask16 __U, __m128i __A, __m128i __B)
{
- return (__mmask16) __builtin_ia32_ptestnmb128 ((__v16qi) __A,
- (__v16qi) __B, __U);
+ return _mm_mask_cmpeq_epi8_mask (__U, _mm_and_si128 (__A, __B),
+ _mm_setzero_hi());
}
static __inline__ __mmask32 __DEFAULT_FN_ATTRS
_mm256_testn_epi8_mask (__m256i __A, __m256i __B)
{
- return (__mmask32) __builtin_ia32_ptestnmb256 ((__v32qi) __A,
- (__v32qi) __B,
- (__mmask32) -1);
+ return _mm256_cmpeq_epi8_mask (_mm256_and_si256 (__A, __B),
+ _mm256_setzero_si256());
}
static __inline__ __mmask32 __DEFAULT_FN_ATTRS
_mm256_mask_testn_epi8_mask (__mmask32 __U, __m256i __A, __m256i __B)
{
- return (__mmask32) __builtin_ia32_ptestnmb256 ((__v32qi) __A,
- (__v32qi) __B, __U);
+ return _mm256_mask_cmpeq_epi8_mask (__U, _mm256_and_si256 (__A, __B),
+ _mm256_setzero_si256());
}
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm_testn_epi16_mask (__m128i __A, __m128i __B)
{
- return (__mmask8) __builtin_ia32_ptestnmw128 ((__v8hi) __A,
- (__v8hi) __B,
- (__mmask8) -1);
+ return _mm_cmpeq_epi16_mask (_mm_and_si128 (__A, __B), _mm_setzero_hi());
}
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm_mask_testn_epi16_mask (__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__mmask8) __builtin_ia32_ptestnmw128 ((__v8hi) __A,
- (__v8hi) __B, __U);
+ return _mm_mask_cmpeq_epi16_mask (__U, _mm_and_si128(__A, __B), _mm_setzero_hi());
}
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
_mm256_testn_epi16_mask (__m256i __A, __m256i __B)
{
- return (__mmask16) __builtin_ia32_ptestnmw256 ((__v16hi) __A,
- (__v16hi) __B,
- (__mmask16) -1);
+ return _mm256_cmpeq_epi16_mask (_mm256_and_si256(__A, __B),
+ _mm256_setzero_si256());
}
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
_mm256_mask_testn_epi16_mask (__mmask16 __U, __m256i __A, __m256i __B)
{
- return (__mmask16) __builtin_ia32_ptestnmw256 ((__v16hi) __A,
- (__v16hi) __B, __U);
+ return _mm256_mask_cmpeq_epi16_mask (__U, _mm256_and_si256 (__A, __B),
+ _mm256_setzero_si256());
}
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
@@ -3025,33 +2634,33 @@ _mm256_maskz_broadcastw_epi16 (__mmask16 __M, __m128i __A)
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_mask_set1_epi16 (__m256i __O, __mmask16 __M, short __A)
{
- return (__m256i) __builtin_ia32_pbroadcastw256_gpr_mask (__A,
- (__v16hi) __O,
- __M);
+ return (__m256i) __builtin_ia32_selectw_256 (__M,
+ (__v16hi) _mm256_set1_epi16(__A),
+ (__v16hi) __O);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_maskz_set1_epi16 (__mmask16 __M, short __A)
{
- return (__m256i) __builtin_ia32_pbroadcastw256_gpr_mask (__A,
- (__v16hi) _mm256_setzero_si256 (),
- __M);
+ return (__m256i) __builtin_ia32_selectw_256(__M,
+ (__v16hi)_mm256_set1_epi16(__A),
+ (__v16hi) _mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_mask_set1_epi16 (__m128i __O, __mmask8 __M, short __A)
{
- return (__m128i) __builtin_ia32_pbroadcastw128_gpr_mask (__A,
- (__v8hi) __O,
- __M);
+ return (__m128i) __builtin_ia32_selectw_128(__M,
+ (__v8hi) _mm_set1_epi16(__A),
+ (__v8hi) __O);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_maskz_set1_epi16 (__mmask8 __M, short __A)
{
- return (__m128i) __builtin_ia32_pbroadcastw128_gpr_mask (__A,
- (__v8hi) _mm_setzero_si128 (),
- __M);
+ return (__m128i) __builtin_ia32_selectw_128(__M,
+ (__v8hi) _mm_set1_epi16(__A),
+ (__v8hi) _mm_setzero_si128());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512vlcdintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512vlcdintrin.h
index 7b02e2e1f92a2..8f1cd25f0b50c 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512vlcdintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512vlcdintrin.h
@@ -33,26 +33,26 @@
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_broadcastmb_epi64 (__mmask8 __A)
-{
- return (__m128i) __builtin_ia32_broadcastmb128 (__A);
+{
+ return (__m128i) _mm_set1_epi64x((long long) __A);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_broadcastmb_epi64 (__mmask8 __A)
{
- return (__m256i) __builtin_ia32_broadcastmb256 (__A);
+ return (__m256i) _mm256_set1_epi64x((long long)__A);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_broadcastmw_epi32 (__mmask16 __A)
{
- return (__m128i) __builtin_ia32_broadcastmw128 (__A);
+ return (__m128i) _mm_set1_epi32((int)__A);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_broadcastmw_epi32 (__mmask16 __A)
{
- return (__m256i) __builtin_ia32_broadcastmw256 (__A);
+ return (__m256i) _mm256_set1_epi32((int)__A);
}
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512vldqintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512vldqintrin.h
index aecd7df34d050..d80df9eaffea9 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512vldqintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512vldqintrin.h
@@ -978,25 +978,25 @@ _mm256_movepi64_mask (__m256i __A)
static __inline__ __m256 __DEFAULT_FN_ATTRS
_mm256_broadcast_f32x2 (__m128 __A)
{
- return (__m256) __builtin_ia32_broadcastf32x2_256_mask ((__v4sf) __A,
- (__v8sf)_mm256_undefined_ps(),
- (__mmask8) -1);
+ return (__m256)__builtin_shufflevector((__v4sf)__A,
+ (__v4sf)_mm_undefined_ps(),
+ 0, 1, 0, 1, 0, 1, 0, 1);
}
static __inline__ __m256 __DEFAULT_FN_ATTRS
_mm256_mask_broadcast_f32x2 (__m256 __O, __mmask8 __M, __m128 __A)
{
- return (__m256) __builtin_ia32_broadcastf32x2_256_mask ((__v4sf) __A,
- (__v8sf) __O,
- __M);
+ return (__m256)__builtin_ia32_selectps_256((__mmask8)__M,
+ (__v8sf)_mm256_broadcast_f32x2(__A),
+ (__v8sf)__O);
}
static __inline__ __m256 __DEFAULT_FN_ATTRS
_mm256_maskz_broadcast_f32x2 (__mmask8 __M, __m128 __A)
{
- return (__m256) __builtin_ia32_broadcastf32x2_256_mask ((__v4sf) __A,
- (__v8sf) _mm256_setzero_ps (),
- __M);
+ return (__m256)__builtin_ia32_selectps_256((__mmask8)__M,
+ (__v8sf)_mm256_broadcast_f32x2(__A),
+ (__v8sf)_mm256_setzero_ps());
}
static __inline__ __m256d __DEFAULT_FN_ATTRS
@@ -1025,49 +1025,49 @@ _mm256_maskz_broadcast_f64x2 (__mmask8 __M, __m128d __A)
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_broadcast_i32x2 (__m128i __A)
{
- return (__m128i) __builtin_ia32_broadcasti32x2_128_mask ((__v4si) __A,
- (__v4si)_mm_undefined_si128(),
- (__mmask8) -1);
+ return (__m128i)__builtin_shufflevector((__v4si)__A,
+ (__v4si)_mm_undefined_si128(),
+ 0, 1, 0, 1);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_mask_broadcast_i32x2 (__m128i __O, __mmask8 __M, __m128i __A)
{
- return (__m128i) __builtin_ia32_broadcasti32x2_128_mask ((__v4si) __A,
- (__v4si) __O,
- __M);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M,
+ (__v4si)_mm_broadcast_i32x2(__A),
+ (__v4si)__O);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_maskz_broadcast_i32x2 (__mmask8 __M, __m128i __A)
{
- return (__m128i) __builtin_ia32_broadcasti32x2_128_mask ((__v4si) __A,
- (__v4si) _mm_setzero_si128 (),
- __M);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M,
+ (__v4si)_mm_broadcast_i32x2(__A),
+ (__v4si)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_broadcast_i32x2 (__m128i __A)
{
- return (__m256i) __builtin_ia32_broadcasti32x2_256_mask ((__v4si) __A,
- (__v8si)_mm256_undefined_si256(),
- (__mmask8) -1);
+ return (__m256i)__builtin_shufflevector((__v4si)__A,
+ (__v4si)_mm_undefined_si128(),
+ 0, 1, 0, 1, 0, 1, 0, 1);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_mask_broadcast_i32x2 (__m256i __O, __mmask8 __M, __m128i __A)
{
- return (__m256i) __builtin_ia32_broadcasti32x2_256_mask ((__v4si) __A,
- (__v8si) __O,
- __M);
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M,
+ (__v8si)_mm256_broadcast_i32x2(__A),
+ (__v8si)__O);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_maskz_broadcast_i32x2 (__mmask8 __M, __m128i __A)
{
- return (__m256i) __builtin_ia32_broadcasti32x2_256_mask ((__v4si) __A,
- (__v8si) _mm256_setzero_si256 (),
- __M);
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M,
+ (__v8si)_mm256_broadcast_i32x2(__A),
+ (__v8si)_mm256_setzero_si256());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512vlintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512vlintrin.h
index 99bb050de4d71..fb8056e3f8d83 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512vlintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512vlintrin.h
@@ -38,582 +38,205 @@ _mm_setzero_di(void) {
/* Integer compare */
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmpeq_epi32_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_pcmpeqd128_mask((__v4si)__a, (__v4si)__b,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmpeq_epi32_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_pcmpeqd128_mask((__v4si)__a, (__v4si)__b,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmpeq_epu32_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpd128_mask((__v4si)__a, (__v4si)__b, 0,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmpeq_epu32_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpd128_mask((__v4si)__a, (__v4si)__b, 0,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_cmpeq_epi32_mask(__m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_pcmpeqd256_mask((__v8si)__a, (__v8si)__b,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpeq_epi32_mask(__mmask8 __u, __m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_pcmpeqd256_mask((__v8si)__a, (__v8si)__b,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_cmpeq_epu32_mask(__m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_ucmpd256_mask((__v8si)__a, (__v8si)__b, 0,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpeq_epu32_mask(__mmask8 __u, __m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_ucmpd256_mask((__v8si)__a, (__v8si)__b, 0,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmpeq_epi64_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_pcmpeqq128_mask((__v2di)__a, (__v2di)__b,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmpeq_epi64_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_pcmpeqq128_mask((__v2di)__a, (__v2di)__b,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmpeq_epu64_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpq128_mask((__v2di)__a, (__v2di)__b, 0,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmpeq_epu64_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpq128_mask((__v2di)__a, (__v2di)__b, 0,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_cmpeq_epi64_mask(__m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_pcmpeqq256_mask((__v4di)__a, (__v4di)__b,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpeq_epi64_mask(__mmask8 __u, __m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_pcmpeqq256_mask((__v4di)__a, (__v4di)__b,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_cmpeq_epu64_mask(__m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_ucmpq256_mask((__v4di)__a, (__v4di)__b, 0,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpeq_epu64_mask(__mmask8 __u, __m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_ucmpq256_mask((__v4di)__a, (__v4di)__b, 0,
- __u);
-}
-
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmpge_epi32_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_cmpd128_mask((__v4si)__a, (__v4si)__b, 5,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmpge_epi32_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_cmpd128_mask((__v4si)__a, (__v4si)__b, 5,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmpge_epu32_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpd128_mask((__v4si)__a, (__v4si)__b, 5,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmpge_epu32_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpd128_mask((__v4si)__a, (__v4si)__b, 5,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_cmpge_epi32_mask(__m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_cmpd256_mask((__v8si)__a, (__v8si)__b, 5,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpge_epi32_mask(__mmask8 __u, __m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_cmpd256_mask((__v8si)__a, (__v8si)__b, 5,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_cmpge_epu32_mask(__m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_ucmpd256_mask((__v8si)__a, (__v8si)__b, 5,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpge_epu32_mask(__mmask8 __u, __m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_ucmpd256_mask((__v8si)__a, (__v8si)__b, 5,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmpge_epi64_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_cmpq128_mask((__v2di)__a, (__v2di)__b, 5,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmpge_epi64_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_cmpq128_mask((__v2di)__a, (__v2di)__b, 5,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmpge_epu64_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpq128_mask((__v2di)__a, (__v2di)__b, 5,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmpge_epu64_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpq128_mask((__v2di)__a, (__v2di)__b, 5,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_cmpge_epi64_mask(__m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_cmpq256_mask((__v4di)__a, (__v4di)__b, 5,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpge_epi64_mask(__mmask8 __u, __m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_cmpq256_mask((__v4di)__a, (__v4di)__b, 5,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_cmpge_epu64_mask(__m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_ucmpq256_mask((__v4di)__a, (__v4di)__b, 5,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpge_epu64_mask(__mmask8 __u, __m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_ucmpq256_mask((__v4di)__a, (__v4di)__b, 5,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmpgt_epi32_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_pcmpgtd128_mask((__v4si)__a, (__v4si)__b,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmpgt_epi32_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_pcmpgtd128_mask((__v4si)__a, (__v4si)__b,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmpgt_epu32_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpd128_mask((__v4si)__a, (__v4si)__b, 6,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmpgt_epu32_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpd128_mask((__v4si)__a, (__v4si)__b, 6,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_cmpgt_epi32_mask(__m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_pcmpgtd256_mask((__v8si)__a, (__v8si)__b,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpgt_epi32_mask(__mmask8 __u, __m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_pcmpgtd256_mask((__v8si)__a, (__v8si)__b,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_cmpgt_epu32_mask(__m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_ucmpd256_mask((__v8si)__a, (__v8si)__b, 6,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpgt_epu32_mask(__mmask8 __u, __m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_ucmpd256_mask((__v8si)__a, (__v8si)__b, 6,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmpgt_epi64_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_pcmpgtq128_mask((__v2di)__a, (__v2di)__b,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmpgt_epi64_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_pcmpgtq128_mask((__v2di)__a, (__v2di)__b,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmpgt_epu64_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpq128_mask((__v2di)__a, (__v2di)__b, 6,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmpgt_epu64_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpq128_mask((__v2di)__a, (__v2di)__b, 6,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_cmpgt_epi64_mask(__m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_pcmpgtq256_mask((__v4di)__a, (__v4di)__b,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpgt_epi64_mask(__mmask8 __u, __m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_pcmpgtq256_mask((__v4di)__a, (__v4di)__b,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_cmpgt_epu64_mask(__m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_ucmpq256_mask((__v4di)__a, (__v4di)__b, 6,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpgt_epu64_mask(__mmask8 __u, __m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_ucmpq256_mask((__v4di)__a, (__v4di)__b, 6,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmple_epi32_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_cmpd128_mask((__v4si)__a, (__v4si)__b, 2,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmple_epi32_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_cmpd128_mask((__v4si)__a, (__v4si)__b, 2,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmple_epu32_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpd128_mask((__v4si)__a, (__v4si)__b, 2,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmple_epu32_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpd128_mask((__v4si)__a, (__v4si)__b, 2,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_cmple_epi32_mask(__m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_cmpd256_mask((__v8si)__a, (__v8si)__b, 2,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_mask_cmple_epi32_mask(__mmask8 __u, __m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_cmpd256_mask((__v8si)__a, (__v8si)__b, 2,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_cmple_epu32_mask(__m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_ucmpd256_mask((__v8si)__a, (__v8si)__b, 2,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_mask_cmple_epu32_mask(__mmask8 __u, __m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_ucmpd256_mask((__v8si)__a, (__v8si)__b, 2,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmple_epi64_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_cmpq128_mask((__v2di)__a, (__v2di)__b, 2,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmple_epi64_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_cmpq128_mask((__v2di)__a, (__v2di)__b, 2,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmple_epu64_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpq128_mask((__v2di)__a, (__v2di)__b, 2,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmple_epu64_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpq128_mask((__v2di)__a, (__v2di)__b, 2,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_cmple_epi64_mask(__m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_cmpq256_mask((__v4di)__a, (__v4di)__b, 2,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_mask_cmple_epi64_mask(__mmask8 __u, __m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_cmpq256_mask((__v4di)__a, (__v4di)__b, 2,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_cmple_epu64_mask(__m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_ucmpq256_mask((__v4di)__a, (__v4di)__b, 2,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_mask_cmple_epu64_mask(__mmask8 __u, __m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_ucmpq256_mask((__v4di)__a, (__v4di)__b, 2,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmplt_epi32_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_cmpd128_mask((__v4si)__a, (__v4si)__b, 1,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmplt_epi32_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_cmpd128_mask((__v4si)__a, (__v4si)__b, 1,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmplt_epu32_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpd128_mask((__v4si)__a, (__v4si)__b, 1,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmplt_epu32_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpd128_mask((__v4si)__a, (__v4si)__b, 1,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_cmplt_epi32_mask(__m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_cmpd256_mask((__v8si)__a, (__v8si)__b, 1,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_mask_cmplt_epi32_mask(__mmask8 __u, __m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_cmpd256_mask((__v8si)__a, (__v8si)__b, 1,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_cmplt_epu32_mask(__m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_ucmpd256_mask((__v8si)__a, (__v8si)__b, 1,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_mask_cmplt_epu32_mask(__mmask8 __u, __m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_ucmpd256_mask((__v8si)__a, (__v8si)__b, 1,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmplt_epi64_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_cmpq128_mask((__v2di)__a, (__v2di)__b, 1,
- (__mmask8)-1);
-}
+#define _mm_cmpeq_epi32_mask(A, B) \
+ _mm_cmp_epi32_mask((A), (B), _MM_CMPINT_EQ)
+#define _mm_mask_cmpeq_epi32_mask(k, A, B) \
+ _mm_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_EQ)
+#define _mm_cmpge_epi32_mask(A, B) \
+ _mm_cmp_epi32_mask((A), (B), _MM_CMPINT_GE)
+#define _mm_mask_cmpge_epi32_mask(k, A, B) \
+ _mm_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_GE)
+#define _mm_cmpgt_epi32_mask(A, B) \
+ _mm_cmp_epi32_mask((A), (B), _MM_CMPINT_GT)
+#define _mm_mask_cmpgt_epi32_mask(k, A, B) \
+ _mm_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_GT)
+#define _mm_cmple_epi32_mask(A, B) \
+ _mm_cmp_epi32_mask((A), (B), _MM_CMPINT_LE)
+#define _mm_mask_cmple_epi32_mask(k, A, B) \
+ _mm_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_LE)
+#define _mm_cmplt_epi32_mask(A, B) \
+ _mm_cmp_epi32_mask((A), (B), _MM_CMPINT_LT)
+#define _mm_mask_cmplt_epi32_mask(k, A, B) \
+ _mm_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_LT)
+#define _mm_cmpneq_epi32_mask(A, B) \
+ _mm_cmp_epi32_mask((A), (B), _MM_CMPINT_NE)
+#define _mm_mask_cmpneq_epi32_mask(k, A, B) \
+ _mm_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_NE)
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmplt_epi64_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_cmpq128_mask((__v2di)__a, (__v2di)__b, 1,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmplt_epu64_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpq128_mask((__v2di)__a, (__v2di)__b, 1,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmplt_epu64_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpq128_mask((__v2di)__a, (__v2di)__b, 1,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_cmplt_epi64_mask(__m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_cmpq256_mask((__v4di)__a, (__v4di)__b, 1,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_mask_cmplt_epi64_mask(__mmask8 __u, __m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_cmpq256_mask((__v4di)__a, (__v4di)__b, 1,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_cmplt_epu64_mask(__m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_ucmpq256_mask((__v4di)__a, (__v4di)__b, 1,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_mask_cmplt_epu64_mask(__mmask8 __u, __m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_ucmpq256_mask((__v4di)__a, (__v4di)__b, 1,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmpneq_epi32_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_cmpd128_mask((__v4si)__a, (__v4si)__b, 4,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmpneq_epi32_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_cmpd128_mask((__v4si)__a, (__v4si)__b, 4,
- __u);
-}
+#define _mm256_cmpeq_epi32_mask(A, B) \
+ _mm256_cmp_epi32_mask((A), (B), _MM_CMPINT_EQ)
+#define _mm256_mask_cmpeq_epi32_mask(k, A, B) \
+ _mm256_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_EQ)
+#define _mm256_cmpge_epi32_mask(A, B) \
+ _mm256_cmp_epi32_mask((A), (B), _MM_CMPINT_GE)
+#define _mm256_mask_cmpge_epi32_mask(k, A, B) \
+ _mm256_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_GE)
+#define _mm256_cmpgt_epi32_mask(A, B) \
+ _mm256_cmp_epi32_mask((A), (B), _MM_CMPINT_GT)
+#define _mm256_mask_cmpgt_epi32_mask(k, A, B) \
+ _mm256_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_GT)
+#define _mm256_cmple_epi32_mask(A, B) \
+ _mm256_cmp_epi32_mask((A), (B), _MM_CMPINT_LE)
+#define _mm256_mask_cmple_epi32_mask(k, A, B) \
+ _mm256_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_LE)
+#define _mm256_cmplt_epi32_mask(A, B) \
+ _mm256_cmp_epi32_mask((A), (B), _MM_CMPINT_LT)
+#define _mm256_mask_cmplt_epi32_mask(k, A, B) \
+ _mm256_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_LT)
+#define _mm256_cmpneq_epi32_mask(A, B) \
+ _mm256_cmp_epi32_mask((A), (B), _MM_CMPINT_NE)
+#define _mm256_mask_cmpneq_epi32_mask(k, A, B) \
+ _mm256_mask_cmp_epi32_mask((k), (A), (B), _MM_CMPINT_NE)
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmpneq_epu32_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpd128_mask((__v4si)__a, (__v4si)__b, 4,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmpneq_epu32_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpd128_mask((__v4si)__a, (__v4si)__b, 4,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_cmpneq_epi32_mask(__m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_cmpd256_mask((__v8si)__a, (__v8si)__b, 4,
- (__mmask8)-1);
-}
+#define _mm_cmpeq_epu32_mask(A, B) \
+ _mm_cmp_epu32_mask((A), (B), _MM_CMPINT_EQ)
+#define _mm_mask_cmpeq_epu32_mask(k, A, B) \
+ _mm_mask_cmp_epu32_mask((k), (A), (B), _MM_CMPINT_EQ)
+#define _mm_cmpge_epu32_mask(A, B) \
+ _mm_cmp_epu32_mask((A), (B), _MM_CMPINT_GE)
+#define _mm_mask_cmpge_epu32_mask(k, A, B) \
+ _mm_mask_cmp_epu32_mask((k), (A), (B), _MM_CMPINT_GE)
+#define _mm_cmpgt_epu32_mask(A, B) \
+ _mm_cmp_epu32_mask((A), (B), _MM_CMPINT_GT)
+#define _mm_mask_cmpgt_epu32_mask(k, A, B) \
+ _mm_mask_cmp_epu32_mask((k), (A), (B), _MM_CMPINT_GT)
+#define _mm_cmple_epu32_mask(A, B) \
+ _mm_cmp_epu32_mask((A), (B), _MM_CMPINT_LE)
+#define _mm_mask_cmple_epu32_mask(k, A, B) \
+ _mm_mask_cmp_epu32_mask((k), (A), (B), _MM_CMPINT_LE)
+#define _mm_cmplt_epu32_mask(A, B) \
+ _mm_cmp_epu32_mask((A), (B), _MM_CMPINT_LT)
+#define _mm_mask_cmplt_epu32_mask(k, A, B) \
+ _mm_mask_cmp_epu32_mask((k), (A), (B), _MM_CMPINT_LT)
+#define _mm_cmpneq_epu32_mask(A, B) \
+ _mm_cmp_epu32_mask((A), (B), _MM_CMPINT_NE)
+#define _mm_mask_cmpneq_epu32_mask(k, A, B) \
+ _mm_mask_cmp_epu32_mask((k), (A), (B), _MM_CMPINT_NE)
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpneq_epi32_mask(__mmask8 __u, __m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_cmpd256_mask((__v8si)__a, (__v8si)__b, 4,
- __u);
-}
+#define _mm256_cmpeq_epu32_mask(A, B) \
+ _mm256_cmp_epu32_mask((A), (B), _MM_CMPINT_EQ)
+#define _mm256_mask_cmpeq_epu32_mask(k, A, B) \
+ _mm256_mask_cmp_epu32_mask((k), (A), (B), _MM_CMPINT_EQ)
+#define _mm256_cmpge_epu32_mask(A, B) \
+ _mm256_cmp_epu32_mask((A), (B), _MM_CMPINT_GE)
+#define _mm256_mask_cmpge_epu32_mask(k, A, B) \
+ _mm256_mask_cmp_epu32_mask((k), (A), (B), _MM_CMPINT_GE)
+#define _mm256_cmpgt_epu32_mask(A, B) \
+ _mm256_cmp_epu32_mask((A), (B), _MM_CMPINT_GT)
+#define _mm256_mask_cmpgt_epu32_mask(k, A, B) \
+ _mm256_mask_cmp_epu32_mask((k), (A), (B), _MM_CMPINT_GT)
+#define _mm256_cmple_epu32_mask(A, B) \
+ _mm256_cmp_epu32_mask((A), (B), _MM_CMPINT_LE)
+#define _mm256_mask_cmple_epu32_mask(k, A, B) \
+ _mm256_mask_cmp_epu32_mask((k), (A), (B), _MM_CMPINT_LE)
+#define _mm256_cmplt_epu32_mask(A, B) \
+ _mm256_cmp_epu32_mask((A), (B), _MM_CMPINT_LT)
+#define _mm256_mask_cmplt_epu32_mask(k, A, B) \
+ _mm256_mask_cmp_epu32_mask((k), (A), (B), _MM_CMPINT_LT)
+#define _mm256_cmpneq_epu32_mask(A, B) \
+ _mm256_cmp_epu32_mask((A), (B), _MM_CMPINT_NE)
+#define _mm256_mask_cmpneq_epu32_mask(k, A, B) \
+ _mm256_mask_cmp_epu32_mask((k), (A), (B), _MM_CMPINT_NE)
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_cmpneq_epu32_mask(__m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_ucmpd256_mask((__v8si)__a, (__v8si)__b, 4,
- (__mmask8)-1);
-}
+#define _mm_cmpeq_epi64_mask(A, B) \
+ _mm_cmp_epi64_mask((A), (B), _MM_CMPINT_EQ)
+#define _mm_mask_cmpeq_epi64_mask(k, A, B) \
+ _mm_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_EQ)
+#define _mm_cmpge_epi64_mask(A, B) \
+ _mm_cmp_epi64_mask((A), (B), _MM_CMPINT_GE)
+#define _mm_mask_cmpge_epi64_mask(k, A, B) \
+ _mm_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_GE)
+#define _mm_cmpgt_epi64_mask(A, B) \
+ _mm_cmp_epi64_mask((A), (B), _MM_CMPINT_GT)
+#define _mm_mask_cmpgt_epi64_mask(k, A, B) \
+ _mm_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_GT)
+#define _mm_cmple_epi64_mask(A, B) \
+ _mm_cmp_epi64_mask((A), (B), _MM_CMPINT_LE)
+#define _mm_mask_cmple_epi64_mask(k, A, B) \
+ _mm_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_LE)
+#define _mm_cmplt_epi64_mask(A, B) \
+ _mm_cmp_epi64_mask((A), (B), _MM_CMPINT_LT)
+#define _mm_mask_cmplt_epi64_mask(k, A, B) \
+ _mm_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_LT)
+#define _mm_cmpneq_epi64_mask(A, B) \
+ _mm_cmp_epi64_mask((A), (B), _MM_CMPINT_NE)
+#define _mm_mask_cmpneq_epi64_mask(k, A, B) \
+ _mm_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_NE)
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpneq_epu32_mask(__mmask8 __u, __m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_ucmpd256_mask((__v8si)__a, (__v8si)__b, 4,
- __u);
-}
+#define _mm256_cmpeq_epi64_mask(A, B) \
+ _mm256_cmp_epi64_mask((A), (B), _MM_CMPINT_EQ)
+#define _mm256_mask_cmpeq_epi64_mask(k, A, B) \
+ _mm256_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_EQ)
+#define _mm256_cmpge_epi64_mask(A, B) \
+ _mm256_cmp_epi64_mask((A), (B), _MM_CMPINT_GE)
+#define _mm256_mask_cmpge_epi64_mask(k, A, B) \
+ _mm256_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_GE)
+#define _mm256_cmpgt_epi64_mask(A, B) \
+ _mm256_cmp_epi64_mask((A), (B), _MM_CMPINT_GT)
+#define _mm256_mask_cmpgt_epi64_mask(k, A, B) \
+ _mm256_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_GT)
+#define _mm256_cmple_epi64_mask(A, B) \
+ _mm256_cmp_epi64_mask((A), (B), _MM_CMPINT_LE)
+#define _mm256_mask_cmple_epi64_mask(k, A, B) \
+ _mm256_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_LE)
+#define _mm256_cmplt_epi64_mask(A, B) \
+ _mm256_cmp_epi64_mask((A), (B), _MM_CMPINT_LT)
+#define _mm256_mask_cmplt_epi64_mask(k, A, B) \
+ _mm256_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_LT)
+#define _mm256_cmpneq_epi64_mask(A, B) \
+ _mm256_cmp_epi64_mask((A), (B), _MM_CMPINT_NE)
+#define _mm256_mask_cmpneq_epi64_mask(k, A, B) \
+ _mm256_mask_cmp_epi64_mask((k), (A), (B), _MM_CMPINT_NE)
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmpneq_epi64_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_cmpq128_mask((__v2di)__a, (__v2di)__b, 4,
- (__mmask8)-1);
-}
+#define _mm_cmpeq_epu64_mask(A, B) \
+ _mm_cmp_epu64_mask((A), (B), _MM_CMPINT_EQ)
+#define _mm_mask_cmpeq_epu64_mask(k, A, B) \
+ _mm_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_EQ)
+#define _mm_cmpge_epu64_mask(A, B) \
+ _mm_cmp_epu64_mask((A), (B), _MM_CMPINT_GE)
+#define _mm_mask_cmpge_epu64_mask(k, A, B) \
+ _mm_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_GE)
+#define _mm_cmpgt_epu64_mask(A, B) \
+ _mm_cmp_epu64_mask((A), (B), _MM_CMPINT_GT)
+#define _mm_mask_cmpgt_epu64_mask(k, A, B) \
+ _mm_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_GT)
+#define _mm_cmple_epu64_mask(A, B) \
+ _mm_cmp_epu64_mask((A), (B), _MM_CMPINT_LE)
+#define _mm_mask_cmple_epu64_mask(k, A, B) \
+ _mm_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_LE)
+#define _mm_cmplt_epu64_mask(A, B) \
+ _mm_cmp_epu64_mask((A), (B), _MM_CMPINT_LT)
+#define _mm_mask_cmplt_epu64_mask(k, A, B) \
+ _mm_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_LT)
+#define _mm_cmpneq_epu64_mask(A, B) \
+ _mm_cmp_epu64_mask((A), (B), _MM_CMPINT_NE)
+#define _mm_mask_cmpneq_epu64_mask(k, A, B) \
+ _mm_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_NE)
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmpneq_epi64_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_cmpq128_mask((__v2di)__a, (__v2di)__b, 4,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_cmpneq_epu64_mask(__m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpq128_mask((__v2di)__a, (__v2di)__b, 4,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm_mask_cmpneq_epu64_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- return (__mmask8)__builtin_ia32_ucmpq128_mask((__v2di)__a, (__v2di)__b, 4,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_cmpneq_epi64_mask(__m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_cmpq256_mask((__v4di)__a, (__v4di)__b, 4,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpneq_epi64_mask(__mmask8 __u, __m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_cmpq256_mask((__v4di)__a, (__v4di)__b, 4,
- __u);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_cmpneq_epu64_mask(__m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_ucmpq256_mask((__v4di)__a, (__v4di)__b, 4,
- (__mmask8)-1);
-}
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
-_mm256_mask_cmpneq_epu64_mask(__mmask8 __u, __m256i __a, __m256i __b) {
- return (__mmask8)__builtin_ia32_ucmpq256_mask((__v4di)__a, (__v4di)__b, 4,
- __u);
-}
+#define _mm256_cmpeq_epu64_mask(A, B) \
+ _mm256_cmp_epu64_mask((A), (B), _MM_CMPINT_EQ)
+#define _mm256_mask_cmpeq_epu64_mask(k, A, B) \
+ _mm256_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_EQ)
+#define _mm256_cmpge_epu64_mask(A, B) \
+ _mm256_cmp_epu64_mask((A), (B), _MM_CMPINT_GE)
+#define _mm256_mask_cmpge_epu64_mask(k, A, B) \
+ _mm256_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_GE)
+#define _mm256_cmpgt_epu64_mask(A, B) \
+ _mm256_cmp_epu64_mask((A), (B), _MM_CMPINT_GT)
+#define _mm256_mask_cmpgt_epu64_mask(k, A, B) \
+ _mm256_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_GT)
+#define _mm256_cmple_epu64_mask(A, B) \
+ _mm256_cmp_epu64_mask((A), (B), _MM_CMPINT_LE)
+#define _mm256_mask_cmple_epu64_mask(k, A, B) \
+ _mm256_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_LE)
+#define _mm256_cmplt_epu64_mask(A, B) \
+ _mm256_cmp_epu64_mask((A), (B), _MM_CMPINT_LT)
+#define _mm256_mask_cmplt_epu64_mask(k, A, B) \
+ _mm256_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_LT)
+#define _mm256_cmpneq_epu64_mask(A, B) \
+ _mm256_cmp_epu64_mask((A), (B), _MM_CMPINT_NE)
+#define _mm256_mask_cmpneq_epu64_mask(k, A, B) \
+ _mm256_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_NE)
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_mask_add_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
@@ -5723,59 +5346,72 @@ _mm256_maskz_movedup_pd (__mmask8 __U, __m256d __A)
(__v4df)_mm256_setzero_pd());
}
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_set1_epi32(__m128i __O, __mmask8 __M, int __A)
+{
+ return (__m128i)__builtin_ia32_selectd_128(__M,
+ (__v4si) _mm_set1_epi32(__A),
+ (__v4si)__O);
+}
-#define _mm_mask_set1_epi32(O, M, A) __extension__ ({ \
- (__m128i)__builtin_ia32_pbroadcastd128_gpr_mask((int)(A), \
- (__v4si)(__m128i)(O), \
- (__mmask8)(M)); })
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_set1_epi32( __mmask8 __M, int __A)
+{
+ return (__m128i)__builtin_ia32_selectd_128(__M,
+ (__v4si) _mm_set1_epi32(__A),
+ (__v4si)_mm_setzero_si128());
+}
-#define _mm_maskz_set1_epi32(M, A) __extension__ ({ \
- (__m128i)__builtin_ia32_pbroadcastd128_gpr_mask((int)(A), \
- (__v4si)_mm_setzero_si128(), \
- (__mmask8)(M)); })
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_set1_epi32(__m256i __O, __mmask8 __M, int __A)
+{
+ return (__m256i)__builtin_ia32_selectd_256(__M,
+ (__v8si) _mm256_set1_epi32(__A),
+ (__v8si)__O);
+}
-#define _mm256_mask_set1_epi32(O, M, A) __extension__ ({ \
- (__m256i)__builtin_ia32_pbroadcastd256_gpr_mask((int)(A), \
- (__v8si)(__m256i)(O), \
- (__mmask8)(M)); })
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_set1_epi32( __mmask8 __M, int __A)
+{
+ return (__m256i)__builtin_ia32_selectd_256(__M,
+ (__v8si) _mm256_set1_epi32(__A),
+ (__v8si)_mm256_setzero_si256());
+}
-#define _mm256_maskz_set1_epi32(M, A) __extension__ ({ \
- (__m256i)__builtin_ia32_pbroadcastd256_gpr_mask((int)(A), \
- (__v8si)_mm256_setzero_si256(), \
- (__mmask8)(M)); })
#ifdef __x86_64__
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_mask_set1_epi64 (__m128i __O, __mmask8 __M, long long __A)
{
- return (__m128i) __builtin_ia32_pbroadcastq128_gpr_mask (__A, (__v2di) __O,
- __M);
+ return (__m128i) __builtin_ia32_selectq_128(__M,
+ (__v2di) _mm_set1_epi64x(__A),
+ (__v2di) __O);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_maskz_set1_epi64 (__mmask8 __M, long long __A)
{
- return (__m128i) __builtin_ia32_pbroadcastq128_gpr_mask (__A,
- (__v2di)
- _mm_setzero_si128 (),
- __M);
+ return (__m128i) __builtin_ia32_selectq_128(__M,
+ (__v2di) _mm_set1_epi64x(__A),
+ (__v2di) _mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_mask_set1_epi64 (__m256i __O, __mmask8 __M, long long __A)
{
- return (__m256i) __builtin_ia32_pbroadcastq256_gpr_mask (__A, (__v4di) __O,
- __M);
+ return (__m256i) __builtin_ia32_selectq_256(__M,
+ (__v4di) _mm256_set1_epi64x(__A),
+ (__v4di) __O) ;
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_maskz_set1_epi64 (__mmask8 __M, long long __A)
{
- return (__m256i) __builtin_ia32_pbroadcastq256_gpr_mask (__A,
- (__v4di)
- _mm256_setzero_si256 (),
- __M);
+ return (__m256i) __builtin_ia32_selectq_256(__M,
+ (__v4di) _mm256_set1_epi64x(__A),
+ (__v4di) _mm256_setzero_si256());
}
+
#endif
#define _mm_fixupimm_pd(A, B, C, imm) __extension__ ({ \
@@ -6490,125 +6126,111 @@ _mm256_maskz_permutevar_ps(__mmask8 __U, __m256 __A, __m256i __C)
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm_test_epi32_mask (__m128i __A, __m128i __B)
{
- return (__mmask8) __builtin_ia32_ptestmd128 ((__v4si) __A,
- (__v4si) __B,
- (__mmask8) -1);
+ return _mm_cmpneq_epi32_mask (_mm_and_si128 (__A, __B), _mm_setzero_di());
}
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm_mask_test_epi32_mask (__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__mmask8) __builtin_ia32_ptestmd128 ((__v4si) __A,
- (__v4si) __B, __U);
+ return _mm_mask_cmpneq_epi32_mask (__U, _mm_and_si128 (__A, __B),
+ _mm_setzero_di());
}
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm256_test_epi32_mask (__m256i __A, __m256i __B)
{
- return (__mmask8) __builtin_ia32_ptestmd256 ((__v8si) __A,
- (__v8si) __B,
- (__mmask8) -1);
+ return _mm256_cmpneq_epi32_mask (_mm256_and_si256 (__A, __B),
+ _mm256_setzero_si256());
}
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm256_mask_test_epi32_mask (__mmask8 __U, __m256i __A, __m256i __B)
{
- return (__mmask8) __builtin_ia32_ptestmd256 ((__v8si) __A,
- (__v8si) __B, __U);
+ return _mm256_mask_cmpneq_epi32_mask (__U, _mm256_and_si256 (__A, __B),
+ _mm256_setzero_si256());
}
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm_test_epi64_mask (__m128i __A, __m128i __B)
{
- return (__mmask8) __builtin_ia32_ptestmq128 ((__v2di) __A,
- (__v2di) __B,
- (__mmask8) -1);
+ return _mm_cmpneq_epi64_mask (_mm_and_si128 (__A, __B), _mm_setzero_di());
}
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm_mask_test_epi64_mask (__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__mmask8) __builtin_ia32_ptestmq128 ((__v2di) __A,
- (__v2di) __B, __U);
+ return _mm_mask_cmpneq_epi64_mask (__U, _mm_and_si128 (__A, __B),
+ _mm_setzero_di());
}
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm256_test_epi64_mask (__m256i __A, __m256i __B)
{
- return (__mmask8) __builtin_ia32_ptestmq256 ((__v4di) __A,
- (__v4di) __B,
- (__mmask8) -1);
+ return _mm256_cmpneq_epi64_mask (_mm256_and_si256 (__A, __B),
+ _mm256_setzero_si256());
}
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm256_mask_test_epi64_mask (__mmask8 __U, __m256i __A, __m256i __B)
{
- return (__mmask8) __builtin_ia32_ptestmq256 ((__v4di) __A,
- (__v4di) __B, __U);
+ return _mm256_mask_cmpneq_epi64_mask (__U, _mm256_and_si256 (__A, __B),
+ _mm256_setzero_si256());
}
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm_testn_epi32_mask (__m128i __A, __m128i __B)
{
- return (__mmask8) __builtin_ia32_ptestnmd128 ((__v4si) __A,
- (__v4si) __B,
- (__mmask8) -1);
+ return _mm_cmpeq_epi32_mask (_mm_and_si128 (__A, __B), _mm_setzero_di());
}
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm_mask_testn_epi32_mask (__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__mmask8) __builtin_ia32_ptestnmd128 ((__v4si) __A,
- (__v4si) __B, __U);
+ return _mm_mask_cmpeq_epi32_mask (__U, _mm_and_si128 (__A, __B),
+ _mm_setzero_di());
}
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm256_testn_epi32_mask (__m256i __A, __m256i __B)
{
- return (__mmask8) __builtin_ia32_ptestnmd256 ((__v8si) __A,
- (__v8si) __B,
- (__mmask8) -1);
+ return _mm256_cmpeq_epi32_mask (_mm256_and_si256 (__A, __B),
+ _mm256_setzero_si256());
}
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm256_mask_testn_epi32_mask (__mmask8 __U, __m256i __A, __m256i __B)
{
- return (__mmask8) __builtin_ia32_ptestnmd256 ((__v8si) __A,
- (__v8si) __B, __U);
+ return _mm256_mask_cmpeq_epi32_mask (__U, _mm256_and_si256 (__A, __B),
+ _mm256_setzero_si256());
}
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm_testn_epi64_mask (__m128i __A, __m128i __B)
{
- return (__mmask8) __builtin_ia32_ptestnmq128 ((__v2di) __A,
- (__v2di) __B,
- (__mmask8) -1);
+ return _mm_cmpeq_epi64_mask (_mm_and_si128 (__A, __B), _mm_setzero_di());
}
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm_mask_testn_epi64_mask (__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__mmask8) __builtin_ia32_ptestnmq128 ((__v2di) __A,
- (__v2di) __B, __U);
+ return _mm_mask_cmpeq_epi64_mask (__U, _mm_and_si128 (__A, __B),
+ _mm_setzero_di());
}
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm256_testn_epi64_mask (__m256i __A, __m256i __B)
{
- return (__mmask8) __builtin_ia32_ptestnmq256 ((__v4di) __A,
- (__v4di) __B,
- (__mmask8) -1);
+ return _mm256_cmpeq_epi64_mask (_mm256_and_si256 (__A, __B),
+ _mm256_setzero_si256());
}
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
_mm256_mask_testn_epi64_mask (__mmask8 __U, __m256i __A, __m256i __B)
{
- return (__mmask8) __builtin_ia32_ptestnmq256 ((__v4di) __A,
- (__v4di) __B, __U);
+ return _mm256_mask_cmpeq_epi64_mask (__U, _mm256_and_si256 (__A, __B),
+ _mm256_setzero_si256());
}
-
-
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_mask_unpackhi_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
@@ -6964,85 +6586,81 @@ _mm256_maskz_srai_epi64(__mmask8 __U, __m256i __A, int __imm)
#define _mm256_shuffle_f32x4(A, B, imm) __extension__ ({ \
- (__m256)__builtin_ia32_shuf_f32x4_256_mask((__v8sf)(__m256)(A), \
- (__v8sf)(__m256)(B), (int)(imm), \
- (__v8sf)_mm256_setzero_ps(), \
- (__mmask8)-1); })
+ (__m256)__builtin_shufflevector((__v8sf)(__m256)(A), \
+ (__v8sf)(__m256)(B), \
+ 0 + ((((imm) >> 0) & 0x1) * 4), \
+ 1 + ((((imm) >> 0) & 0x1) * 4), \
+ 2 + ((((imm) >> 0) & 0x1) * 4), \
+ 3 + ((((imm) >> 0) & 0x1) * 4), \
+ 8 + ((((imm) >> 1) & 0x1) * 4), \
+ 9 + ((((imm) >> 1) & 0x1) * 4), \
+ 10 + ((((imm) >> 1) & 0x1) * 4), \
+ 11 + ((((imm) >> 1) & 0x1) * 4)); })
#define _mm256_mask_shuffle_f32x4(W, U, A, B, imm) __extension__ ({ \
- (__m256)__builtin_ia32_shuf_f32x4_256_mask((__v8sf)(__m256)(A), \
- (__v8sf)(__m256)(B), (int)(imm), \
- (__v8sf)(__m256)(W), \
- (__mmask8)(U)); })
+ (__m256)__builtin_ia32_selectps_256((__mmask8)(U), \
+ (__v8sf)_mm256_shuffle_f32x4((A), (B), (imm)), \
+ (__v8sf)(__m256)(W)); })
#define _mm256_maskz_shuffle_f32x4(U, A, B, imm) __extension__ ({ \
- (__m256)__builtin_ia32_shuf_f32x4_256_mask((__v8sf)(__m256)(A), \
- (__v8sf)(__m256)(B), (int)(imm), \
- (__v8sf)_mm256_setzero_ps(), \
- (__mmask8)(U)); })
+ (__m256)__builtin_ia32_selectps_256((__mmask8)(U), \
+ (__v8sf)_mm256_shuffle_f32x4((A), (B), (imm)), \
+ (__v8sf)_mm256_setzero_ps()); })
#define _mm256_shuffle_f64x2(A, B, imm) __extension__ ({ \
- (__m256d)__builtin_ia32_shuf_f64x2_256_mask((__v4df)(__m256d)(A), \
- (__v4df)(__m256d)(B), \
- (int)(imm), \
- (__v4df)_mm256_setzero_pd(), \
- (__mmask8)-1); })
+ (__m256d)__builtin_shufflevector((__v4df)(__m256d)(A), \
+ (__v4df)(__m256d)(B), \
+ 0 + ((((imm) >> 0) & 0x1) * 2), \
+ 1 + ((((imm) >> 0) & 0x1) * 2), \
+ 4 + ((((imm) >> 1) & 0x1) * 2), \
+ 5 + ((((imm) >> 1) & 0x1) * 2)); })
#define _mm256_mask_shuffle_f64x2(W, U, A, B, imm) __extension__ ({ \
- (__m256d)__builtin_ia32_shuf_f64x2_256_mask((__v4df)(__m256d)(A), \
- (__v4df)(__m256d)(B), \
- (int)(imm), \
- (__v4df)(__m256d)(W), \
- (__mmask8)(U)); })
+ (__m256d)__builtin_ia32_selectpd_256((__mmask8)(U), \
+ (__v4df)_mm256_shuffle_f64x2((A), (B), (imm)), \
+ (__v4df)(__m256)(W)); })
#define _mm256_maskz_shuffle_f64x2(U, A, B, imm) __extension__ ({ \
- (__m256d)__builtin_ia32_shuf_f64x2_256_mask((__v4df)(__m256d)(A), \
- (__v4df)(__m256d)(B), \
- (int)(imm), \
- (__v4df)_mm256_setzero_pd(), \
- (__mmask8)(U)); })
+ (__m256d)__builtin_ia32_selectpd_256((__mmask8)(U), \
+ (__v4df)_mm256_shuffle_f64x2((A), (B), (imm)), \
+ (__v4df)_mm256_setzero_pd()); })
#define _mm256_shuffle_i32x4(A, B, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_shuf_i32x4_256_mask((__v8si)(__m256i)(A), \
- (__v8si)(__m256i)(B), \
- (int)(imm), \
- (__v8si)_mm256_setzero_si256(), \
- (__mmask8)-1); })
+ (__m256i)__builtin_shufflevector((__v4di)(__m256i)(A), \
+ (__v4di)(__m256i)(B), \
+ 0 + ((((imm) >> 0) & 0x1) * 2), \
+ 1 + ((((imm) >> 0) & 0x1) * 2), \
+ 4 + ((((imm) >> 1) & 0x1) * 2), \
+ 5 + ((((imm) >> 1) & 0x1) * 2)); })
#define _mm256_mask_shuffle_i32x4(W, U, A, B, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_shuf_i32x4_256_mask((__v8si)(__m256i)(A), \
- (__v8si)(__m256i)(B), \
- (int)(imm), \
- (__v8si)(__m256i)(W), \
- (__mmask8)(U)); })
+ (__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \
+ (__v8si)_mm256_shuffle_i32x4((A), (B), (imm)), \
+ (__v8si)(__m256)(W)); })
#define _mm256_maskz_shuffle_i32x4(U, A, B, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_shuf_i32x4_256_mask((__v8si)(__m256i)(A), \
- (__v8si)(__m256i)(B), \
- (int)(imm), \
- (__v8si)_mm256_setzero_si256(), \
- (__mmask8)(U)); })
+ (__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \
+ (__v8si)_mm256_shuffle_i32x4((A), (B), (imm)), \
+ (__v8si)_mm256_setzero_si256()); })
#define _mm256_shuffle_i64x2(A, B, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_shuf_i64x2_256_mask((__v4di)(__m256i)(A), \
- (__v4di)(__m256i)(B), \
- (int)(imm), \
- (__v4di)_mm256_setzero_si256(), \
- (__mmask8)-1); })
+ (__m256i)__builtin_shufflevector((__v4di)(__m256i)(A), \
+ (__v4di)(__m256i)(B), \
+ 0 + ((((imm) >> 0) & 0x1) * 2), \
+ 1 + ((((imm) >> 0) & 0x1) * 2), \
+ 4 + ((((imm) >> 1) & 0x1) * 2), \
+ 5 + ((((imm) >> 1) & 0x1) * 2)); })
#define _mm256_mask_shuffle_i64x2(W, U, A, B, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_shuf_i64x2_256_mask((__v4di)(__m256i)(A), \
- (__v4di)(__m256i)(B), \
- (int)(imm), \
- (__v4di)(__m256i)(W), \
- (__mmask8)(U)); })
+ (__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \
+ (__v4di)_mm256_shuffle_i64x2((A), (B), (imm)), \
+ (__v4di)(__m256)(W)); })
+
#define _mm256_maskz_shuffle_i64x2(U, A, B, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_shuf_i64x2_256_mask((__v4di)(__m256i)(A), \
- (__v4di)(__m256i)(B), \
- (int)(imm), \
- (__v4di)_mm256_setzero_si256(), \
- (__mmask8)(U)); })
+ (__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \
+ (__v4di)_mm256_shuffle_i64x2((A), (B), (imm)), \
+ (__v4di)_mm256_setzero_si256()); })
#define _mm_mask_shuffle_pd(W, U, A, B, M) __extension__ ({ \
(__m128d)__builtin_ia32_selectpd_128((__mmask8)(U), \
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512vpopcntdqvlintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512vpopcntdqvlintrin.h
new file mode 100644
index 0000000000000..c2058a8f51543
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512vpopcntdqvlintrin.h
@@ -0,0 +1,99 @@
+/*===------------- avx512vpopcntdqintrin.h - AVX512VPOPCNTDQ intrinsics
+ *------------------===
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+#ifndef __IMMINTRIN_H
+#error \
+ "Never use <avx512vpopcntdqvlintrin.h> directly; include <immintrin.h> instead."
+#endif
+
+#ifndef __AVX512VPOPCNTDQVLINTRIN_H
+#define __AVX512VPOPCNTDQVLINTRIN_H
+
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS \
+ __attribute__((__always_inline__, __nodebug__, __target__("avx512vpopcntdq,avx512vl")))
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_popcnt_epi64(__m128i __A) {
+ return (__m128i)__builtin_ia32_vpopcntq_128((__v2di)__A);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_popcnt_epi64(__m128i __W, __mmask8 __U, __m128i __A) {
+ return (__m128i)__builtin_ia32_selectq_128(
+ (__mmask8)__U, (__v2di)_mm_popcnt_epi64(__A), (__v2di)__W);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_popcnt_epi64(__mmask8 __U, __m128i __A) {
+ return _mm_mask_popcnt_epi64((__m128i)_mm_setzero_si128(), __U, __A);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_popcnt_epi32(__m128i __A) {
+ return (__m128i)__builtin_ia32_vpopcntd_128((__v4si)__A);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_popcnt_epi32(__m128i __W, __mmask8 __U, __m128i __A) {
+ return (__m128i)__builtin_ia32_selectd_128(
+ (__mmask8)__U, (__v4si)_mm_popcnt_epi32(__A), (__v4si)__W);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_popcnt_epi32(__mmask8 __U, __m128i __A) {
+ return _mm_mask_popcnt_epi32((__m128i)_mm_setzero_si128(), __U, __A);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS _mm256_popcnt_epi64(__m256i __A) {
+ return (__m256i)__builtin_ia32_vpopcntq_256((__v4di)__A);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_popcnt_epi64(__m256i __W, __mmask8 __U, __m256i __A) {
+ return (__m256i)__builtin_ia32_selectq_256(
+ (__mmask8)__U, (__v4di)_mm256_popcnt_epi64(__A), (__v4di)__W);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_popcnt_epi64(__mmask8 __U, __m256i __A) {
+ return _mm256_mask_popcnt_epi64((__m256i)_mm256_setzero_si256(), __U, __A);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS _mm256_popcnt_epi32(__m256i __A) {
+ return (__m256i)__builtin_ia32_vpopcntd_256((__v8si)__A);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_popcnt_epi32(__m256i __W, __mmask8 __U, __m256i __A) {
+ return (__m256i)__builtin_ia32_selectd_256(
+ (__mmask8)__U, (__v8si)_mm256_popcnt_epi32(__A), (__v8si)__W);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_popcnt_epi32(__mmask8 __U, __m256i __A) {
+ return _mm256_mask_popcnt_epi32((__m256i)_mm256_setzero_si256(), __U, __A);
+}
+
+#undef __DEFAULT_FN_ATTRS
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/cetintrin.h b/contrib/llvm/tools/clang/lib/Headers/cetintrin.h
new file mode 100644
index 0000000000000..1256a3f63a162
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/cetintrin.h
@@ -0,0 +1,93 @@
+/*===---- cetintrin.h - CET intrinsic ------------------------------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __IMMINTRIN_H
+#error "Never use <cetintrin.h> directly; include <immintrin.h> instead."
+#endif
+
+#ifndef __CETINTRIN_H
+#define __CETINTRIN_H
+
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS \
+ __attribute__((__always_inline__, __nodebug__, __target__("shstk")))
+
+static __inline__ void __DEFAULT_FN_ATTRS _incsspd(int __a) {
+ __builtin_ia32_incsspd(__a);
+}
+
+#ifdef __x86_64__
+static __inline__ void __DEFAULT_FN_ATTRS _incsspq(unsigned long long __a) {
+ __builtin_ia32_incsspq(__a);
+}
+#endif /* __x86_64__ */
+
+static __inline__ unsigned int __DEFAULT_FN_ATTRS _rdsspd(unsigned int __a) {
+ return __builtin_ia32_rdsspd(__a);
+}
+
+#ifdef __x86_64__
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS _rdsspq(unsigned long long __a) {
+ return __builtin_ia32_rdsspq(__a);
+}
+#endif /* __x86_64__ */
+
+static __inline__ void __DEFAULT_FN_ATTRS _saveprevssp() {
+ __builtin_ia32_saveprevssp();
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS _rstorssp(void * __p) {
+ __builtin_ia32_rstorssp(__p);
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS _wrssd(unsigned int __a, void * __p) {
+ __builtin_ia32_wrssd(__a, __p);
+}
+
+#ifdef __x86_64__
+static __inline__ void __DEFAULT_FN_ATTRS _wrssq(unsigned long long __a, void * __p) {
+ __builtin_ia32_wrssq(__a, __p);
+}
+#endif /* __x86_64__ */
+
+static __inline__ void __DEFAULT_FN_ATTRS _wrussd(unsigned int __a, void * __p) {
+ __builtin_ia32_wrussd(__a, __p);
+}
+
+#ifdef __x86_64__
+static __inline__ void __DEFAULT_FN_ATTRS _wrussq(unsigned long long __a, void * __p) {
+ __builtin_ia32_wrussq(__a, __p);
+}
+#endif /* __x86_64__ */
+
+static __inline__ void __DEFAULT_FN_ATTRS _setssbsy() {
+ __builtin_ia32_setssbsy();
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS _clrssbsy(void * __p) {
+ __builtin_ia32_clrssbsy(__p);
+}
+
+#undef __DEFAULT_FN_ATTRS
+
+#endif /* __CETINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/clflushoptintrin.h b/contrib/llvm/tools/clang/lib/Headers/clflushoptintrin.h
index 60e0ead762754..f1f133023441a 100644
--- a/contrib/llvm/tools/clang/lib/Headers/clflushoptintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/clflushoptintrin.h
@@ -32,7 +32,7 @@
#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("clflushopt")))
static __inline__ void __DEFAULT_FN_ATTRS
-_mm_clflushopt(char * __m) {
+_mm_clflushopt(void const * __m) {
__builtin_ia32_clflushopt(__m);
}
diff --git a/contrib/llvm/tools/clang/lib/Headers/clwbintrin.h b/contrib/llvm/tools/clang/lib/Headers/clwbintrin.h
new file mode 100644
index 0000000000000..2594a6c387561
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/clwbintrin.h
@@ -0,0 +1,52 @@
+/*===---- clwbintrin.h - CLWB intrinsic ------------------------------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __IMMINTRIN_H
+#error "Never use <clwbintrin.h> directly; include <immintrin.h> instead."
+#endif
+
+#ifndef __CLWBINTRIN_H
+#define __CLWBINTRIN_H
+
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("clwb")))
+
+/// \brief Writes back to memory the cache line (if modified) that contains the
+/// linear address specified in \a __p from any level of the cache hierarchy in
+/// the cache coherence domain
+///
+/// \headerfile <immintrin.h>
+///
+/// This intrinsic corresponds to the <c> CLWB </c> instruction.
+///
+/// \param __p
+/// A pointer to the memory location used to identify the cache line to be
+/// written back.
+static __inline__ void __DEFAULT_FN_ATTRS
+_mm_clwb(void const *__p) {
+ __builtin_ia32_clwb(__p);
+}
+
+#undef __DEFAULT_FN_ATTRS
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/cuda_wrappers/algorithm b/contrib/llvm/tools/clang/lib/Headers/cuda_wrappers/algorithm
index 95d9beb73c682..cedd70762c486 100644
--- a/contrib/llvm/tools/clang/lib/Headers/cuda_wrappers/algorithm
+++ b/contrib/llvm/tools/clang/lib/Headers/cuda_wrappers/algorithm
@@ -80,7 +80,7 @@ min(const __T &__a, const __T &__b, __Cmp __cmp) {
template <class __T>
inline __device__ const __T &
min(const __T &__a, const __T &__b) {
- return __a < __b ? __b : __a;
+ return __a < __b ? __a : __b;
}
#ifdef _LIBCPP_END_NAMESPACE_STD
diff --git a/contrib/llvm/tools/clang/lib/Headers/cuda_wrappers/new b/contrib/llvm/tools/clang/lib/Headers/cuda_wrappers/new
index b77131af0e5b7..71b7a52363ce6 100644
--- a/contrib/llvm/tools/clang/lib/Headers/cuda_wrappers/new
+++ b/contrib/llvm/tools/clang/lib/Headers/cuda_wrappers/new
@@ -26,7 +26,6 @@
#include_next <new>
-// Device overrides for placement new and delete.
#pragma push_macro("CUDA_NOEXCEPT")
#if __cplusplus >= 201103L
#define CUDA_NOEXCEPT noexcept
@@ -34,6 +33,55 @@
#define CUDA_NOEXCEPT
#endif
+// Device overrides for non-placement new and delete.
+__device__ inline void *operator new(__SIZE_TYPE__ size) {
+ if (size == 0) {
+ size = 1;
+ }
+ return ::malloc(size);
+}
+__device__ inline void *operator new(__SIZE_TYPE__ size,
+ const std::nothrow_t &) CUDA_NOEXCEPT {
+ return ::operator new(size);
+}
+
+__device__ inline void *operator new[](__SIZE_TYPE__ size) {
+ return ::operator new(size);
+}
+__device__ inline void *operator new[](__SIZE_TYPE__ size,
+ const std::nothrow_t &) {
+ return ::operator new(size);
+}
+
+__device__ inline void operator delete(void* ptr) CUDA_NOEXCEPT {
+ if (ptr) {
+ ::free(ptr);
+ }
+}
+__device__ inline void operator delete(void *ptr,
+ const std::nothrow_t &) CUDA_NOEXCEPT {
+ ::operator delete(ptr);
+}
+
+__device__ inline void operator delete[](void* ptr) CUDA_NOEXCEPT {
+ ::operator delete(ptr);
+}
+__device__ inline void operator delete[](void *ptr,
+ const std::nothrow_t &) CUDA_NOEXCEPT {
+ ::operator delete(ptr);
+}
+
+// Sized delete, C++14 only.
+#if __cplusplus >= 201402L
+__device__ void operator delete(void *ptr, __SIZE_TYPE__ size) CUDA_NOEXCEPT {
+ ::operator delete(ptr);
+}
+__device__ void operator delete[](void *ptr, __SIZE_TYPE__ size) CUDA_NOEXCEPT {
+ ::operator delete(ptr);
+}
+#endif
+
+// Device overrides for placement new and delete.
__device__ inline void *operator new(__SIZE_TYPE__, void *__ptr) CUDA_NOEXCEPT {
return __ptr;
}
@@ -42,6 +90,7 @@ __device__ inline void *operator new[](__SIZE_TYPE__, void *__ptr) CUDA_NOEXCEPT
}
__device__ inline void operator delete(void *, void *) CUDA_NOEXCEPT {}
__device__ inline void operator delete[](void *, void *) CUDA_NOEXCEPT {}
+
#pragma pop_macro("CUDA_NOEXCEPT")
#endif // include guard
diff --git a/contrib/llvm/tools/clang/lib/Headers/emmintrin.h b/contrib/llvm/tools/clang/lib/Headers/emmintrin.h
index 709815cbb4c2d..3372508a7f818 100644
--- a/contrib/llvm/tools/clang/lib/Headers/emmintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/emmintrin.h
@@ -2258,7 +2258,11 @@ _mm_adds_epu16(__m128i __a, __m128i __b)
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_avg_epu8(__m128i __a, __m128i __b)
{
- return (__m128i)__builtin_ia32_pavgb128((__v16qi)__a, (__v16qi)__b);
+ typedef unsigned short __v16hu __attribute__ ((__vector_size__ (32)));
+ return (__m128i)__builtin_convertvector(
+ ((__builtin_convertvector((__v16qu)__a, __v16hu) +
+ __builtin_convertvector((__v16qu)__b, __v16hu)) + 1)
+ >> 1, __v16qu);
}
/// \brief Computes the rounded avarages of corresponding elements of two
@@ -2278,7 +2282,11 @@ _mm_avg_epu8(__m128i __a, __m128i __b)
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_avg_epu16(__m128i __a, __m128i __b)
{
- return (__m128i)__builtin_ia32_pavgw128((__v8hi)__a, (__v8hi)__b);
+ typedef unsigned int __v8su __attribute__ ((__vector_size__ (32)));
+ return (__m128i)__builtin_convertvector(
+ ((__builtin_convertvector((__v8hu)__a, __v8su) +
+ __builtin_convertvector((__v8hu)__b, __v8su)) + 1)
+ >> 1, __v8hu);
}
/// \brief Multiplies the corresponding elements of two 128-bit signed [8 x i16]
diff --git a/contrib/llvm/tools/clang/lib/Headers/float.h b/contrib/llvm/tools/clang/lib/Headers/float.h
index 502143d4e4813..44d4d05494f5d 100644
--- a/contrib/llvm/tools/clang/lib/Headers/float.h
+++ b/contrib/llvm/tools/clang/lib/Headers/float.h
@@ -143,4 +143,18 @@
# define LDBL_DECIMAL_DIG __LDBL_DECIMAL_DIG__
#endif
+#ifdef __STDC_WANT_IEC_60559_TYPES_EXT__
+# define FLT16_MANT_DIG __FLT16_MANT_DIG__
+# define FLT16_DECIMAL_DIG __FLT16_DECIMAL_DIG__
+# define FLT16_DIG __FLT16_DIG__
+# define FLT16_MIN_EXP __FLT16_MIN_EXP__
+# define FLT16_MIN_10_EXP __FLT16_MIN_10_EXP__
+# define FLT16_MAX_EXP __FLT16_MAX_EXP__
+# define FLT16_MAX_10_EXP __FLT16_MAX_10_EXP__
+# define FLT16_MAX __FLT16_MAX__
+# define FLT16_EPSILON __FLT16_EPSILON__
+# define FLT16_MIN __FLT16_MIN__
+# define FLT16_TRUE_MIN __FLT16_TRUE_MIN__
+#endif /* __STDC_WANT_IEC_60559_TYPES_EXT__ */
+
#endif /* __FLOAT_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/fma4intrin.h b/contrib/llvm/tools/clang/lib/Headers/fma4intrin.h
index 11aa8ceacf375..962b1a60a2585 100644
--- a/contrib/llvm/tools/clang/lib/Headers/fma4intrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/fma4intrin.h
@@ -60,73 +60,73 @@ _mm_macc_sd(__m128d __A, __m128d __B, __m128d __C)
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_msub_ps(__m128 __A, __m128 __B, __m128 __C)
{
- return (__m128)__builtin_ia32_vfmsubps((__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
+ return (__m128)__builtin_ia32_vfmaddps((__v4sf)__A, (__v4sf)__B, -(__v4sf)__C);
}
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_msub_pd(__m128d __A, __m128d __B, __m128d __C)
{
- return (__m128d)__builtin_ia32_vfmsubpd((__v2df)__A, (__v2df)__B, (__v2df)__C);
+ return (__m128d)__builtin_ia32_vfmaddpd((__v2df)__A, (__v2df)__B, -(__v2df)__C);
}
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_msub_ss(__m128 __A, __m128 __B, __m128 __C)
{
- return (__m128)__builtin_ia32_vfmsubss((__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
+ return (__m128)__builtin_ia32_vfmaddss((__v4sf)__A, (__v4sf)__B, -(__v4sf)__C);
}
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_msub_sd(__m128d __A, __m128d __B, __m128d __C)
{
- return (__m128d)__builtin_ia32_vfmsubsd((__v2df)__A, (__v2df)__B, (__v2df)__C);
+ return (__m128d)__builtin_ia32_vfmaddsd((__v2df)__A, (__v2df)__B, -(__v2df)__C);
}
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_nmacc_ps(__m128 __A, __m128 __B, __m128 __C)
{
- return (__m128)__builtin_ia32_vfnmaddps((__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
+ return (__m128)__builtin_ia32_vfmaddps(-(__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
}
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_nmacc_pd(__m128d __A, __m128d __B, __m128d __C)
{
- return (__m128d)__builtin_ia32_vfnmaddpd((__v2df)__A, (__v2df)__B, (__v2df)__C);
+ return (__m128d)__builtin_ia32_vfmaddpd(-(__v2df)__A, (__v2df)__B, (__v2df)__C);
}
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_nmacc_ss(__m128 __A, __m128 __B, __m128 __C)
{
- return (__m128)__builtin_ia32_vfnmaddss((__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
+ return (__m128)__builtin_ia32_vfmaddss(-(__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
}
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_nmacc_sd(__m128d __A, __m128d __B, __m128d __C)
{
- return (__m128d)__builtin_ia32_vfnmaddsd((__v2df)__A, (__v2df)__B, (__v2df)__C);
+ return (__m128d)__builtin_ia32_vfmaddsd(-(__v2df)__A, (__v2df)__B, (__v2df)__C);
}
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_nmsub_ps(__m128 __A, __m128 __B, __m128 __C)
{
- return (__m128)__builtin_ia32_vfnmsubps((__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
+ return (__m128)__builtin_ia32_vfmaddps(-(__v4sf)__A, (__v4sf)__B, -(__v4sf)__C);
}
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_nmsub_pd(__m128d __A, __m128d __B, __m128d __C)
{
- return (__m128d)__builtin_ia32_vfnmsubpd((__v2df)__A, (__v2df)__B, (__v2df)__C);
+ return (__m128d)__builtin_ia32_vfmaddpd(-(__v2df)__A, (__v2df)__B, -(__v2df)__C);
}
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_nmsub_ss(__m128 __A, __m128 __B, __m128 __C)
{
- return (__m128)__builtin_ia32_vfnmsubss((__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
+ return (__m128)__builtin_ia32_vfmaddss(-(__v4sf)__A, (__v4sf)__B, -(__v4sf)__C);
}
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_nmsub_sd(__m128d __A, __m128d __B, __m128d __C)
{
- return (__m128d)__builtin_ia32_vfnmsubsd((__v2df)__A, (__v2df)__B, (__v2df)__C);
+ return (__m128d)__builtin_ia32_vfmaddsd(-(__v2df)__A, (__v2df)__B, -(__v2df)__C);
}
static __inline__ __m128 __DEFAULT_FN_ATTRS
@@ -144,13 +144,13 @@ _mm_maddsub_pd(__m128d __A, __m128d __B, __m128d __C)
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_msubadd_ps(__m128 __A, __m128 __B, __m128 __C)
{
- return (__m128)__builtin_ia32_vfmsubaddps((__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
+ return (__m128)__builtin_ia32_vfmaddsubps((__v4sf)__A, (__v4sf)__B, -(__v4sf)__C);
}
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_msubadd_pd(__m128d __A, __m128d __B, __m128d __C)
{
- return (__m128d)__builtin_ia32_vfmsubaddpd((__v2df)__A, (__v2df)__B, (__v2df)__C);
+ return (__m128d)__builtin_ia32_vfmaddsubpd((__v2df)__A, (__v2df)__B, -(__v2df)__C);
}
static __inline__ __m256 __DEFAULT_FN_ATTRS
@@ -168,37 +168,37 @@ _mm256_macc_pd(__m256d __A, __m256d __B, __m256d __C)
static __inline__ __m256 __DEFAULT_FN_ATTRS
_mm256_msub_ps(__m256 __A, __m256 __B, __m256 __C)
{
- return (__m256)__builtin_ia32_vfmsubps256((__v8sf)__A, (__v8sf)__B, (__v8sf)__C);
+ return (__m256)__builtin_ia32_vfmaddps256((__v8sf)__A, (__v8sf)__B, -(__v8sf)__C);
}
static __inline__ __m256d __DEFAULT_FN_ATTRS
_mm256_msub_pd(__m256d __A, __m256d __B, __m256d __C)
{
- return (__m256d)__builtin_ia32_vfmsubpd256((__v4df)__A, (__v4df)__B, (__v4df)__C);
+ return (__m256d)__builtin_ia32_vfmaddpd256((__v4df)__A, (__v4df)__B, -(__v4df)__C);
}
static __inline__ __m256 __DEFAULT_FN_ATTRS
_mm256_nmacc_ps(__m256 __A, __m256 __B, __m256 __C)
{
- return (__m256)__builtin_ia32_vfnmaddps256((__v8sf)__A, (__v8sf)__B, (__v8sf)__C);
+ return (__m256)__builtin_ia32_vfmaddps256(-(__v8sf)__A, (__v8sf)__B, (__v8sf)__C);
}
static __inline__ __m256d __DEFAULT_FN_ATTRS
_mm256_nmacc_pd(__m256d __A, __m256d __B, __m256d __C)
{
- return (__m256d)__builtin_ia32_vfnmaddpd256((__v4df)__A, (__v4df)__B, (__v4df)__C);
+ return (__m256d)__builtin_ia32_vfmaddpd256(-(__v4df)__A, (__v4df)__B, (__v4df)__C);
}
static __inline__ __m256 __DEFAULT_FN_ATTRS
_mm256_nmsub_ps(__m256 __A, __m256 __B, __m256 __C)
{
- return (__m256)__builtin_ia32_vfnmsubps256((__v8sf)__A, (__v8sf)__B, (__v8sf)__C);
+ return (__m256)__builtin_ia32_vfmaddps256(-(__v8sf)__A, (__v8sf)__B, -(__v8sf)__C);
}
static __inline__ __m256d __DEFAULT_FN_ATTRS
_mm256_nmsub_pd(__m256d __A, __m256d __B, __m256d __C)
{
- return (__m256d)__builtin_ia32_vfnmsubpd256((__v4df)__A, (__v4df)__B, (__v4df)__C);
+ return (__m256d)__builtin_ia32_vfmaddpd256(-(__v4df)__A, (__v4df)__B, -(__v4df)__C);
}
static __inline__ __m256 __DEFAULT_FN_ATTRS
@@ -216,13 +216,13 @@ _mm256_maddsub_pd(__m256d __A, __m256d __B, __m256d __C)
static __inline__ __m256 __DEFAULT_FN_ATTRS
_mm256_msubadd_ps(__m256 __A, __m256 __B, __m256 __C)
{
- return (__m256)__builtin_ia32_vfmsubaddps256((__v8sf)__A, (__v8sf)__B, (__v8sf)__C);
+ return (__m256)__builtin_ia32_vfmaddsubps256((__v8sf)__A, (__v8sf)__B, -(__v8sf)__C);
}
static __inline__ __m256d __DEFAULT_FN_ATTRS
_mm256_msubadd_pd(__m256d __A, __m256d __B, __m256d __C)
{
- return (__m256d)__builtin_ia32_vfmsubaddpd256((__v4df)__A, (__v4df)__B, (__v4df)__C);
+ return (__m256d)__builtin_ia32_vfmaddsubpd256((__v4df)__A, (__v4df)__B, -(__v4df)__C);
}
#undef __DEFAULT_FN_ATTRS
diff --git a/contrib/llvm/tools/clang/lib/Headers/fmaintrin.h b/contrib/llvm/tools/clang/lib/Headers/fmaintrin.h
index 0e2ef0b1716bb..478a0ac81cf26 100644
--- a/contrib/llvm/tools/clang/lib/Headers/fmaintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/fmaintrin.h
@@ -46,85 +46,85 @@ _mm_fmadd_pd(__m128d __A, __m128d __B, __m128d __C)
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_fmadd_ss(__m128 __A, __m128 __B, __m128 __C)
{
- return (__m128)__builtin_ia32_vfmaddss((__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
+ return (__m128)__builtin_ia32_vfmaddss3((__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
}
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_fmadd_sd(__m128d __A, __m128d __B, __m128d __C)
{
- return (__m128d)__builtin_ia32_vfmaddsd((__v2df)__A, (__v2df)__B, (__v2df)__C);
+ return (__m128d)__builtin_ia32_vfmaddsd3((__v2df)__A, (__v2df)__B, (__v2df)__C);
}
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_fmsub_ps(__m128 __A, __m128 __B, __m128 __C)
{
- return (__m128)__builtin_ia32_vfmsubps((__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
+ return (__m128)__builtin_ia32_vfmaddps((__v4sf)__A, (__v4sf)__B, -(__v4sf)__C);
}
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_fmsub_pd(__m128d __A, __m128d __B, __m128d __C)
{
- return (__m128d)__builtin_ia32_vfmsubpd((__v2df)__A, (__v2df)__B, (__v2df)__C);
+ return (__m128d)__builtin_ia32_vfmaddpd((__v2df)__A, (__v2df)__B, -(__v2df)__C);
}
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_fmsub_ss(__m128 __A, __m128 __B, __m128 __C)
{
- return (__m128)__builtin_ia32_vfmsubss((__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
+ return (__m128)__builtin_ia32_vfmaddss3((__v4sf)__A, (__v4sf)__B, -(__v4sf)__C);
}
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_fmsub_sd(__m128d __A, __m128d __B, __m128d __C)
{
- return (__m128d)__builtin_ia32_vfmsubsd((__v2df)__A, (__v2df)__B, (__v2df)__C);
+ return (__m128d)__builtin_ia32_vfmaddsd3((__v2df)__A, (__v2df)__B, -(__v2df)__C);
}
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_fnmadd_ps(__m128 __A, __m128 __B, __m128 __C)
{
- return (__m128)__builtin_ia32_vfnmaddps((__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
+ return (__m128)__builtin_ia32_vfmaddps(-(__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
}
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_fnmadd_pd(__m128d __A, __m128d __B, __m128d __C)
{
- return (__m128d)__builtin_ia32_vfnmaddpd((__v2df)__A, (__v2df)__B, (__v2df)__C);
+ return (__m128d)__builtin_ia32_vfmaddpd(-(__v2df)__A, (__v2df)__B, (__v2df)__C);
}
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_fnmadd_ss(__m128 __A, __m128 __B, __m128 __C)
{
- return (__m128)__builtin_ia32_vfnmaddss((__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
+ return (__m128)__builtin_ia32_vfmaddss3((__v4sf)__A, -(__v4sf)__B, (__v4sf)__C);
}
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_fnmadd_sd(__m128d __A, __m128d __B, __m128d __C)
{
- return (__m128d)__builtin_ia32_vfnmaddsd((__v2df)__A, (__v2df)__B, (__v2df)__C);
+ return (__m128d)__builtin_ia32_vfmaddsd3((__v2df)__A, -(__v2df)__B, (__v2df)__C);
}
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_fnmsub_ps(__m128 __A, __m128 __B, __m128 __C)
{
- return (__m128)__builtin_ia32_vfnmsubps((__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
+ return (__m128)__builtin_ia32_vfmaddps(-(__v4sf)__A, (__v4sf)__B, -(__v4sf)__C);
}
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_fnmsub_pd(__m128d __A, __m128d __B, __m128d __C)
{
- return (__m128d)__builtin_ia32_vfnmsubpd((__v2df)__A, (__v2df)__B, (__v2df)__C);
+ return (__m128d)__builtin_ia32_vfmaddpd(-(__v2df)__A, (__v2df)__B, -(__v2df)__C);
}
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_fnmsub_ss(__m128 __A, __m128 __B, __m128 __C)
{
- return (__m128)__builtin_ia32_vfnmsubss((__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
+ return (__m128)__builtin_ia32_vfmaddss3((__v4sf)__A, -(__v4sf)__B, -(__v4sf)__C);
}
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_fnmsub_sd(__m128d __A, __m128d __B, __m128d __C)
{
- return (__m128d)__builtin_ia32_vfnmsubsd((__v2df)__A, (__v2df)__B, (__v2df)__C);
+ return (__m128d)__builtin_ia32_vfmaddsd3((__v2df)__A, -(__v2df)__B, -(__v2df)__C);
}
static __inline__ __m128 __DEFAULT_FN_ATTRS
@@ -142,13 +142,13 @@ _mm_fmaddsub_pd(__m128d __A, __m128d __B, __m128d __C)
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_fmsubadd_ps(__m128 __A, __m128 __B, __m128 __C)
{
- return (__m128)__builtin_ia32_vfmsubaddps((__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
+ return (__m128)__builtin_ia32_vfmaddsubps((__v4sf)__A, (__v4sf)__B, -(__v4sf)__C);
}
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_fmsubadd_pd(__m128d __A, __m128d __B, __m128d __C)
{
- return (__m128d)__builtin_ia32_vfmsubaddpd((__v2df)__A, (__v2df)__B, (__v2df)__C);
+ return (__m128d)__builtin_ia32_vfmaddsubpd((__v2df)__A, (__v2df)__B, -(__v2df)__C);
}
static __inline__ __m256 __DEFAULT_FN_ATTRS
@@ -166,37 +166,37 @@ _mm256_fmadd_pd(__m256d __A, __m256d __B, __m256d __C)
static __inline__ __m256 __DEFAULT_FN_ATTRS
_mm256_fmsub_ps(__m256 __A, __m256 __B, __m256 __C)
{
- return (__m256)__builtin_ia32_vfmsubps256((__v8sf)__A, (__v8sf)__B, (__v8sf)__C);
+ return (__m256)__builtin_ia32_vfmaddps256((__v8sf)__A, (__v8sf)__B, -(__v8sf)__C);
}
static __inline__ __m256d __DEFAULT_FN_ATTRS
_mm256_fmsub_pd(__m256d __A, __m256d __B, __m256d __C)
{
- return (__m256d)__builtin_ia32_vfmsubpd256((__v4df)__A, (__v4df)__B, (__v4df)__C);
+ return (__m256d)__builtin_ia32_vfmaddpd256((__v4df)__A, (__v4df)__B, -(__v4df)__C);
}
static __inline__ __m256 __DEFAULT_FN_ATTRS
_mm256_fnmadd_ps(__m256 __A, __m256 __B, __m256 __C)
{
- return (__m256)__builtin_ia32_vfnmaddps256((__v8sf)__A, (__v8sf)__B, (__v8sf)__C);
+ return (__m256)__builtin_ia32_vfmaddps256(-(__v8sf)__A, (__v8sf)__B, (__v8sf)__C);
}
static __inline__ __m256d __DEFAULT_FN_ATTRS
_mm256_fnmadd_pd(__m256d __A, __m256d __B, __m256d __C)
{
- return (__m256d)__builtin_ia32_vfnmaddpd256((__v4df)__A, (__v4df)__B, (__v4df)__C);
+ return (__m256d)__builtin_ia32_vfmaddpd256(-(__v4df)__A, (__v4df)__B, (__v4df)__C);
}
static __inline__ __m256 __DEFAULT_FN_ATTRS
_mm256_fnmsub_ps(__m256 __A, __m256 __B, __m256 __C)
{
- return (__m256)__builtin_ia32_vfnmsubps256((__v8sf)__A, (__v8sf)__B, (__v8sf)__C);
+ return (__m256)__builtin_ia32_vfmaddps256(-(__v8sf)__A, (__v8sf)__B, -(__v8sf)__C);
}
static __inline__ __m256d __DEFAULT_FN_ATTRS
_mm256_fnmsub_pd(__m256d __A, __m256d __B, __m256d __C)
{
- return (__m256d)__builtin_ia32_vfnmsubpd256((__v4df)__A, (__v4df)__B, (__v4df)__C);
+ return (__m256d)__builtin_ia32_vfmaddpd256(-(__v4df)__A, (__v4df)__B, -(__v4df)__C);
}
static __inline__ __m256 __DEFAULT_FN_ATTRS
@@ -214,13 +214,13 @@ _mm256_fmaddsub_pd(__m256d __A, __m256d __B, __m256d __C)
static __inline__ __m256 __DEFAULT_FN_ATTRS
_mm256_fmsubadd_ps(__m256 __A, __m256 __B, __m256 __C)
{
- return (__m256)__builtin_ia32_vfmsubaddps256((__v8sf)__A, (__v8sf)__B, (__v8sf)__C);
+ return (__m256)__builtin_ia32_vfmaddsubps256((__v8sf)__A, (__v8sf)__B, -(__v8sf)__C);
}
static __inline__ __m256d __DEFAULT_FN_ATTRS
_mm256_fmsubadd_pd(__m256d __A, __m256d __B, __m256d __C)
{
- return (__m256d)__builtin_ia32_vfmsubaddpd256((__v4df)__A, (__v4df)__B, (__v4df)__C);
+ return (__m256d)__builtin_ia32_vfmaddsubpd256((__v4df)__A, (__v4df)__B, -(__v4df)__C);
}
#undef __DEFAULT_FN_ATTRS
diff --git a/contrib/llvm/tools/clang/lib/Headers/immintrin.h b/contrib/llvm/tools/clang/lib/Headers/immintrin.h
index c5f25bfcb5c14..64ad6e6584224 100644
--- a/contrib/llvm/tools/clang/lib/Headers/immintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/immintrin.h
@@ -58,6 +58,10 @@
#include <clflushoptintrin.h>
#endif
+#if !defined(_MSC_VER) || __has_feature(modules) || defined(__CLWB__)
+#include <clwbintrin.h>
+#endif
+
#if !defined(_MSC_VER) || __has_feature(modules) || defined(__AVX__)
#include <avxintrin.h>
#endif
@@ -150,6 +154,11 @@ _mm256_cvtph_ps(__m128i __a)
#include <avx512vpopcntdqintrin.h>
#endif
+#if !defined(_MSC_VER) || __has_feature(modules) || \
+ (defined(__AVX512VL__) && defined(__AVX512VPOPCNTDQ__))
+#include <avx512vpopcntdqvlintrin.h>
+#endif
+
#if !defined(_MSC_VER) || __has_feature(modules) || defined(__AVX512DQ__)
#include <avx512dqintrin.h>
#endif
@@ -315,6 +324,10 @@ _writegsbase_u64(unsigned long long __V)
#include <xsavesintrin.h>
#endif
+#if !defined(_MSC_VER) || __has_feature(modules) || defined(__SHSTK__)
+#include <cetintrin.h>
+#endif
+
/* Some intrinsics inside adxintrin.h are available only on processors with ADX,
* whereas others are also available at all times. */
#include <adxintrin.h>
diff --git a/contrib/llvm/tools/clang/lib/Headers/intrin.h b/contrib/llvm/tools/clang/lib/Headers/intrin.h
index 881d05c0d1649..b30aa215a452e 100644
--- a/contrib/llvm/tools/clang/lib/Headers/intrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/intrin.h
@@ -38,6 +38,10 @@
#include <armintr.h>
#endif
+#if defined(_M_ARM64)
+#include <arm64intr.h>
+#endif
+
/* For the definition of jmp_buf. */
#if __STDC_HOSTED__
#include <setjmp.h>
@@ -828,7 +832,7 @@ _InterlockedCompareExchange_nf(long volatile *_Destination,
__ATOMIC_SEQ_CST, __ATOMIC_RELAXED);
return _Comparand;
}
-static __inline__ short __DEFAULT_FN_ATTRS
+static __inline__ long __DEFAULT_FN_ATTRS
_InterlockedCompareExchange_rel(long volatile *_Destination,
long _Exchange, long _Comparand) {
__atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0,
diff --git a/contrib/llvm/tools/clang/lib/Headers/opencl-c.h b/contrib/llvm/tools/clang/lib/Headers/opencl-c.h
index 58c8daf3a5369..ce204b04c0305 100644
--- a/contrib/llvm/tools/clang/lib/Headers/opencl-c.h
+++ b/contrib/llvm/tools/clang/lib/Headers/opencl-c.h
@@ -11381,6 +11381,8 @@ half16 __ovld __cnfn bitselect(half16 a, half16 b, half16 c);
* For each component of a vector type,
* result[i] = if MSB of c[i] is set ? b[i] : a[i].
* For a scalar type, result = c ? b : a.
+ * b and a must have the same type.
+ * c must have the same number of elements and bits as a.
*/
char __ovld __cnfn select(char a, char b, char c);
uchar __ovld __cnfn select(uchar a, uchar b, char c);
@@ -11394,60 +11396,7 @@ char8 __ovld __cnfn select(char8 a, char8 b, char8 c);
uchar8 __ovld __cnfn select(uchar8 a, uchar8 b, char8 c);
char16 __ovld __cnfn select(char16 a, char16 b, char16 c);
uchar16 __ovld __cnfn select(uchar16 a, uchar16 b, char16 c);
-short __ovld __cnfn select(short a, short b, char c);
-ushort __ovld __cnfn select(ushort a, ushort b, char c);
-short2 __ovld __cnfn select(short2 a, short2 b, char2 c);
-ushort2 __ovld __cnfn select(ushort2 a, ushort2 b, char2 c);
-short3 __ovld __cnfn select(short3 a, short3 b, char3 c);
-ushort3 __ovld __cnfn select(ushort3 a, ushort3 b, char3 c);
-short4 __ovld __cnfn select(short4 a, short4 b, char4 c);
-ushort4 __ovld __cnfn select(ushort4 a, ushort4 b, char4 c);
-short8 __ovld __cnfn select(short8 a, short8 b, char8 c);
-ushort8 __ovld __cnfn select(ushort8 a, ushort8 b, char8 c);
-short16 __ovld __cnfn select(short16 a, short16 b, char16 c);
-ushort16 __ovld __cnfn select(ushort16 a, ushort16 b, char16 c);
-int __ovld __cnfn select(int a, int b, char c);
-uint __ovld __cnfn select(uint a, uint b, char c);
-int2 __ovld __cnfn select(int2 a, int2 b, char2 c);
-uint2 __ovld __cnfn select(uint2 a, uint2 b, char2 c);
-int3 __ovld __cnfn select(int3 a, int3 b, char3 c);
-uint3 __ovld __cnfn select(uint3 a, uint3 b, char3 c);
-int4 __ovld __cnfn select(int4 a, int4 b, char4 c);
-uint4 __ovld __cnfn select(uint4 a, uint4 b, char4 c);
-int8 __ovld __cnfn select(int8 a, int8 b, char8 c);
-uint8 __ovld __cnfn select(uint8 a, uint8 b, char8 c);
-int16 __ovld __cnfn select(int16 a, int16 b, char16 c);
-uint16 __ovld __cnfn select(uint16 a, uint16 b, char16 c);
-long __ovld __cnfn select(long a, long b, char c);
-ulong __ovld __cnfn select(ulong a, ulong b, char c);
-long2 __ovld __cnfn select(long2 a, long2 b, char2 c);
-ulong2 __ovld __cnfn select(ulong2 a, ulong2 b, char2 c);
-long3 __ovld __cnfn select(long3 a, long3 b, char3 c);
-ulong3 __ovld __cnfn select(ulong3 a, ulong3 b, char3 c);
-long4 __ovld __cnfn select(long4 a, long4 b, char4 c);
-ulong4 __ovld __cnfn select(ulong4 a, ulong4 b, char4 c);
-long8 __ovld __cnfn select(long8 a, long8 b, char8 c);
-ulong8 __ovld __cnfn select(ulong8 a, ulong8 b, char8 c);
-long16 __ovld __cnfn select(long16 a, long16 b, char16 c);
-ulong16 __ovld __cnfn select(ulong16 a, ulong16 b, char16 c);
-float __ovld __cnfn select(float a, float b, char c);
-float2 __ovld __cnfn select(float2 a, float2 b, char2 c);
-float3 __ovld __cnfn select(float3 a, float3 b, char3 c);
-float4 __ovld __cnfn select(float4 a, float4 b, char4 c);
-float8 __ovld __cnfn select(float8 a, float8 b, char8 c);
-float16 __ovld __cnfn select(float16 a, float16 b, char16 c);
-char __ovld __cnfn select(char a, char b, short c);
-uchar __ovld __cnfn select(uchar a, uchar b, short c);
-char2 __ovld __cnfn select(char2 a, char2 b, short2 c);
-uchar2 __ovld __cnfn select(uchar2 a, uchar2 b, short2 c);
-char3 __ovld __cnfn select(char3 a, char3 b, short3 c);
-uchar3 __ovld __cnfn select(uchar3 a, uchar3 b, short3 c);
-char4 __ovld __cnfn select(char4 a, char4 b, short4 c);
-uchar4 __ovld __cnfn select(uchar4 a, uchar4 b, short4 c);
-char8 __ovld __cnfn select(char8 a, char8 b, short8 c);
-uchar8 __ovld __cnfn select(uchar8 a, uchar8 b, short8 c);
-char16 __ovld __cnfn select(char16 a, char16 b, short16 c);
-uchar16 __ovld __cnfn select(uchar16 a, uchar16 b, short16 c);
+
short __ovld __cnfn select(short a, short b, short c);
ushort __ovld __cnfn select(ushort a, ushort b, short c);
short2 __ovld __cnfn select(short2 a, short2 b, short2 c);
@@ -11460,60 +11409,7 @@ short8 __ovld __cnfn select(short8 a, short8 b, short8 c);
ushort8 __ovld __cnfn select(ushort8 a, ushort8 b, short8 c);
short16 __ovld __cnfn select(short16 a, short16 b, short16 c);
ushort16 __ovld __cnfn select(ushort16 a, ushort16 b, short16 c);
-int __ovld __cnfn select(int a, int b, short c);
-uint __ovld __cnfn select(uint a, uint b, short c);
-int2 __ovld __cnfn select(int2 a, int2 b, short2 c);
-uint2 __ovld __cnfn select(uint2 a, uint2 b, short2 c);
-int3 __ovld __cnfn select(int3 a, int3 b, short3 c);
-uint3 __ovld __cnfn select(uint3 a, uint3 b, short3 c);
-int4 __ovld __cnfn select(int4 a, int4 b, short4 c);
-uint4 __ovld __cnfn select(uint4 a, uint4 b, short4 c);
-int8 __ovld __cnfn select(int8 a, int8 b, short8 c);
-uint8 __ovld __cnfn select(uint8 a, uint8 b, short8 c);
-int16 __ovld __cnfn select(int16 a, int16 b, short16 c);
-uint16 __ovld __cnfn select(uint16 a, uint16 b, short16 c);
-long __ovld __cnfn select(long a, long b, short c);
-ulong __ovld __cnfn select(ulong a, ulong b, short c);
-long2 __ovld __cnfn select(long2 a, long2 b, short2 c);
-ulong2 __ovld __cnfn select(ulong2 a, ulong2 b, short2 c);
-long3 __ovld __cnfn select(long3 a, long3 b, short3 c);
-ulong3 __ovld __cnfn select(ulong3 a, ulong3 b, short3 c);
-long4 __ovld __cnfn select(long4 a, long4 b, short4 c);
-ulong4 __ovld __cnfn select(ulong4 a, ulong4 b, short4 c);
-long8 __ovld __cnfn select(long8 a, long8 b, short8 c);
-ulong8 __ovld __cnfn select(ulong8 a, ulong8 b, short8 c);
-long16 __ovld __cnfn select(long16 a, long16 b, short16 c);
-ulong16 __ovld __cnfn select(ulong16 a, ulong16 b, short16 c);
-float __ovld __cnfn select(float a, float b, short c);
-float2 __ovld __cnfn select(float2 a, float2 b, short2 c);
-float3 __ovld __cnfn select(float3 a, float3 b, short3 c);
-float4 __ovld __cnfn select(float4 a, float4 b, short4 c);
-float8 __ovld __cnfn select(float8 a, float8 b, short8 c);
-float16 __ovld __cnfn select(float16 a, float16 b, short16 c);
-char __ovld __cnfn select(char a, char b, int c);
-uchar __ovld __cnfn select(uchar a, uchar b, int c);
-char2 __ovld __cnfn select(char2 a, char2 b, int2 c);
-uchar2 __ovld __cnfn select(uchar2 a, uchar2 b, int2 c);
-char3 __ovld __cnfn select(char3 a, char3 b, int3 c);
-uchar3 __ovld __cnfn select(uchar3 a, uchar3 b, int3 c);
-char4 __ovld __cnfn select(char4 a, char4 b, int4 c);
-uchar4 __ovld __cnfn select(uchar4 a, uchar4 b, int4 c);
-char8 __ovld __cnfn select(char8 a, char8 b, int8 c);
-uchar8 __ovld __cnfn select(uchar8 a, uchar8 b, int8 c);
-char16 __ovld __cnfn select(char16 a, char16 b, int16 c);
-uchar16 __ovld __cnfn select(uchar16 a, uchar16 b, int16 c);
-short __ovld __cnfn select(short a, short b, int c);
-ushort __ovld __cnfn select(ushort a, ushort b, int c);
-short2 __ovld __cnfn select(short2 a, short2 b, int2 c);
-ushort2 __ovld __cnfn select(ushort2 a, ushort2 b, int2 c);
-short3 __ovld __cnfn select(short3 a, short3 b, int3 c);
-ushort3 __ovld __cnfn select(ushort3 a, ushort3 b, int3 c);
-short4 __ovld __cnfn select(short4 a, short4 b, int4 c);
-ushort4 __ovld __cnfn select(ushort4 a, ushort4 b, int4 c);
-short8 __ovld __cnfn select(short8 a, short8 b, int8 c);
-ushort8 __ovld __cnfn select(ushort8 a, ushort8 b, int8 c);
-short16 __ovld __cnfn select(short16 a, short16 b, int16 c);
-ushort16 __ovld __cnfn select(ushort16 a, ushort16 b, int16 c);
+
int __ovld __cnfn select(int a, int b, int c);
uint __ovld __cnfn select(uint a, uint b, int c);
int2 __ovld __cnfn select(int2 a, int2 b, int2 c);
@@ -11526,60 +11422,13 @@ int8 __ovld __cnfn select(int8 a, int8 b, int8 c);
uint8 __ovld __cnfn select(uint8 a, uint8 b, int8 c);
int16 __ovld __cnfn select(int16 a, int16 b, int16 c);
uint16 __ovld __cnfn select(uint16 a, uint16 b, int16 c);
-long __ovld __cnfn select(long a, long b, int c);
-ulong __ovld __cnfn select(ulong a, ulong b, int c);
-long2 __ovld __cnfn select(long2 a, long2 b, int2 c);
-ulong2 __ovld __cnfn select(ulong2 a, ulong2 b, int2 c);
-long3 __ovld __cnfn select(long3 a, long3 b, int3 c);
-ulong3 __ovld __cnfn select(ulong3 a, ulong3 b, int3 c);
-long4 __ovld __cnfn select(long4 a, long4 b, int4 c);
-ulong4 __ovld __cnfn select(ulong4 a, ulong4 b, int4 c);
-long8 __ovld __cnfn select(long8 a, long8 b, int8 c);
-ulong8 __ovld __cnfn select(ulong8 a, ulong8 b, int8 c);
-long16 __ovld __cnfn select(long16 a, long16 b, int16 c);
-ulong16 __ovld __cnfn select(ulong16 a, ulong16 b, int16 c);
float __ovld __cnfn select(float a, float b, int c);
float2 __ovld __cnfn select(float2 a, float2 b, int2 c);
float3 __ovld __cnfn select(float3 a, float3 b, int3 c);
float4 __ovld __cnfn select(float4 a, float4 b, int4 c);
float8 __ovld __cnfn select(float8 a, float8 b, int8 c);
float16 __ovld __cnfn select(float16 a, float16 b, int16 c);
-char __ovld __cnfn select(char a, char b, long c);
-uchar __ovld __cnfn select(uchar a, uchar b, long c);
-char2 __ovld __cnfn select(char2 a, char2 b, long2 c);
-uchar2 __ovld __cnfn select(uchar2 a, uchar2 b, long2 c);
-char3 __ovld __cnfn select(char3 a, char3 b, long3 c);
-uchar3 __ovld __cnfn select(uchar3 a, uchar3 b, long3 c);
-char4 __ovld __cnfn select(char4 a, char4 b, long4 c);
-uchar4 __ovld __cnfn select(uchar4 a, uchar4 b, long4 c);
-char8 __ovld __cnfn select(char8 a, char8 b, long8 c);
-uchar8 __ovld __cnfn select(uchar8 a, uchar8 b, long8 c);
-char16 __ovld __cnfn select(char16 a, char16 b, long16 c);
-uchar16 __ovld __cnfn select(uchar16 a, uchar16 b, long16 c);
-short __ovld __cnfn select(short a, short b, long c);
-ushort __ovld __cnfn select(ushort a, ushort b, long c);
-short2 __ovld __cnfn select(short2 a, short2 b, long2 c);
-ushort2 __ovld __cnfn select(ushort2 a, ushort2 b, long2 c);
-short3 __ovld __cnfn select(short3 a, short3 b, long3 c);
-ushort3 __ovld __cnfn select(ushort3 a, ushort3 b, long3 c);
-short4 __ovld __cnfn select(short4 a, short4 b, long4 c);
-ushort4 __ovld __cnfn select(ushort4 a, ushort4 b, long4 c);
-short8 __ovld __cnfn select(short8 a, short8 b, long8 c);
-ushort8 __ovld __cnfn select(ushort8 a, ushort8 b, long8 c);
-short16 __ovld __cnfn select(short16 a, short16 b, long16 c);
-ushort16 __ovld __cnfn select(ushort16 a, ushort16 b, long16 c);
-int __ovld __cnfn select(int a, int b, long c);
-uint __ovld __cnfn select(uint a, uint b, long c);
-int2 __ovld __cnfn select(int2 a, int2 b, long2 c);
-uint2 __ovld __cnfn select(uint2 a, uint2 b, long2 c);
-int3 __ovld __cnfn select(int3 a, int3 b, long3 c);
-uint3 __ovld __cnfn select(uint3 a, uint3 b, long3 c);
-int4 __ovld __cnfn select(int4 a, int4 b, long4 c);
-uint4 __ovld __cnfn select(uint4 a, uint4 b, long4 c);
-int8 __ovld __cnfn select(int8 a, int8 b, long8 c);
-uint8 __ovld __cnfn select(uint8 a, uint8 b, long8 c);
-int16 __ovld __cnfn select(int16 a, int16 b, long16 c);
-uint16 __ovld __cnfn select(uint16 a, uint16 b, long16 c);
+
long __ovld __cnfn select(long a, long b, long c);
ulong __ovld __cnfn select(ulong a, ulong b, long c);
long2 __ovld __cnfn select(long2 a, long2 b, long2 c);
@@ -11592,12 +11441,7 @@ long8 __ovld __cnfn select(long8 a, long8 b, long8 c);
ulong8 __ovld __cnfn select(ulong8 a, ulong8 b, long8 c);
long16 __ovld __cnfn select(long16 a, long16 b, long16 c);
ulong16 __ovld __cnfn select(ulong16 a, ulong16 b, long16 c);
-float __ovld __cnfn select(float a, float b, long c);
-float2 __ovld __cnfn select(float2 a, float2 b, long2 c);
-float3 __ovld __cnfn select(float3 a, float3 b, long3 c);
-float4 __ovld __cnfn select(float4 a, float4 b, long4 c);
-float8 __ovld __cnfn select(float8 a, float8 b, long8 c);
-float16 __ovld __cnfn select(float16 a, float16 b, long16 c);
+
char __ovld __cnfn select(char a, char b, uchar c);
uchar __ovld __cnfn select(uchar a, uchar b, uchar c);
char2 __ovld __cnfn select(char2 a, char2 b, uchar2 c);
@@ -11610,60 +11454,7 @@ char8 __ovld __cnfn select(char8 a, char8 b, uchar8 c);
uchar8 __ovld __cnfn select(uchar8 a, uchar8 b, uchar8 c);
char16 __ovld __cnfn select(char16 a, char16 b, uchar16 c);
uchar16 __ovld __cnfn select(uchar16 a, uchar16 b, uchar16 c);
-short __ovld __cnfn select(short a, short b, uchar c);
-ushort __ovld __cnfn select(ushort a, ushort b, uchar c);
-short2 __ovld __cnfn select(short2 a, short2 b, uchar2 c);
-ushort2 __ovld __cnfn select(ushort2 a, ushort2 b, uchar2 c);
-short3 __ovld __cnfn select(short3 a, short3 b, uchar3 c);
-ushort3 __ovld __cnfn select(ushort3 a, ushort3 b, uchar3 c);
-short4 __ovld __cnfn select(short4 a, short4 b, uchar4 c);
-ushort4 __ovld __cnfn select(ushort4 a, ushort4 b, uchar4 c);
-short8 __ovld __cnfn select(short8 a, short8 b, uchar8 c);
-ushort8 __ovld __cnfn select(ushort8 a, ushort8 b, uchar8 c);
-short16 __ovld __cnfn select(short16 a, short16 b, uchar16 c);
-ushort16 __ovld __cnfn select(ushort16 a, ushort16 b, uchar16 c);
-int __ovld __cnfn select(int a, int b, uchar c);
-uint __ovld __cnfn select(uint a, uint b, uchar c);
-int2 __ovld __cnfn select(int2 a, int2 b, uchar2 c);
-uint2 __ovld __cnfn select(uint2 a, uint2 b, uchar2 c);
-int3 __ovld __cnfn select(int3 a, int3 b, uchar3 c);
-uint3 __ovld __cnfn select(uint3 a, uint3 b, uchar3 c);
-int4 __ovld __cnfn select(int4 a, int4 b, uchar4 c);
-uint4 __ovld __cnfn select(uint4 a, uint4 b, uchar4 c);
-int8 __ovld __cnfn select(int8 a, int8 b, uchar8 c);
-uint8 __ovld __cnfn select(uint8 a, uint8 b, uchar8 c);
-int16 __ovld __cnfn select(int16 a, int16 b, uchar16 c);
-uint16 __ovld __cnfn select(uint16 a, uint16 b, uchar16 c);
-long __ovld __cnfn select(long a, long b, uchar c);
-ulong __ovld __cnfn select(ulong a, ulong b, uchar c);
-long2 __ovld __cnfn select(long2 a, long2 b, uchar2 c);
-ulong2 __ovld __cnfn select(ulong2 a, ulong2 b, uchar2 c);
-long3 __ovld __cnfn select(long3 a, long3 b, uchar3 c);
-ulong3 __ovld __cnfn select(ulong3 a, ulong3 b, uchar3 c);
-long4 __ovld __cnfn select(long4 a, long4 b, uchar4 c);
-ulong4 __ovld __cnfn select(ulong4 a, ulong4 b, uchar4 c);
-long8 __ovld __cnfn select(long8 a, long8 b, uchar8 c);
-ulong8 __ovld __cnfn select(ulong8 a, ulong8 b, uchar8 c);
-long16 __ovld __cnfn select(long16 a, long16 b, uchar16 c);
-ulong16 __ovld __cnfn select(ulong16 a, ulong16 b, uchar16 c);
-float __ovld __cnfn select(float a, float b, uchar c);
-float2 __ovld __cnfn select(float2 a, float2 b, uchar2 c);
-float3 __ovld __cnfn select(float3 a, float3 b, uchar3 c);
-float4 __ovld __cnfn select(float4 a, float4 b, uchar4 c);
-float8 __ovld __cnfn select(float8 a, float8 b, uchar8 c);
-float16 __ovld __cnfn select(float16 a, float16 b, uchar16 c);
-char __ovld __cnfn select(char a, char b, ushort c);
-uchar __ovld __cnfn select(uchar a, uchar b, ushort c);
-char2 __ovld __cnfn select(char2 a, char2 b, ushort2 c);
-uchar2 __ovld __cnfn select(uchar2 a, uchar2 b, ushort2 c);
-char3 __ovld __cnfn select(char3 a, char3 b, ushort3 c);
-uchar3 __ovld __cnfn select(uchar3 a, uchar3 b, ushort3 c);
-char4 __ovld __cnfn select(char4 a, char4 b, ushort4 c);
-uchar4 __ovld __cnfn select(uchar4 a, uchar4 b, ushort4 c);
-char8 __ovld __cnfn select(char8 a, char8 b, ushort8 c);
-uchar8 __ovld __cnfn select(uchar8 a, uchar8 b, ushort8 c);
-char16 __ovld __cnfn select(char16 a, char16 b, ushort16 c);
-uchar16 __ovld __cnfn select(uchar16 a, uchar16 b, ushort16 c);
+
short __ovld __cnfn select(short a, short b, ushort c);
ushort __ovld __cnfn select(ushort a, ushort b, ushort c);
short2 __ovld __cnfn select(short2 a, short2 b, ushort2 c);
@@ -11676,60 +11467,7 @@ short8 __ovld __cnfn select(short8 a, short8 b, ushort8 c);
ushort8 __ovld __cnfn select(ushort8 a, ushort8 b, ushort8 c);
short16 __ovld __cnfn select(short16 a, short16 b, ushort16 c);
ushort16 __ovld __cnfn select(ushort16 a, ushort16 b, ushort16 c);
-int __ovld __cnfn select(int a, int b, ushort c);
-uint __ovld __cnfn select(uint a, uint b, ushort c);
-int2 __ovld __cnfn select(int2 a, int2 b, ushort2 c);
-uint2 __ovld __cnfn select(uint2 a, uint2 b, ushort2 c);
-int3 __ovld __cnfn select(int3 a, int3 b, ushort3 c);
-uint3 __ovld __cnfn select(uint3 a, uint3 b, ushort3 c);
-int4 __ovld __cnfn select(int4 a, int4 b, ushort4 c);
-uint4 __ovld __cnfn select(uint4 a, uint4 b, ushort4 c);
-int8 __ovld __cnfn select(int8 a, int8 b, ushort8 c);
-uint8 __ovld __cnfn select(uint8 a, uint8 b, ushort8 c);
-int16 __ovld __cnfn select(int16 a, int16 b, ushort16 c);
-uint16 __ovld __cnfn select(uint16 a, uint16 b, ushort16 c);
-long __ovld __cnfn select(long a, long b, ushort c);
-ulong __ovld __cnfn select(ulong a, ulong b, ushort c);
-long2 __ovld __cnfn select(long2 a, long2 b, ushort2 c);
-ulong2 __ovld __cnfn select(ulong2 a, ulong2 b, ushort2 c);
-long3 __ovld __cnfn select(long3 a, long3 b, ushort3 c);
-ulong3 __ovld __cnfn select(ulong3 a, ulong3 b, ushort3 c);
-long4 __ovld __cnfn select(long4 a, long4 b, ushort4 c);
-ulong4 __ovld __cnfn select(ulong4 a, ulong4 b, ushort4 c);
-long8 __ovld __cnfn select(long8 a, long8 b, ushort8 c);
-ulong8 __ovld __cnfn select(ulong8 a, ulong8 b, ushort8 c);
-long16 __ovld __cnfn select(long16 a, long16 b, ushort16 c);
-ulong16 __ovld __cnfn select(ulong16 a, ulong16 b, ushort16 c);
-float __ovld __cnfn select(float a, float b, ushort c);
-float2 __ovld __cnfn select(float2 a, float2 b, ushort2 c);
-float3 __ovld __cnfn select(float3 a, float3 b, ushort3 c);
-float4 __ovld __cnfn select(float4 a, float4 b, ushort4 c);
-float8 __ovld __cnfn select(float8 a, float8 b, ushort8 c);
-float16 __ovld __cnfn select(float16 a, float16 b, ushort16 c);
-char __ovld __cnfn select(char a, char b, uint c);
-uchar __ovld __cnfn select(uchar a, uchar b, uint c);
-char2 __ovld __cnfn select(char2 a, char2 b, uint2 c);
-uchar2 __ovld __cnfn select(uchar2 a, uchar2 b, uint2 c);
-char3 __ovld __cnfn select(char3 a, char3 b, uint3 c);
-uchar3 __ovld __cnfn select(uchar3 a, uchar3 b, uint3 c);
-char4 __ovld __cnfn select(char4 a, char4 b, uint4 c);
-uchar4 __ovld __cnfn select(uchar4 a, uchar4 b, uint4 c);
-char8 __ovld __cnfn select(char8 a, char8 b, uint8 c);
-uchar8 __ovld __cnfn select(uchar8 a, uchar8 b, uint8 c);
-char16 __ovld __cnfn select(char16 a, char16 b, uint16 c);
-uchar16 __ovld __cnfn select(uchar16 a, uchar16 b, uint16 c);
-short __ovld __cnfn select(short a, short b, uint c);
-ushort __ovld __cnfn select(ushort a, ushort b, uint c);
-short2 __ovld __cnfn select(short2 a, short2 b, uint2 c);
-ushort2 __ovld __cnfn select(ushort2 a, ushort2 b, uint2 c);
-short3 __ovld __cnfn select(short3 a, short3 b, uint3 c);
-ushort3 __ovld __cnfn select(ushort3 a, ushort3 b, uint3 c);
-short4 __ovld __cnfn select(short4 a, short4 b, uint4 c);
-ushort4 __ovld __cnfn select(ushort4 a, ushort4 b, uint4 c);
-short8 __ovld __cnfn select(short8 a, short8 b, uint8 c);
-ushort8 __ovld __cnfn select(ushort8 a, ushort8 b, uint8 c);
-short16 __ovld __cnfn select(short16 a, short16 b, uint16 c);
-ushort16 __ovld __cnfn select(ushort16 a, ushort16 b, uint16 c);
+
int __ovld __cnfn select(int a, int b, uint c);
uint __ovld __cnfn select(uint a, uint b, uint c);
int2 __ovld __cnfn select(int2 a, int2 b, uint2 c);
@@ -11742,60 +11480,13 @@ int8 __ovld __cnfn select(int8 a, int8 b, uint8 c);
uint8 __ovld __cnfn select(uint8 a, uint8 b, uint8 c);
int16 __ovld __cnfn select(int16 a, int16 b, uint16 c);
uint16 __ovld __cnfn select(uint16 a, uint16 b, uint16 c);
-long __ovld __cnfn select(long a, long b, uint c);
-ulong __ovld __cnfn select(ulong a, ulong b, uint c);
-long2 __ovld __cnfn select(long2 a, long2 b, uint2 c);
-ulong2 __ovld __cnfn select(ulong2 a, ulong2 b, uint2 c);
-long3 __ovld __cnfn select(long3 a, long3 b, uint3 c);
-ulong3 __ovld __cnfn select(ulong3 a, ulong3 b, uint3 c);
-long4 __ovld __cnfn select(long4 a, long4 b, uint4 c);
-ulong4 __ovld __cnfn select(ulong4 a, ulong4 b, uint4 c);
-long8 __ovld __cnfn select(long8 a, long8 b, uint8 c);
-ulong8 __ovld __cnfn select(ulong8 a, ulong8 b, uint8 c);
-long16 __ovld __cnfn select(long16 a, long16 b, uint16 c);
-ulong16 __ovld __cnfn select(ulong16 a, ulong16 b, uint16 c);
float __ovld __cnfn select(float a, float b, uint c);
float2 __ovld __cnfn select(float2 a, float2 b, uint2 c);
float3 __ovld __cnfn select(float3 a, float3 b, uint3 c);
float4 __ovld __cnfn select(float4 a, float4 b, uint4 c);
float8 __ovld __cnfn select(float8 a, float8 b, uint8 c);
float16 __ovld __cnfn select(float16 a, float16 b, uint16 c);
-char __ovld __cnfn select(char a, char b, ulong c);
-uchar __ovld __cnfn select(uchar a, uchar b, ulong c);
-char2 __ovld __cnfn select(char2 a, char2 b, ulong2 c);
-uchar2 __ovld __cnfn select(uchar2 a, uchar2 b, ulong2 c);
-char3 __ovld __cnfn select(char3 a, char3 b, ulong3 c);
-uchar3 __ovld __cnfn select(uchar3 a, uchar3 b, ulong3 c);
-char4 __ovld __cnfn select(char4 a, char4 b, ulong4 c);
-uchar4 __ovld __cnfn select(uchar4 a, uchar4 b, ulong4 c);
-char8 __ovld __cnfn select(char8 a, char8 b, ulong8 c);
-uchar8 __ovld __cnfn select(uchar8 a, uchar8 b, ulong8 c);
-char16 __ovld __cnfn select(char16 a, char16 b, ulong16 c);
-uchar16 __ovld __cnfn select(uchar16 a, uchar16 b, ulong16 c);
-short __ovld __cnfn select(short a, short b, ulong c);
-ushort __ovld __cnfn select(ushort a, ushort b, ulong c);
-short2 __ovld __cnfn select(short2 a, short2 b, ulong2 c);
-ushort2 __ovld __cnfn select(ushort2 a, ushort2 b, ulong2 c);
-short3 __ovld __cnfn select(short3 a, short3 b, ulong3 c);
-ushort3 __ovld __cnfn select(ushort3 a, ushort3 b, ulong3 c);
-short4 __ovld __cnfn select(short4 a, short4 b, ulong4 c);
-ushort4 __ovld __cnfn select(ushort4 a, ushort4 b, ulong4 c);
-short8 __ovld __cnfn select(short8 a, short8 b, ulong8 c);
-ushort8 __ovld __cnfn select(ushort8 a, ushort8 b, ulong8 c);
-short16 __ovld __cnfn select(short16 a, short16 b, ulong16 c);
-ushort16 __ovld __cnfn select(ushort16 a, ushort16 b, ulong16 c);
-int __ovld __cnfn select(int a, int b, ulong c);
-uint __ovld __cnfn select(uint a, uint b, ulong c);
-int2 __ovld __cnfn select(int2 a, int2 b, ulong2 c);
-uint2 __ovld __cnfn select(uint2 a, uint2 b, ulong2 c);
-int3 __ovld __cnfn select(int3 a, int3 b, ulong3 c);
-uint3 __ovld __cnfn select(uint3 a, uint3 b, ulong3 c);
-int4 __ovld __cnfn select(int4 a, int4 b, ulong4 c);
-uint4 __ovld __cnfn select(uint4 a, uint4 b, ulong4 c);
-int8 __ovld __cnfn select(int8 a, int8 b, ulong8 c);
-uint8 __ovld __cnfn select(uint8 a, uint8 b, ulong8 c);
-int16 __ovld __cnfn select(int16 a, int16 b, ulong16 c);
-uint16 __ovld __cnfn select(uint16 a, uint16 b, ulong16 c);
+
long __ovld __cnfn select(long a, long b, ulong c);
ulong __ovld __cnfn select(ulong a, ulong b, ulong c);
long2 __ovld __cnfn select(long2 a, long2 b, ulong2 c);
@@ -11808,12 +11499,7 @@ long8 __ovld __cnfn select(long8 a, long8 b, ulong8 c);
ulong8 __ovld __cnfn select(ulong8 a, ulong8 b, ulong8 c);
long16 __ovld __cnfn select(long16 a, long16 b, ulong16 c);
ulong16 __ovld __cnfn select(ulong16 a, ulong16 b, ulong16 c);
-float __ovld __cnfn select(float a, float b, ulong c);
-float2 __ovld __cnfn select(float2 a, float2 b, ulong2 c);
-float3 __ovld __cnfn select(float3 a, float3 b, ulong3 c);
-float4 __ovld __cnfn select(float4 a, float4 b, ulong4 c);
-float8 __ovld __cnfn select(float8 a, float8 b, ulong8 c);
-float16 __ovld __cnfn select(float16 a, float16 b, ulong16 c);
+
#ifdef cl_khr_fp64
double __ovld __cnfn select(double a, double b, long c);
double2 __ovld __cnfn select(double2 a, double2 b, long2 c);
@@ -13141,13 +12827,14 @@ void __ovld __conv barrier(cl_mem_fence_flags flags);
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
-typedef enum memory_scope
-{
- memory_scope_work_item,
- memory_scope_work_group,
- memory_scope_device,
- memory_scope_all_svm_devices,
- memory_scope_sub_group
+typedef enum memory_scope {
+ memory_scope_work_item = __OPENCL_MEMORY_SCOPE_WORK_ITEM,
+ memory_scope_work_group = __OPENCL_MEMORY_SCOPE_WORK_GROUP,
+ memory_scope_device = __OPENCL_MEMORY_SCOPE_DEVICE,
+ memory_scope_all_svm_devices = __OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES,
+#if defined(cl_intel_subgroups) || defined(cl_khr_subgroups)
+ memory_scope_sub_group = __OPENCL_MEMORY_SCOPE_SUB_GROUP
+#endif
} memory_scope;
void __ovld __conv work_group_barrier(cl_mem_fence_flags flags, memory_scope scope);
@@ -13952,11 +13639,11 @@ unsigned long __ovld atom_xor(volatile __local unsigned long *p, unsigned long v
// enum values aligned with what clang uses in EmitAtomicExpr()
typedef enum memory_order
{
- memory_order_relaxed,
- memory_order_acquire,
- memory_order_release,
- memory_order_acq_rel,
- memory_order_seq_cst
+ memory_order_relaxed = __ATOMIC_RELAXED,
+ memory_order_acquire = __ATOMIC_ACQUIRE,
+ memory_order_release = __ATOMIC_RELEASE,
+ memory_order_acq_rel = __ATOMIC_ACQ_REL,
+ memory_order_seq_cst = __ATOMIC_SEQ_CST
} memory_order;
// double atomics support requires extensions cl_khr_int64_base_atomics and cl_khr_int64_extended_atomics
@@ -16199,6 +15886,313 @@ double __ovld __conv sub_group_scan_inclusive_max(double x);
#endif //cl_khr_subgroups cl_intel_subgroups
+#if defined(cl_intel_subgroups)
+// Intel-Specific Sub Group Functions
+float __ovld __conv intel_sub_group_shuffle( float x, uint c );
+float2 __ovld __conv intel_sub_group_shuffle( float2 x, uint c );
+float3 __ovld __conv intel_sub_group_shuffle( float3 x, uint c );
+float4 __ovld __conv intel_sub_group_shuffle( float4 x, uint c );
+float8 __ovld __conv intel_sub_group_shuffle( float8 x, uint c );
+float16 __ovld __conv intel_sub_group_shuffle( float16 x, uint c );
+
+int __ovld __conv intel_sub_group_shuffle( int x, uint c );
+int2 __ovld __conv intel_sub_group_shuffle( int2 x, uint c );
+int3 __ovld __conv intel_sub_group_shuffle( int3 x, uint c );
+int4 __ovld __conv intel_sub_group_shuffle( int4 x, uint c );
+int8 __ovld __conv intel_sub_group_shuffle( int8 x, uint c );
+int16 __ovld __conv intel_sub_group_shuffle( int16 x, uint c );
+
+uint __ovld __conv intel_sub_group_shuffle( uint x, uint c );
+uint2 __ovld __conv intel_sub_group_shuffle( uint2 x, uint c );
+uint3 __ovld __conv intel_sub_group_shuffle( uint3 x, uint c );
+uint4 __ovld __conv intel_sub_group_shuffle( uint4 x, uint c );
+uint8 __ovld __conv intel_sub_group_shuffle( uint8 x, uint c );
+uint16 __ovld __conv intel_sub_group_shuffle( uint16 x, uint c );
+
+long __ovld __conv intel_sub_group_shuffle( long x, uint c );
+ulong __ovld __conv intel_sub_group_shuffle( ulong x, uint c );
+
+float __ovld __conv intel_sub_group_shuffle_down( float cur, float next, uint c );
+float2 __ovld __conv intel_sub_group_shuffle_down( float2 cur, float2 next, uint c );
+float3 __ovld __conv intel_sub_group_shuffle_down( float3 cur, float3 next, uint c );
+float4 __ovld __conv intel_sub_group_shuffle_down( float4 cur, float4 next, uint c );
+float8 __ovld __conv intel_sub_group_shuffle_down( float8 cur, float8 next, uint c );
+float16 __ovld __conv intel_sub_group_shuffle_down( float16 cur, float16 next, uint c );
+
+int __ovld __conv intel_sub_group_shuffle_down( int cur, int next, uint c );
+int2 __ovld __conv intel_sub_group_shuffle_down( int2 cur, int2 next, uint c );
+int3 __ovld __conv intel_sub_group_shuffle_down( int3 cur, int3 next, uint c );
+int4 __ovld __conv intel_sub_group_shuffle_down( int4 cur, int4 next, uint c );
+int8 __ovld __conv intel_sub_group_shuffle_down( int8 cur, int8 next, uint c );
+int16 __ovld __conv intel_sub_group_shuffle_down( int16 cur, int16 next, uint c );
+
+uint __ovld __conv intel_sub_group_shuffle_down( uint cur, uint next, uint c );
+uint2 __ovld __conv intel_sub_group_shuffle_down( uint2 cur, uint2 next, uint c );
+uint3 __ovld __conv intel_sub_group_shuffle_down( uint3 cur, uint3 next, uint c );
+uint4 __ovld __conv intel_sub_group_shuffle_down( uint4 cur, uint4 next, uint c );
+uint8 __ovld __conv intel_sub_group_shuffle_down( uint8 cur, uint8 next, uint c );
+uint16 __ovld __conv intel_sub_group_shuffle_down( uint16 cur, uint16 next, uint c );
+
+long __ovld __conv intel_sub_group_shuffle_down( long prev, long cur, uint c );
+ulong __ovld __conv intel_sub_group_shuffle_down( ulong prev, ulong cur, uint c );
+
+float __ovld __conv intel_sub_group_shuffle_up( float prev, float cur, uint c );
+float2 __ovld __conv intel_sub_group_shuffle_up( float2 prev, float2 cur, uint c );
+float3 __ovld __conv intel_sub_group_shuffle_up( float3 prev, float3 cur, uint c );
+float4 __ovld __conv intel_sub_group_shuffle_up( float4 prev, float4 cur, uint c );
+float8 __ovld __conv intel_sub_group_shuffle_up( float8 prev, float8 cur, uint c );
+float16 __ovld __conv intel_sub_group_shuffle_up( float16 prev, float16 cur, uint c );
+
+int __ovld __conv intel_sub_group_shuffle_up( int prev, int cur, uint c );
+int2 __ovld __conv intel_sub_group_shuffle_up( int2 prev, int2 cur, uint c );
+int3 __ovld __conv intel_sub_group_shuffle_up( int3 prev, int3 cur, uint c );
+int4 __ovld __conv intel_sub_group_shuffle_up( int4 prev, int4 cur, uint c );
+int8 __ovld __conv intel_sub_group_shuffle_up( int8 prev, int8 cur, uint c );
+int16 __ovld __conv intel_sub_group_shuffle_up( int16 prev, int16 cur, uint c );
+
+uint __ovld __conv intel_sub_group_shuffle_up( uint prev, uint cur, uint c );
+uint2 __ovld __conv intel_sub_group_shuffle_up( uint2 prev, uint2 cur, uint c );
+uint3 __ovld __conv intel_sub_group_shuffle_up( uint3 prev, uint3 cur, uint c );
+uint4 __ovld __conv intel_sub_group_shuffle_up( uint4 prev, uint4 cur, uint c );
+uint8 __ovld __conv intel_sub_group_shuffle_up( uint8 prev, uint8 cur, uint c );
+uint16 __ovld __conv intel_sub_group_shuffle_up( uint16 prev, uint16 cur, uint c );
+
+long __ovld __conv intel_sub_group_shuffle_up( long prev, long cur, uint c );
+ulong __ovld __conv intel_sub_group_shuffle_up( ulong prev, ulong cur, uint c );
+
+float __ovld __conv intel_sub_group_shuffle_xor( float x, uint c );
+float2 __ovld __conv intel_sub_group_shuffle_xor( float2 x, uint c );
+float3 __ovld __conv intel_sub_group_shuffle_xor( float3 x, uint c );
+float4 __ovld __conv intel_sub_group_shuffle_xor( float4 x, uint c );
+float8 __ovld __conv intel_sub_group_shuffle_xor( float8 x, uint c );
+float16 __ovld __conv intel_sub_group_shuffle_xor( float16 x, uint c );
+
+int __ovld __conv intel_sub_group_shuffle_xor( int x, uint c );
+int2 __ovld __conv intel_sub_group_shuffle_xor( int2 x, uint c );
+int3 __ovld __conv intel_sub_group_shuffle_xor( int3 x, uint c );
+int4 __ovld __conv intel_sub_group_shuffle_xor( int4 x, uint c );
+int8 __ovld __conv intel_sub_group_shuffle_xor( int8 x, uint c );
+int16 __ovld __conv intel_sub_group_shuffle_xor( int16 x, uint c );
+
+uint __ovld __conv intel_sub_group_shuffle_xor( uint x, uint c );
+uint2 __ovld __conv intel_sub_group_shuffle_xor( uint2 x, uint c );
+uint3 __ovld __conv intel_sub_group_shuffle_xor( uint3 x, uint c );
+uint4 __ovld __conv intel_sub_group_shuffle_xor( uint4 x, uint c );
+uint8 __ovld __conv intel_sub_group_shuffle_xor( uint8 x, uint c );
+uint16 __ovld __conv intel_sub_group_shuffle_xor( uint16 x, uint c );
+
+long __ovld __conv intel_sub_group_shuffle_xor( long x, uint c );
+ulong __ovld __conv intel_sub_group_shuffle_xor( ulong x, uint c );
+
+uint __ovld __conv intel_sub_group_block_read( read_only image2d_t image, int2 coord );
+uint2 __ovld __conv intel_sub_group_block_read2( read_only image2d_t image, int2 coord );
+uint4 __ovld __conv intel_sub_group_block_read4( read_only image2d_t image, int2 coord );
+uint8 __ovld __conv intel_sub_group_block_read8( read_only image2d_t image, int2 coord );
+
+#if (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+uint __ovld __conv intel_sub_group_block_read(read_write image2d_t image, int2 coord);
+uint2 __ovld __conv intel_sub_group_block_read2(read_write image2d_t image, int2 coord);
+uint4 __ovld __conv intel_sub_group_block_read4(read_write image2d_t image, int2 coord);
+uint8 __ovld __conv intel_sub_group_block_read8(read_write image2d_t image, int2 coord);
+#endif // (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+
+uint __ovld __conv intel_sub_group_block_read( const __global uint* p );
+uint2 __ovld __conv intel_sub_group_block_read2( const __global uint* p );
+uint4 __ovld __conv intel_sub_group_block_read4( const __global uint* p );
+uint8 __ovld __conv intel_sub_group_block_read8( const __global uint* p );
+
+void __ovld __conv intel_sub_group_block_write(write_only image2d_t image, int2 coord, uint data);
+void __ovld __conv intel_sub_group_block_write2(write_only image2d_t image, int2 coord, uint2 data);
+void __ovld __conv intel_sub_group_block_write4(write_only image2d_t image, int2 coord, uint4 data);
+void __ovld __conv intel_sub_group_block_write8(write_only image2d_t image, int2 coord, uint8 data);
+
+#if (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+void __ovld __conv intel_sub_group_block_write(read_write image2d_t image, int2 coord, uint data);
+void __ovld __conv intel_sub_group_block_write2(read_write image2d_t image, int2 coord, uint2 data);
+void __ovld __conv intel_sub_group_block_write4(read_write image2d_t image, int2 coord, uint4 data);
+void __ovld __conv intel_sub_group_block_write8(read_write image2d_t image, int2 coord, uint8 data);
+#endif // (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+
+void __ovld __conv intel_sub_group_block_write( __global uint* p, uint data );
+void __ovld __conv intel_sub_group_block_write2( __global uint* p, uint2 data );
+void __ovld __conv intel_sub_group_block_write4( __global uint* p, uint4 data );
+void __ovld __conv intel_sub_group_block_write8( __global uint* p, uint8 data );
+
+#ifdef cl_khr_fp16
+half __ovld __conv intel_sub_group_shuffle( half x, uint c );
+half __ovld __conv intel_sub_group_shuffle_down( half prev, half cur, uint c );
+half __ovld __conv intel_sub_group_shuffle_up( half prev, half cur, uint c );
+half __ovld __conv intel_sub_group_shuffle_xor( half x, uint c );
+#endif
+
+#if defined(cl_khr_fp64)
+double __ovld __conv intel_sub_group_shuffle( double x, uint c );
+double __ovld __conv intel_sub_group_shuffle_down( double prev, double cur, uint c );
+double __ovld __conv intel_sub_group_shuffle_up( double prev, double cur, uint c );
+double __ovld __conv intel_sub_group_shuffle_xor( double x, uint c );
+#endif
+
+#endif //cl_intel_subgroups
+
+#if defined(cl_intel_subgroups_short)
+short __ovld __conv intel_sub_group_broadcast( short x, uint sub_group_local_id );
+short2 __ovld __conv intel_sub_group_broadcast( short2 x, uint sub_group_local_id );
+short3 __ovld __conv intel_sub_group_broadcast( short3 x, uint sub_group_local_id );
+short4 __ovld __conv intel_sub_group_broadcast( short4 x, uint sub_group_local_id );
+short8 __ovld __conv intel_sub_group_broadcast( short8 x, uint sub_group_local_id );
+
+ushort __ovld __conv intel_sub_group_broadcast( ushort x, uint sub_group_local_id );
+ushort2 __ovld __conv intel_sub_group_broadcast( ushort2 x, uint sub_group_local_id );
+ushort3 __ovld __conv intel_sub_group_broadcast( ushort3 x, uint sub_group_local_id );
+ushort4 __ovld __conv intel_sub_group_broadcast( ushort4 x, uint sub_group_local_id );
+ushort8 __ovld __conv intel_sub_group_broadcast( ushort8 x, uint sub_group_local_id );
+
+short __ovld __conv intel_sub_group_shuffle( short x, uint c );
+short2 __ovld __conv intel_sub_group_shuffle( short2 x, uint c );
+short3 __ovld __conv intel_sub_group_shuffle( short3 x, uint c );
+short4 __ovld __conv intel_sub_group_shuffle( short4 x, uint c );
+short8 __ovld __conv intel_sub_group_shuffle( short8 x, uint c );
+short16 __ovld __conv intel_sub_group_shuffle( short16 x, uint c);
+
+ushort __ovld __conv intel_sub_group_shuffle( ushort x, uint c );
+ushort2 __ovld __conv intel_sub_group_shuffle( ushort2 x, uint c );
+ushort3 __ovld __conv intel_sub_group_shuffle( ushort3 x, uint c );
+ushort4 __ovld __conv intel_sub_group_shuffle( ushort4 x, uint c );
+ushort8 __ovld __conv intel_sub_group_shuffle( ushort8 x, uint c );
+ushort16 __ovld __conv intel_sub_group_shuffle( ushort16 x, uint c );
+
+short __ovld __conv intel_sub_group_shuffle_down( short cur, short next, uint c );
+short2 __ovld __conv intel_sub_group_shuffle_down( short2 cur, short2 next, uint c );
+short3 __ovld __conv intel_sub_group_shuffle_down( short3 cur, short3 next, uint c );
+short4 __ovld __conv intel_sub_group_shuffle_down( short4 cur, short4 next, uint c );
+short8 __ovld __conv intel_sub_group_shuffle_down( short8 cur, short8 next, uint c );
+short16 __ovld __conv intel_sub_group_shuffle_down( short16 cur, short16 next, uint c );
+
+ushort __ovld __conv intel_sub_group_shuffle_down( ushort cur, ushort next, uint c );
+ushort2 __ovld __conv intel_sub_group_shuffle_down( ushort2 cur, ushort2 next, uint c );
+ushort3 __ovld __conv intel_sub_group_shuffle_down( ushort3 cur, ushort3 next, uint c );
+ushort4 __ovld __conv intel_sub_group_shuffle_down( ushort4 cur, ushort4 next, uint c );
+ushort8 __ovld __conv intel_sub_group_shuffle_down( ushort8 cur, ushort8 next, uint c );
+ushort16 __ovld __conv intel_sub_group_shuffle_down( ushort16 cur, ushort16 next, uint c );
+
+short __ovld __conv intel_sub_group_shuffle_up( short cur, short next, uint c );
+short2 __ovld __conv intel_sub_group_shuffle_up( short2 cur, short2 next, uint c );
+short3 __ovld __conv intel_sub_group_shuffle_up( short3 cur, short3 next, uint c );
+short4 __ovld __conv intel_sub_group_shuffle_up( short4 cur, short4 next, uint c );
+short8 __ovld __conv intel_sub_group_shuffle_up( short8 cur, short8 next, uint c );
+short16 __ovld __conv intel_sub_group_shuffle_up( short16 cur, short16 next, uint c );
+
+ushort __ovld __conv intel_sub_group_shuffle_up( ushort cur, ushort next, uint c );
+ushort2 __ovld __conv intel_sub_group_shuffle_up( ushort2 cur, ushort2 next, uint c );
+ushort3 __ovld __conv intel_sub_group_shuffle_up( ushort3 cur, ushort3 next, uint c );
+ushort4 __ovld __conv intel_sub_group_shuffle_up( ushort4 cur, ushort4 next, uint c );
+ushort8 __ovld __conv intel_sub_group_shuffle_up( ushort8 cur, ushort8 next, uint c );
+ushort16 __ovld __conv intel_sub_group_shuffle_up( ushort16 cur, ushort16 next, uint c );
+
+short __ovld __conv intel_sub_group_shuffle_xor( short x, uint c );
+short2 __ovld __conv intel_sub_group_shuffle_xor( short2 x, uint c );
+short3 __ovld __conv intel_sub_group_shuffle_xor( short3 x, uint c );
+short4 __ovld __conv intel_sub_group_shuffle_xor( short4 x, uint c );
+short8 __ovld __conv intel_sub_group_shuffle_xor( short8 x, uint c );
+short16 __ovld __conv intel_sub_group_shuffle_xor( short16 x, uint c );
+
+ushort __ovld __conv intel_sub_group_shuffle_xor( ushort x, uint c );
+ushort2 __ovld __conv intel_sub_group_shuffle_xor( ushort2 x, uint c );
+ushort3 __ovld __conv intel_sub_group_shuffle_xor( ushort3 x, uint c );
+ushort4 __ovld __conv intel_sub_group_shuffle_xor( ushort4 x, uint c );
+ushort8 __ovld __conv intel_sub_group_shuffle_xor( ushort8 x, uint c );
+ushort16 __ovld __conv intel_sub_group_shuffle_xor( ushort16 x, uint c );
+
+short __ovld __conv intel_sub_group_reduce_add( short x );
+ushort __ovld __conv intel_sub_group_reduce_add( ushort x );
+short __ovld __conv intel_sub_group_reduce_min( short x );
+ushort __ovld __conv intel_sub_group_reduce_min( ushort x );
+short __ovld __conv intel_sub_group_reduce_max( short x );
+ushort __ovld __conv intel_sub_group_reduce_max( ushort x );
+
+short __ovld __conv intel_sub_group_scan_exclusive_add( short x );
+ushort __ovld __conv intel_sub_group_scan_exclusive_add( ushort x );
+short __ovld __conv intel_sub_group_scan_exclusive_min( short x );
+ushort __ovld __conv intel_sub_group_scan_exclusive_min( ushort x );
+short __ovld __conv intel_sub_group_scan_exclusive_max( short x );
+ushort __ovld __conv intel_sub_group_scan_exclusive_max( ushort x );
+
+short __ovld __conv intel_sub_group_scan_inclusive_add( short x );
+ushort __ovld __conv intel_sub_group_scan_inclusive_add( ushort x );
+short __ovld __conv intel_sub_group_scan_inclusive_min( short x );
+ushort __ovld __conv intel_sub_group_scan_inclusive_min( ushort x );
+short __ovld __conv intel_sub_group_scan_inclusive_max( short x );
+ushort __ovld __conv intel_sub_group_scan_inclusive_max( ushort x );
+
+uint __ovld __conv intel_sub_group_block_read_ui( read_only image2d_t image, int2 byte_coord );
+uint2 __ovld __conv intel_sub_group_block_read_ui2( read_only image2d_t image, int2 byte_coord );
+uint4 __ovld __conv intel_sub_group_block_read_ui4( read_only image2d_t image, int2 byte_coord );
+uint8 __ovld __conv intel_sub_group_block_read_ui8( read_only image2d_t image, int2 byte_coord );
+
+#if (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+uint __ovld __conv intel_sub_group_block_read_ui( read_write image2d_t image, int2 byte_coord );
+uint2 __ovld __conv intel_sub_group_block_read_ui2( read_write image2d_t image, int2 byte_coord );
+uint4 __ovld __conv intel_sub_group_block_read_ui4( read_write image2d_t image, int2 byte_coord );
+uint8 __ovld __conv intel_sub_group_block_read_ui8( read_write image2d_t image, int2 byte_coord );
+#endif // (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+
+uint __ovld __conv intel_sub_group_block_read_ui( const __global uint* p );
+uint2 __ovld __conv intel_sub_group_block_read_ui2( const __global uint* p );
+uint4 __ovld __conv intel_sub_group_block_read_ui4( const __global uint* p );
+uint8 __ovld __conv intel_sub_group_block_read_ui8( const __global uint* p );
+
+void __ovld __conv intel_sub_group_block_write_ui( read_only image2d_t image, int2 byte_coord, uint data );
+void __ovld __conv intel_sub_group_block_write_ui2( read_only image2d_t image, int2 byte_coord, uint2 data );
+void __ovld __conv intel_sub_group_block_write_ui4( read_only image2d_t image, int2 byte_coord, uint4 data );
+void __ovld __conv intel_sub_group_block_write_ui8( read_only image2d_t image, int2 byte_coord, uint8 data );
+
+#if (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+void __ovld __conv intel_sub_group_block_write_ui( read_write image2d_t image, int2 byte_coord, uint data );
+void __ovld __conv intel_sub_group_block_write_ui2( read_write image2d_t image, int2 byte_coord, uint2 data );
+void __ovld __conv intel_sub_group_block_write_ui4( read_write image2d_t image, int2 byte_coord, uint4 data );
+void __ovld __conv intel_sub_group_block_write_ui8( read_write image2d_t image, int2 byte_coord, uint8 data );
+#endif // (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+
+void __ovld __conv intel_sub_group_block_write_ui( __global uint* p, uint data );
+void __ovld __conv intel_sub_group_block_write_ui2( __global uint* p, uint2 data );
+void __ovld __conv intel_sub_group_block_write_ui4( __global uint* p, uint4 data );
+void __ovld __conv intel_sub_group_block_write_ui8( __global uint* p, uint8 data );
+
+ushort __ovld __conv intel_sub_group_block_read_us( read_only image2d_t image, int2 coord );
+ushort2 __ovld __conv intel_sub_group_block_read_us2( read_only image2d_t image, int2 coord );
+ushort4 __ovld __conv intel_sub_group_block_read_us4( read_only image2d_t image, int2 coord );
+ushort8 __ovld __conv intel_sub_group_block_read_us8( read_only image2d_t image, int2 coord );
+
+#if (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+ushort __ovld __conv intel_sub_group_block_read_us(read_write image2d_t image, int2 coord);
+ushort2 __ovld __conv intel_sub_group_block_read_us2(read_write image2d_t image, int2 coord);
+ushort4 __ovld __conv intel_sub_group_block_read_us4(read_write image2d_t image, int2 coord);
+ushort8 __ovld __conv intel_sub_group_block_read_us8(read_write image2d_t image, int2 coord);
+#endif // (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+
+ushort __ovld __conv intel_sub_group_block_read_us( const __global ushort* p );
+ushort2 __ovld __conv intel_sub_group_block_read_us2( const __global ushort* p );
+ushort4 __ovld __conv intel_sub_group_block_read_us4( const __global ushort* p );
+ushort8 __ovld __conv intel_sub_group_block_read_us8( const __global ushort* p );
+
+void __ovld __conv intel_sub_group_block_write_us(write_only image2d_t image, int2 coord, ushort data);
+void __ovld __conv intel_sub_group_block_write_us2(write_only image2d_t image, int2 coord, ushort2 data);
+void __ovld __conv intel_sub_group_block_write_us4(write_only image2d_t image, int2 coord, ushort4 data);
+void __ovld __conv intel_sub_group_block_write_us8(write_only image2d_t image, int2 coord, ushort8 data);
+
+#if (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+void __ovld __conv intel_sub_group_block_write_us(read_write image2d_t image, int2 coord, ushort data);
+void __ovld __conv intel_sub_group_block_write_us2(read_write image2d_t image, int2 coord, ushort2 data);
+void __ovld __conv intel_sub_group_block_write_us4(read_write image2d_t image, int2 coord, ushort4 data);
+void __ovld __conv intel_sub_group_block_write_us8(read_write image2d_t image, int2 coord, ushort8 data);
+#endif // (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+
+void __ovld __conv intel_sub_group_block_write_us( __global ushort* p, ushort data );
+void __ovld __conv intel_sub_group_block_write_us2( __global ushort* p, ushort2 data );
+void __ovld __conv intel_sub_group_block_write_us4( __global ushort* p, ushort4 data );
+void __ovld __conv intel_sub_group_block_write_us8( __global ushort* p, ushort8 data );
+#endif // cl_intel_subgroups_short
+
#ifdef cl_amd_media_ops
uint __ovld amd_bitalign(uint a, uint b, uint c);
uint2 __ovld amd_bitalign(uint2 a, uint2 b, uint2 c);
diff --git a/contrib/llvm/tools/clang/lib/Headers/stdbool.h b/contrib/llvm/tools/clang/lib/Headers/stdbool.h
index 0467893f3403f..5cb66b55d02ab 100644
--- a/contrib/llvm/tools/clang/lib/Headers/stdbool.h
+++ b/contrib/llvm/tools/clang/lib/Headers/stdbool.h
@@ -32,12 +32,15 @@
#define true 1
#define false 0
#elif defined(__GNUC__) && !defined(__STRICT_ANSI__)
-/* Define _Bool, bool, false, true as a GNU extension. */
+/* Define _Bool as a GNU extension. */
#define _Bool bool
+#if __cplusplus < 201103L
+/* For C++98, define bool, false, true as a GNU extension. */
#define bool bool
#define false false
#define true true
#endif
+#endif
#define __bool_true_false_are_defined 1
diff --git a/contrib/llvm/tools/clang/lib/Headers/unwind.h b/contrib/llvm/tools/clang/lib/Headers/unwind.h
index 4f74a3478740e..345fa4d0c1930 100644
--- a/contrib/llvm/tools/clang/lib/Headers/unwind.h
+++ b/contrib/llvm/tools/clang/lib/Headers/unwind.h
@@ -76,7 +76,13 @@ typedef intptr_t _sleb128_t;
typedef uintptr_t _uleb128_t;
struct _Unwind_Context;
+#if defined(__arm__) && !(defined(__USING_SJLJ_EXCEPTIONS__) || defined(__ARM_DWARF_EH__))
+struct _Unwind_Control_Block;
+typedef struct _Unwind_Control_Block _Unwind_Exception; /* Alias */
+#else
struct _Unwind_Exception;
+typedef struct _Unwind_Exception _Unwind_Exception;
+#endif
typedef enum {
_URC_NO_REASON = 0,
#if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \
@@ -109,8 +115,42 @@ typedef enum {
} _Unwind_Action;
typedef void (*_Unwind_Exception_Cleanup_Fn)(_Unwind_Reason_Code,
- struct _Unwind_Exception *);
+ _Unwind_Exception *);
+#if defined(__arm__) && !(defined(__USING_SJLJ_EXCEPTIONS__) || defined(__ARM_DWARF_EH__))
+typedef struct _Unwind_Control_Block _Unwind_Control_Block;
+typedef uint32_t _Unwind_EHT_Header;
+
+struct _Unwind_Control_Block {
+ uint64_t exception_class;
+ void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block *);
+ /* unwinder cache (private fields for the unwinder's use) */
+ struct {
+ uint32_t reserved1; /* forced unwind stop function, 0 if not forced */
+ uint32_t reserved2; /* personality routine */
+ uint32_t reserved3; /* callsite */
+ uint32_t reserved4; /* forced unwind stop argument */
+ uint32_t reserved5;
+ } unwinder_cache;
+ /* propagation barrier cache (valid after phase 1) */
+ struct {
+ uint32_t sp;
+ uint32_t bitpattern[5];
+ } barrier_cache;
+ /* cleanup cache (preserved over cleanup) */
+ struct {
+ uint32_t bitpattern[4];
+ } cleanup_cache;
+ /* personality cache (for personality's benefit) */
+ struct {
+ uint32_t fnstart; /* function start address */
+ _Unwind_EHT_Header *ehtp; /* pointer to EHT entry header word */
+ uint32_t additional; /* additional data */
+ uint32_t reserved1;
+ } pr_cache;
+ long long int : 0; /* force alignment of next item to 8-byte boundary */
+} __attribute__((__aligned__(8)));
+#else
struct _Unwind_Exception {
_Unwind_Exception_Class exception_class;
_Unwind_Exception_Cleanup_Fn exception_cleanup;
@@ -120,23 +160,24 @@ struct _Unwind_Exception {
* aligned". GCC has interpreted this to mean "use the maximum useful
* alignment for the target"; so do we. */
} __attribute__((__aligned__));
+#endif
typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)(int, _Unwind_Action,
_Unwind_Exception_Class,
- struct _Unwind_Exception *,
+ _Unwind_Exception *,
struct _Unwind_Context *,
void *);
-typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)(
- int, _Unwind_Action, _Unwind_Exception_Class, struct _Unwind_Exception *,
- struct _Unwind_Context *);
+typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)(int, _Unwind_Action,
+ _Unwind_Exception_Class,
+ _Unwind_Exception *,
+ struct _Unwind_Context *);
typedef _Unwind_Personality_Fn __personality_routine;
typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn)(struct _Unwind_Context *,
void *);
-#if defined(__arm__) && !defined(__APPLE__)
-
+#if defined(__arm__) && !(defined(__USING_SJLJ_EXCEPTIONS__) || defined(__ARM_DWARF_EH__))
typedef enum {
_UVRSC_CORE = 0, /* integer register */
_UVRSC_VFP = 1, /* vfp */
@@ -158,14 +199,12 @@ typedef enum {
_UVRSR_FAILED = 2
} _Unwind_VRS_Result;
-#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__ARM_DWARF_EH__)
typedef uint32_t _Unwind_State;
#define _US_VIRTUAL_UNWIND_FRAME ((_Unwind_State)0)
#define _US_UNWIND_FRAME_STARTING ((_Unwind_State)1)
#define _US_UNWIND_FRAME_RESUME ((_Unwind_State)2)
#define _US_ACTION_MASK ((_Unwind_State)3)
#define _US_FORCE_UNWIND ((_Unwind_State)8)
-#endif
_Unwind_VRS_Result _Unwind_VRS_Get(struct _Unwind_Context *__context,
_Unwind_VRS_RegClass __regclass,
@@ -224,13 +263,12 @@ _Unwind_Ptr _Unwind_GetRegionStart(struct _Unwind_Context *);
/* DWARF EH functions; currently not available on Darwin/ARM */
#if !defined(__APPLE__) || !defined(__arm__)
-
-_Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception *);
-_Unwind_Reason_Code _Unwind_ForcedUnwind(struct _Unwind_Exception *,
- _Unwind_Stop_Fn, void *);
-void _Unwind_DeleteException(struct _Unwind_Exception *);
-void _Unwind_Resume(struct _Unwind_Exception *);
-_Unwind_Reason_Code _Unwind_Resume_or_Rethrow(struct _Unwind_Exception *);
+_Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception *);
+_Unwind_Reason_Code _Unwind_ForcedUnwind(_Unwind_Exception *, _Unwind_Stop_Fn,
+ void *);
+void _Unwind_DeleteException(_Unwind_Exception *);
+void _Unwind_Resume(_Unwind_Exception *);
+_Unwind_Reason_Code _Unwind_Resume_or_Rethrow(_Unwind_Exception *);
#endif
@@ -241,11 +279,11 @@ typedef struct SjLj_Function_Context *_Unwind_FunctionContext_t;
void _Unwind_SjLj_Register(_Unwind_FunctionContext_t);
void _Unwind_SjLj_Unregister(_Unwind_FunctionContext_t);
-_Unwind_Reason_Code _Unwind_SjLj_RaiseException(struct _Unwind_Exception *);
-_Unwind_Reason_Code _Unwind_SjLj_ForcedUnwind(struct _Unwind_Exception *,
+_Unwind_Reason_Code _Unwind_SjLj_RaiseException(_Unwind_Exception *);
+_Unwind_Reason_Code _Unwind_SjLj_ForcedUnwind(_Unwind_Exception *,
_Unwind_Stop_Fn, void *);
-void _Unwind_SjLj_Resume(struct _Unwind_Exception *);
-_Unwind_Reason_Code _Unwind_SjLj_Resume_or_Rethrow(struct _Unwind_Exception *);
+void _Unwind_SjLj_Resume(_Unwind_Exception *);
+_Unwind_Reason_Code _Unwind_SjLj_Resume_or_Rethrow(_Unwind_Exception *);
void *_Unwind_FindEnclosingFunction(void *);
diff --git a/contrib/llvm/tools/clang/lib/Index/CodegenNameGenerator.cpp b/contrib/llvm/tools/clang/lib/Index/CodegenNameGenerator.cpp
index 92740b05703b5..bf52e2108baaf 100644
--- a/contrib/llvm/tools/clang/lib/Index/CodegenNameGenerator.cpp
+++ b/contrib/llvm/tools/clang/lib/Index/CodegenNameGenerator.cpp
@@ -68,7 +68,38 @@ struct CodegenNameGenerator::Implementation {
return Name;
}
+ enum ObjCKind {
+ ObjCClass,
+ ObjCMetaclass,
+ };
+
+ std::vector<std::string> getAllManglings(const ObjCContainerDecl *OCD) {
+ StringRef ClassName;
+ if (const auto *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
+ ClassName = OID->getObjCRuntimeNameAsString();
+ else if (const auto *OID = dyn_cast<ObjCImplementationDecl>(OCD))
+ ClassName = OID->getObjCRuntimeNameAsString();
+
+ if (ClassName.empty())
+ return {};
+
+ auto Mangle = [&](ObjCKind Kind, StringRef ClassName) -> std::string {
+ SmallString<40> Mangled;
+ auto Prefix = getClassSymbolPrefix(Kind, OCD->getASTContext());
+ llvm::Mangler::getNameWithPrefix(Mangled, Prefix + ClassName, DL);
+ return Mangled.str();
+ };
+
+ return {
+ Mangle(ObjCClass, ClassName),
+ Mangle(ObjCMetaclass, ClassName),
+ };
+ }
+
std::vector<std::string> getAllManglings(const Decl *D) {
+ if (const auto *OCD = dyn_cast<ObjCContainerDecl>(D))
+ return getAllManglings(OCD);
+
if (!(isa<CXXRecordDecl>(D) || isa<CXXMethodDecl>(D)))
return {};
@@ -135,12 +166,14 @@ private:
}
void writeObjCClassName(const ObjCInterfaceDecl *D, raw_ostream &OS) {
- OS << getClassSymbolPrefix();
+ OS << getClassSymbolPrefix(ObjCClass, D->getASTContext());
OS << D->getObjCRuntimeNameAsString();
}
- static StringRef getClassSymbolPrefix() {
- return "OBJC_CLASS_$_";
+ static StringRef getClassSymbolPrefix(ObjCKind Kind, const ASTContext &Context) {
+ if (Context.getLangOpts().ObjCRuntime.isGNUFamily())
+ return Kind == ObjCMetaclass ? "_OBJC_METACLASS_" : "_OBJC_CLASS_";
+ return Kind == ObjCMetaclass ? "OBJC_METACLASS_$_" : "OBJC_CLASS_$_";
}
std::string getMangledStructor(const NamedDecl *ND, unsigned StructorType) {
diff --git a/contrib/llvm/tools/clang/lib/Index/CommentToXML.cpp b/contrib/llvm/tools/clang/lib/Index/CommentToXML.cpp
index e568c838b7b0f..918068a2405f7 100644
--- a/contrib/llvm/tools/clang/lib/Index/CommentToXML.cpp
+++ b/contrib/llvm/tools/clang/lib/Index/CommentToXML.cpp
@@ -579,6 +579,7 @@ void getSourceTextOfDeclaration(const DeclInfo *ThisDecl,
PrintingPolicy PPolicy(LangOpts);
PPolicy.PolishForDeclaration = true;
PPolicy.TerseOutput = true;
+ PPolicy.ConstantsAsWritten = true;
ThisDecl->CurrentDecl->print(OS, PPolicy,
/*Indentation*/0, /*PrintInstantiation*/false);
}
diff --git a/contrib/llvm/tools/clang/lib/Index/IndexBody.cpp b/contrib/llvm/tools/clang/lib/Index/IndexBody.cpp
index 6bbd38102509f..ac34956b24840 100644
--- a/contrib/llvm/tools/clang/lib/Index/IndexBody.cpp
+++ b/contrib/llvm/tools/clang/lib/Index/IndexBody.cpp
@@ -427,6 +427,17 @@ public:
return true;
}
+
+ bool VisitOffsetOfExpr(OffsetOfExpr *S) {
+ for (unsigned I = 0, E = S->getNumComponents(); I != E; ++I) {
+ const OffsetOfNode &Component = S->getComponent(I);
+ if (Component.getKind() == OffsetOfNode::Field)
+ IndexCtx.handleReference(Component.getField(), Component.getLocEnd(),
+ Parent, ParentDC, SymbolRoleSet(), {});
+ // FIXME: Try to resolve dependent field references.
+ }
+ return true;
+ }
};
} // anonymous namespace
diff --git a/contrib/llvm/tools/clang/lib/Index/IndexDecl.cpp b/contrib/llvm/tools/clang/lib/Index/IndexDecl.cpp
index c5230c0f9acf8..e14750e046eb9 100644
--- a/contrib/llvm/tools/clang/lib/Index/IndexDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Index/IndexDecl.cpp
@@ -233,9 +233,8 @@ public:
if (auto *CXXMD = dyn_cast<CXXMethodDecl>(D)) {
if (CXXMD->isVirtual())
Roles |= (unsigned)SymbolRole::Dynamic;
- for (auto I = CXXMD->begin_overridden_methods(),
- E = CXXMD->end_overridden_methods(); I != E; ++I) {
- Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, *I);
+ for (const CXXMethodDecl *O : CXXMD->overridden_methods()) {
+ Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, O);
}
}
gatherTemplatePseudoOverrides(D, Relations);
@@ -267,6 +266,10 @@ public:
TypeNameInfo->getTypeLoc().getLocStart(),
Dtor->getParent(), Dtor->getDeclContext());
}
+ } else if (const auto *Guide = dyn_cast<CXXDeductionGuideDecl>(D)) {
+ IndexCtx.handleReference(Guide->getDeducedTemplate()->getTemplatedDecl(),
+ Guide->getLocation(), Guide,
+ Guide->getDeclContext());
}
// Template specialization arguments.
if (const ASTTemplateArgumentListInfo *TemplateArgInfo =
@@ -350,12 +353,10 @@ public:
gatherTemplatePseudoOverrides(D, Relations);
IndexCtx.indexTagDecl(D, Relations);
} else {
- auto *Parent = dyn_cast<NamedDecl>(D->getDeclContext());
SmallVector<SymbolRelation, 1> Relations;
gatherTemplatePseudoOverrides(D, Relations);
- return IndexCtx.handleReference(D, D->getLocation(), Parent,
- D->getLexicalDeclContext(),
- SymbolRoleSet(), Relations);
+ return IndexCtx.handleDecl(D, D->getLocation(), SymbolRoleSet(),
+ Relations, D->getLexicalDeclContext());
}
}
return true;
@@ -607,6 +608,24 @@ public:
SymbolRoleSet());
}
+ bool VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) {
+ TRY_DECL(D, IndexCtx.handleDecl(D));
+ const DeclContext *DC = D->getDeclContext()->getRedeclContext();
+ const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
+ IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
+ D->getLexicalDeclContext());
+ return true;
+ }
+
+ bool VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) {
+ TRY_DECL(D, IndexCtx.handleDecl(D));
+ const DeclContext *DC = D->getDeclContext()->getRedeclContext();
+ const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
+ IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
+ D->getLexicalDeclContext());
+ return true;
+ }
+
bool VisitClassTemplateSpecializationDecl(const
ClassTemplateSpecializationDecl *D) {
// FIXME: Notify subsequent callbacks if info comes from implicit
@@ -644,7 +663,6 @@ public:
}
bool VisitTemplateDecl(const TemplateDecl *D) {
- // FIXME: Template parameters.
// Index the default values for the template parameters.
const NamedDecl *Parent = D->getTemplatedDecl();
@@ -661,7 +679,7 @@ public:
} else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(TP)) {
if (TTPD->hasDefaultArgument())
handleTemplateArgumentLoc(TTPD->getDefaultArgument(), Parent,
- /*DC=*/nullptr);
+ TP->getLexicalDeclContext());
}
}
}
diff --git a/contrib/llvm/tools/clang/lib/Index/IndexSymbol.cpp b/contrib/llvm/tools/clang/lib/Index/IndexSymbol.cpp
index 0dc3720208caf..03db0cd53f7a5 100644
--- a/contrib/llvm/tools/clang/lib/Index/IndexSymbol.cpp
+++ b/contrib/llvm/tools/clang/lib/Index/IndexSymbol.cpp
@@ -201,25 +201,22 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
Info.Properties |= (unsigned)SymbolProperty::UnitTest;
break;
}
- case Decl::ObjCMethod:
- if (cast<ObjCMethodDecl>(D)->isInstanceMethod()) {
- const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(D);
- Info.Kind = SymbolKind::InstanceMethod;
- if (MD->isPropertyAccessor()) {
- if (MD->param_size())
- Info.SubKind = SymbolSubKind::AccessorSetter;
- else
- Info.SubKind = SymbolSubKind::AccessorGetter;
- }
- } else {
- Info.Kind = SymbolKind::ClassMethod;
+ case Decl::ObjCMethod: {
+ const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(D);
+ Info.Kind = MD->isInstanceMethod() ? SymbolKind::InstanceMethod : SymbolKind::ClassMethod;
+ if (MD->isPropertyAccessor()) {
+ if (MD->param_size())
+ Info.SubKind = SymbolSubKind::AccessorSetter;
+ else
+ Info.SubKind = SymbolSubKind::AccessorGetter;
}
Info.Lang = SymbolLanguage::ObjC;
- if (isUnitTest(cast<ObjCMethodDecl>(D)))
+ if (isUnitTest(MD))
Info.Properties |= (unsigned)SymbolProperty::UnitTest;
if (D->hasAttr<IBActionAttr>())
Info.Properties |= (unsigned)SymbolProperty::IBAnnotated;
break;
+ }
case Decl::ObjCProperty:
Info.Kind = SymbolKind::InstanceProperty;
Info.Lang = SymbolLanguage::ObjC;
@@ -303,6 +300,18 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
Info.Kind = SymbolKind::TypeAlias;
Info.Lang = SymbolLanguage::CXX;
break;
+ case Decl::UnresolvedUsingTypename:
+ Info.Kind = SymbolKind::Using;
+ Info.SubKind = SymbolSubKind::UsingTypename;
+ Info.Lang = SymbolLanguage::CXX;
+ Info.Properties |= (unsigned)SymbolProperty::Generic;
+ break;
+ case Decl::UnresolvedUsingValue:
+ Info.Kind = SymbolKind::Using;
+ Info.SubKind = SymbolSubKind::UsingValue;
+ Info.Lang = SymbolLanguage::CXX;
+ Info.Properties |= (unsigned)SymbolProperty::Generic;
+ break;
case Decl::Binding:
Info.Kind = SymbolKind::Variable;
Info.Lang = SymbolLanguage::CXX;
@@ -451,6 +460,7 @@ StringRef index::getSymbolKindString(SymbolKind K) {
case SymbolKind::Destructor: return "destructor";
case SymbolKind::ConversionFunction: return "coversion-func";
case SymbolKind::Parameter: return "param";
+ case SymbolKind::Using: return "using";
}
llvm_unreachable("invalid symbol kind");
}
@@ -462,6 +472,8 @@ StringRef index::getSymbolSubKindString(SymbolSubKind K) {
case SymbolSubKind::CXXMoveConstructor: return "cxx-move-ctor";
case SymbolSubKind::AccessorGetter: return "acc-get";
case SymbolSubKind::AccessorSetter: return "acc-set";
+ case SymbolSubKind::UsingTypename: return "using-typename";
+ case SymbolSubKind::UsingValue: return "using-value";
}
llvm_unreachable("invalid symbol subkind");
}
diff --git a/contrib/llvm/tools/clang/lib/Index/IndexTypeSourceInfo.cpp b/contrib/llvm/tools/clang/lib/Index/IndexTypeSourceInfo.cpp
index ae27ebe6ea4c0..c8ff3d72d4be1 100644
--- a/contrib/llvm/tools/clang/lib/Index/IndexTypeSourceInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/Index/IndexTypeSourceInfo.cpp
@@ -126,8 +126,9 @@ public:
return true;
}
- bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
- if (const TemplateSpecializationType *T = TL.getTypePtr()) {
+ template<typename TypeLocType>
+ bool HandleTemplateSpecializationTypeLoc(TypeLocType TL) {
+ if (const auto *T = TL.getTypePtr()) {
if (IndexCtx.shouldIndexImplicitTemplateInsts()) {
if (CXXRecordDecl *RD = T->getAsCXXRecordDecl())
IndexCtx.handleReference(RD, TL.getTemplateNameLoc(),
@@ -141,6 +142,14 @@ public:
return true;
}
+ bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
+ return HandleTemplateSpecializationTypeLoc(TL);
+ }
+
+ bool VisitDeducedTemplateSpecializationTypeLoc(DeducedTemplateSpecializationTypeLoc TL) {
+ return HandleTemplateSpecializationTypeLoc(TL);
+ }
+
bool VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
const DependentNameType *DNT = TL.getTypePtr();
const NestedNameSpecifier *NNS = DNT->getQualifier();
diff --git a/contrib/llvm/tools/clang/lib/Index/IndexingAction.cpp b/contrib/llvm/tools/clang/lib/Index/IndexingAction.cpp
index 84d31200bab43..411657bf3dcdd 100644
--- a/contrib/llvm/tools/clang/lib/Index/IndexingAction.cpp
+++ b/contrib/llvm/tools/clang/lib/Index/IndexingAction.cpp
@@ -8,10 +8,11 @@
//===----------------------------------------------------------------------===//
#include "clang/Index/IndexingAction.h"
-#include "clang/Index/IndexDataConsumer.h"
#include "IndexingContext.h"
+#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/MultiplexConsumer.h"
+#include "clang/Index/IndexDataConsumer.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Serialization/ASTReader.h"
@@ -42,16 +43,18 @@ bool IndexDataConsumer::handleModuleOccurence(const ImportDecl *ImportD,
namespace {
class IndexASTConsumer : public ASTConsumer {
+ std::shared_ptr<Preprocessor> PP;
IndexingContext &IndexCtx;
public:
- IndexASTConsumer(IndexingContext &IndexCtx)
- : IndexCtx(IndexCtx) {}
+ IndexASTConsumer(std::shared_ptr<Preprocessor> PP, IndexingContext &IndexCtx)
+ : PP(std::move(PP)), IndexCtx(IndexCtx) {}
protected:
void Initialize(ASTContext &Context) override {
IndexCtx.setASTContext(Context);
IndexCtx.getDataConsumer().initialize(Context);
+ IndexCtx.getDataConsumer().setPreprocessor(PP);
}
bool HandleTopLevelDecl(DeclGroupRef DG) override {
@@ -80,8 +83,10 @@ protected:
: DataConsumer(std::move(dataConsumer)),
IndexCtx(Opts, *DataConsumer) {}
- std::unique_ptr<IndexASTConsumer> createIndexASTConsumer() {
- return llvm::make_unique<IndexASTConsumer>(IndexCtx);
+ std::unique_ptr<IndexASTConsumer>
+ createIndexASTConsumer(CompilerInstance &CI) {
+ return llvm::make_unique<IndexASTConsumer>(CI.getPreprocessorPtr(),
+ IndexCtx);
}
void finish() {
@@ -98,7 +103,7 @@ public:
protected:
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) override {
- return createIndexASTConsumer();
+ return createIndexASTConsumer(CI);
}
void EndSourceFileAction() override {
@@ -142,7 +147,7 @@ WrappingIndexAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
std::vector<std::unique_ptr<ASTConsumer>> Consumers;
Consumers.push_back(std::move(OtherConsumer));
- Consumers.push_back(createIndexASTConsumer());
+ Consumers.push_back(createIndexASTConsumer(CI));
return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
}
@@ -173,6 +178,7 @@ void index::indexASTUnit(ASTUnit &Unit,
IndexingContext IndexCtx(Opts, *DataConsumer);
IndexCtx.setASTContext(Unit.getASTContext());
DataConsumer->initialize(Unit.getASTContext());
+ DataConsumer->setPreprocessor(Unit.getPreprocessorPtr());
indexTranslationUnit(Unit, IndexCtx);
DataConsumer->finish();
}
@@ -198,7 +204,7 @@ void index::indexModuleFile(serialization::ModuleFile &Mod,
IndexCtx.setASTContext(Ctx);
DataConsumer->initialize(Ctx);
- for (const Decl *D :Reader.getModuleFileLevelDecls(Mod)) {
+ for (const Decl *D : Reader.getModuleFileLevelDecls(Mod)) {
IndexCtx.indexTopLevelDecl(D);
}
DataConsumer->finish();
diff --git a/contrib/llvm/tools/clang/lib/Index/IndexingContext.cpp b/contrib/llvm/tools/clang/lib/Index/IndexingContext.cpp
index addee691e8046..de9fe39df0310 100644
--- a/contrib/llvm/tools/clang/lib/Index/IndexingContext.cpp
+++ b/contrib/llvm/tools/clang/lib/Index/IndexingContext.cpp
@@ -231,8 +231,8 @@ static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, AST
/// Whether the given NamedDecl should be skipped because it has no name.
static bool shouldSkipNamelessDecl(const NamedDecl *ND) {
- return ND->getDeclName().isEmpty() && !isa<TagDecl>(ND) &&
- !isa<ObjCCategoryDecl>(ND);
+ return (ND->getDeclName().isEmpty() && !isa<TagDecl>(ND) &&
+ !isa<ObjCCategoryDecl>(ND)) || isa<CXXDeductionGuideDecl>(ND);
}
static const Decl *adjustParent(const Decl *Parent) {
diff --git a/contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp b/contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp
index 21054b099a8e7..3a06554b256c6 100644
--- a/contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp
+++ b/contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp
@@ -99,6 +99,8 @@ public:
void VisitVarDecl(const VarDecl *D);
void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D);
void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D);
+ void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D);
+ void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D);
void VisitLinkageSpecDecl(const LinkageSpecDecl *D) {
IgnoreResults = true;
@@ -112,14 +114,6 @@ public:
IgnoreResults = true;
}
- void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) {
- IgnoreResults = true;
- }
-
- void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) {
- IgnoreResults = true;
- }
-
bool ShouldGenerateLocation(const NamedDecl *D);
bool isLocal(const NamedDecl *D) {
@@ -609,6 +603,16 @@ bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) {
return IgnoreResults;
}
+static void printQualifier(llvm::raw_ostream &Out, ASTContext &Ctx, NestedNameSpecifier *NNS) {
+ // FIXME: Encode the qualifier, don't just print it.
+ PrintingPolicy PO(Ctx.getLangOpts());
+ PO.SuppressTagKeyword = true;
+ PO.SuppressUnwrittenScope = true;
+ PO.ConstantArraySizeAsWritten = false;
+ PO.AnonymousTagLocations = false;
+ NNS->print(Out, PO);
+}
+
void USRGenerator::VisitType(QualType T) {
// This method mangles in USR information for types. It can possibly
// just reuse the naming-mangling logic used by codegen, although the
@@ -676,6 +680,7 @@ void USRGenerator::VisitType(QualType T) {
c = 'K'; break;
case BuiltinType::Int128:
c = 'J'; break;
+ case BuiltinType::Float16:
case BuiltinType::Half:
c = 'h'; break;
case BuiltinType::Float:
@@ -749,8 +754,12 @@ void USRGenerator::VisitType(QualType T) {
if (const FunctionProtoType *FT = T->getAs<FunctionProtoType>()) {
Out << 'F';
VisitType(FT->getReturnType());
- for (const auto &I : FT->param_types())
+ Out << '(';
+ for (const auto &I : FT->param_types()) {
+ Out << '#';
VisitType(I);
+ }
+ Out << ')';
if (FT->isVariadic())
Out << '.';
return;
@@ -797,13 +806,7 @@ void USRGenerator::VisitType(QualType T) {
}
if (const DependentNameType *DNT = T->getAs<DependentNameType>()) {
Out << '^';
- // FIXME: Encode the qualifier, don't just print it.
- PrintingPolicy PO(Ctx.getLangOpts());
- PO.SuppressTagKeyword = true;
- PO.SuppressUnwrittenScope = true;
- PO.ConstantArraySizeAsWritten = false;
- PO.AnonymousTagLocations = false;
- DNT->getQualifier()->print(Out, PO);
+ printQualifier(Out, Ctx, DNT->getQualifier());
Out << ':' << DNT->getIdentifier()->getName();
return;
}
@@ -817,6 +820,25 @@ void USRGenerator::VisitType(QualType T) {
T = VT->getElementType();
continue;
}
+ if (const auto *const AT = dyn_cast<ArrayType>(T)) {
+ Out << '{';
+ switch (AT->getSizeModifier()) {
+ case ArrayType::Static:
+ Out << 's';
+ break;
+ case ArrayType::Star:
+ Out << '*';
+ break;
+ case ArrayType::Normal:
+ Out << 'n';
+ break;
+ }
+ if (const auto *const CAT = dyn_cast<ConstantArrayType>(T))
+ Out << CAT->getSize();
+
+ T = AT->getElementType();
+ continue;
+ }
// Unhandled type.
Out << ' ';
@@ -912,6 +934,26 @@ void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {
}
}
+void USRGenerator::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) {
+ if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
+ return;
+ VisitDeclContext(D->getDeclContext());
+ Out << "@UUV@";
+ printQualifier(Out, D->getASTContext(), D->getQualifier());
+ EmitDeclName(D);
+}
+
+void USRGenerator::VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) {
+ if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
+ return;
+ VisitDeclContext(D->getDeclContext());
+ Out << "@UUT@";
+ printQualifier(Out, D->getASTContext(), D->getQualifier());
+ Out << D->getName(); // Simple name.
+}
+
+
+
//===----------------------------------------------------------------------===//
// USR generation functions.
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp b/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp
index 1ebcc0a1c657c..aa2588659ddfe 100644
--- a/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp
@@ -1,4 +1,4 @@
-//===--- HeaderSearch.cpp - Resolve Header File Locations ---===//
+//===- HeaderSearch.cpp - Resolve Header File Locations -------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,25 +12,38 @@
//===----------------------------------------------------------------------===//
#include "clang/Lex/HeaderSearch.h"
+#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/Module.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/VirtualFileSystem.h"
+#include "clang/Lex/DirectoryLookup.h"
#include "clang/Lex/ExternalPreprocessorSource.h"
#include "clang/Lex/HeaderMap.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/LexDiagnostic.h"
-#include "clang/Lex/Lexer.h"
+#include "clang/Lex/ModuleMap.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
#include "llvm/Support/Capacity.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
#include <cstdio>
+#include <cstring>
+#include <string>
+#include <system_error>
#include <utility>
-#if defined(LLVM_ON_UNIX)
-#include <limits.h>
-#endif
+
using namespace clang;
const IdentifierInfo *
@@ -52,7 +65,7 @@ HeaderFileInfo::getControllingMacro(ExternalPreprocessorSource *External) {
return ControllingMacro;
}
-ExternalHeaderFileInfoSource::~ExternalHeaderFileInfoSource() {}
+ExternalHeaderFileInfoSource::~ExternalHeaderFileInfoSource() = default;
HeaderSearch::HeaderSearch(std::shared_ptr<HeaderSearchOptions> HSOpts,
SourceManager &SourceMgr, DiagnosticsEngine &Diags,
@@ -60,17 +73,7 @@ HeaderSearch::HeaderSearch(std::shared_ptr<HeaderSearchOptions> HSOpts,
const TargetInfo *Target)
: HSOpts(std::move(HSOpts)), Diags(Diags),
FileMgr(SourceMgr.getFileManager()), FrameworkMap(64),
- ModMap(SourceMgr, Diags, LangOpts, Target, *this) {
- AngledDirIdx = 0;
- SystemDirIdx = 0;
- NoCurDirSearch = false;
-
- ExternalLookup = nullptr;
- ExternalSource = nullptr;
- NumIncluded = 0;
- NumMultiIncludeFileOptzn = 0;
- NumFrameworkLookups = NumSubFrameworkLookups = 0;
-}
+ ModMap(SourceMgr, Diags, LangOpts, Target, *this) {}
HeaderSearch::~HeaderSearch() {
// Delete headermaps.
@@ -128,36 +131,40 @@ void HeaderSearch::getHeaderMapFileNames(
Names.push_back(HM.first->getName());
}
-std::string HeaderSearch::getModuleFileName(Module *Module) {
+std::string HeaderSearch::getCachedModuleFileName(Module *Module) {
const FileEntry *ModuleMap =
getModuleMap().getModuleMapFileForUniquing(Module);
- return getModuleFileName(Module->Name, ModuleMap->getName(),
- /*UsePrebuiltPath*/false);
+ return getCachedModuleFileName(Module->Name, ModuleMap->getName());
}
-std::string HeaderSearch::getModuleFileName(StringRef ModuleName,
- StringRef ModuleMapPath,
- bool UsePrebuiltPath) {
- if (UsePrebuiltPath) {
- if (HSOpts->PrebuiltModulePaths.empty())
- return std::string();
+std::string HeaderSearch::getPrebuiltModuleFileName(StringRef ModuleName,
+ bool FileMapOnly) {
+ // First check the module name to pcm file map.
+ auto i (HSOpts->PrebuiltModuleFiles.find(ModuleName));
+ if (i != HSOpts->PrebuiltModuleFiles.end())
+ return i->second;
- // Go though each prebuilt module path and try to find the pcm file.
- for (const std::string &Dir : HSOpts->PrebuiltModulePaths) {
- SmallString<256> Result(Dir);
- llvm::sys::fs::make_absolute(Result);
+ if (FileMapOnly || HSOpts->PrebuiltModulePaths.empty())
+ return {};
- llvm::sys::path::append(Result, ModuleName + ".pcm");
- if (getFileMgr().getFile(Result.str()))
- return Result.str().str();
- }
- return std::string();
+ // Then go through each prebuilt module directory and try to find the pcm
+ // file.
+ for (const std::string &Dir : HSOpts->PrebuiltModulePaths) {
+ SmallString<256> Result(Dir);
+ llvm::sys::fs::make_absolute(Result);
+ llvm::sys::path::append(Result, ModuleName + ".pcm");
+ if (getFileMgr().getFile(Result.str()))
+ return Result.str().str();
}
+ return {};
+}
+std::string HeaderSearch::getCachedModuleFileName(StringRef ModuleName,
+ StringRef ModuleMapPath) {
// If we don't have a module cache path or aren't supposed to use one, we
// can't do anything.
if (getModuleCachePath().empty())
- return std::string();
+ return {};
SmallString<256> Result(getModuleCachePath());
llvm::sys::fs::make_absolute(Result);
@@ -177,7 +184,7 @@ std::string HeaderSearch::getModuleFileName(StringRef ModuleName,
Parent = ".";
auto *Dir = FileMgr.getDirectory(Parent);
if (!Dir)
- return std::string();
+ return {};
auto DirName = FileMgr.getCanonicalName(Dir);
auto FileName = llvm::sys::path::filename(ModuleMapPath);
@@ -376,7 +383,6 @@ const FileEntry *DirectoryLookup::LookupFile(
Filename = StringRef(MappedName.begin(), MappedName.size());
HasBeenMapped = true;
Result = HM->LookupFile(Filename, HS.getFileMgr());
-
} else {
Result = HS.getFileMgr().getFile(Dest);
}
@@ -587,7 +593,6 @@ void HeaderSearch::setTarget(const TargetInfo &Target) {
ModMap.setTarget(Target);
}
-
//===----------------------------------------------------------------------===//
// Header File Location.
//===----------------------------------------------------------------------===//
@@ -954,7 +959,6 @@ LookupSubframeworkHeader(StringRef Filename,
HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
if (!(FE = FileMgr.getFile(HeadersFilename, /*openFile=*/true))) {
-
// Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h"
HeadersFilename = FrameworkName;
HeadersFilename += "PrivateHeaders/";
@@ -1111,7 +1115,7 @@ bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP,
// FIXME: this is a workaround for the lack of proper modules-aware support
// for #import / #pragma once
- auto TryEnterImported = [&](void) -> bool {
+ auto TryEnterImported = [&]() -> bool {
if (!ModulesEnabled)
return false;
// Ensure FileInfo bits are up to date.
@@ -1444,7 +1448,6 @@ Module *HeaderSearch::loadFrameworkModule(StringRef Name,
return ModMap.findModule(Name);
}
-
HeaderSearch::LoadModuleMapResult
HeaderSearch::loadModuleMapFile(StringRef DirName, bool IsSystem,
bool IsFramework) {
diff --git a/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp b/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp
index 61bcef8cb760e..830354ab23f0d 100644
--- a/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp
@@ -1,4 +1,4 @@
-//===--- Lexer.cpp - C Language Family Lexer ------------------------------===//
+//===- Lexer.cpp - C Language Family Lexer --------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,17 +15,29 @@
#include "UnicodeCharSets.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TokenKinds.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/LiteralSupport.h"
+#include "clang/Lex/MultipleIncludeOpt.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorOptions.h"
+#include "clang/Lex/Token.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/TokenKinds.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/NativeFormatting.h"
#include "llvm/Support/UnicodeCharRanges.h"
#include <algorithm>
#include <cassert>
@@ -63,7 +75,7 @@ tok::ObjCKeywordKind Token::getObjCKeywordID() const {
// Lexer Class Implementation
//===----------------------------------------------------------------------===//
-void Lexer::anchor() { }
+void Lexer::anchor() {}
void Lexer::InitLexer(const char *BufStart, const char *BufPtr,
const char *BufEnd) {
@@ -120,31 +132,21 @@ void Lexer::InitLexer(const char *BufStart, const char *BufPtr,
/// assumes that the associated file buffer and Preprocessor objects will
/// outlive it, so it doesn't take ownership of either of them.
Lexer::Lexer(FileID FID, const llvm::MemoryBuffer *InputFile, Preprocessor &PP)
- : PreprocessorLexer(&PP, FID),
- FileLoc(PP.getSourceManager().getLocForStartOfFile(FID)),
- LangOpts(PP.getLangOpts()) {
-
+ : PreprocessorLexer(&PP, FID),
+ FileLoc(PP.getSourceManager().getLocForStartOfFile(FID)),
+ LangOpts(PP.getLangOpts()) {
InitLexer(InputFile->getBufferStart(), InputFile->getBufferStart(),
InputFile->getBufferEnd());
resetExtendedTokenMode();
}
-void Lexer::resetExtendedTokenMode() {
- assert(PP && "Cannot reset token mode without a preprocessor");
- if (LangOpts.TraditionalCPP)
- SetKeepWhitespaceMode(true);
- else
- SetCommentRetentionState(PP->getCommentRetentionState());
-}
-
/// Lexer constructor - Create a new raw lexer object. This object is only
/// suitable for calls to 'LexFromRawLexer'. This lexer assumes that the text
/// range will outlive it, so it doesn't take ownership of it.
Lexer::Lexer(SourceLocation fileloc, const LangOptions &langOpts,
const char *BufStart, const char *BufPtr, const char *BufEnd)
- : FileLoc(fileloc), LangOpts(langOpts) {
-
+ : FileLoc(fileloc), LangOpts(langOpts) {
InitLexer(BufStart, BufPtr, BufEnd);
// We *are* in raw mode.
@@ -159,6 +161,14 @@ Lexer::Lexer(FileID FID, const llvm::MemoryBuffer *FromFile,
: Lexer(SM.getLocForStartOfFile(FID), langOpts, FromFile->getBufferStart(),
FromFile->getBufferStart(), FromFile->getBufferEnd()) {}
+void Lexer::resetExtendedTokenMode() {
+ assert(PP && "Cannot reset token mode without a preprocessor");
+ if (LangOpts.TraditionalCPP)
+ SetKeepWhitespaceMode(true);
+ else
+ SetCommentRetentionState(PP->getCommentRetentionState());
+}
+
/// Create_PragmaLexer: Lexer constructor - Create a new lexer object for
/// _Pragma expansion. This has a variety of magic semantics that this method
/// sets up. It returns a new'd Lexer that must be delete'd when done.
@@ -209,30 +219,39 @@ Lexer *Lexer::Create_PragmaLexer(SourceLocation SpellingLoc,
return L;
}
-/// Stringify - Convert the specified string into a C string, with surrounding
-/// ""'s, and with escaped \ and " characters.
+template <typename T> static void StringifyImpl(T &Str, char Quote) {
+ typename T::size_type i = 0, e = Str.size();
+ while (i < e) {
+ if (Str[i] == '\\' || Str[i] == Quote) {
+ Str.insert(Str.begin() + i, '\\');
+ i += 2;
+ ++e;
+ } else if (Str[i] == '\n' || Str[i] == '\r') {
+ // Replace '\r\n' and '\n\r' to '\\' followed by 'n'.
+ if ((i < e - 1) && (Str[i + 1] == '\n' || Str[i + 1] == '\r') &&
+ Str[i] != Str[i + 1]) {
+ Str[i] = '\\';
+ Str[i + 1] = 'n';
+ } else {
+ // Replace '\n' and '\r' to '\\' followed by 'n'.
+ Str[i] = '\\';
+ Str.insert(Str.begin() + i + 1, 'n');
+ ++e;
+ }
+ i += 2;
+ } else
+ ++i;
+ }
+}
+
std::string Lexer::Stringify(StringRef Str, bool Charify) {
std::string Result = Str;
char Quote = Charify ? '\'' : '"';
- for (unsigned i = 0, e = Result.size(); i != e; ++i) {
- if (Result[i] == '\\' || Result[i] == Quote) {
- Result.insert(Result.begin()+i, '\\');
- ++i; ++e;
- }
- }
+ StringifyImpl(Result, Quote);
return Result;
}
-/// Stringify - Convert the specified string into a C string by escaping '\'
-/// and " characters. This does not add surrounding ""'s to the string.
-void Lexer::Stringify(SmallVectorImpl<char> &Str) {
- for (unsigned i = 0, e = Str.size(); i != e; ++i) {
- if (Str[i] == '\\' || Str[i] == '"') {
- Str.insert(Str.begin()+i, '\\');
- ++i; ++e;
- }
- }
-}
+void Lexer::Stringify(SmallVectorImpl<char> &Str) { StringifyImpl(Str, '"'); }
//===----------------------------------------------------------------------===//
// Token Spelling
@@ -307,7 +326,7 @@ StringRef Lexer::getSpelling(SourceLocation loc,
StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
if (invalidTemp) {
if (invalid) *invalid = true;
- return StringRef();
+ return {};
}
const char *tokenBegin = file.data() + locInfo.second;
@@ -345,7 +364,7 @@ std::string Lexer::getSpelling(const Token &Tok, const SourceManager &SourceMgr,
if (Invalid)
*Invalid = CharDataInvalid;
if (CharDataInvalid)
- return std::string();
+ return {};
// If this token contains nothing interesting, return it directly.
if (!Tok.needsCleaning())
@@ -367,7 +386,7 @@ std::string Lexer::getSpelling(const Token &Tok, const SourceManager &SourceMgr,
/// to point to a constant buffer with the data already in it (avoiding a
/// copy). The caller is not allowed to modify the returned buffer pointer
/// if an internal buffer is returned.
-unsigned Lexer::getSpelling(const Token &Tok, const char *&Buffer,
+unsigned Lexer::getSpelling(const Token &Tok, const char *&Buffer,
const SourceManager &SourceMgr,
const LangOptions &LangOpts, bool *Invalid) {
assert((int)Tok.getLength() >= 0 && "Token character range is bogus!");
@@ -463,19 +482,15 @@ static const char *findBeginningOfLine(StringRef Buffer, unsigned Offset) {
const char *BufStart = Buffer.data();
if (Offset >= Buffer.size())
return nullptr;
- const char *StrData = BufStart + Offset;
-
- if (StrData[0] == '\n' || StrData[0] == '\r')
- return StrData;
- const char *LexStart = StrData;
- while (LexStart != BufStart) {
- if (LexStart[0] == '\n' || LexStart[0] == '\r') {
+ const char *LexStart = BufStart + Offset;
+ for (; LexStart != BufStart; --LexStart) {
+ if (isVerticalWhitespace(LexStart[0]) &&
+ !Lexer::isNewLineEscaped(BufStart, LexStart)) {
+ // LexStart should point at first character of logical line.
++LexStart;
break;
}
-
- --LexStart;
}
return LexStart;
}
@@ -487,7 +502,7 @@ static SourceLocation getBeginningOfFileToken(SourceLocation Loc,
std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
if (LocInfo.first.isInvalid())
return Loc;
-
+
bool Invalid = false;
StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid);
if (Invalid)
@@ -499,31 +514,31 @@ static SourceLocation getBeginningOfFileToken(SourceLocation Loc,
const char *LexStart = findBeginningOfLine(Buffer, LocInfo.second);
if (!LexStart || LexStart == StrData)
return Loc;
-
+
// Create a lexer starting at the beginning of this token.
SourceLocation LexerStartLoc = Loc.getLocWithOffset(-LocInfo.second);
Lexer TheLexer(LexerStartLoc, LangOpts, Buffer.data(), LexStart,
Buffer.end());
TheLexer.SetCommentRetentionState(true);
-
+
// Lex tokens until we find the token that contains the source location.
Token TheTok;
do {
TheLexer.LexFromRawLexer(TheTok);
-
+
if (TheLexer.getBufferLocation() > StrData) {
// Lexing this token has taken the lexer past the source location we're
// looking for. If the current token encompasses our source location,
// return the beginning of that token.
if (TheLexer.getBufferLocation() - TheTok.getLength() <= StrData)
return TheTok.getLocation();
-
+
// We ended up skipping over the source location entirely, which means
// that it points into whitespace. We're done here.
break;
}
} while (TheTok.getKind() != tok::eof);
-
+
// We've passed our source location; just return the original source location.
return Loc;
}
@@ -531,34 +546,34 @@ static SourceLocation getBeginningOfFileToken(SourceLocation Loc,
SourceLocation Lexer::GetBeginningOfToken(SourceLocation Loc,
const SourceManager &SM,
const LangOptions &LangOpts) {
- if (Loc.isFileID())
- return getBeginningOfFileToken(Loc, SM, LangOpts);
-
- if (!SM.isMacroArgExpansion(Loc))
- return Loc;
+ if (Loc.isFileID())
+ return getBeginningOfFileToken(Loc, SM, LangOpts);
+
+ if (!SM.isMacroArgExpansion(Loc))
+ return Loc;
- SourceLocation FileLoc = SM.getSpellingLoc(Loc);
- SourceLocation BeginFileLoc = getBeginningOfFileToken(FileLoc, SM, LangOpts);
- std::pair<FileID, unsigned> FileLocInfo = SM.getDecomposedLoc(FileLoc);
- std::pair<FileID, unsigned> BeginFileLocInfo
- = SM.getDecomposedLoc(BeginFileLoc);
- assert(FileLocInfo.first == BeginFileLocInfo.first &&
- FileLocInfo.second >= BeginFileLocInfo.second);
- return Loc.getLocWithOffset(BeginFileLocInfo.second - FileLocInfo.second);
+ SourceLocation FileLoc = SM.getSpellingLoc(Loc);
+ SourceLocation BeginFileLoc = getBeginningOfFileToken(FileLoc, SM, LangOpts);
+ std::pair<FileID, unsigned> FileLocInfo = SM.getDecomposedLoc(FileLoc);
+ std::pair<FileID, unsigned> BeginFileLocInfo =
+ SM.getDecomposedLoc(BeginFileLoc);
+ assert(FileLocInfo.first == BeginFileLocInfo.first &&
+ FileLocInfo.second >= BeginFileLocInfo.second);
+ return Loc.getLocWithOffset(BeginFileLocInfo.second - FileLocInfo.second);
}
namespace {
- enum PreambleDirectiveKind {
- PDK_Skipped,
- PDK_Unknown
- };
+enum PreambleDirectiveKind {
+ PDK_Skipped,
+ PDK_Unknown
+};
-} // end anonymous namespace
+} // namespace
-std::pair<unsigned, bool> Lexer::ComputePreamble(StringRef Buffer,
- const LangOptions &LangOpts,
- unsigned MaxLines) {
+PreambleBounds Lexer::ComputePreamble(StringRef Buffer,
+ const LangOptions &LangOpts,
+ unsigned MaxLines) {
// Create a lexer starting at the beginning of the file. Note that we use a
// "fake" file source location at offset 1 so that the lexer will track our
// position within the file.
@@ -568,9 +583,6 @@ std::pair<unsigned, bool> Lexer::ComputePreamble(StringRef Buffer,
Buffer.end());
TheLexer.SetCommentRetentionState(true);
- // StartLoc will differ from FileLoc if there is a BOM that was skipped.
- SourceLocation StartLoc = TheLexer.getSourceLocation();
-
bool InPreprocessorDirective = false;
Token TheTok;
SourceLocation ActiveCommentLoc;
@@ -599,17 +611,17 @@ std::pair<unsigned, bool> Lexer::ComputePreamble(StringRef Buffer,
if (TheTok.getKind() == tok::eof) {
break;
}
-
+
// If we haven't hit the end of the preprocessor directive, skip this
// token.
if (!TheTok.isAtStartOfLine())
continue;
-
+
// We've passed the end of the preprocessor directive, and will look
// at this token again below.
InPreprocessorDirective = false;
}
-
+
// Keep track of the # of lines in the preamble.
if (TheTok.isAtStartOfLine()) {
unsigned TokOffset = TheTok.getLocation().getRawEncoding() - StartOffset;
@@ -626,13 +638,13 @@ std::pair<unsigned, bool> Lexer::ComputePreamble(StringRef Buffer,
ActiveCommentLoc = TheTok.getLocation();
continue;
}
-
+
if (TheTok.isAtStartOfLine() && TheTok.getKind() == tok::hash) {
- // This is the start of a preprocessor directive.
+ // This is the start of a preprocessor directive.
Token HashTok = TheTok;
InPreprocessorDirective = true;
ActiveCommentLoc = SourceLocation();
-
+
// Figure out which directive this is. Since we're lexing raw tokens,
// we don't have an identifier table available. Instead, just look at
// the raw identifier to recognize and categorize preprocessor directives.
@@ -672,7 +684,7 @@ std::pair<unsigned, bool> Lexer::ComputePreamble(StringRef Buffer,
break;
}
}
-
+
// We only end up here if we didn't recognize the preprocessor
// directive or it was one that can't occur in the preamble at this
// point. Roll back the current token to the location of the '#'.
@@ -685,14 +697,14 @@ std::pair<unsigned, bool> Lexer::ComputePreamble(StringRef Buffer,
// the preamble.
break;
} while (true);
-
+
SourceLocation End;
if (ActiveCommentLoc.isValid())
End = ActiveCommentLoc; // don't truncate a decl comment.
else
End = TheTok.getLocation();
- return std::make_pair(End.getRawEncoding() - StartLoc.getRawEncoding(),
+ return PreambleBounds(End.getRawEncoding() - FileLoc.getRawEncoding(),
TheTok.isAtStartOfLine());
}
@@ -707,13 +719,13 @@ SourceLocation Lexer::AdvanceToTokenCharacter(SourceLocation TokStart,
// trigraphs.
bool Invalid = false;
const char *TokPtr = SM.getCharacterData(TokStart, &Invalid);
-
+
// If they request the first char of the token, we're trivially done.
if (Invalid || (CharNo == 0 && Lexer::isObviouslySimpleCharacter(*TokPtr)))
return TokStart;
-
+
unsigned PhysOffset = 0;
-
+
// The usual case is that tokens don't contain anything interesting. Skip
// over the uninteresting characters. If a token only consists of simple
// chars, this method is extremely fast.
@@ -724,7 +736,7 @@ SourceLocation Lexer::AdvanceToTokenCharacter(SourceLocation TokStart,
--CharNo;
++PhysOffset;
}
-
+
// If we have a character that may be a trigraph or escaped newline, use a
// lexer to parse it correctly.
for (; CharNo; --CharNo) {
@@ -733,14 +745,14 @@ SourceLocation Lexer::AdvanceToTokenCharacter(SourceLocation TokStart,
TokPtr += Size;
PhysOffset += Size;
}
-
+
// Final detail: if we end up on an escaped newline, we want to return the
// location of the actual byte of the token. For example foo\<newline>bar
// advanced by 3 should return the location of b, not of \\. One compounding
// detail of this is that the escape may be made by a trigraph.
if (!Lexer::isObviouslySimpleCharacter(*TokPtr))
PhysOffset += Lexer::SkipEscapedNewLines(TokPtr)-TokPtr;
-
+
return TokStart.getLocWithOffset(PhysOffset);
}
@@ -763,11 +775,11 @@ SourceLocation Lexer::getLocForEndOfToken(SourceLocation Loc, unsigned Offset,
const SourceManager &SM,
const LangOptions &LangOpts) {
if (Loc.isInvalid())
- return SourceLocation();
+ return {};
if (Loc.isMacroID()) {
if (Offset > 0 || !isAtEndOfMacroExpansion(Loc, SM, LangOpts, &Loc))
- return SourceLocation(); // Points inside the macro expansion.
+ return {}; // Points inside the macro expansion.
}
unsigned Len = Lexer::MeasureTokenLength(Loc, SM, LangOpts);
@@ -775,7 +787,7 @@ SourceLocation Lexer::getLocForEndOfToken(SourceLocation Loc, unsigned Offset,
Len = Len - Offset;
else
return Loc;
-
+
return Loc.getLocWithOffset(Len);
}
@@ -838,7 +850,7 @@ static CharSourceRange makeRangeFromFileLocs(CharSourceRange Range,
if (Range.isTokenRange()) {
End = Lexer::getLocForEndOfToken(End, 0, SM,LangOpts);
if (End.isInvalid())
- return CharSourceRange();
+ return {};
}
// Break down the source locations.
@@ -846,12 +858,12 @@ static CharSourceRange makeRangeFromFileLocs(CharSourceRange Range,
unsigned BeginOffs;
std::tie(FID, BeginOffs) = SM.getDecomposedLoc(Begin);
if (FID.isInvalid())
- return CharSourceRange();
+ return {};
unsigned EndOffs;
if (!SM.isInFileID(End, FID, &EndOffs) ||
BeginOffs > EndOffs)
- return CharSourceRange();
+ return {};
return CharSourceRange::getCharRange(Begin, End);
}
@@ -862,14 +874,14 @@ CharSourceRange Lexer::makeFileCharRange(CharSourceRange Range,
SourceLocation Begin = Range.getBegin();
SourceLocation End = Range.getEnd();
if (Begin.isInvalid() || End.isInvalid())
- return CharSourceRange();
+ return {};
if (Begin.isFileID() && End.isFileID())
return makeRangeFromFileLocs(Range, SM, LangOpts);
if (Begin.isMacroID() && End.isFileID()) {
if (!isAtStartOfMacroExpansion(Begin, SM, LangOpts, &Begin))
- return CharSourceRange();
+ return {};
Range.setBegin(Begin);
return makeRangeFromFileLocs(Range, SM, LangOpts);
}
@@ -879,7 +891,7 @@ CharSourceRange Lexer::makeFileCharRange(CharSourceRange Range,
&End)) ||
(Range.isCharRange() && !isAtStartOfMacroExpansion(End, SM, LangOpts,
&End)))
- return CharSourceRange();
+ return {};
Range.setEnd(End);
return makeRangeFromFileLocs(Range, SM, LangOpts);
}
@@ -900,13 +912,13 @@ CharSourceRange Lexer::makeFileCharRange(CharSourceRange Range,
const SrcMgr::SLocEntry &BeginEntry = SM.getSLocEntry(SM.getFileID(Begin),
&Invalid);
if (Invalid)
- return CharSourceRange();
+ return {};
if (BeginEntry.getExpansion().isMacroArgExpansion()) {
const SrcMgr::SLocEntry &EndEntry = SM.getSLocEntry(SM.getFileID(End),
&Invalid);
if (Invalid)
- return CharSourceRange();
+ return {};
if (EndEntry.getExpansion().isMacroArgExpansion() &&
BeginEntry.getExpansion().getExpansionLocStart() ==
@@ -917,7 +929,7 @@ CharSourceRange Lexer::makeFileCharRange(CharSourceRange Range,
}
}
- return CharSourceRange();
+ return {};
}
StringRef Lexer::getSourceText(CharSourceRange Range,
@@ -927,21 +939,21 @@ StringRef Lexer::getSourceText(CharSourceRange Range,
Range = makeFileCharRange(Range, SM, LangOpts);
if (Range.isInvalid()) {
if (Invalid) *Invalid = true;
- return StringRef();
+ return {};
}
// Break down the source location.
std::pair<FileID, unsigned> beginInfo = SM.getDecomposedLoc(Range.getBegin());
if (beginInfo.first.isInvalid()) {
if (Invalid) *Invalid = true;
- return StringRef();
+ return {};
}
unsigned EndOffs;
if (!SM.isInFileID(Range.getEnd(), beginInfo.first, &EndOffs) ||
beginInfo.second > EndOffs) {
if (Invalid) *Invalid = true;
- return StringRef();
+ return {};
}
// Try to the load the file buffer.
@@ -949,7 +961,7 @@ StringRef Lexer::getSourceText(CharSourceRange Range,
StringRef file = SM.getBufferData(beginInfo.first, &invalidTemp);
if (invalidTemp) {
if (Invalid) *Invalid = true;
- return StringRef();
+ return {};
}
if (Invalid) *Invalid = false;
@@ -972,7 +984,7 @@ StringRef Lexer::getImmediateMacroName(SourceLocation Loc,
// For macro arguments we need to check that the argument did not come
// from an inner macro, e.g: "MAC1( MAC2(foo) )"
-
+
// Loc points to the argument id of the macro definition, move to the
// macro expansion.
Loc = SM.getImmediateExpansionRange(Loc).first;
@@ -1013,7 +1025,7 @@ StringRef Lexer::getImmediateMacroNameForDiagnostics(
// If the macro's spelling has no FileID, then it's actually a token paste
// or stringization (or similar) and not a macro at all.
if (!SM.getFileEntryForID(SM.getFileID(SM.getSpellingLoc(Loc))))
- return StringRef();
+ return {};
// Find the spelling location of the start of the non-argument expansion
// range. This is where the macro name was spelled in order to begin
@@ -1032,20 +1044,40 @@ bool Lexer::isIdentifierBodyChar(char c, const LangOptions &LangOpts) {
return isIdentifierBody(c, LangOpts.DollarIdents);
}
+bool Lexer::isNewLineEscaped(const char *BufferStart, const char *Str) {
+ assert(isVerticalWhitespace(Str[0]));
+ if (Str - 1 < BufferStart)
+ return false;
+
+ if ((Str[0] == '\n' && Str[-1] == '\r') ||
+ (Str[0] == '\r' && Str[-1] == '\n')) {
+ if (Str - 2 < BufferStart)
+ return false;
+ --Str;
+ }
+ --Str;
+
+ // Rewind to first non-space character:
+ while (Str > BufferStart && isHorizontalWhitespace(*Str))
+ --Str;
+
+ return *Str == '\\';
+}
+
StringRef Lexer::getIndentationForLine(SourceLocation Loc,
const SourceManager &SM) {
if (Loc.isInvalid() || Loc.isMacroID())
- return "";
+ return {};
std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
if (LocInfo.first.isInvalid())
- return "";
+ return {};
bool Invalid = false;
StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid);
if (Invalid)
- return "";
+ return {};
const char *Line = findBeginningOfLine(Buffer, LocInfo.second);
if (!Line)
- return "";
+ return {};
StringRef Rest = Buffer.substr(Line - Buffer.data());
size_t NumWhitespaceChars = Rest.find_first_not_of(" \t");
return NumWhitespaceChars == StringRef::npos
@@ -1199,18 +1231,12 @@ const char *Lexer::SkipEscapedNewLines(const char *P) {
}
}
-/// \brief Checks that the given token is the first token that occurs after the
-/// given location (this excludes comments and whitespace). Returns the location
-/// immediately after the specified token. If the token is not found or the
-/// location is inside a macro, the returned source location will be invalid.
-SourceLocation Lexer::findLocationAfterToken(SourceLocation Loc,
- tok::TokenKind TKind,
- const SourceManager &SM,
- const LangOptions &LangOpts,
- bool SkipTrailingWhitespaceAndNewLine) {
+Optional<Token> Lexer::findNextToken(SourceLocation Loc,
+ const SourceManager &SM,
+ const LangOptions &LangOpts) {
if (Loc.isMacroID()) {
if (!Lexer::isAtEndOfMacroExpansion(Loc, SM, LangOpts, &Loc))
- return SourceLocation();
+ return None;
}
Loc = Lexer::getLocForEndOfToken(Loc, 0, SM, LangOpts);
@@ -1221,7 +1247,7 @@ SourceLocation Lexer::findLocationAfterToken(SourceLocation Loc,
bool InvalidTemp = false;
StringRef File = SM.getBufferData(LocInfo.first, &InvalidTemp);
if (InvalidTemp)
- return SourceLocation();
+ return None;
const char *TokenBegin = File.data() + LocInfo.second;
@@ -1231,15 +1257,25 @@ SourceLocation Lexer::findLocationAfterToken(SourceLocation Loc,
// Find the token.
Token Tok;
lexer.LexFromRawLexer(Tok);
- if (Tok.isNot(TKind))
- return SourceLocation();
- SourceLocation TokenLoc = Tok.getLocation();
+ return Tok;
+}
+
+/// \brief Checks that the given token is the first token that occurs after the
+/// given location (this excludes comments and whitespace). Returns the location
+/// immediately after the specified token. If the token is not found or the
+/// location is inside a macro, the returned source location will be invalid.
+SourceLocation Lexer::findLocationAfterToken(
+ SourceLocation Loc, tok::TokenKind TKind, const SourceManager &SM,
+ const LangOptions &LangOpts, bool SkipTrailingWhitespaceAndNewLine) {
+ Optional<Token> Tok = findNextToken(Loc, SM, LangOpts);
+ if (!Tok || Tok->isNot(TKind))
+ return {};
+ SourceLocation TokenLoc = Tok->getLocation();
// Calculate how much whitespace needs to be skipped if any.
unsigned NumWhitespaceChars = 0;
if (SkipTrailingWhitespaceAndNewLine) {
- const char *TokenEnd = SM.getCharacterData(TokenLoc) +
- Tok.getLength();
+ const char *TokenEnd = SM.getCharacterData(TokenLoc) + Tok->getLength();
unsigned char C = *TokenEnd;
while (isHorizontalWhitespace(C)) {
C = *(++TokenEnd);
@@ -1256,7 +1292,7 @@ SourceLocation Lexer::findLocationAfterToken(SourceLocation Loc,
}
}
- return TokenLoc.getLocWithOffset(Tok.getLength() + NumWhitespaceChars);
+ return TokenLoc.getLocWithOffset(Tok->getLength() + NumWhitespaceChars);
}
/// getCharAndSizeSlow - Peek a single 'character' from the specified buffer,
@@ -1274,7 +1310,6 @@ SourceLocation Lexer::findLocationAfterToken(SourceLocation Loc,
///
/// NOTE: When this method is updated, getCharAndSizeSlowNoWarn (below) should
/// be updated to match.
-///
char Lexer::getCharAndSizeSlow(const char *Ptr, unsigned &Size,
Token *Tok) {
// If we have a slash, look for an escaped newline.
@@ -1378,9 +1413,9 @@ Slash:
// Helper methods for lexing.
//===----------------------------------------------------------------------===//
-/// \brief Routine that indiscriminately skips bytes in the source file.
-void Lexer::SkipBytes(unsigned Bytes, bool StartOfLine) {
- BufferPtr += Bytes;
+/// \brief Routine that indiscriminately sets the offset into the source file.
+void Lexer::SetByteOffset(unsigned Offset, bool StartOfLine) {
+ BufferPtr = BufferStart + Offset;
if (BufferPtr > BufferEnd)
BufferPtr = BufferEnd;
// FIXME: What exactly does the StartOfLine bit mean? There are two
@@ -1466,6 +1501,75 @@ static void maybeDiagnoseIDCharCompat(DiagnosticsEngine &Diags, uint32_t C,
}
}
+/// After encountering UTF-8 character C and interpreting it as an identifier
+/// character, check whether it's a homoglyph for a common non-identifier
+/// source character that is unlikely to be an intentional identifier
+/// character and warn if so.
+static void maybeDiagnoseUTF8Homoglyph(DiagnosticsEngine &Diags, uint32_t C,
+ CharSourceRange Range) {
+ // FIXME: Handle Unicode quotation marks (smart quotes, fullwidth quotes).
+ struct HomoglyphPair {
+ uint32_t Character;
+ char LooksLike;
+ bool operator<(HomoglyphPair R) const { return Character < R.Character; }
+ };
+ static constexpr HomoglyphPair SortedHomoglyphs[] = {
+ {U'\u01c3', '!'}, // LATIN LETTER RETROFLEX CLICK
+ {U'\u037e', ';'}, // GREEK QUESTION MARK
+ {U'\u2212', '-'}, // MINUS SIGN
+ {U'\u2215', '/'}, // DIVISION SLASH
+ {U'\u2216', '\\'}, // SET MINUS
+ {U'\u2217', '*'}, // ASTERISK OPERATOR
+ {U'\u2223', '|'}, // DIVIDES
+ {U'\u2227', '^'}, // LOGICAL AND
+ {U'\u2236', ':'}, // RATIO
+ {U'\u223c', '~'}, // TILDE OPERATOR
+ {U'\ua789', ':'}, // MODIFIER LETTER COLON
+ {U'\uff01', '!'}, // FULLWIDTH EXCLAMATION MARK
+ {U'\uff03', '#'}, // FULLWIDTH NUMBER SIGN
+ {U'\uff04', '$'}, // FULLWIDTH DOLLAR SIGN
+ {U'\uff05', '%'}, // FULLWIDTH PERCENT SIGN
+ {U'\uff06', '&'}, // FULLWIDTH AMPERSAND
+ {U'\uff08', '('}, // FULLWIDTH LEFT PARENTHESIS
+ {U'\uff09', ')'}, // FULLWIDTH RIGHT PARENTHESIS
+ {U'\uff0a', '*'}, // FULLWIDTH ASTERISK
+ {U'\uff0b', '+'}, // FULLWIDTH ASTERISK
+ {U'\uff0c', ','}, // FULLWIDTH COMMA
+ {U'\uff0d', '-'}, // FULLWIDTH HYPHEN-MINUS
+ {U'\uff0e', '.'}, // FULLWIDTH FULL STOP
+ {U'\uff0f', '/'}, // FULLWIDTH SOLIDUS
+ {U'\uff1a', ':'}, // FULLWIDTH COLON
+ {U'\uff1b', ';'}, // FULLWIDTH SEMICOLON
+ {U'\uff1c', '<'}, // FULLWIDTH LESS-THAN SIGN
+ {U'\uff1d', '='}, // FULLWIDTH EQUALS SIGN
+ {U'\uff1e', '>'}, // FULLWIDTH GREATER-THAN SIGN
+ {U'\uff1f', '?'}, // FULLWIDTH QUESTION MARK
+ {U'\uff20', '@'}, // FULLWIDTH COMMERCIAL AT
+ {U'\uff3b', '['}, // FULLWIDTH LEFT SQUARE BRACKET
+ {U'\uff3c', '\\'}, // FULLWIDTH REVERSE SOLIDUS
+ {U'\uff3d', ']'}, // FULLWIDTH RIGHT SQUARE BRACKET
+ {U'\uff3e', '^'}, // FULLWIDTH CIRCUMFLEX ACCENT
+ {U'\uff5b', '{'}, // FULLWIDTH LEFT CURLY BRACKET
+ {U'\uff5c', '|'}, // FULLWIDTH VERTICAL LINE
+ {U'\uff5d', '}'}, // FULLWIDTH RIGHT CURLY BRACKET
+ {U'\uff5e', '~'}, // FULLWIDTH TILDE
+ {0, 0}
+ };
+ auto Homoglyph =
+ std::lower_bound(std::begin(SortedHomoglyphs),
+ std::end(SortedHomoglyphs) - 1, HomoglyphPair{C, '\0'});
+ if (Homoglyph->Character == C) {
+ llvm::SmallString<5> CharBuf;
+ {
+ llvm::raw_svector_ostream CharOS(CharBuf);
+ llvm::write_hex(CharOS, C, llvm::HexPrintStyle::Upper, 4);
+ }
+ const char LooksLikeStr[] = {Homoglyph->LooksLike, 0};
+ Diags.Report(Range.getBegin(), diag::warn_utf8_symbol_homoglyph)
+ << Range << CharBuf << LooksLikeStr;
+ }
+}
+
bool Lexer::tryConsumeIdentifierUCN(const char *&CurPtr, unsigned Size,
Token &Result) {
const char *UCNPtr = CurPtr + Size;
@@ -1500,10 +1604,13 @@ bool Lexer::tryConsumeIdentifierUTF8Char(const char *&CurPtr) {
!isAllowedIDChar(static_cast<uint32_t>(CodePoint), LangOpts))
return false;
- if (!isLexingRawMode())
+ if (!isLexingRawMode()) {
maybeDiagnoseIDCharCompat(PP->getDiagnostics(), CodePoint,
makeCharRange(*this, CurPtr, UnicodePtr),
/*IsFirst=*/false);
+ maybeDiagnoseUTF8Homoglyph(PP->getDiagnostics(), CodePoint,
+ makeCharRange(*this, CurPtr, UnicodePtr));
+ }
CurPtr = UnicodePtr;
return true;
@@ -1569,7 +1676,6 @@ FinishIdentifier:
CurPtr = ConsumeChar(CurPtr, Size, Result);
C = getCharAndSize(CurPtr, Size);
continue;
-
} else if (C == '\\' && tryConsumeIdentifierUCN(CurPtr, Size, Result)) {
C = getCharAndSize(CurPtr, Size);
continue;
@@ -1632,7 +1738,7 @@ bool Lexer::LexNumericConstant(Token &Result, const char *CurPtr) {
if (!LangOpts.C99) {
if (!isHexaLiteral(BufferPtr, LangOpts))
IsHexFloat = false;
- else if (!getLangOpts().CPlusPlus1z &&
+ else if (!getLangOpts().CPlusPlus17 &&
std::find(BufferPtr, CurPtr, '_') != CurPtr)
IsHexFloat = false;
}
@@ -1778,7 +1884,7 @@ bool Lexer::LexStringLiteral(Token &Result, const char *CurPtr,
// getAndAdvanceChar.
if (C == '\\')
C = getAndAdvanceChar(CurPtr, Result);
-
+
if (C == '\n' || C == '\r' || // Newline.
(C == 0 && CurPtr-1 == BufferEnd)) { // End of file.
if (!isLexingRawMode() && !LangOpts.AsmPreprocessor)
@@ -1786,7 +1892,7 @@ bool Lexer::LexStringLiteral(Token &Result, const char *CurPtr,
FormTokenWithChars(Result, CurPtr-1, tok::unknown);
return true;
}
-
+
if (C == 0) {
if (isCodeCompletionPoint(CurPtr-1)) {
PP->CodeCompleteNaturalLanguage();
@@ -2000,7 +2106,6 @@ bool Lexer::LexCharConstant(Token &Result, const char *CurPtr,
/// Update BufferPtr to point to the next non-whitespace character and return.
///
/// This method forms a token and returns true if KeepWhitespaceMode is enabled.
-///
bool Lexer::SkipWhitespace(Token &Result, const char *CurPtr,
bool &TokAtPhysicalStartOfLine) {
// Whitespace - Skip it, then return the token after the whitespace.
@@ -2131,7 +2236,8 @@ bool Lexer::SkipLineComment(Token &Result, const char *CurPtr,
// If we read multiple characters, and one of those characters was a \r or
// \n, then we had an escaped newline within the comment. Emit diagnostic
// unless the next line is also a // comment.
- if (CurPtr != OldPtr+1 && C != '/' && CurPtr[0] != '/') {
+ if (CurPtr != OldPtr + 1 && C != '/' &&
+ (CurPtr == BufferEnd + 1 || CurPtr[0] != '/')) {
for (; OldPtr != CurPtr; ++OldPtr)
if (OldPtr[0] == '\n' || OldPtr[0] == '\r') {
// Okay, we found a // comment that ends in a newline, if the next
@@ -2214,7 +2320,7 @@ bool Lexer::SaveLineComment(Token &Result, const char *CurPtr) {
std::string Spelling = PP->getSpelling(Result, &Invalid);
if (Invalid)
return true;
-
+
assert(Spelling[0] == '/' && Spelling[1] == '/' && "Not line comment?");
Spelling[1] = '*'; // Change prefix to "/*".
Spelling += "*/"; // add suffix.
@@ -2540,7 +2646,7 @@ bool Lexer::LexEndOfFile(Token &Result, const char *CurPtr) {
resetExtendedTokenMode();
return true; // Have a token.
}
-
+
// If we are in raw mode, return this event as an EOF token. Let the caller
// that put us in raw mode handle the event.
if (isLexingRawMode()) {
@@ -2549,7 +2655,7 @@ bool Lexer::LexEndOfFile(Token &Result, const char *CurPtr) {
FormTokenWithChars(Result, BufferEnd, tok::eof);
return true;
}
-
+
if (PP->isRecordingPreamble() && PP->isInPrimaryFile()) {
PP->setRecordedPreambleConditionalStack(ConditionalStack);
ConditionalStack.clear();
@@ -2661,7 +2767,7 @@ bool Lexer::IsStartOfConflictMarker(const char *CurPtr) {
if (CurPtr != BufferStart &&
CurPtr[-1] != '\n' && CurPtr[-1] != '\r')
return false;
-
+
// Check to see if we have <<<<<<< or >>>>.
if (!StringRef(CurPtr, BufferEnd - CurPtr).startswith("<<<<<<<") &&
!StringRef(CurPtr, BufferEnd - CurPtr).startswith(">>>> "))
@@ -2671,7 +2777,7 @@ bool Lexer::IsStartOfConflictMarker(const char *CurPtr) {
// it.
if (CurrentConflictMarkerState || isLexingRawMode())
return false;
-
+
ConflictMarkerKind Kind = *CurPtr == '<' ? CMK_Normal : CMK_Perforce;
// Check to see if there is an ending marker somewhere in the buffer at the
@@ -2681,7 +2787,7 @@ bool Lexer::IsStartOfConflictMarker(const char *CurPtr) {
// Diagnose this, and ignore to the end of line.
Diag(CurPtr, diag::err_conflict_marker);
CurrentConflictMarkerState = Kind;
-
+
// Skip ahead to the end of line. We know this exists because the
// end-of-conflict marker starts with \r or \n.
while (*CurPtr != '\r' && *CurPtr != '\n') {
@@ -2691,7 +2797,7 @@ bool Lexer::IsStartOfConflictMarker(const char *CurPtr) {
BufferPtr = CurPtr;
return true;
}
-
+
// No end of conflict marker found.
return false;
}
@@ -2705,35 +2811,35 @@ bool Lexer::HandleEndOfConflictMarker(const char *CurPtr) {
if (CurPtr != BufferStart &&
CurPtr[-1] != '\n' && CurPtr[-1] != '\r')
return false;
-
+
// If we have a situation where we don't care about conflict markers, ignore
// it.
if (!CurrentConflictMarkerState || isLexingRawMode())
return false;
-
+
// Check to see if we have the marker (4 characters in a row).
for (unsigned i = 1; i != 4; ++i)
if (CurPtr[i] != CurPtr[0])
return false;
-
+
// If we do have it, search for the end of the conflict marker. This could
// fail if it got skipped with a '#if 0' or something. Note that CurPtr might
// be the end of conflict marker.
if (const char *End = FindConflictEnd(CurPtr, BufferEnd,
CurrentConflictMarkerState)) {
CurPtr = End;
-
+
// Skip ahead to the end of line.
while (CurPtr != BufferEnd && *CurPtr != '\r' && *CurPtr != '\n')
++CurPtr;
-
+
BufferPtr = CurPtr;
-
+
// No longer in the conflict marker.
CurrentConflictMarkerState = CMK_None;
return true;
}
-
+
return false;
}
@@ -2872,7 +2978,6 @@ uint32_t Lexer::tryReadUCN(const char *&StartPtr, const char *SlashLoc,
}
return 0;
-
} else if (CodePoint >= 0xD800 && CodePoint <= 0xDFFF) {
// C++03 allows UCNs representing surrogate characters. C99 and C++11 don't.
// We don't use isLexingRawMode() here because we need to diagnose bad
@@ -3042,7 +3147,7 @@ LexNextToken:
// We know the lexer hasn't changed, so just try again with this lexer.
// (We manually eliminate the tail call to avoid recursion.)
goto LexNextToken;
-
+
case 26: // DOS & CP/M EOF: "^Z".
// If we're in Microsoft extensions mode, treat this as end of file.
if (LangOpts.MicrosoftExt) {
@@ -3054,9 +3159,12 @@ LexNextToken:
// If Microsoft extensions are disabled, this is just random garbage.
Kind = tok::unknown;
break;
-
- case '\n':
+
case '\r':
+ if (CurPtr[0] == '\n')
+ Char = getAndAdvanceChar(CurPtr, Result);
+ LLVM_FALLTHROUGH;
+ case '\n':
// If we are inside a preprocessor directive and we see the end of line,
// we know we are done with the directive, so return an EOD token.
if (ParsingPreprocessorDirective) {
@@ -3114,7 +3222,7 @@ LexNextToken:
// We only saw whitespace, so just try again with this lexer.
// (We manually eliminate the tail call to avoid recursion.)
goto LexNextToken;
-
+
// C99 6.4.4.1: Integer Constants.
// C99 6.4.4.2: Floating Constants.
case '0': case '1': case '2': case '3': case '4':
@@ -3157,7 +3265,7 @@ LexNextToken:
ConsumeChar(ConsumeChar(CurPtr, SizeTmp, Result),
SizeTmp2, Result),
tok::utf8_string_literal);
- if (Char2 == '\'' && LangOpts.CPlusPlus1z)
+ if (Char2 == '\'' && LangOpts.CPlusPlus17)
return LexCharConstant(
Result, ConsumeChar(ConsumeChar(CurPtr, SizeTmp, Result),
SizeTmp2, Result),
@@ -3501,6 +3609,24 @@ LexNextToken:
Kind = tok::lessless;
}
} else if (Char == '=') {
+ char After = getCharAndSize(CurPtr+SizeTmp, SizeTmp2);
+ if (After == '>') {
+ if (getLangOpts().CPlusPlus2a) {
+ if (!isLexingRawMode())
+ Diag(BufferPtr, diag::warn_cxx17_compat_spaceship);
+ CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp, Result),
+ SizeTmp2, Result);
+ Kind = tok::spaceship;
+ break;
+ }
+ // Suggest adding a space between the '<=' and the '>' to avoid a
+ // change in semantics if this turns up in C++ <=17 mode.
+ if (getLangOpts().CPlusPlus && !isLexingRawMode()) {
+ Diag(BufferPtr, diag::warn_cxx2a_compat_spaceship)
+ << FixItHint::CreateInsertion(
+ getSourceLocation(CurPtr + SizeTmp, SizeTmp2), " ");
+ }
+ }
CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
Kind = tok::lessequal;
} else if (LangOpts.Digraphs && Char == ':') { // '<:' -> '['
@@ -3526,7 +3652,8 @@ LexNextToken:
} else if (LangOpts.Digraphs && Char == '%') { // '<%' -> '{'
CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
Kind = tok::l_brace;
- } else if (Char == '#' && lexEditorPlaceholder(Result, CurPtr)) {
+ } else if (Char == '#' && /*Not a trigraph*/ SizeTmp == 1 &&
+ lexEditorPlaceholder(Result, CurPtr)) {
return true;
} else {
Kind = tok::less;
@@ -3594,7 +3721,9 @@ LexNextToken:
if (LangOpts.Digraphs && Char == '>') {
Kind = tok::r_square; // ':>' -> ']'
CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
- } else if (LangOpts.CPlusPlus && Char == ':') {
+ } else if ((LangOpts.CPlusPlus ||
+ LangOpts.DoubleSquareBracketAttributes) &&
+ Char == ':') {
Kind = tok::coloncolon;
CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
} else {
@@ -3610,7 +3739,7 @@ LexNextToken:
// If this is '====' and we're in a conflict marker, ignore it.
if (CurPtr[1] == '=' && HandleEndOfConflictMarker(CurPtr-1))
goto LexNextToken;
-
+
Kind = tok::equalequal;
CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
} else {
@@ -3681,6 +3810,7 @@ LexNextToken:
// We can't just reset CurPtr to BufferPtr because BufferPtr may point to
// an escaped newline.
--CurPtr;
+ const char *UTF8StartPtr = CurPtr;
llvm::ConversionResult Status =
llvm::convertUTF8Sequence((const llvm::UTF8 **)&CurPtr,
(const llvm::UTF8 *)BufferEnd,
@@ -3695,9 +3825,12 @@ LexNextToken:
// (We manually eliminate the tail call to avoid recursion.)
goto LexNextToken;
}
+ if (!isLexingRawMode())
+ maybeDiagnoseUTF8Homoglyph(PP->getDiagnostics(), CodePoint,
+ makeCharRange(*this, UTF8StartPtr, CurPtr));
return LexUnicode(Result, CodePoint, CurPtr);
}
-
+
if (isLexingRawMode() || ParsingPreprocessorDirective ||
PP->isPreprocessedOutput()) {
++CurPtr;
diff --git a/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp b/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp
index a598a467816a8..cbec5e6b63856 100644
--- a/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp
@@ -544,6 +544,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
isHalf = false;
isFloat = false;
isImaginary = false;
+ isFloat16 = false;
isFloat128 = false;
MicrosoftInteger = 0;
hadError = false;
@@ -588,6 +589,13 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
if (!isFPConstant) break; // Error for integer constant.
if (isHalf || isFloat || isLong || isFloat128)
break; // HF, FF, LF, QF invalid.
+
+ if (s + 2 < ThisTokEnd && s[1] == '1' && s[2] == '6') {
+ s += 2; // success, eat up 2 characters.
+ isFloat16 = true;
+ continue;
+ }
+
isFloat = true;
continue; // Success.
case 'q': // FP Suffix for "__float128"
@@ -658,9 +666,6 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
break;
}
}
- // "i", "if", and "il" are user-defined suffixes in C++1y.
- if (*s == 'i' && PP.getLangOpts().CPlusPlus14)
- break;
// fall through.
case 'j':
case 'J':
@@ -672,35 +677,35 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
break;
}
- if (s != ThisTokEnd) {
+ // "i", "if", and "il" are user-defined suffixes in C++1y.
+ if (s != ThisTokEnd || isImaginary) {
// FIXME: Don't bother expanding UCNs if !tok.hasUCN().
expandUCNs(UDSuffixBuf, StringRef(SuffixBegin, ThisTokEnd - SuffixBegin));
if (isValidUDSuffix(PP.getLangOpts(), UDSuffixBuf)) {
- // Any suffix pieces we might have parsed are actually part of the
- // ud-suffix.
- isLong = false;
- isUnsigned = false;
- isLongLong = false;
- isFloat = false;
- isHalf = false;
- isImaginary = false;
- MicrosoftInteger = 0;
+ if (!isImaginary) {
+ // Any suffix pieces we might have parsed are actually part of the
+ // ud-suffix.
+ isLong = false;
+ isUnsigned = false;
+ isLongLong = false;
+ isFloat = false;
+ isFloat16 = false;
+ isHalf = false;
+ isImaginary = false;
+ MicrosoftInteger = 0;
+ }
saw_ud_suffix = true;
return;
}
- // Report an error if there are any.
- PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, SuffixBegin - ThisTokBegin),
- diag::err_invalid_suffix_constant)
- << StringRef(SuffixBegin, ThisTokEnd-SuffixBegin) << isFPConstant;
- hadError = true;
- return;
- }
-
- if (isImaginary) {
- PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, SuffixBegin - ThisTokBegin),
- diag::ext_imaginary_constant);
+ if (s != ThisTokEnd) {
+ // Report an error if there are any.
+ PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, SuffixBegin - ThisTokBegin),
+ diag::err_invalid_suffix_constant)
+ << StringRef(SuffixBegin, ThisTokEnd - SuffixBegin) << isFPConstant;
+ hadError = true;
+ }
}
}
@@ -850,8 +855,8 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) {
PP.Diag(TokLoc, PP.getLangOpts().CPlusPlus
? diag::ext_hex_literal_invalid
: diag::ext_hex_constant_invalid);
- else if (PP.getLangOpts().CPlusPlus1z)
- PP.Diag(TokLoc, diag::warn_cxx1z_hex_literal);
+ else if (PP.getLangOpts().CPlusPlus17)
+ PP.Diag(TokLoc, diag::warn_cxx17_hex_literal);
} else if (saw_period) {
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin),
diag::err_hex_constant_requires)
diff --git a/contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp b/contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp
index f791d8d4bacc2..5c0f0623c3e17 100644
--- a/contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp
@@ -33,7 +33,7 @@ MacroArgs *MacroArgs::create(const MacroInfo *MI,
// See if we have an entry with a big enough argument list to reuse on the
// free list. If so, reuse it.
for (MacroArgs **Entry = &PP.MacroArgCache; *Entry;
- Entry = &(*Entry)->ArgCache)
+ Entry = &(*Entry)->ArgCache) {
if ((*Entry)->NumUnexpArgTokens >= UnexpArgTokens.size() &&
(*Entry)->NumUnexpArgTokens < ClosestMatch) {
ResultEnt = Entry;
@@ -44,14 +44,12 @@ MacroArgs *MacroArgs::create(const MacroInfo *MI,
// Otherwise, use the best fit.
ClosestMatch = (*Entry)->NumUnexpArgTokens;
}
-
+ }
MacroArgs *Result;
if (!ResultEnt) {
- // Allocate memory for a MacroArgs object with the lexer tokens at the end.
- Result = (MacroArgs *)malloc(sizeof(MacroArgs) +
- UnexpArgTokens.size() * sizeof(Token));
- // Construct the MacroArgs object.
- new (Result)
+ // Allocate memory for a MacroArgs object with the lexer tokens at the end,
+ // and construct the MacroArgs object.
+ Result = new (std::malloc(totalSizeToAlloc<Token>(UnexpArgTokens.size())))
MacroArgs(UnexpArgTokens.size(), VarargsElided, MI->getNumParams());
} else {
Result = *ResultEnt;
@@ -63,9 +61,14 @@ MacroArgs *MacroArgs::create(const MacroInfo *MI,
}
// Copy the actual unexpanded tokens to immediately after the result ptr.
- if (!UnexpArgTokens.empty())
- std::copy(UnexpArgTokens.begin(), UnexpArgTokens.end(),
- const_cast<Token*>(Result->getUnexpArgument(0)));
+ if (!UnexpArgTokens.empty()) {
+ static_assert(std::is_trivial<Token>::value,
+ "assume trivial copyability if copying into the "
+ "uninitialized array (as opposed to reusing a cached "
+ "MacroArgs)");
+ std::copy(UnexpArgTokens.begin(), UnexpArgTokens.end(),
+ Result->getTrailingObjects<Token>());
+ }
return Result;
}
@@ -93,6 +96,8 @@ MacroArgs *MacroArgs::deallocate() {
// Run the dtor to deallocate the vectors.
this->~MacroArgs();
// Release the memory for the object.
+ static_assert(std::is_trivially_destructible<Token>::value,
+ "assume trivially destructible and forego destructors");
free(this);
return Next;
@@ -113,10 +118,13 @@ unsigned MacroArgs::getArgLength(const Token *ArgPtr) {
/// getUnexpArgument - Return the unexpanded tokens for the specified formal.
///
const Token *MacroArgs::getUnexpArgument(unsigned Arg) const {
+
+ assert(Arg < getNumMacroArguments() && "Invalid arg #");
// The unexpanded argument tokens start immediately after the MacroArgs object
// in memory.
- const Token *Start = (const Token *)(this+1);
+ const Token *Start = getTrailingObjects<Token>();
const Token *Result = Start;
+
// Scan to find Arg.
for (; Arg; ++Result) {
assert(Result < Start+NumUnexpArgTokens && "Invalid arg #");
@@ -127,6 +135,16 @@ const Token *MacroArgs::getUnexpArgument(unsigned Arg) const {
return Result;
}
+// This function assumes that the variadic arguments are the tokens
+// corresponding to the last parameter (ellipsis) - and since tokens are
+// separated by the 'eof' token, if that is the only token corresponding to that
+// last parameter, we know no variadic arguments were supplied.
+bool MacroArgs::invokedWithVariadicArgument(const MacroInfo *const MI) const {
+ if (!MI->isVariadic())
+ return false;
+ const int VariadicArgIndex = getNumMacroArguments() - 1;
+ return getUnexpArgument(VariadicArgIndex)->isNot(tok::eof);
+}
/// ArgNeedsPreexpansion - If we can prove that the argument won't be affected
/// by pre-expansion, return false. Otherwise, conservatively return true.
@@ -145,14 +163,13 @@ bool MacroArgs::ArgNeedsPreexpansion(const Token *ArgTok,
/// getPreExpArgument - Return the pre-expanded form of the specified
/// argument.
-const std::vector<Token> &
-MacroArgs::getPreExpArgument(unsigned Arg, const MacroInfo *MI,
- Preprocessor &PP) {
- assert(Arg < MI->getNumParams() && "Invalid argument number!");
+const std::vector<Token> &MacroArgs::getPreExpArgument(unsigned Arg,
+ Preprocessor &PP) {
+ assert(Arg < getNumMacroArguments() && "Invalid argument number!");
// If we have already computed this, return it.
- if (PreExpArgTokens.size() < MI->getNumParams())
- PreExpArgTokens.resize(MI->getNumParams());
+ if (PreExpArgTokens.size() < getNumMacroArguments())
+ PreExpArgTokens.resize(getNumMacroArguments());
std::vector<Token> &Result = PreExpArgTokens[Arg];
if (!Result.empty()) return Result;
diff --git a/contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp b/contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp
index 6dc7841bc160b..b13767aa1d673 100644
--- a/contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp
@@ -1,4 +1,4 @@
-//===--- MacroInfo.cpp - Information about #defined identifiers -----------===//
+//===- MacroInfo.cpp - Information about #defined identifiers -------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,25 +12,29 @@
//===----------------------------------------------------------------------===//
#include "clang/Lex/MacroInfo.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TokenKinds.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/Token.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <utility>
+
using namespace clang;
MacroInfo::MacroInfo(SourceLocation DefLoc)
- : Location(DefLoc),
- ParameterList(nullptr),
- NumParameters(0),
- IsDefinitionLengthCached(false),
- IsFunctionLike(false),
- IsC99Varargs(false),
- IsGNUVarargs(false),
- IsBuiltinMacro(false),
- HasCommaPasting(false),
- IsDisabled(false),
- IsUsed(false),
- IsAllowRedefinitionsWithoutWarning(false),
- IsWarnIfUnused(false),
- UsedForHeaderGuard(false) {
-}
+ : Location(DefLoc), IsDefinitionLengthCached(false), IsFunctionLike(false),
+ IsC99Varargs(false), IsGNUVarargs(false), IsBuiltinMacro(false),
+ HasCommaPasting(false), IsDisabled(false), IsUsed(false),
+ IsAllowRedefinitionsWithoutWarning(false), IsWarnIfUnused(false),
+ UsedForHeaderGuard(false) {}
unsigned MacroInfo::getDefinitionLengthSlow(const SourceManager &SM) const {
assert(!IsDefinitionLengthCached);
diff --git a/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp b/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp
index 40f78ce25ceb3..fbbae7a095203 100644
--- a/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp
@@ -1,4 +1,4 @@
-//===--- ModuleMap.cpp - Describe the layout of modules ---------*- C++ -*-===//
+//===- ModuleMap.cpp - Describe the layout of modules ---------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,29 +11,47 @@
// of a module as it relates to headers.
//
//===----------------------------------------------------------------------===//
+
#include "clang/Lex/ModuleMap.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/Module.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
-#include "clang/Basic/TargetOptions.h"
+#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/LiteralSupport.h"
+#include "clang/Lex/Token.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Allocator.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Host.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
-#include <stdlib.h>
-#if defined(LLVM_ON_UNIX)
-#include <limits.h>
-#endif
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <cstring>
+#include <string>
+#include <system_error>
+#include <utility>
+
using namespace clang;
Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) {
@@ -80,7 +98,7 @@ ModuleMap::resolveExport(Module *Mod,
// Resolve the module-id.
Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain);
if (!Context)
- return Module::ExportDecl();
+ return {};
return Module::ExportDecl(Context, Unresolved.Wildcard);
}
@@ -256,8 +274,7 @@ ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
const LangOptions &LangOpts, const TargetInfo *Target,
HeaderSearch &HeaderInfo)
: SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
- HeaderInfo(HeaderInfo), BuiltinIncludeDir(nullptr),
- SourceModule(nullptr), NumCreatedModules(0) {
+ HeaderInfo(HeaderInfo) {
MMapLangOpts.LineComment = true;
}
@@ -345,7 +362,7 @@ ModuleMap::KnownHeader
ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File,
SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) {
if (UmbrellaDirs.empty())
- return KnownHeader();
+ return {};
const DirectoryEntry *Dir = File->getDir();
assert(Dir && "file in no directory");
@@ -373,7 +390,7 @@ ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File,
// Resolve the parent path to a directory entry.
Dir = SourceMgr.getFileManager().getDirectory(DirName);
} while (Dir);
- return KnownHeader();
+ return {};
}
static bool violatesPrivateInclude(Module *RequestingModule,
@@ -503,7 +520,7 @@ ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File,
bool AllowTextual) {
auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader)
- return ModuleMap::KnownHeader();
+ return {};
return R;
};
@@ -593,7 +610,7 @@ ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) {
return Header;
}
- return KnownHeader();
+ return {};
}
ArrayRef<ModuleMap::KnownHeader>
@@ -746,8 +763,18 @@ std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
return std::make_pair(Result, true);
}
+Module *ModuleMap::createGlobalModuleForInterfaceUnit(SourceLocation Loc) {
+ assert(!PendingGlobalModule && "created multiple global modules");
+ PendingGlobalModule.reset(
+ new Module("<global>", Loc, nullptr, /*IsFramework*/ false,
+ /*IsExplicit*/ true, NumCreatedModules++));
+ PendingGlobalModule->Kind = Module::GlobalModuleFragment;
+ return PendingGlobalModule.get();
+}
+
Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
- StringRef Name) {
+ StringRef Name,
+ Module *GlobalModule) {
assert(LangOpts.CurrentModule == Name && "module name mismatch");
assert(!Modules[Name] && "redefining existing module");
@@ -757,6 +784,12 @@ Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
Result->Kind = Module::ModuleInterfaceUnit;
Modules[Name] = SourceModule = Result;
+ // Reparent the current global module fragment as a submodule of this module.
+ assert(GlobalModule == PendingGlobalModule.get() &&
+ "unexpected global module");
+ GlobalModule->setParent(Result);
+ PendingGlobalModule.release(); // now owned by parent
+
// Mark the main source file as being within the newly-created module so that
// declarations and macros are properly visibility-restricted to it.
auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
@@ -1173,6 +1206,7 @@ bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
//----------------------------------------------------------------------------//
namespace clang {
+
/// \brief A token in a module map file.
struct MMToken {
enum TokenKind {
@@ -1186,6 +1220,7 @@ namespace clang {
ExcludeKeyword,
ExplicitKeyword,
ExportKeyword,
+ ExportAsKeyword,
ExternKeyword,
FrameworkKeyword,
LinkKeyword,
@@ -1210,6 +1245,7 @@ namespace clang {
union {
// If Kind != IntegerLiteral.
const char *StringData;
+
// If Kind == IntegerLiteral.
uint64_t IntegerValue;
};
@@ -1259,7 +1295,7 @@ namespace clang {
bool IsSystem;
/// \brief Whether an error occurred.
- bool HadError;
+ bool HadError = false;
/// \brief Stores string data for the various string literals referenced
/// during parsing.
@@ -1269,7 +1305,7 @@ namespace clang {
MMToken Tok;
/// \brief The active module.
- Module *ActiveModule;
+ Module *ActiveModule = nullptr;
/// \brief Whether a module uses the 'requires excluded' hack to mark its
/// contents as 'textual'.
@@ -1288,22 +1324,24 @@ namespace clang {
/// (or the end of the file).
void skipUntil(MMToken::TokenKind K);
- typedef SmallVector<std::pair<std::string, SourceLocation>, 2> ModuleId;
+ using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>;
+
bool parseModuleId(ModuleId &Id);
void parseModuleDecl();
void parseExternModuleDecl();
void parseRequiresDecl();
- void parseHeaderDecl(clang::MMToken::TokenKind,
- SourceLocation LeadingLoc);
+ void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc);
void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
void parseExportDecl();
+ void parseExportAsDecl();
void parseUseDecl();
void parseLinkDecl();
void parseConfigMacros();
void parseConflict();
void parseInferredModuleDecl(bool Framework, bool Explicit);
- typedef ModuleMap::Attributes Attributes;
+ using Attributes = ModuleMap::Attributes;
+
bool parseOptionalAttributes(Attributes &Attrs);
public:
@@ -1314,10 +1352,9 @@ namespace clang {
const FileEntry *ModuleMapFile,
const DirectoryEntry *Directory,
bool IsSystem)
- : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
- ModuleMapFile(ModuleMapFile), Directory(Directory),
- IsSystem(IsSystem), HadError(false), ActiveModule(nullptr)
- {
+ : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
+ ModuleMapFile(ModuleMapFile), Directory(Directory),
+ IsSystem(IsSystem) {
Tok.clear();
consumeToken();
}
@@ -1327,7 +1364,8 @@ namespace clang {
bool terminatedByDirective() { return false; }
SourceLocation getLocation() { return Tok.getLocation(); }
};
-}
+
+} // namespace clang
SourceLocation ModuleMapParser::consumeToken() {
SourceLocation Result = Tok.getLocation();
@@ -1348,6 +1386,7 @@ retry:
.Case("exclude", MMToken::ExcludeKeyword)
.Case("explicit", MMToken::ExplicitKeyword)
.Case("export", MMToken::ExportKeyword)
+ .Case("export_as", MMToken::ExportAsKeyword)
.Case("extern", MMToken::ExternKeyword)
.Case("framework", MMToken::FrameworkKeyword)
.Case("header", MMToken::HeaderKeyword)
@@ -1548,20 +1587,26 @@ bool ModuleMapParser::parseModuleId(ModuleId &Id) {
}
namespace {
+
/// \brief Enumerates the known attributes.
enum AttributeKind {
/// \brief An unknown attribute.
AT_unknown,
+
/// \brief The 'system' attribute.
AT_system,
+
/// \brief The 'extern_c' attribute.
AT_extern_c,
+
/// \brief The 'exhaustive' attribute.
AT_exhaustive,
+
/// \brief The 'no_undeclared_includes' attribute.
AT_no_undeclared_includes
};
-}
+
+} // namespace
/// \brief Parse a module declaration.
///
@@ -1575,6 +1620,7 @@ namespace {
/// header-declaration
/// submodule-declaration
/// export-declaration
+/// export-as-declaration
/// link-declaration
///
/// submodule-declaration:
@@ -1683,7 +1729,6 @@ void ModuleMapParser::parseModuleDecl() {
if (parseOptionalAttributes(Attrs))
return;
-
// Parse the opening brace.
if (!Tok.is(MMToken::LBrace)) {
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
@@ -1809,6 +1854,10 @@ void ModuleMapParser::parseModuleDecl() {
parseExportDecl();
break;
+ case MMToken::ExportAsKeyword:
+ parseExportAsDecl();
+ break;
+
case MMToken::UseKeyword:
parseUseDecl();
break;
@@ -2269,6 +2318,41 @@ void ModuleMapParser::parseExportDecl() {
ActiveModule->UnresolvedExports.push_back(Unresolved);
}
+/// \brief Parse a module export_as declaration.
+///
+/// export-as-declaration:
+/// 'export_as' identifier
+void ModuleMapParser::parseExportAsDecl() {
+ assert(Tok.is(MMToken::ExportAsKeyword));
+ consumeToken();
+
+ if (!Tok.is(MMToken::Identifier)) {
+ Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
+ HadError = true;
+ return;
+ }
+
+ if (ActiveModule->Parent) {
+ Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as);
+ consumeToken();
+ return;
+ }
+
+ if (!ActiveModule->ExportAsModule.empty()) {
+ if (ActiveModule->ExportAsModule == Tok.getString()) {
+ Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as)
+ << ActiveModule->Name << Tok.getString();
+ } else {
+ Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as)
+ << ActiveModule->Name << ActiveModule->ExportAsModule
+ << Tok.getString();
+ }
+ }
+
+ ActiveModule->ExportAsModule = Tok.getString();
+ consumeToken();
+}
+
/// \brief Parse a module use declaration.
///
/// use-declaration:
@@ -2516,7 +2600,7 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
Done = true;
break;
- case MMToken::ExcludeKeyword: {
+ case MMToken::ExcludeKeyword:
if (ActiveModule) {
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
<< (ActiveModule != nullptr);
@@ -2535,7 +2619,6 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
.push_back(Tok.getString());
consumeToken();
break;
- }
case MMToken::ExportKeyword:
if (!ActiveModule) {
@@ -2674,6 +2757,7 @@ bool ModuleMapParser::parseModuleMapFile() {
case MMToken::Exclaim:
case MMToken::ExcludeKeyword:
case MMToken::ExportKeyword:
+ case MMToken::ExportAsKeyword:
case MMToken::HeaderKeyword:
case MMToken::Identifier:
case MMToken::LBrace:
diff --git a/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp
index b2450f516ba2a..ca3e70fd1060e 100644
--- a/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp
@@ -33,6 +33,7 @@
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Lex/PTHLexer.h"
#include "clang/Lex/Token.h"
+#include "clang/Lex/VariadicMacroSupport.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
@@ -349,15 +350,19 @@ void Preprocessor::CheckEndOfDirective(const char *DirType, bool EnableMacros) {
/// If ElseOk is true, then \#else directives are ok, if not, then we have
/// already seen one so a \#else directive is a duplicate. When this returns,
/// the caller can lex the first valid token.
-void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc,
+void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
+ SourceLocation IfTokenLoc,
bool FoundNonSkipPortion,
bool FoundElse,
SourceLocation ElseLoc) {
++NumSkipped;
assert(!CurTokenLexer && CurPPLexer && "Lexing a macro, not a file?");
- CurPPLexer->pushConditionalLevel(IfTokenLoc, /*isSkipping*/false,
- FoundNonSkipPortion, FoundElse);
+ if (PreambleConditionalStack.reachedEOFWhileSkipping())
+ PreambleConditionalStack.clearSkipInfo();
+ else
+ CurPPLexer->pushConditionalLevel(IfTokenLoc, /*isSkipping*/ false,
+ FoundNonSkipPortion, FoundElse);
if (CurPTHLexer) {
PTHSkipExcludedConditionalBlock();
@@ -380,16 +385,12 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc,
// If this is the end of the buffer, we have an error.
if (Tok.is(tok::eof)) {
- // Emit errors for each unterminated conditional on the stack, including
- // the current one.
- while (!CurPPLexer->ConditionalStack.empty()) {
- if (CurLexer->getFileLoc() != CodeCompletionFileLoc)
- Diag(CurPPLexer->ConditionalStack.back().IfLoc,
- diag::err_pp_unterminated_conditional);
- CurPPLexer->ConditionalStack.pop_back();
- }
-
+ // We don't emit errors for unterminated conditionals here,
+ // Lexer::LexEndOfFile can do that propertly.
// Just return and let the caller lex after this #include.
+ if (PreambleConditionalStack.isRecording())
+ PreambleConditionalStack.SkipInfo.emplace(
+ HashTokenLoc, IfTokenLoc, FoundNonSkipPortion, FoundElse, ElseLoc);
break;
}
@@ -557,10 +558,10 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc,
// the #if block.
CurPPLexer->LexingRawMode = false;
- if (Callbacks) {
- SourceLocation BeginLoc = ElseLoc.isValid() ? ElseLoc : IfTokenLoc;
- Callbacks->SourceRangeSkipped(SourceRange(BeginLoc, Tok.getLocation()));
- }
+ if (Callbacks)
+ Callbacks->SourceRangeSkipped(
+ SourceRange(HashTokenLoc, CurPPLexer->getSourceLocation()),
+ Tok.getLocation());
}
void Preprocessor::PTHSkipExcludedConditionalBlock() {
@@ -948,15 +949,17 @@ void Preprocessor::HandleDirective(Token &Result) {
default: break;
// C99 6.10.1 - Conditional Inclusion.
case tok::pp_if:
- return HandleIfDirective(Result, ReadAnyTokensBeforeDirective);
+ return HandleIfDirective(Result, SavedHash, ReadAnyTokensBeforeDirective);
case tok::pp_ifdef:
- return HandleIfdefDirective(Result, false, true/*not valid for miopt*/);
+ return HandleIfdefDirective(Result, SavedHash, false,
+ true /*not valid for miopt*/);
case tok::pp_ifndef:
- return HandleIfdefDirective(Result, true, ReadAnyTokensBeforeDirective);
+ return HandleIfdefDirective(Result, SavedHash, true,
+ ReadAnyTokensBeforeDirective);
case tok::pp_elif:
- return HandleElifDirective(Result);
+ return HandleElifDirective(Result, SavedHash);
case tok::pp_else:
- return HandleElseDirective(Result);
+ return HandleElseDirective(Result, SavedHash);
case tok::pp_endif:
return HandleEndifDirective(Result);
@@ -2135,19 +2138,19 @@ void Preprocessor::HandleIncludeMacrosDirective(SourceLocation HashLoc,
// Preprocessor Macro Directive Handling.
//===----------------------------------------------------------------------===//
-/// ReadMacroParameterList - The ( starting an argument list of a macro
-/// definition has just been read. Lex the rest of the arguments and the
+/// ReadMacroParameterList - The ( starting a parameter list of a macro
+/// definition has just been read. Lex the rest of the parameters and the
/// closing ), updating MI with what we learn. Return true if an error occurs
-/// parsing the arg list.
+/// parsing the param list.
bool Preprocessor::ReadMacroParameterList(MacroInfo *MI, Token &Tok) {
- SmallVector<IdentifierInfo*, 32> Arguments;
+ SmallVector<IdentifierInfo*, 32> Parameters;
while (true) {
LexUnexpandedToken(Tok);
switch (Tok.getKind()) {
case tok::r_paren:
- // Found the end of the argument list.
- if (Arguments.empty()) // #define FOO()
+ // Found the end of the parameter list.
+ if (Parameters.empty()) // #define FOO()
return false;
// Otherwise we have #define FOO(A,)
Diag(Tok, diag::err_pp_expected_ident_in_arg_list);
@@ -2170,10 +2173,10 @@ bool Preprocessor::ReadMacroParameterList(MacroInfo *MI, Token &Tok) {
Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);
return true;
}
- // Add the __VA_ARGS__ identifier as an argument.
- Arguments.push_back(Ident__VA_ARGS__);
+ // Add the __VA_ARGS__ identifier as a parameter.
+ Parameters.push_back(Ident__VA_ARGS__);
MI->setIsC99Varargs();
- MI->setParameterList(Arguments, BP);
+ MI->setParameterList(Parameters, BP);
return false;
case tok::eod: // #define X(
Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);
@@ -2188,16 +2191,16 @@ bool Preprocessor::ReadMacroParameterList(MacroInfo *MI, Token &Tok) {
return true;
}
- // If this is already used as an argument, it is used multiple times (e.g.
+ // If this is already used as a parameter, it is used multiple times (e.g.
// #define X(A,A.
- if (std::find(Arguments.begin(), Arguments.end(), II) !=
- Arguments.end()) { // C99 6.10.3p6
+ if (std::find(Parameters.begin(), Parameters.end(), II) !=
+ Parameters.end()) { // C99 6.10.3p6
Diag(Tok, diag::err_pp_duplicate_name_in_arg_list) << II;
return true;
}
- // Add the argument to the macro info.
- Arguments.push_back(II);
+ // Add the parameter to the macro info.
+ Parameters.push_back(II);
// Lex the token after the identifier.
LexUnexpandedToken(Tok);
@@ -2207,7 +2210,7 @@ bool Preprocessor::ReadMacroParameterList(MacroInfo *MI, Token &Tok) {
Diag(Tok, diag::err_pp_expected_comma_in_arg_list);
return true;
case tok::r_paren: // #define X(A)
- MI->setParameterList(Arguments, BP);
+ MI->setParameterList(Parameters, BP);
return false;
case tok::comma: // #define X(A,
break;
@@ -2223,7 +2226,7 @@ bool Preprocessor::ReadMacroParameterList(MacroInfo *MI, Token &Tok) {
}
MI->setIsGNUVarargs();
- MI->setParameterList(Arguments, BP);
+ MI->setParameterList(Parameters, BP);
return false;
}
}
@@ -2290,6 +2293,10 @@ MacroInfo *Preprocessor::ReadOptionalMacroParameterListAndBody(
Token Tok;
LexUnexpandedToken(Tok);
+ // Used to un-poison and then re-poison identifiers of the __VA_ARGS__ ilk
+ // within their appropriate context.
+ VariadicMacroScopeGuard VariadicMacroScopeGuard(*this);
+
// If this is a function-like macro definition, parse the argument list,
// marking each of the identifiers as being used as macro arguments. Also,
// check other constraints on the first token of the macro body.
@@ -2314,14 +2321,14 @@ MacroInfo *Preprocessor::ReadOptionalMacroParameterListAndBody(
return nullptr;
}
- // If this is a definition of a variadic C99 function-like macro, not using
- // the GNU named varargs extension, enabled __VA_ARGS__.
+ // If this is a definition of an ISO C/C++ variadic function-like macro (not
+ // using the GNU named varargs extension) inform our variadic scope guard
+ // which un-poisons and re-poisons certain identifiers (e.g. __VA_ARGS__)
+ // allowed only within the definition of a variadic macro.
- // "Poison" __VA_ARGS__, which can only appear in the expansion of a macro.
- // This gets unpoisoned where it is allowed.
- assert(Ident__VA_ARGS__->isPoisoned() && "__VA_ARGS__ should be poisoned!");
- if (MI->isC99Varargs())
- Ident__VA_ARGS__->setIsPoisoned(false);
+ if (MI->isC99Varargs()) {
+ VariadicMacroScopeGuard.enterScope();
+ }
// Read the first token after the arg list for down below.
LexUnexpandedToken(Tok);
@@ -2367,12 +2374,50 @@ MacroInfo *Preprocessor::ReadOptionalMacroParameterListAndBody(
// Otherwise, read the body of a function-like macro. While we are at it,
// check C99 6.10.3.2p1: ensure that # operators are followed by macro
// parameters in function-like macro expansions.
+
+ VAOptDefinitionContext VAOCtx(*this);
+
while (Tok.isNot(tok::eod)) {
LastTok = Tok;
if (!Tok.isOneOf(tok::hash, tok::hashat, tok::hashhash)) {
MI->AddTokenToBody(Tok);
+ if (VAOCtx.isVAOptToken(Tok)) {
+ // If we're already within a VAOPT, emit an error.
+ if (VAOCtx.isInVAOpt()) {
+ Diag(Tok, diag::err_pp_vaopt_nested_use);
+ return nullptr;
+ }
+ // Ensure VAOPT is followed by a '(' .
+ LexUnexpandedToken(Tok);
+ if (Tok.isNot(tok::l_paren)) {
+ Diag(Tok, diag::err_pp_missing_lparen_in_vaopt_use);
+ return nullptr;
+ }
+ MI->AddTokenToBody(Tok);
+ VAOCtx.sawVAOptFollowedByOpeningParens(Tok.getLocation());
+ LexUnexpandedToken(Tok);
+ if (Tok.is(tok::hashhash)) {
+ Diag(Tok, diag::err_vaopt_paste_at_start);
+ return nullptr;
+ }
+ continue;
+ } else if (VAOCtx.isInVAOpt()) {
+ if (Tok.is(tok::r_paren)) {
+ if (VAOCtx.sawClosingParen()) {
+ const unsigned NumTokens = MI->getNumTokens();
+ assert(NumTokens >= 3 && "Must have seen at least __VA_OPT__( "
+ "and a subsequent tok::r_paren");
+ if (MI->getReplacementToken(NumTokens - 2).is(tok::hashhash)) {
+ Diag(Tok, diag::err_vaopt_paste_at_end);
+ return nullptr;
+ }
+ }
+ } else if (Tok.is(tok::l_paren)) {
+ VAOCtx.sawOpeningParen(Tok.getLocation());
+ }
+ }
// Get the next token of the macro.
LexUnexpandedToken(Tok);
continue;
@@ -2413,12 +2458,14 @@ MacroInfo *Preprocessor::ReadOptionalMacroParameterListAndBody(
continue;
}
+ // Our Token is a stringization operator.
// Get the next token of the macro.
LexUnexpandedToken(Tok);
- // Check for a valid macro arg identifier.
- if (Tok.getIdentifierInfo() == nullptr ||
- MI->getParameterNum(Tok.getIdentifierInfo()) == -1) {
+ // Check for a valid macro arg identifier or __VA_OPT__.
+ if (!VAOCtx.isVAOptToken(Tok) &&
+ (Tok.getIdentifierInfo() == nullptr ||
+ MI->getParameterNum(Tok.getIdentifierInfo()) == -1)) {
// If this is assembler-with-cpp mode, we accept random gibberish after
// the '#' because '#' is often a comment character. However, change
@@ -2431,26 +2478,33 @@ MacroInfo *Preprocessor::ReadOptionalMacroParameterListAndBody(
} else {
Diag(Tok, diag::err_pp_stringize_not_parameter)
<< LastTok.is(tok::hashat);
-
- // Disable __VA_ARGS__ again.
- Ident__VA_ARGS__->setIsPoisoned(true);
return nullptr;
}
}
// Things look ok, add the '#' and param name tokens to the macro.
MI->AddTokenToBody(LastTok);
- MI->AddTokenToBody(Tok);
- LastTok = Tok;
- // Get the next token of the macro.
- LexUnexpandedToken(Tok);
+ // If the token following '#' is VAOPT, let the next iteration handle it
+ // and check it for correctness, otherwise add the token and prime the
+ // loop with the next one.
+ if (!VAOCtx.isVAOptToken(Tok)) {
+ MI->AddTokenToBody(Tok);
+ LastTok = Tok;
+
+ // Get the next token of the macro.
+ LexUnexpandedToken(Tok);
+ }
+ }
+ if (VAOCtx.isInVAOpt()) {
+ assert(Tok.is(tok::eod) && "Must be at End Of preprocessing Directive");
+ Diag(Tok, diag::err_pp_expected_after)
+ << LastTok.getKind() << tok::r_paren;
+ Diag(VAOCtx.getUnmatchedOpeningParenLoc(), diag::note_matching) << tok::l_paren;
+ return nullptr;
}
}
MI->setDefinitionEndLoc(LastTok.getLocation());
- // Disable __VA_ARGS__ again.
- Ident__VA_ARGS__->setIsPoisoned(true);
-
return MI;
}
/// HandleDefineDirective - Implements \#define. This consumes the entire macro
@@ -2614,7 +2668,9 @@ void Preprocessor::HandleUndefDirective() {
/// true if any tokens have been returned or pp-directives activated before this
/// \#ifndef has been lexed.
///
-void Preprocessor::HandleIfdefDirective(Token &Result, bool isIfndef,
+void Preprocessor::HandleIfdefDirective(Token &Result,
+ const Token &HashToken,
+ bool isIfndef,
bool ReadAnyTokensBeforeDirective) {
++NumIf;
Token DirectiveTok = Result;
@@ -2626,8 +2682,9 @@ void Preprocessor::HandleIfdefDirective(Token &Result, bool isIfndef,
if (MacroNameTok.is(tok::eod)) {
// Skip code until we get to #endif. This helps with recovery by not
// emitting an error when the #endif is reached.
- SkipExcludedConditionalBlock(DirectiveTok.getLocation(),
- /*Foundnonskip*/false, /*FoundElse*/false);
+ SkipExcludedConditionalBlock(HashToken.getLocation(),
+ DirectiveTok.getLocation(),
+ /*Foundnonskip*/ false, /*FoundElse*/ false);
return;
}
@@ -2675,15 +2732,17 @@ void Preprocessor::HandleIfdefDirective(Token &Result, bool isIfndef,
/*foundelse*/false);
} else {
// No, skip the contents of this block.
- SkipExcludedConditionalBlock(DirectiveTok.getLocation(),
- /*Foundnonskip*/false,
- /*FoundElse*/false);
+ SkipExcludedConditionalBlock(HashToken.getLocation(),
+ DirectiveTok.getLocation(),
+ /*Foundnonskip*/ false,
+ /*FoundElse*/ false);
}
}
/// HandleIfDirective - Implements the \#if directive.
///
void Preprocessor::HandleIfDirective(Token &IfToken,
+ const Token &HashToken,
bool ReadAnyTokensBeforeDirective) {
++NumIf;
@@ -2721,8 +2780,9 @@ void Preprocessor::HandleIfDirective(Token &IfToken,
/*foundnonskip*/true, /*foundelse*/false);
} else {
// No, skip the contents of this block.
- SkipExcludedConditionalBlock(IfToken.getLocation(), /*Foundnonskip*/false,
- /*FoundElse*/false);
+ SkipExcludedConditionalBlock(HashToken.getLocation(), IfToken.getLocation(),
+ /*Foundnonskip*/ false,
+ /*FoundElse*/ false);
}
}
@@ -2754,7 +2814,7 @@ void Preprocessor::HandleEndifDirective(Token &EndifToken) {
/// HandleElseDirective - Implements the \#else directive.
///
-void Preprocessor::HandleElseDirective(Token &Result) {
+void Preprocessor::HandleElseDirective(Token &Result, const Token &HashToken) {
++NumElse;
// #else directive in a non-skipping conditional... start skipping.
@@ -2785,13 +2845,15 @@ void Preprocessor::HandleElseDirective(Token &Result) {
}
// Finally, skip the rest of the contents of this block.
- SkipExcludedConditionalBlock(CI.IfLoc, /*Foundnonskip*/true,
- /*FoundElse*/true, Result.getLocation());
+ SkipExcludedConditionalBlock(HashToken.getLocation(), CI.IfLoc,
+ /*Foundnonskip*/ true,
+ /*FoundElse*/ true, Result.getLocation());
}
/// HandleElifDirective - Implements the \#elif directive.
///
-void Preprocessor::HandleElifDirective(Token &ElifToken) {
+void Preprocessor::HandleElifDirective(Token &ElifToken,
+ const Token &HashToken) {
++NumElse;
// #elif directive in a non-skipping conditional... start skipping.
@@ -2828,7 +2890,7 @@ void Preprocessor::HandleElifDirective(Token &ElifToken) {
}
// Finally, skip the rest of the contents of this block.
- SkipExcludedConditionalBlock(CI.IfLoc, /*Foundnonskip*/true,
- /*FoundElse*/CI.FoundElse,
- ElifToken.getLocation());
+ SkipExcludedConditionalBlock(
+ HashToken.getLocation(), CI.IfLoc, /*Foundnonskip*/ true,
+ /*FoundElse*/ CI.FoundElse, ElifToken.getLocation());
}
diff --git a/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp b/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp
index 36d7028da6886..e484e9c4c3a38 100644
--- a/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp
@@ -40,10 +40,9 @@ bool Preprocessor::isInPrimaryFile() const {
// If there are any stacked lexers, we're in a #include.
assert(IsFileLexer(IncludeMacroStack[0]) &&
"Top level include stack isn't our primary lexer?");
- return std::none_of(IncludeMacroStack.begin() + 1, IncludeMacroStack.end(),
- [this](const IncludeStackInfo &ISI) -> bool {
- return IsFileLexer(ISI);
- });
+ return std::none_of(
+ IncludeMacroStack.begin() + 1, IncludeMacroStack.end(),
+ [&](const IncludeStackInfo &ISI) -> bool { return IsFileLexer(ISI); });
}
/// getCurrentLexer - Return the current file lexer being lexed from. Note
diff --git a/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp b/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp
index 3f8ede23da563..41633f90c34da 100644
--- a/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp
@@ -369,11 +369,17 @@ void Preprocessor::RegisterBuiltinMacros() {
Ident__has_extension = RegisterBuiltinMacro(*this, "__has_extension");
Ident__has_builtin = RegisterBuiltinMacro(*this, "__has_builtin");
Ident__has_attribute = RegisterBuiltinMacro(*this, "__has_attribute");
+ Ident__has_c_attribute = RegisterBuiltinMacro(*this, "__has_c_attribute");
Ident__has_declspec = RegisterBuiltinMacro(*this, "__has_declspec_attribute");
Ident__has_include = RegisterBuiltinMacro(*this, "__has_include");
Ident__has_include_next = RegisterBuiltinMacro(*this, "__has_include_next");
Ident__has_warning = RegisterBuiltinMacro(*this, "__has_warning");
Ident__is_identifier = RegisterBuiltinMacro(*this, "__is_identifier");
+ Ident__is_target_arch = RegisterBuiltinMacro(*this, "__is_target_arch");
+ Ident__is_target_vendor = RegisterBuiltinMacro(*this, "__is_target_vendor");
+ Ident__is_target_os = RegisterBuiltinMacro(*this, "__is_target_os");
+ Ident__is_target_environment =
+ RegisterBuiltinMacro(*this, "__is_target_environment");
// Modules.
Ident__building_module = RegisterBuiltinMacro(*this, "__building_module");
@@ -1023,7 +1029,7 @@ Token *Preprocessor::cacheMacroExpandedTokens(TokenLexer *tokLexer,
size_t newIndex = MacroExpandedTokens.size();
bool cacheNeedsToGrow = tokens.size() >
- MacroExpandedTokens.capacity()-MacroExpandedTokens.size();
+ MacroExpandedTokens.capacity()-MacroExpandedTokens.size();
MacroExpandedTokens.append(tokens.begin(), tokens.end());
if (cacheNeedsToGrow) {
@@ -1098,6 +1104,8 @@ static bool HasFeature(const Preprocessor &PP, StringRef Feature) {
.Case("address_sanitizer",
LangOpts.Sanitize.hasOneOf(SanitizerKind::Address |
SanitizerKind::KernelAddress))
+ .Case("hwaddress_sanitizer",
+ LangOpts.Sanitize.hasOneOf(SanitizerKind::HWAddress))
.Case("assume_nonnull", true)
.Case("attribute_analyzer_noreturn", true)
.Case("attribute_availability", true)
@@ -1135,9 +1143,11 @@ static bool HasFeature(const Preprocessor &PP, StringRef Feature) {
.Case("nullability_on_arrays", true)
.Case("memory_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Memory))
.Case("thread_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Thread))
- .Case("dataflow_sanitizer", LangOpts.Sanitize.has(SanitizerKind::DataFlow))
+ .Case("dataflow_sanitizer",
+ LangOpts.Sanitize.has(SanitizerKind::DataFlow))
.Case("efficiency_sanitizer",
LangOpts.Sanitize.hasOneOf(SanitizerKind::Efficiency))
+ .Case("scudo", LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo))
// Objective-C features
.Case("objc_arr", LangOpts.ObjCAutoRefCount) // FIXME: REMOVE?
.Case("objc_arc", LangOpts.ObjCAutoRefCount)
@@ -1588,6 +1598,56 @@ static IdentifierInfo *ExpectFeatureIdentifierInfo(Token &Tok,
return nullptr;
}
+/// Implements the __is_target_arch builtin macro.
+static bool isTargetArch(const TargetInfo &TI, const IdentifierInfo *II) {
+ std::string ArchName = II->getName().lower() + "--";
+ llvm::Triple Arch(ArchName);
+ const llvm::Triple &TT = TI.getTriple();
+ if (TT.isThumb()) {
+ // arm matches thumb or thumbv7. armv7 matches thumbv7.
+ if ((Arch.getSubArch() == llvm::Triple::NoSubArch ||
+ Arch.getSubArch() == TT.getSubArch()) &&
+ ((TT.getArch() == llvm::Triple::thumb &&
+ Arch.getArch() == llvm::Triple::arm) ||
+ (TT.getArch() == llvm::Triple::thumbeb &&
+ Arch.getArch() == llvm::Triple::armeb)))
+ return true;
+ }
+ // Check the parsed arch when it has no sub arch to allow Clang to
+ // match thumb to thumbv7 but to prohibit matching thumbv6 to thumbv7.
+ return (Arch.getSubArch() == llvm::Triple::NoSubArch ||
+ Arch.getSubArch() == TT.getSubArch()) &&
+ Arch.getArch() == TT.getArch();
+}
+
+/// Implements the __is_target_vendor builtin macro.
+static bool isTargetVendor(const TargetInfo &TI, const IdentifierInfo *II) {
+ StringRef VendorName = TI.getTriple().getVendorName();
+ if (VendorName.empty())
+ VendorName = "unknown";
+ return VendorName.equals_lower(II->getName());
+}
+
+/// Implements the __is_target_os builtin macro.
+static bool isTargetOS(const TargetInfo &TI, const IdentifierInfo *II) {
+ std::string OSName =
+ (llvm::Twine("unknown-unknown-") + II->getName().lower()).str();
+ llvm::Triple OS(OSName);
+ if (OS.getOS() == llvm::Triple::Darwin) {
+ // Darwin matches macos, ios, etc.
+ return TI.getTriple().isOSDarwin();
+ }
+ return TI.getTriple().getOS() == OS.getOS();
+}
+
+/// Implements the __is_target_environment builtin macro.
+static bool isTargetEnvironment(const TargetInfo &TI,
+ const IdentifierInfo *II) {
+ std::string EnvName = (llvm::Twine("---") + II->getName().lower()).str();
+ llvm::Triple Env(EnvName);
+ return TI.getTriple().getEnvironment() == Env.getEnvironment();
+}
+
/// ExpandBuiltinMacro - If an identifier token is read that is to be expanded
/// as a builtin macro, handle it and return the next token as 'Tok'.
void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
@@ -1750,6 +1810,10 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
.Case("__make_integer_seq", LangOpts.CPlusPlus)
.Case("__type_pack_element", LangOpts.CPlusPlus)
.Case("__builtin_available", true)
+ .Case("__is_target_arch", true)
+ .Case("__is_target_vendor", true)
+ .Case("__is_target_os", true)
+ .Case("__is_target_environment", true)
.Default(false);
}
});
@@ -1774,30 +1838,34 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
return II ? hasAttribute(AttrSyntax::Declspec, nullptr, II,
getTargetInfo(), getLangOpts()) : 0;
});
- } else if (II == Ident__has_cpp_attribute) {
- EvaluateFeatureLikeBuiltinMacro(OS, Tok, II, *this,
- [this](Token &Tok, bool &HasLexedNextToken) -> int {
- IdentifierInfo *ScopeII = nullptr;
- IdentifierInfo *II = ExpectFeatureIdentifierInfo(Tok, *this,
- diag::err_feature_check_malformed);
- if (!II)
- return false;
+ } else if (II == Ident__has_cpp_attribute ||
+ II == Ident__has_c_attribute) {
+ bool IsCXX = II == Ident__has_cpp_attribute;
+ EvaluateFeatureLikeBuiltinMacro(
+ OS, Tok, II, *this, [&](Token &Tok, bool &HasLexedNextToken) -> int {
+ IdentifierInfo *ScopeII = nullptr;
+ IdentifierInfo *II = ExpectFeatureIdentifierInfo(
+ Tok, *this, diag::err_feature_check_malformed);
+ if (!II)
+ return false;
- // It is possible to receive a scope token. Read the "::", if it is
- // available, and the subsequent identifier.
- LexUnexpandedToken(Tok);
- if (Tok.isNot(tok::coloncolon))
- HasLexedNextToken = true;
- else {
- ScopeII = II;
+ // It is possible to receive a scope token. Read the "::", if it is
+ // available, and the subsequent identifier.
LexUnexpandedToken(Tok);
- II = ExpectFeatureIdentifierInfo(Tok, *this,
- diag::err_feature_check_malformed);
- }
+ if (Tok.isNot(tok::coloncolon))
+ HasLexedNextToken = true;
+ else {
+ ScopeII = II;
+ LexUnexpandedToken(Tok);
+ II = ExpectFeatureIdentifierInfo(Tok, *this,
+ diag::err_feature_check_malformed);
+ }
- return II ? hasAttribute(AttrSyntax::CXX, ScopeII, II,
- getTargetInfo(), getLangOpts()) : 0;
- });
+ AttrSyntax Syntax = IsCXX ? AttrSyntax::CXX : AttrSyntax::C;
+ return II ? hasAttribute(Syntax, ScopeII, II, getTargetInfo(),
+ getLangOpts())
+ : 0;
+ });
} else if (II == Ident__has_include ||
II == Ident__has_include_next) {
// The argument to these two builtins should be a parenthesized
@@ -1897,6 +1965,34 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
Diag(LParenLoc, diag::note_matching) << tok::l_paren;
}
return;
+ } else if (II == Ident__is_target_arch) {
+ EvaluateFeatureLikeBuiltinMacro(
+ OS, Tok, II, *this, [this](Token &Tok, bool &HasLexedNextToken) -> int {
+ IdentifierInfo *II = ExpectFeatureIdentifierInfo(
+ Tok, *this, diag::err_feature_check_malformed);
+ return II && isTargetArch(getTargetInfo(), II);
+ });
+ } else if (II == Ident__is_target_vendor) {
+ EvaluateFeatureLikeBuiltinMacro(
+ OS, Tok, II, *this, [this](Token &Tok, bool &HasLexedNextToken) -> int {
+ IdentifierInfo *II = ExpectFeatureIdentifierInfo(
+ Tok, *this, diag::err_feature_check_malformed);
+ return II && isTargetVendor(getTargetInfo(), II);
+ });
+ } else if (II == Ident__is_target_os) {
+ EvaluateFeatureLikeBuiltinMacro(
+ OS, Tok, II, *this, [this](Token &Tok, bool &HasLexedNextToken) -> int {
+ IdentifierInfo *II = ExpectFeatureIdentifierInfo(
+ Tok, *this, diag::err_feature_check_malformed);
+ return II && isTargetOS(getTargetInfo(), II);
+ });
+ } else if (II == Ident__is_target_environment) {
+ EvaluateFeatureLikeBuiltinMacro(
+ OS, Tok, II, *this, [this](Token &Tok, bool &HasLexedNextToken) -> int {
+ IdentifierInfo *II = ExpectFeatureIdentifierInfo(
+ Tok, *this, diag::err_feature_check_malformed);
+ return II && isTargetEnvironment(getTargetInfo(), II);
+ });
} else {
llvm_unreachable("Unknown identifier!");
}
diff --git a/contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp b/contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp
index ec806e8445311..d6c20a13d27be 100644
--- a/contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp
@@ -1,4 +1,4 @@
-//===--- PTHLexer.cpp - Lex from a token stream ---------------------------===//
+//===- PTHLexer.cpp - Lex from a token stream -----------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,19 +12,32 @@
//===----------------------------------------------------------------------===//
#include "clang/Lex/PTHLexer.h"
+#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemStatCache.h"
#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/PTHManager.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/Token.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/EndianStream.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/OnDiskHashTable.h"
+#include <cassert>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
#include <memory>
-#include <system_error>
+#include <utility>
+
using namespace clang;
static const unsigned StoredTokenSize = 1 + 1 + 2 + 4 + 4;
@@ -35,9 +48,8 @@ static const unsigned StoredTokenSize = 1 + 1 + 2 + 4 + 4;
PTHLexer::PTHLexer(Preprocessor &PP, FileID FID, const unsigned char *D,
const unsigned char *ppcond, PTHManager &PM)
- : PreprocessorLexer(&PP, FID), TokBuf(D), CurPtr(D), LastHashTokPtr(nullptr),
- PPCond(ppcond), CurPPCondPtr(ppcond), PTHMgr(PM) {
-
+ : PreprocessorLexer(&PP, FID), TokBuf(D), CurPtr(D), PPCond(ppcond),
+ CurPPCondPtr(ppcond), PTHMgr(PM) {
FileStartLoc = PP.getSourceManager().getLocForStartOfFile(FID);
}
@@ -167,7 +179,7 @@ void PTHLexer::DiscardToEndOfLine() {
// We don't need to actually reconstruct full tokens from the token buffer.
// This saves some copies and it also reduces IdentifierInfo* lookup.
const unsigned char* p = CurPtr;
- while (1) {
+ while (true) {
// Read the token kind. Are we at the end of the file?
tok::TokenKind x = (tok::TokenKind) (uint8_t) *p;
if (x == tok::eof) break;
@@ -186,6 +198,7 @@ void PTHLexer::DiscardToEndOfLine() {
/// SkipBlock - Used by Preprocessor to skip the current conditional block.
bool PTHLexer::SkipBlock() {
using namespace llvm::support;
+
assert(CurPPCondPtr && "No cached PP conditional information.");
assert(LastHashTokPtr && "No known '#' token.");
@@ -303,23 +316,24 @@ SourceLocation PTHLexer::getSourceLocation() {
/// to map from FileEntry objects managed by FileManager to offsets within
/// the PTH file.
namespace {
+
class PTHFileData {
const uint32_t TokenOff;
const uint32_t PPCondOff;
+
public:
PTHFileData(uint32_t tokenOff, uint32_t ppCondOff)
- : TokenOff(tokenOff), PPCondOff(ppCondOff) {}
+ : TokenOff(tokenOff), PPCondOff(ppCondOff) {}
uint32_t getTokenOffset() const { return TokenOff; }
uint32_t getPPCondOffset() const { return PPCondOff; }
};
-
class PTHFileLookupCommonTrait {
public:
- typedef std::pair<unsigned char, StringRef> internal_key_type;
- typedef unsigned hash_value_type;
- typedef unsigned offset_type;
+ using internal_key_type = std::pair<unsigned char, StringRef>;
+ using hash_value_type = unsigned;
+ using offset_type = unsigned;
static hash_value_type ComputeHash(internal_key_type x) {
return llvm::HashString(x.second);
@@ -328,6 +342,7 @@ public:
static std::pair<unsigned, unsigned>
ReadKeyDataLength(const unsigned char*& d) {
using namespace llvm::support;
+
unsigned keyLen =
(unsigned)endian::readNext<uint16_t, little, unaligned>(d);
unsigned dataLen = (unsigned) *(d++);
@@ -340,12 +355,12 @@ public:
}
};
-} // end anonymous namespace
+} // namespace
class PTHManager::PTHFileLookupTrait : public PTHFileLookupCommonTrait {
public:
- typedef const FileEntry* external_key_type;
- typedef PTHFileData data_type;
+ using external_key_type = const FileEntry *;
+ using data_type = PTHFileData;
static internal_key_type GetInternalKey(const FileEntry* FE) {
return std::make_pair((unsigned char) 0x1, FE->getName());
@@ -357,8 +372,9 @@ public:
static PTHFileData ReadData(const internal_key_type& k,
const unsigned char* d, unsigned) {
- assert(k.first == 0x1 && "Only file lookups can match!");
using namespace llvm::support;
+
+ assert(k.first == 0x1 && "Only file lookups can match!");
uint32_t x = endian::readNext<uint32_t, little, unaligned>(d);
uint32_t y = endian::readNext<uint32_t, little, unaligned>(d);
return PTHFileData(x, y);
@@ -367,11 +383,11 @@ public:
class PTHManager::PTHStringLookupTrait {
public:
- typedef uint32_t data_type;
- typedef const std::pair<const char*, unsigned> external_key_type;
- typedef external_key_type internal_key_type;
- typedef uint32_t hash_value_type;
- typedef unsigned offset_type;
+ using data_type = uint32_t;
+ using external_key_type = const std::pair<const char *, unsigned>;
+ using internal_key_type = external_key_type;
+ using hash_value_type = uint32_t;
+ using offset_type = unsigned;
static bool EqualKey(const internal_key_type& a,
const internal_key_type& b) {
@@ -390,6 +406,7 @@ public:
static std::pair<unsigned, unsigned>
ReadKeyDataLength(const unsigned char*& d) {
using namespace llvm::support;
+
return std::make_pair(
(unsigned)endian::readNext<uint16_t, little, unaligned>(d),
sizeof(uint32_t));
@@ -404,6 +421,7 @@ public:
static uint32_t ReadData(const internal_key_type& k, const unsigned char* d,
unsigned) {
using namespace llvm::support;
+
return endian::readNext<uint32_t, little, unaligned>(d);
}
};
@@ -420,11 +438,10 @@ PTHManager::PTHManager(
const unsigned char *spellingBase, const char *originalSourceFile)
: Buf(std::move(buf)), PerIDCache(std::move(perIDCache)),
FileLookup(std::move(fileLookup)), IdDataTable(idDataTable),
- StringIdLookup(std::move(stringIdLookup)), NumIds(numIds), PP(nullptr),
+ StringIdLookup(std::move(stringIdLookup)), NumIds(numIds),
SpellingBase(spellingBase), OriginalSourceFile(originalSourceFile) {}
-PTHManager::~PTHManager() {
-}
+PTHManager::~PTHManager() = default;
static void InvalidPTH(DiagnosticsEngine &Diags, const char *Msg) {
Diags.Report(Diags.getCustomDiagID(DiagnosticsEngine::Error, "%0")) << Msg;
@@ -557,6 +574,7 @@ PTHManager *PTHManager::Create(StringRef file, DiagnosticsEngine &Diags) {
IdentifierInfo* PTHManager::LazilyCreateIdentifierInfo(unsigned PersistentID) {
using namespace llvm::support;
+
// Look in the PTH file for the string data for the IdentifierInfo object.
const unsigned char* TableEntry = IdDataTable + sizeof(uint32_t)*PersistentID;
const unsigned char *IDData =
@@ -566,7 +584,7 @@ IdentifierInfo* PTHManager::LazilyCreateIdentifierInfo(unsigned PersistentID) {
// Allocate the object.
std::pair<IdentifierInfo,const unsigned char*> *Mem =
- Alloc.Allocate<std::pair<IdentifierInfo,const unsigned char*> >();
+ Alloc.Allocate<std::pair<IdentifierInfo, const unsigned char *>>();
Mem->second = IDData;
assert(IDData[0] != '\0');
@@ -626,26 +644,26 @@ PTHLexer *PTHManager::CreateLexer(FileID FID) {
//===----------------------------------------------------------------------===//
namespace {
+
class PTHStatData {
public:
uint64_t Size;
time_t ModTime;
llvm::sys::fs::UniqueID UniqueID;
- const bool HasData;
+ const bool HasData = false;
bool IsDirectory;
+ PTHStatData() = default;
PTHStatData(uint64_t Size, time_t ModTime, llvm::sys::fs::UniqueID UniqueID,
bool IsDirectory)
: Size(Size), ModTime(ModTime), UniqueID(UniqueID), HasData(true),
IsDirectory(IsDirectory) {}
-
- PTHStatData() : HasData(false) {}
};
class PTHStatLookupTrait : public PTHFileLookupCommonTrait {
public:
- typedef StringRef external_key_type; // const char*
- typedef PTHStatData data_type;
+ using external_key_type = StringRef; // const char*
+ using data_type = PTHStatData;
static internal_key_type GetInternalKey(StringRef path) {
// The key 'kind' doesn't matter here because it is ignored in EqualKey.
@@ -660,7 +678,6 @@ public:
static data_type ReadData(const internal_key_type& k, const unsigned char* d,
unsigned) {
-
if (k.first /* File or Directory */) {
bool IsDirectory = true;
if (k.first == 0x1 /* File */) {
@@ -682,11 +699,14 @@ public:
return data_type();
}
};
-} // end anonymous namespace
+
+} // namespace
namespace clang {
+
class PTHStatCache : public FileSystemStatCache {
- typedef llvm::OnDiskChainedHashTable<PTHStatLookupTrait> CacheTy;
+ using CacheTy = llvm::OnDiskChainedHashTable<PTHStatLookupTrait>;
+
CacheTy Cache;
public:
@@ -720,7 +740,8 @@ public:
return CacheExists;
}
};
-}
+
+} // namespace clang
std::unique_ptr<FileSystemStatCache> PTHManager::createStatCache() {
return llvm::make_unique<PTHStatCache>(*FileLookup);
diff --git a/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp
index bf2363a0a6f45..b8acd92521fb5 100644
--- a/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp
@@ -1,4 +1,4 @@
-//===--- Pragma.cpp - Pragma registration and handling --------------------===//
+//===- Pragma.cpp - Pragma registration and handling ----------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,15 +13,21 @@
//===----------------------------------------------------------------------===//
#include "clang/Lex/Pragma.h"
+#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/Module.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Lex/Lexer.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/ModuleLoader.h"
#include "clang/Lex/PPCallbacks.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorLexer.h"
@@ -30,25 +36,27 @@
#include "clang/Lex/TokenLexer.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
#include <cassert>
+#include <cstddef>
#include <cstdint>
#include <limits>
#include <string>
+#include <utility>
#include <vector>
using namespace clang;
// Out-of-line destructor to provide a home for the class.
-PragmaHandler::~PragmaHandler() {
-}
+PragmaHandler::~PragmaHandler() = default;
//===----------------------------------------------------------------------===//
// EmptyPragmaHandler Implementation.
@@ -144,15 +152,14 @@ namespace {
class LexingFor_PragmaRAII {
Preprocessor &PP;
bool InMacroArgPreExpansion;
- bool Failed;
+ bool Failed = false;
Token &OutTok;
Token PragmaTok;
public:
LexingFor_PragmaRAII(Preprocessor &PP, bool InMacroArgPreExpansion,
Token &Tok)
- : PP(PP), InMacroArgPreExpansion(InMacroArgPreExpansion),
- Failed(false), OutTok(Tok) {
+ : PP(PP), InMacroArgPreExpansion(InMacroArgPreExpansion), OutTok(Tok) {
if (InMacroArgPreExpansion) {
PragmaTok = OutTok;
PP.EnableBacktrackAtThisPos();
@@ -186,13 +193,12 @@ public:
}
};
-} // end anonymous namespace
+} // namespace
/// Handle_Pragma - Read a _Pragma directive, slice it up, process it, then
/// return the first token after the directive. The _Pragma token has just
/// been read into 'Tok'.
void Preprocessor::Handle_Pragma(Token &Tok) {
-
// This works differently if we are pre-expanding a macro argument.
// In that case we don't actually "activate" the pragma now, we only lex it
// until we are sure it is lexically correct and then we backtrack so that
@@ -381,7 +387,6 @@ void Preprocessor::HandleMicrosoft__pragma(Token &Tok) {
}
/// HandlePragmaOnce - Handle \#pragma once. OnceTok is the 'once'.
-///
void Preprocessor::HandlePragmaOnce(Token &OnceTok) {
// Don't honor the 'once' when handling the primary source file, unless
// this is a prefix to a TU, which indicates we're generating a PCH file, or
@@ -406,7 +411,6 @@ void Preprocessor::HandlePragmaMark() {
}
/// HandlePragmaPoison - Handle \#pragma GCC poison. PoisonTok is the 'poison'.
-///
void Preprocessor::HandlePragmaPoison() {
Token Tok;
@@ -461,7 +465,6 @@ void Preprocessor::HandlePragmaSystemHeader(Token &SysHeaderTok) {
// Mark the file as a system header.
HeaderInfo.MarkFileSystemHeader(TheLexer->getFileEntry());
-
PresumedLoc PLoc = SourceMgr.getPresumedLoc(SysHeaderTok.getLocation());
if (PLoc.isInvalid())
return;
@@ -482,7 +485,6 @@ void Preprocessor::HandlePragmaSystemHeader(Token &SysHeaderTok) {
}
/// HandlePragmaDependency - Handle \#pragma GCC dependency "foo" blah.
-///
void Preprocessor::HandlePragmaDependency(Token &DependencyTok) {
Token FilenameTok;
CurPPLexer->LexIncludeFilename(FilenameTok);
@@ -623,7 +625,7 @@ void Preprocessor::HandlePragmaPopMacro(Token &PopMacroTok) {
if (!IdentInfo) return;
// Find the vector<MacroInfo*> associated with the macro.
- llvm::DenseMap<IdentifierInfo*, std::vector<MacroInfo*> >::iterator iter =
+ llvm::DenseMap<IdentifierInfo *, std::vector<MacroInfo *>>::iterator iter =
PragmaPushMacroInfo.find(IdentInfo);
if (iter != PragmaPushMacroInfo.end()) {
// Forget the MacroInfo currently associated with IdentInfo.
@@ -962,6 +964,7 @@ namespace {
/// PragmaOnceHandler - "\#pragma once" marks the file as atomically included.
struct PragmaOnceHandler : public PragmaHandler {
PragmaOnceHandler() : PragmaHandler("once") {}
+
void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &OnceTok) override {
PP.CheckEndOfDirective("pragma once");
@@ -1116,7 +1119,6 @@ struct PragmaDebugHandler : public PragmaHandler {
#ifdef _MSC_VER
#pragma warning(default : 4717)
#endif
-
};
/// PragmaDiagnosticHandler - e.g. '\#pragma GCC diagnostic ignored "-Wformat"'
@@ -1125,8 +1127,8 @@ private:
const char *Namespace;
public:
- explicit PragmaDiagnosticHandler(const char *NS) :
- PragmaHandler("diagnostic"), Namespace(NS) {}
+ explicit PragmaDiagnosticHandler(const char *NS)
+ : PragmaHandler("diagnostic"), Namespace(NS) {}
void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &DiagToken) override {
@@ -1330,6 +1332,7 @@ struct PragmaWarningHandler : public PragmaHandler {
/// PragmaIncludeAliasHandler - "\#pragma include_alias("...")".
struct PragmaIncludeAliasHandler : public PragmaHandler {
PragmaIncludeAliasHandler() : PragmaHandler("include_alias") {}
+
void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &IncludeAliasTok) override {
PP.HandlePragmaIncludeAlias(IncludeAliasTok);
@@ -1370,7 +1373,8 @@ private:
public:
PragmaMessageHandler(PPCallbacks::PragmaMessageKind Kind,
StringRef Namespace = StringRef())
- : PragmaHandler(PragmaKind(Kind, true)), Kind(Kind), Namespace(Namespace) {}
+ : PragmaHandler(PragmaKind(Kind, true)), Kind(Kind),
+ Namespace(Namespace) {}
void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &Tok) override {
@@ -1615,8 +1619,7 @@ struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler {
/// PragmaSTDC_CX_LIMITED_RANGEHandler - "\#pragma STDC CX_LIMITED_RANGE ...".
struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler {
- PragmaSTDC_CX_LIMITED_RANGEHandler()
- : PragmaHandler("CX_LIMITED_RANGE") {}
+ PragmaSTDC_CX_LIMITED_RANGEHandler() : PragmaHandler("CX_LIMITED_RANGE") {}
void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &Tok) override {
@@ -1627,7 +1630,7 @@ struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler {
/// PragmaSTDC_UnknownHandler - "\#pragma STDC ...".
struct PragmaSTDC_UnknownHandler : public PragmaHandler {
- PragmaSTDC_UnknownHandler() {}
+ PragmaSTDC_UnknownHandler() = default;
void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &UnknownTok) override {
@@ -1725,6 +1728,7 @@ struct PragmaAssumeNonNullHandler : public PragmaHandler {
// The start location we want after processing this.
SourceLocation NewLoc;
+ PPCallbacks *Callbacks = PP.getPPCallbacks();
if (IsBegin) {
// Complain about attempts to re-enter an audit.
@@ -1733,6 +1737,8 @@ struct PragmaAssumeNonNullHandler : public PragmaHandler {
PP.Diag(BeginLoc, diag::note_pragma_entered_here);
}
NewLoc = Loc;
+ if (Callbacks)
+ Callbacks->PragmaAssumeNonNullBegin(NewLoc);
} else {
// Complain about attempts to leave an audit that doesn't exist.
if (!BeginLoc.isValid()) {
@@ -1740,6 +1746,8 @@ struct PragmaAssumeNonNullHandler : public PragmaHandler {
return;
}
NewLoc = SourceLocation();
+ if (Callbacks)
+ Callbacks->PragmaAssumeNonNullEnd(NewLoc);
}
PP.setPragmaAssumeNonNullLoc(NewLoc);
@@ -1758,7 +1766,7 @@ struct PragmaAssumeNonNullHandler : public PragmaHandler {
/// <a href="http://msdn.microsoft.com/en-us/library/b6xkz944(v=vs.80).aspx">editor-only</a>
/// pragma, just skipped by compiler.
struct PragmaRegionHandler : public PragmaHandler {
- PragmaRegionHandler(const char *pragma) : PragmaHandler(pragma) { }
+ PragmaRegionHandler(const char *pragma) : PragmaHandler(pragma) {}
void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &NameTok) override {
@@ -1769,7 +1777,7 @@ struct PragmaRegionHandler : public PragmaHandler {
}
};
-} // end anonymous namespace
+} // namespace
/// RegisterBuiltinPragmas - Install the standard preprocessor pragmas:
/// \#pragma GCC poison/system_header/dependency and \#pragma once.
diff --git a/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp b/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp
index 03c4cbe589d50..af439dbfa5842 100644
--- a/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp
@@ -1,4 +1,4 @@
-//===--- PreprocessingRecord.cpp - Record of Preprocessing ------*- C++ -*-===//
+//===- PreprocessingRecord.cpp - Record of Preprocessing ------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,15 +11,34 @@
// of what occurred during preprocessing, and its helpers.
//
//===----------------------------------------------------------------------===//
+
#include "clang/Lex/PreprocessingRecord.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TokenKinds.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/Token.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Capacity.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstring>
+#include <iterator>
+#include <utility>
+#include <vector>
using namespace clang;
-ExternalPreprocessingRecordSource::~ExternalPreprocessingRecordSource() { }
+ExternalPreprocessingRecordSource::~ExternalPreprocessingRecordSource() =
+ default;
InclusionDirective::InclusionDirective(PreprocessingRecord &PPRec,
InclusionKind Kind, StringRef FileName,
@@ -33,10 +52,7 @@ InclusionDirective::InclusionDirective(PreprocessingRecord &PPRec,
this->FileName = StringRef(Memory, FileName.size());
}
-PreprocessingRecord::PreprocessingRecord(SourceManager &SM)
- : SourceMgr(SM),
- ExternalSource(nullptr) {
-}
+PreprocessingRecord::PreprocessingRecord(SourceManager &SM) : SourceMgr(SM) {}
/// \brief Returns a pair of [Begin, End) iterators of preprocessed entities
/// that source range \p Range encompasses.
@@ -166,7 +182,7 @@ template <SourceLocation (SourceRange::*getRangeLoc)() const>
struct PPEntityComp {
const SourceManager &SM;
- explicit PPEntityComp(const SourceManager &SM) : SM(SM) { }
+ explicit PPEntityComp(const SourceManager &SM) : SM(SM) {}
bool operator()(PreprocessedEntity *L, PreprocessedEntity *R) const {
SourceLocation LHS = getLoc(L);
@@ -190,7 +206,7 @@ struct PPEntityComp {
}
};
-}
+} // namespace
unsigned PreprocessingRecord::findBeginLocalPreprocessedEntity(
SourceLocation Loc) const {
@@ -271,7 +287,7 @@ PreprocessingRecord::addPreprocessedEntity(PreprocessedEntity *Entity) {
// FM(M1, M2)
// \endcode
- typedef std::vector<PreprocessedEntity *>::iterator pp_iter;
+ using pp_iter = std::vector<PreprocessedEntity *>::iterator;
// Usually there are few macro expansions when defining the filename, do a
// linear search for a few entities.
@@ -400,8 +416,9 @@ void PreprocessingRecord::Defined(const Token &MacroNameTok,
MacroNameTok.getLocation());
}
-void PreprocessingRecord::SourceRangeSkipped(SourceRange Range) {
- SkippedRanges.push_back(Range);
+void PreprocessingRecord::SourceRangeSkipped(SourceRange Range,
+ SourceLocation EndifLoc) {
+ SkippedRanges.emplace_back(Range.getBegin(), EndifLoc);
}
void PreprocessingRecord::MacroExpands(const Token &Id,
@@ -429,7 +446,7 @@ void PreprocessingRecord::MacroUndefined(const Token &Id,
void PreprocessingRecord::InclusionDirective(
SourceLocation HashLoc,
- const clang::Token &IncludeTok,
+ const Token &IncludeTok,
StringRef FileName,
bool IsAngled,
CharSourceRange FilenameRange,
@@ -469,10 +486,10 @@ void PreprocessingRecord::InclusionDirective(
EndLoc = EndLoc.getLocWithOffset(-1); // the InclusionDirective expects
// a token range.
}
- clang::InclusionDirective *ID
- = new (*this) clang::InclusionDirective(*this, Kind, FileName, !IsAngled,
- (bool)Imported,
- File, SourceRange(HashLoc, EndLoc));
+ clang::InclusionDirective *ID =
+ new (*this) clang::InclusionDirective(*this, Kind, FileName, !IsAngled,
+ (bool)Imported, File,
+ SourceRange(HashLoc, EndLoc));
addPreprocessedEntity(ID);
}
diff --git a/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp b/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp
index 7979be773aa13..c291a4b99d101 100644
--- a/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp
@@ -1,4 +1,4 @@
-//===--- Preprocess.cpp - C Language Family Preprocessor Implementation ---===//
+//===- Preprocess.cpp - C Language Family Preprocessor Implementation -----===//
//
// The LLVM Compiler Infrastructure
//
@@ -28,22 +28,33 @@
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemStatCache.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/Module.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/CodeCompletionHandler.h"
#include "clang/Lex/ExternalPreprocessorSource.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Lex/Lexer.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Lex/MacroArgs.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/ModuleLoader.h"
+#include "clang/Lex/PTHLexer.h"
#include "clang/Lex/PTHManager.h"
#include "clang/Lex/Pragma.h"
#include "clang/Lex/PreprocessingRecord.h"
+#include "clang/Lex/PreprocessorLexer.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Lex/ScratchBuffer.h"
+#include "clang/Lex/Token.h"
+#include "clang/Lex/TokenLexer.h"
#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
@@ -65,8 +76,7 @@ using namespace clang;
LLVM_INSTANTIATE_REGISTRY(PragmaHandlerRegistry)
-//===----------------------------------------------------------------------===//
-ExternalPreprocessorSource::~ExternalPreprocessorSource() { }
+ExternalPreprocessorSource::~ExternalPreprocessorSource() = default;
Preprocessor::Preprocessor(std::shared_ptr<PreprocessorOptions> PPOpts,
DiagnosticsEngine &diags, LangOptions &opts,
@@ -74,34 +84,16 @@ Preprocessor::Preprocessor(std::shared_ptr<PreprocessorOptions> PPOpts,
HeaderSearch &Headers, ModuleLoader &TheModuleLoader,
IdentifierInfoLookup *IILookup, bool OwnsHeaders,
TranslationUnitKind TUKind)
- : PPOpts(std::move(PPOpts)), Diags(&diags), LangOpts(opts), Target(nullptr),
- AuxTarget(nullptr), FileMgr(Headers.getFileMgr()), SourceMgr(SM),
+ : PPOpts(std::move(PPOpts)), Diags(&diags), LangOpts(opts),
+ FileMgr(Headers.getFileMgr()), SourceMgr(SM),
PCMCache(PCMCache), ScratchBuf(new ScratchBuffer(SourceMgr)),
HeaderInfo(Headers), TheModuleLoader(TheModuleLoader),
ExternalSource(nullptr), Identifiers(opts, IILookup),
- PragmaHandlers(new PragmaNamespace(StringRef())),
- IncrementalProcessing(false), TUKind(TUKind), CodeComplete(nullptr),
- CodeCompletionFile(nullptr), CodeCompletionOffset(0),
- LastTokenWasAt(false), ModuleImportExpectsIdentifier(false),
- CodeCompletionReached(false), CodeCompletionII(nullptr),
- MainFileDir(nullptr), SkipMainFilePreamble(0, true), CurPPLexer(nullptr),
- CurDirLookup(nullptr), CurLexerKind(CLK_Lexer),
- CurLexerSubmodule(nullptr), Callbacks(nullptr),
- CurSubmoduleState(&NullSubmoduleState), MacroArgCache(nullptr),
- Record(nullptr), MIChainHead(nullptr) {
+ PragmaHandlers(new PragmaNamespace(StringRef())), TUKind(TUKind),
+ SkipMainFilePreamble(0, true),
+ CurSubmoduleState(&NullSubmoduleState) {
OwnsHeaderSearch = OwnsHeaders;
- CounterValue = 0; // __COUNTER__ starts at 0.
-
- // Clear stats.
- NumDirectives = NumDefined = NumUndefined = NumPragma = 0;
- NumIf = NumElse = NumEndif = 0;
- NumEnteredSourceFiles = 0;
- NumMacroExpanded = NumFnMacroExpanded = NumBuiltinMacroExpanded = 0;
- NumFastMacroExpanded = NumTokenPaste = NumFastTokenPaste = 0;
- MaxIncludeStackDepth = 0;
- NumSkipped = 0;
-
// Default to discarding comments.
KeepComments = false;
KeepMacroComments = false;
@@ -117,16 +109,20 @@ Preprocessor::Preprocessor(std::shared_ptr<PreprocessorOptions> PPOpts,
ParsingIfOrElifDirective = false;
PreprocessedOutput = false;
- CachedLexPos = 0;
-
// We haven't read anything from the external source.
ReadMacrosFromExternalSource = false;
-
- // "Poison" __VA_ARGS__, which can only appear in the expansion of a macro.
- // This gets unpoisoned where it is allowed.
+
+ // "Poison" __VA_ARGS__, __VA_OPT__ which can only appear in the expansion of
+ // a macro. They get unpoisoned where it is allowed.
(Ident__VA_ARGS__ = getIdentifierInfo("__VA_ARGS__"))->setIsPoisoned();
SetPoisonReason(Ident__VA_ARGS__,diag::ext_pp_bad_vaargs_use);
-
+ if (getLangOpts().CPlusPlus2a) {
+ (Ident__VA_OPT__ = getIdentifierInfo("__VA_OPT__"))->setIsPoisoned();
+ SetPoisonReason(Ident__VA_OPT__,diag::ext_pp_bad_vaopt_use);
+ } else {
+ Ident__VA_OPT__ = nullptr;
+ }
+
// Initialize the pragma handlers.
RegisterBuiltinPragmas();
@@ -516,9 +512,9 @@ void Preprocessor::EnterMainSourceFile() {
// If we've been asked to skip bytes in the main file (e.g., as part of a
// precompiled preamble), do so now.
if (SkipMainFilePreamble.first > 0)
- CurLexer->SkipBytes(SkipMainFilePreamble.first,
- SkipMainFilePreamble.second);
-
+ CurLexer->SetByteOffset(SkipMainFilePreamble.first,
+ SkipMainFilePreamble.second);
+
// Tell the header info that the main file was entered. If the file is later
// #imported, it won't be re-entered.
if (const FileEntry *FE = SourceMgr.getFileEntryForID(MainFileID))
@@ -544,6 +540,13 @@ void Preprocessor::replayPreambleConditionalStack() {
"CurPPLexer is null when calling replayPreambleConditionalStack.");
CurPPLexer->setConditionalLevels(PreambleConditionalStack.getStack());
PreambleConditionalStack.doneReplaying();
+ if (PreambleConditionalStack.reachedEOFWhileSkipping())
+ SkipExcludedConditionalBlock(
+ PreambleConditionalStack.SkipInfo->HashTokenLoc,
+ PreambleConditionalStack.SkipInfo->IfTokenLoc,
+ PreambleConditionalStack.SkipInfo->FoundNonSkipPortion,
+ PreambleConditionalStack.SkipInfo->FoundElse,
+ PreambleConditionalStack.SkipInfo->ElseLoc);
}
}
@@ -586,7 +589,7 @@ IdentifierInfo *Preprocessor::LookUpIdentifierInfo(Token &Identifier) const {
Identifier.setIdentifierInfo(II);
if (getLangOpts().MSVCCompat && II->isCPlusPlusOperatorKeyword() &&
getSourceManager().isInSystemHeader(Identifier.getLocation()))
- Identifier.setKind(clang::tok::identifier);
+ Identifier.setKind(tok::identifier);
else
Identifier.setKind(II->getTokenID());
@@ -632,6 +635,8 @@ static diag::kind getFutureCompatDiagKind(const IdentifierInfo &II,
return llvm::StringSwitch<diag::kind>(II.getName())
#define CXX11_KEYWORD(NAME, FLAGS) \
.Case(#NAME, diag::warn_cxx11_keyword)
+#define CXX2A_KEYWORD(NAME, FLAGS) \
+ .Case(#NAME, diag::warn_cxx2a_keyword)
#include "clang/Basic/TokenKinds.def"
;
@@ -665,13 +670,15 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) {
// unpoisoned it if we're defining a C99 macro.
if (II.isOutOfDate()) {
bool CurrentIsPoisoned = false;
- if (&II == Ident__VA_ARGS__)
- CurrentIsPoisoned = Ident__VA_ARGS__->isPoisoned();
+ const bool IsSpecialVariadicMacro =
+ &II == Ident__VA_ARGS__ || &II == Ident__VA_OPT__;
+ if (IsSpecialVariadicMacro)
+ CurrentIsPoisoned = II.isPoisoned();
updateOutOfDateIdentifier(II);
Identifier.setKind(II.getTokenID());
- if (&II == Ident__VA_ARGS__)
+ if (IsSpecialVariadicMacro)
II.setIsPoisoned(CurrentIsPoisoned);
}
@@ -924,8 +931,8 @@ void Preprocessor::addCommentHandler(CommentHandler *Handler) {
}
void Preprocessor::removeCommentHandler(CommentHandler *Handler) {
- std::vector<CommentHandler *>::iterator Pos
- = std::find(CommentHandlers.begin(), CommentHandlers.end(), Handler);
+ std::vector<CommentHandler *>::iterator Pos =
+ std::find(CommentHandlers.begin(), CommentHandlers.end(), Handler);
assert(Pos != CommentHandlers.end() && "Comment handler not registered");
CommentHandlers.erase(Pos);
}
@@ -944,11 +951,11 @@ bool Preprocessor::HandleComment(Token &result, SourceRange Comment) {
return true;
}
-ModuleLoader::~ModuleLoader() { }
+ModuleLoader::~ModuleLoader() = default;
-CommentHandler::~CommentHandler() { }
+CommentHandler::~CommentHandler() = default;
-CodeCompletionHandler::~CodeCompletionHandler() { }
+CodeCompletionHandler::~CodeCompletionHandler() = default;
void Preprocessor::createPreprocessingRecord() {
if (Record)
diff --git a/contrib/llvm/tools/clang/lib/Lex/PreprocessorLexer.cpp b/contrib/llvm/tools/clang/lib/Lex/PreprocessorLexer.cpp
index 33ccbc0cfc941..2e85f46f52c59 100644
--- a/contrib/llvm/tools/clang/lib/Lex/PreprocessorLexer.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/PreprocessorLexer.cpp
@@ -1,4 +1,4 @@
-//===--- PreprocessorLexer.cpp - C Language Family Lexer ------------------===//
+//===- PreprocessorLexer.cpp - C Language Family Lexer --------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,14 +15,15 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/Token.h"
+#include <cassert>
+
using namespace clang;
-void PreprocessorLexer::anchor() { }
+void PreprocessorLexer::anchor() {}
PreprocessorLexer::PreprocessorLexer(Preprocessor *pp, FileID fid)
- : PP(pp), FID(fid), InitialNumSLocEntries(0),
- ParsingPreprocessorDirective(false),
- ParsingFilename(false), LexingRawMode(false) {
+ : PP(pp), FID(fid) {
if (pp)
InitialNumSLocEntries = pp->getSourceManager().local_sloc_entry_size();
}
diff --git a/contrib/llvm/tools/clang/lib/Lex/TokenConcatenation.cpp b/contrib/llvm/tools/clang/lib/Lex/TokenConcatenation.cpp
index d1facd9c68796..ec73479cb54f1 100644
--- a/contrib/llvm/tools/clang/lib/Lex/TokenConcatenation.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/TokenConcatenation.cpp
@@ -99,10 +99,14 @@ TokenConcatenation::TokenConcatenation(Preprocessor &pp) : PP(pp) {
TokenInfo[tok::utf32_char_constant ] |= aci_custom;
}
- // These tokens have custom code in C++1z mode.
- if (PP.getLangOpts().CPlusPlus1z)
+ // These tokens have custom code in C++17 mode.
+ if (PP.getLangOpts().CPlusPlus17)
TokenInfo[tok::utf8_char_constant] |= aci_custom;
+ // These tokens have custom code in C++2a mode.
+ if (PP.getLangOpts().CPlusPlus2a)
+ TokenInfo[tok::lessequal ] |= aci_custom_firstchar;
+
// These tokens change behavior if followed by an '='.
TokenInfo[tok::amp ] |= aci_avoid_equal; // &=
TokenInfo[tok::plus ] |= aci_avoid_equal; // +=
@@ -283,5 +287,7 @@ bool TokenConcatenation::AvoidConcat(const Token &PrevPrevTok,
return FirstChar == '#' || FirstChar == '@' || FirstChar == '%';
case tok::arrow: // ->*
return PP.getLangOpts().CPlusPlus && FirstChar == '*';
+ case tok::lessequal: // <=> (C++2a)
+ return PP.getLangOpts().CPlusPlus2a && FirstChar == '>';
}
}
diff --git a/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp b/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp
index c2e49ba919a93..d7f1c7a93fdae 100644
--- a/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp
@@ -1,4 +1,4 @@
-//===--- TokenLexer.cpp - Lex from a token stream -------------------------===//
+//===- TokenLexer.cpp - Lex from a token stream ---------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,12 +12,25 @@
//===----------------------------------------------------------------------===//
#include "clang/Lex/TokenLexer.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TokenKinds.h"
#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Lex/Lexer.h"
#include "clang/Lex/MacroArgs.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/Token.h"
+#include "clang/Lex/VariadicMacroSupport.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/iterator_range.h"
+#include <cassert>
+#include <cstring>
using namespace clang;
@@ -31,7 +44,7 @@ void TokenLexer::Init(Token &Tok, SourceLocation ELEnd, MacroInfo *MI,
Macro = MI;
ActualArgs = Actuals;
- CurToken = 0;
+ CurTokenIdx = 0;
ExpandLocStart = Tok.getLocation();
ExpandLocEnd = ELEnd;
@@ -90,7 +103,7 @@ void TokenLexer::Init(const Token *TokArray, unsigned NumToks,
OwnsTokens = ownsTokens;
DisableMacroExpansion = disableMacroExpansion;
NumTokens = NumToks;
- CurToken = 0;
+ CurTokenIdx = 0;
ExpandLocStart = ExpandLocEnd = SourceLocation();
AtStartOfLine = false;
HasLeadingSpace = false;
@@ -168,6 +181,59 @@ bool TokenLexer::MaybeRemoveCommaBeforeVaArgs(
return true;
}
+void TokenLexer::stringifyVAOPTContents(
+ SmallVectorImpl<Token> &ResultToks, const VAOptExpansionContext &VCtx,
+ const SourceLocation VAOPTClosingParenLoc) {
+ const int NumToksPriorToVAOpt = VCtx.getNumberOfTokensPriorToVAOpt();
+ const unsigned int NumVAOptTokens = ResultToks.size() - NumToksPriorToVAOpt;
+ Token *const VAOPTTokens =
+ NumVAOptTokens ? &ResultToks[NumToksPriorToVAOpt] : nullptr;
+
+ SmallVector<Token, 64> ConcatenatedVAOPTResultToks;
+ // FIXME: Should we keep track within VCtx that we did or didnot
+ // encounter pasting - and only then perform this loop.
+
+ // Perform token pasting (concatenation) prior to stringization.
+ for (unsigned int CurTokenIdx = 0; CurTokenIdx != NumVAOptTokens;
+ ++CurTokenIdx) {
+ if (VAOPTTokens[CurTokenIdx].is(tok::hashhash)) {
+ assert(CurTokenIdx != 0 &&
+ "Can not have __VAOPT__ contents begin with a ##");
+ Token &LHS = VAOPTTokens[CurTokenIdx - 1];
+ pasteTokens(LHS, llvm::makeArrayRef(VAOPTTokens, NumVAOptTokens),
+ CurTokenIdx);
+ // Replace the token prior to the first ## in this iteration.
+ ConcatenatedVAOPTResultToks.back() = LHS;
+ if (CurTokenIdx == NumVAOptTokens)
+ break;
+ }
+ ConcatenatedVAOPTResultToks.push_back(VAOPTTokens[CurTokenIdx]);
+ }
+
+ ConcatenatedVAOPTResultToks.push_back(VCtx.getEOFTok());
+ // Get the SourceLocation that represents the start location within
+ // the macro definition that marks where this string is substituted
+ // into: i.e. the __VA_OPT__ and the ')' within the spelling of the
+ // macro definition, and use it to indicate that the stringified token
+ // was generated from that location.
+ const SourceLocation ExpansionLocStartWithinMacro =
+ getExpansionLocForMacroDefLoc(VCtx.getVAOptLoc());
+ const SourceLocation ExpansionLocEndWithinMacro =
+ getExpansionLocForMacroDefLoc(VAOPTClosingParenLoc);
+
+ Token StringifiedVAOPT = MacroArgs::StringifyArgument(
+ &ConcatenatedVAOPTResultToks[0], PP, VCtx.hasCharifyBefore() /*Charify*/,
+ ExpansionLocStartWithinMacro, ExpansionLocEndWithinMacro);
+
+ if (VCtx.getLeadingSpaceForStringifiedToken())
+ StringifiedVAOPT.setFlag(Token::LeadingSpace);
+
+ StringifiedVAOPT.setFlag(Token::StringifiedInMacro);
+ // Resize (shrink) the token stream to just capture this stringified token.
+ ResultToks.resize(NumToksPriorToVAOpt + 1);
+ ResultToks.back() = StringifiedVAOPT;
+}
+
/// Expand the arguments of a function-like macro so that we can quickly
/// return preexpanded tokens from Tokens.
void TokenLexer::ExpandFunctionArguments() {
@@ -178,28 +244,117 @@ void TokenLexer::ExpandFunctionArguments() {
// we install the newly expanded sequence as the new 'Tokens' list.
bool MadeChange = false;
- for (unsigned i = 0, e = NumTokens; i != e; ++i) {
- // If we found the stringify operator, get the argument stringified. The
- // preprocessor already verified that the following token is a macro name
- // when the #define was parsed.
- const Token &CurTok = Tokens[i];
+ const bool CalledWithVariadicArguments =
+ ActualArgs->invokedWithVariadicArgument(Macro);
+
+ VAOptExpansionContext VCtx(PP);
+
+ for (unsigned I = 0, E = NumTokens; I != E; ++I) {
+ const Token &CurTok = Tokens[I];
// We don't want a space for the next token after a paste
// operator. In valid code, the token will get smooshed onto the
// preceding one anyway. In assembler-with-cpp mode, invalid
// pastes are allowed through: in this case, we do not want the
// extra whitespace to be added. For example, we want ". ## foo"
// -> ".foo" not ". foo".
- if (i != 0 && !Tokens[i-1].is(tok::hashhash) && CurTok.hasLeadingSpace())
+ if (I != 0 && !Tokens[I-1].is(tok::hashhash) && CurTok.hasLeadingSpace())
NextTokGetsSpace = true;
- if (CurTok.isOneOf(tok::hash, tok::hashat)) {
- int ArgNo = Macro->getParameterNum(Tokens[i+1].getIdentifierInfo());
- assert(ArgNo != -1 && "Token following # is not an argument?");
+ if (VCtx.isVAOptToken(CurTok)) {
+ MadeChange = true;
+ assert(Tokens[I + 1].is(tok::l_paren) &&
+ "__VA_OPT__ must be followed by '('");
+
+ ++I; // Skip the l_paren
+ VCtx.sawVAOptFollowedByOpeningParens(CurTok.getLocation(),
+ ResultToks.size());
+
+ continue;
+ }
+
+ // We have entered into the __VA_OPT__ context, so handle tokens
+ // appropriately.
+ if (VCtx.isInVAOpt()) {
+ // If we are about to process a token that is either an argument to
+ // __VA_OPT__ or its closing rparen, then:
+ // 1) If the token is the closing rparen that exits us out of __VA_OPT__,
+ // perform any necessary stringification or placemarker processing,
+ // and/or skip to the next token.
+ // 2) else if macro was invoked without variadic arguments skip this
+ // token.
+ // 3) else (macro was invoked with variadic arguments) process the token
+ // normally.
+ if (Tokens[I].is(tok::l_paren))
+ VCtx.sawOpeningParen(Tokens[I].getLocation());
+ // Continue skipping tokens within __VA_OPT__ if the macro was not
+ // called with variadic arguments, else let the rest of the loop handle
+ // this token. Note sawClosingParen() returns true only if the r_paren matches
+ // the closing r_paren of the __VA_OPT__.
+ if (!Tokens[I].is(tok::r_paren) || !VCtx.sawClosingParen()) {
+ if (!CalledWithVariadicArguments) {
+ // Skip this token.
+ continue;
+ }
+ // ... else the macro was called with variadic arguments, and we do not
+ // have a closing rparen - so process this token normally.
+ } else {
+ // Current token is the closing r_paren which marks the end of the
+ // __VA_OPT__ invocation, so handle any place-marker pasting (if
+ // empty) by removing hashhash either before (if exists) or after. And
+ // also stringify the entire contents if VAOPT was preceded by a hash,
+ // but do so only after any token concatenation that needs to occur
+ // within the contents of VAOPT.
+
+ if (VCtx.hasStringifyOrCharifyBefore()) {
+ // Replace all the tokens just added from within VAOPT into a single
+ // stringified token. This requires token-pasting to eagerly occur
+ // within these tokens. If either the contents of VAOPT were empty
+ // or the macro wasn't called with any variadic arguments, the result
+ // is a token that represents an empty string.
+ stringifyVAOPTContents(ResultToks, VCtx,
+ /*ClosingParenLoc*/ Tokens[I].getLocation());
+
+ } else if (/*No tokens within VAOPT*/ !(
+ ResultToks.size() - VCtx.getNumberOfTokensPriorToVAOpt())) {
+ // Treat VAOPT as a placemarker token. Eat either the '##' before the
+ // RHS/VAOPT (if one exists, suggesting that the LHS (if any) to that
+ // hashhash was not a placemarker) or the '##'
+ // after VAOPT, but not both.
+
+ if (ResultToks.size() && ResultToks.back().is(tok::hashhash)) {
+ ResultToks.pop_back();
+ } else if ((I + 1 != E) && Tokens[I + 1].is(tok::hashhash)) {
+ ++I; // Skip the following hashhash.
+ }
+ }
+ VCtx.reset();
+ // We processed __VA_OPT__'s closing paren (and the exit out of
+ // __VA_OPT__), so skip to the next token.
+ continue;
+ }
+ }
+
+ // If we found the stringify operator, get the argument stringified. The
+ // preprocessor already verified that the following token is a macro
+ // parameter or __VA_OPT__ when the #define was lexed.
+
+ if (CurTok.isOneOf(tok::hash, tok::hashat)) {
+ int ArgNo = Macro->getParameterNum(Tokens[I+1].getIdentifierInfo());
+ assert((ArgNo != -1 || VCtx.isVAOptToken(Tokens[I + 1])) &&
+ "Token following # is not an argument or __VA_OPT__!");
+
+ if (ArgNo == -1) {
+ // Handle the __VA_OPT__ case.
+ VCtx.sawHashOrHashAtBefore(NextTokGetsSpace,
+ CurTok.is(tok::hashat));
+ continue;
+ }
+ // Else handle the simple argument case.
SourceLocation ExpansionLocStart =
getExpansionLocForMacroDefLoc(CurTok.getLocation());
SourceLocation ExpansionLocEnd =
- getExpansionLocForMacroDefLoc(Tokens[i+1].getLocation());
+ getExpansionLocForMacroDefLoc(Tokens[I+1].getLocation());
Token Res;
if (CurTok.is(tok::hash)) // Stringify
@@ -222,7 +377,7 @@ void TokenLexer::ExpandFunctionArguments() {
ResultToks.push_back(Res);
MadeChange = true;
- ++i; // Skip arg name.
+ ++I; // Skip arg name.
NextTokGetsSpace = false;
continue;
}
@@ -230,9 +385,11 @@ void TokenLexer::ExpandFunctionArguments() {
// Find out if there is a paste (##) operator before or after the token.
bool NonEmptyPasteBefore =
!ResultToks.empty() && ResultToks.back().is(tok::hashhash);
- bool PasteBefore = i != 0 && Tokens[i-1].is(tok::hashhash);
- bool PasteAfter = i+1 != e && Tokens[i+1].is(tok::hashhash);
- assert(!NonEmptyPasteBefore || PasteBefore);
+ bool PasteBefore = I != 0 && Tokens[I-1].is(tok::hashhash);
+ bool PasteAfter = I+1 != E && Tokens[I+1].is(tok::hashhash);
+
+ assert((!NonEmptyPasteBefore || PasteBefore || VCtx.isInVAOpt()) &&
+ "unexpected ## in ResultToks");
// Otherwise, if this is not an argument token, just add the token to the
// output buffer.
@@ -275,7 +432,7 @@ void TokenLexer::ExpandFunctionArguments() {
// avoids some work in common cases.
const Token *ArgTok = ActualArgs->getUnexpArgument(ArgNo);
if (ActualArgs->ArgNeedsPreexpansion(ArgTok, PP))
- ResultArgToks = &ActualArgs->getPreExpArgument(ArgNo, Macro, PP)[0];
+ ResultArgToks = &ActualArgs->getPreExpArgument(ArgNo, PP)[0];
else
ResultArgToks = ArgTok; // Use non-preexpanded tokens.
@@ -374,7 +531,7 @@ void TokenLexer::ExpandFunctionArguments() {
if (PasteAfter) {
// Discard the argument token and skip (don't copy to the expansion
// buffer) the paste operator after it.
- ++i;
+ ++I;
continue;
}
@@ -384,7 +541,13 @@ void TokenLexer::ExpandFunctionArguments() {
assert(PasteBefore);
if (NonEmptyPasteBefore) {
assert(ResultToks.back().is(tok::hashhash));
- ResultToks.pop_back();
+ // Do not remove the paste operator if it is the one before __VA_OPT__
+ // (and we are still processing tokens within VA_OPT). We handle the case
+ // of removing the paste operator if __VA_OPT__ reduces to the notional
+ // placemarker above when we encounter the closing paren of VA_OPT.
+ if (!VCtx.isInVAOpt() ||
+ ResultToks.size() > VCtx.getNumberOfTokensPriorToVAOpt())
+ ResultToks.pop_back();
}
// If this is the __VA_ARGS__ token, and if the argument wasn't provided,
@@ -420,7 +583,6 @@ static bool isWideStringLiteralFromMacro(const Token &FirstTok,
}
/// Lex - Lex and return a token from this macro stream.
-///
bool TokenLexer::Lex(Token &Tok) {
// Lexing off the end of the macro, pop this macro off the expansion stack.
if (isAtEnd()) {
@@ -431,7 +593,7 @@ bool TokenLexer::Lex(Token &Tok) {
Tok.startToken();
Tok.setFlagValue(Token::StartOfLine , AtStartOfLine);
Tok.setFlagValue(Token::LeadingSpace, HasLeadingSpace || NextTokGetsSpace);
- if (CurToken == 0)
+ if (CurTokenIdx == 0)
Tok.setFlag(Token::LeadingEmptyMacro);
return PP.HandleEndOfTokenLexer(Tok);
}
@@ -440,25 +602,25 @@ bool TokenLexer::Lex(Token &Tok) {
// If this is the first token of the expanded result, we inherit spacing
// properties later.
- bool isFirstToken = CurToken == 0;
+ bool isFirstToken = CurTokenIdx == 0;
// Get the next token to return.
- Tok = Tokens[CurToken++];
+ Tok = Tokens[CurTokenIdx++];
bool TokenIsFromPaste = false;
// If this token is followed by a token paste (##) operator, paste the tokens!
// Note that ## is a normal token when not expanding a macro.
if (!isAtEnd() && Macro &&
- (Tokens[CurToken].is(tok::hashhash) ||
+ (Tokens[CurTokenIdx].is(tok::hashhash) ||
// Special processing of L#x macros in -fms-compatibility mode.
// Microsoft compiler is able to form a wide string literal from
// 'L#macro_arg' construct in a function-like macro.
(PP.getLangOpts().MSVCCompat &&
- isWideStringLiteralFromMacro(Tok, Tokens[CurToken])))) {
+ isWideStringLiteralFromMacro(Tok, Tokens[CurTokenIdx])))) {
// When handling the microsoft /##/ extension, the final token is
- // returned by PasteTokens, not the pasted token.
- if (PasteTokens(Tok))
+ // returned by pasteTokens, not the pasted token.
+ if (pasteTokens(Tok))
return true;
TokenIsFromPaste = true;
@@ -521,40 +683,57 @@ bool TokenLexer::Lex(Token &Tok) {
return true;
}
-/// PasteTokens - Tok is the LHS of a ## operator, and CurToken is the ##
+bool TokenLexer::pasteTokens(Token &Tok) {
+ return pasteTokens(Tok, llvm::makeArrayRef(Tokens, NumTokens), CurTokenIdx);
+}
+
+/// LHSTok is the LHS of a ## operator, and CurTokenIdx is the ##
/// operator. Read the ## and RHS, and paste the LHS/RHS together. If there
-/// are more ## after it, chomp them iteratively. Return the result as Tok.
+/// are more ## after it, chomp them iteratively. Return the result as LHSTok.
/// If this returns true, the caller should immediately return the token.
-bool TokenLexer::PasteTokens(Token &Tok) {
+bool TokenLexer::pasteTokens(Token &LHSTok, ArrayRef<Token> TokenStream,
+ unsigned int &CurIdx) {
+ assert(CurIdx > 0 && "## can not be the first token within tokens");
+ assert((TokenStream[CurIdx].is(tok::hashhash) ||
+ (PP.getLangOpts().MSVCCompat &&
+ isWideStringLiteralFromMacro(LHSTok, TokenStream[CurIdx]))) &&
+ "Token at this Index must be ## or part of the MSVC 'L "
+ "#macro-arg' pasting pair");
+
// MSVC: If previous token was pasted, this must be a recovery from an invalid
// paste operation. Ignore spaces before this token to mimic MSVC output.
// Required for generating valid UUID strings in some MS headers.
- if (PP.getLangOpts().MicrosoftExt && (CurToken >= 2) &&
- Tokens[CurToken - 2].is(tok::hashhash))
- Tok.clearFlag(Token::LeadingSpace);
+ if (PP.getLangOpts().MicrosoftExt && (CurIdx >= 2) &&
+ TokenStream[CurIdx - 2].is(tok::hashhash))
+ LHSTok.clearFlag(Token::LeadingSpace);
SmallString<128> Buffer;
const char *ResultTokStrPtr = nullptr;
- SourceLocation StartLoc = Tok.getLocation();
+ SourceLocation StartLoc = LHSTok.getLocation();
SourceLocation PasteOpLoc;
+
+ auto IsAtEnd = [&TokenStream, &CurIdx] {
+ return TokenStream.size() == CurIdx;
+ };
+
do {
// Consume the ## operator if any.
- PasteOpLoc = Tokens[CurToken].getLocation();
- if (Tokens[CurToken].is(tok::hashhash))
- ++CurToken;
- assert(!isAtEnd() && "No token on the RHS of a paste operator!");
+ PasteOpLoc = TokenStream[CurIdx].getLocation();
+ if (TokenStream[CurIdx].is(tok::hashhash))
+ ++CurIdx;
+ assert(!IsAtEnd() && "No token on the RHS of a paste operator!");
// Get the RHS token.
- const Token &RHS = Tokens[CurToken];
+ const Token &RHS = TokenStream[CurIdx];
// Allocate space for the result token. This is guaranteed to be enough for
// the two tokens.
- Buffer.resize(Tok.getLength() + RHS.getLength());
+ Buffer.resize(LHSTok.getLength() + RHS.getLength());
// Get the spelling of the LHS token in Buffer.
const char *BufPtr = &Buffer[0];
bool Invalid = false;
- unsigned LHSLen = PP.getSpelling(Tok, BufPtr, &Invalid);
+ unsigned LHSLen = PP.getSpelling(LHSTok, BufPtr, &Invalid);
if (BufPtr != &Buffer[0]) // Really, we want the chars in Buffer!
memcpy(&Buffer[0], BufPtr, LHSLen);
if (Invalid)
@@ -586,7 +765,7 @@ bool TokenLexer::PasteTokens(Token &Tok) {
// Lex the resultant pasted token into Result.
Token Result;
- if (Tok.isAnyIdentifier() && RHS.isAnyIdentifier()) {
+ if (LHSTok.isAnyIdentifier() && RHS.isAnyIdentifier()) {
// Common paste case: identifier+identifier = identifier. Avoid creating
// a lexer and other overhead.
PP.IncrementPasteCounter(true);
@@ -626,7 +805,7 @@ bool TokenLexer::PasteTokens(Token &Tok) {
isInvalid |= Result.is(tok::eof);
// If pasting the two tokens didn't form a full new token, this is an
- // error. This occurs with "x ## +" and other stuff. Return with Tok
+ // error. This occurs with "x ## +" and other stuff. Return with LHSTok
// unmodified and with RHS as the next token to lex.
if (isInvalid) {
// Explicitly convert the token location to have proper expansion
@@ -637,9 +816,9 @@ bool TokenLexer::PasteTokens(Token &Tok) {
// Test for the Microsoft extension of /##/ turning into // here on the
// error path.
- if (PP.getLangOpts().MicrosoftExt && Tok.is(tok::slash) &&
+ if (PP.getLangOpts().MicrosoftExt && LHSTok.is(tok::slash) &&
RHS.is(tok::slash)) {
- HandleMicrosoftCommentPaste(Tok, Loc);
+ HandleMicrosoftCommentPaste(LHSTok, Loc);
return true;
}
@@ -664,15 +843,15 @@ bool TokenLexer::PasteTokens(Token &Tok) {
}
// Transfer properties of the LHS over the Result.
- Result.setFlagValue(Token::StartOfLine , Tok.isAtStartOfLine());
- Result.setFlagValue(Token::LeadingSpace, Tok.hasLeadingSpace());
+ Result.setFlagValue(Token::StartOfLine , LHSTok.isAtStartOfLine());
+ Result.setFlagValue(Token::LeadingSpace, LHSTok.hasLeadingSpace());
// Finally, replace LHS with the result, consume the RHS, and iterate.
- ++CurToken;
- Tok = Result;
- } while (!isAtEnd() && Tokens[CurToken].is(tok::hashhash));
+ ++CurIdx;
+ LHSTok = Result;
+ } while (!IsAtEnd() && TokenStream[CurIdx].is(tok::hashhash));
- SourceLocation EndLoc = Tokens[CurToken - 1].getLocation();
+ SourceLocation EndLoc = TokenStream[CurIdx - 1].getLocation();
// The token's current location indicate where the token was lexed from. We
// need this information to compute the spelling of the token, but any
@@ -690,16 +869,16 @@ bool TokenLexer::PasteTokens(Token &Tok) {
while (SM.getFileID(EndLoc) != MacroFID)
EndLoc = SM.getImmediateExpansionRange(EndLoc).second;
- Tok.setLocation(SM.createExpansionLoc(Tok.getLocation(), StartLoc, EndLoc,
- Tok.getLength()));
+ LHSTok.setLocation(SM.createExpansionLoc(LHSTok.getLocation(), StartLoc, EndLoc,
+ LHSTok.getLength()));
// Now that we got the result token, it will be subject to expansion. Since
// token pasting re-lexes the result token in raw mode, identifier information
// isn't looked up. As such, if the result is an identifier, look up id info.
- if (Tok.is(tok::raw_identifier)) {
+ if (LHSTok.is(tok::raw_identifier)) {
// Look up the identifier info for the token. We disabled identifier lookup
// by saying we're skipping contents, so we need to do this manually.
- PP.LookUpIdentifierInfo(Tok);
+ PP.LookUpIdentifierInfo(LHSTok);
}
return false;
}
@@ -711,7 +890,7 @@ unsigned TokenLexer::isNextTokenLParen() const {
// Out of tokens?
if (isAtEnd())
return 2;
- return Tokens[CurToken].is(tok::l_paren);
+ return Tokens[CurTokenIdx].is(tok::l_paren);
}
/// isParsingPreprocessorDirective - Return true if we are in the middle of a
@@ -831,9 +1010,8 @@ static void updateConsecutiveMacroArgTokens(SourceManager &SM,
/// \brief Creates SLocEntries and updates the locations of macro argument
/// tokens to their new expanded locations.
///
-/// \param ArgIdDefLoc the location of the macro argument id inside the macro
+/// \param ArgIdSpellLoc the location of the macro argument id inside the macro
/// definition.
-/// \param Tokens the macro argument tokens to update.
void TokenLexer::updateLocForMacroArgTokens(SourceLocation ArgIdSpellLoc,
Token *begin_tokens,
Token *end_tokens) {
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp
index 27651c9ca85cb..2b3d4ba85bd8d 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -509,7 +509,8 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) {
// Parse the method body. Function body parsing code is similar enough
// to be re-used for method bodies as well.
- ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope);
+ ParseScope FnScope(this, Scope::FnScope | Scope::DeclScope |
+ Scope::CompoundStmtScope);
Actions.ActOnStartOfFunctionDef(getCurScope(), LM.D);
if (Tok.is(tok::kw_try)) {
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp
index a4610698c46d0..9fe4309ca1244 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp
@@ -912,13 +912,18 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
return;
}
IdentifierLoc *Platform = ParseIdentifierLoc();
- // Canonicalize platform name from "macosx" to "macos".
- if (Platform->Ident && Platform->Ident->getName() == "macosx")
- Platform->Ident = PP.getIdentifierInfo("macos");
- // Canonicalize platform name from "macosx_app_extension" to
- // "macos_app_extension".
- if (Platform->Ident && Platform->Ident->getName() == "macosx_app_extension")
- Platform->Ident = PP.getIdentifierInfo("macos_app_extension");
+ if (const IdentifierInfo *const Ident = Platform->Ident) {
+ // Canonicalize platform name from "macosx" to "macos".
+ if (Ident->getName() == "macosx")
+ Platform->Ident = PP.getIdentifierInfo("macos");
+ // Canonicalize platform name from "macosx_app_extension" to
+ // "macos_app_extension".
+ else if (Ident->getName() == "macosx_app_extension")
+ Platform->Ident = PP.getIdentifierInfo("macos_app_extension");
+ else
+ Platform->Ident = PP.getIdentifierInfo(
+ AvailabilityAttr::canonicalizePlatformName(Ident->getName()));
+ }
// Parse the ',' following the platform name.
if (ExpectAndConsume(tok::comma)) {
@@ -1388,7 +1393,9 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA,
// If the Decl is on a function, add function parameters to the scope.
bool HasFunScope = EnterScope && D->isFunctionOrFunctionTemplate();
- ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope, HasFunScope);
+ ParseScope FnScope(
+ this, Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope,
+ HasFunScope);
if (HasFunScope)
Actions.ActOnReenterFunctionContext(Actions.CurScope, D);
@@ -1555,7 +1562,7 @@ void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs) {
void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs,
unsigned DiagID) {
for (AttributeList *Attr = Attrs.getList(); Attr; Attr = Attr->getNext()) {
- if (!Attr->isCXX11Attribute())
+ if (!Attr->isCXX11Attribute() && !Attr->isC2xAttribute())
continue;
if (Attr->getKind() == AttributeList::UnknownAttribute)
Diag(Attr->getLoc(), diag::warn_unknown_attribute_ignored)
@@ -2124,6 +2131,37 @@ Decl *Parser::ParseDeclarationAfterDeclarator(
Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
Declarator &D, const ParsedTemplateInfo &TemplateInfo, ForRangeInit *FRI) {
+ // RAII type used to track whether we're inside an initializer.
+ struct InitializerScopeRAII {
+ Parser &P;
+ Declarator &D;
+ Decl *ThisDecl;
+
+ InitializerScopeRAII(Parser &P, Declarator &D, Decl *ThisDecl)
+ : P(P), D(D), ThisDecl(ThisDecl) {
+ if (ThisDecl && P.getLangOpts().CPlusPlus) {
+ Scope *S = nullptr;
+ if (D.getCXXScopeSpec().isSet()) {
+ P.EnterScope(0);
+ S = P.getCurScope();
+ }
+ P.Actions.ActOnCXXEnterDeclInitializer(S, ThisDecl);
+ }
+ }
+ ~InitializerScopeRAII() { pop(); }
+ void pop() {
+ if (ThisDecl && P.getLangOpts().CPlusPlus) {
+ Scope *S = nullptr;
+ if (D.getCXXScopeSpec().isSet())
+ S = P.getCurScope();
+ P.Actions.ActOnCXXExitDeclInitializer(S, ThisDecl);
+ if (S)
+ P.ExitScope();
+ }
+ ThisDecl = nullptr;
+ }
+ };
+
// Inform the current actions module that we just parsed this declarator.
Decl *ThisDecl = nullptr;
switch (TemplateInfo.Kind) {
@@ -2201,10 +2239,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
else
Diag(ConsumeToken(), diag::err_default_special_members);
} else {
- if (getLangOpts().CPlusPlus && D.getCXXScopeSpec().isSet()) {
- EnterScope(0);
- Actions.ActOnCXXEnterDeclInitializer(getCurScope(), ThisDecl);
- }
+ InitializerScopeRAII InitScope(*this, D, ThisDecl);
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteInitializer(getCurScope(), ThisDecl);
@@ -2227,10 +2262,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
FRI->RangeExpr = Init;
}
- if (getLangOpts().CPlusPlus && D.getCXXScopeSpec().isSet()) {
- Actions.ActOnCXXExitDeclInitializer(getCurScope(), ThisDecl);
- ExitScope();
- }
+ InitScope.pop();
if (Init.isInvalid()) {
SmallVector<tok::TokenKind, 2> StopTokens;
@@ -2252,23 +2284,27 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
ExprVector Exprs;
CommaLocsTy CommaLocs;
- if (getLangOpts().CPlusPlus && D.getCXXScopeSpec().isSet()) {
- EnterScope(0);
- Actions.ActOnCXXEnterDeclInitializer(getCurScope(), ThisDecl);
+ InitializerScopeRAII InitScope(*this, D, ThisDecl);
+
+ llvm::function_ref<void()> ExprListCompleter;
+ auto ThisVarDecl = dyn_cast_or_null<VarDecl>(ThisDecl);
+ auto ConstructorCompleter = [&, ThisVarDecl] {
+ Actions.CodeCompleteConstructor(
+ getCurScope(), ThisVarDecl->getType()->getCanonicalTypeInternal(),
+ ThisDecl->getLocation(), Exprs);
+ };
+ if (ThisVarDecl) {
+ // ParseExpressionList can sometimes succeed even when ThisDecl is not
+ // VarDecl. This is an error and it is reported in a call to
+ // Actions.ActOnInitializerError(). However, we call
+ // CodeCompleteConstructor only on VarDecls, falling back to default
+ // completer in other cases.
+ ExprListCompleter = ConstructorCompleter;
}
- if (ParseExpressionList(Exprs, CommaLocs, [&] {
- Actions.CodeCompleteConstructor(getCurScope(),
- cast<VarDecl>(ThisDecl)->getType()->getCanonicalTypeInternal(),
- ThisDecl->getLocation(), Exprs);
- })) {
+ if (ParseExpressionList(Exprs, CommaLocs, ExprListCompleter)) {
Actions.ActOnInitializerError(ThisDecl);
SkipUntil(tok::r_paren, StopAtSemi);
-
- if (getLangOpts().CPlusPlus && D.getCXXScopeSpec().isSet()) {
- Actions.ActOnCXXExitDeclInitializer(getCurScope(), ThisDecl);
- ExitScope();
- }
} else {
// Match the ')'.
T.consumeClose();
@@ -2276,10 +2312,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
assert(!Exprs.empty() && Exprs.size()-1 == CommaLocs.size() &&
"Unexpected number of commas!");
- if (getLangOpts().CPlusPlus && D.getCXXScopeSpec().isSet()) {
- Actions.ActOnCXXExitDeclInitializer(getCurScope(), ThisDecl);
- ExitScope();
- }
+ InitScope.pop();
ExprResult Initializer = Actions.ActOnParenListExpr(T.getOpenLocation(),
T.getCloseLocation(),
@@ -2292,17 +2325,11 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
// Parse C++0x braced-init-list.
Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
- if (D.getCXXScopeSpec().isSet()) {
- EnterScope(0);
- Actions.ActOnCXXEnterDeclInitializer(getCurScope(), ThisDecl);
- }
+ InitializerScopeRAII InitScope(*this, D, ThisDecl);
ExprResult Init(ParseBraceInitializer());
- if (D.getCXXScopeSpec().isSet()) {
- Actions.ActOnCXXExitDeclInitializer(getCurScope(), ThisDecl);
- ExitScope();
- }
+ InitScope.pop();
if (Init.isInvalid()) {
Actions.ActOnInitializerError(ThisDecl);
@@ -2898,7 +2925,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
case tok::l_square:
case tok::kw_alignas:
- if (!getLangOpts().CPlusPlus11 || !isCXX11AttributeSpecifier())
+ if (!standardAttributesAllowed() || !isCXX11AttributeSpecifier())
goto DoneWithDeclSpec;
ProhibitAttributes(attrs);
@@ -3201,7 +3228,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// Likewise, if this is a context where the identifier could be a template
// name, check whether this is a deduction guide declaration.
- if (getLangOpts().CPlusPlus1z &&
+ if (getLangOpts().CPlusPlus17 &&
(DSContext == DSC_class || DSContext == DSC_top_level) &&
Actions.isDeductionGuideName(getCurScope(), *Tok.getIdentifierInfo(),
Tok.getLocation()) &&
@@ -3437,11 +3464,6 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
isInvalid = DS.SetConstexprSpec(Loc, PrevSpec, DiagID);
break;
- // concept
- case tok::kw_concept:
- isInvalid = DS.SetConceptSpec(Loc, PrevSpec, DiagID);
- break;
-
// type-specifier
case tok::kw_short:
isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec,
@@ -3503,6 +3525,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec,
DiagID, Policy);
break;
+ case tok::kw__Float16:
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float16, Loc, PrevSpec,
+ DiagID, Policy);
+ break;
case tok::kw___float128:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float128, Loc, PrevSpec,
DiagID, Policy);
@@ -3747,7 +3773,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
/// semicolon.
///
/// struct-declaration:
-/// specifier-qualifier-list struct-declarator-list
+/// [C2x] attributes-specifier-seq[opt]
+/// specifier-qualifier-list struct-declarator-list
/// [GNU] __extension__ struct-declaration
/// [GNU] specifier-qualifier-list
/// struct-declarator-list:
@@ -3771,6 +3798,11 @@ void Parser::ParseStructDeclaration(
return ParseStructDeclaration(DS, FieldsCallback);
}
+ // Parse leading attributes.
+ ParsedAttributesWithRange Attrs(AttrFactory);
+ MaybeParseCXX11Attributes(Attrs);
+ DS.takeAttributesFrom(Attrs);
+
// Parse the common specifier-qualifiers-list piece.
ParseSpecifierQualifierList(DS);
@@ -4381,9 +4413,11 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
ParsedAttributesWithRange attrs(AttrFactory);
MaybeParseGNUAttributes(attrs);
ProhibitAttributes(attrs); // GNU-style attributes are prohibited.
- if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) {
- if (!getLangOpts().CPlusPlus1z)
- Diag(Tok.getLocation(), diag::warn_cxx14_compat_attribute)
+ if (standardAttributesAllowed() && isCXX11AttributeSpecifier()) {
+ if (getLangOpts().CPlusPlus)
+ Diag(Tok.getLocation(), getLangOpts().CPlusPlus17
+ ? diag::warn_cxx14_compat_ns_enum_attribute
+ : diag::ext_ns_enum_attribute)
<< 1 /*enumerator*/;
ParseCXX11Attributes(attrs);
}
@@ -4506,6 +4540,7 @@ bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const {
case tok::kw_half:
case tok::kw_float:
case tok::kw_double:
+ case tok::kw__Float16:
case tok::kw___float128:
case tok::kw_bool:
case tok::kw__Bool:
@@ -4581,6 +4616,7 @@ bool Parser::isTypeSpecifierQualifier() {
case tok::kw_half:
case tok::kw_float:
case tok::kw_double:
+ case tok::kw__Float16:
case tok::kw___float128:
case tok::kw_bool:
case tok::kw__Bool:
@@ -4737,6 +4773,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
case tok::kw_half:
case tok::kw_float:
case tok::kw_double:
+ case tok::kw__Float16:
case tok::kw___float128:
case tok::kw_bool:
case tok::kw__Bool:
@@ -4783,9 +4820,6 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
case tok::annot_decltype:
case tok::kw_constexpr:
- // C++ Concepts TS - concept
- case tok::kw_concept:
-
// C11 _Atomic
case tok::kw__Atomic:
return true;
@@ -4990,7 +5024,7 @@ void Parser::ParseTypeQualifierListOpt(
DeclSpec &DS, unsigned AttrReqs, bool AtomicAllowed,
bool IdentifierRequired,
Optional<llvm::function_ref<void()>> CodeCompletionHandler) {
- if (getLangOpts().CPlusPlus11 && (AttrReqs & AR_CXX11AttributesParsed) &&
+ if (standardAttributesAllowed() && (AttrReqs & AR_CXX11AttributesParsed) &&
isCXX11AttributeSpecifier()) {
ParsedAttributesWithRange attrs(AttrFactory);
ParseCXX11Attributes(attrs);
@@ -5927,7 +5961,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
SmallVector<SourceRange, 2> DynamicExceptionRanges;
ExprResult NoexceptExpr;
CachedTokens *ExceptionSpecTokens = nullptr;
- ParsedAttributes FnAttrs(AttrFactory);
+ ParsedAttributesWithRange FnAttrs(AttrFactory);
TypeResult TrailingReturnType;
/* LocalEndLoc is the end location for the local FunctionTypeLoc.
@@ -5948,6 +5982,11 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
RParenLoc = Tracker.getCloseLocation();
LocalEndLoc = RParenLoc;
EndLoc = RParenLoc;
+
+ // If there are attributes following the identifier list, parse them and
+ // prohibit them.
+ MaybeParseCXX11Attributes(FnAttrs);
+ ProhibitAttributes(FnAttrs);
} else {
if (Tok.isNot(tok::r_paren))
ParseParameterDeclarationClause(D, FirstArgAttrs, ParamInfo,
@@ -5955,7 +5994,8 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
else if (RequiresArg)
Diag(Tok, diag::err_argument_required_after_attribute);
- HasProto = ParamInfo.size() || getLangOpts().CPlusPlus;
+ HasProto = ParamInfo.size() || getLangOpts().CPlusPlus
+ || getLangOpts().OpenCL;
// If we have the closing ')', eat it.
Tracker.consumeClose();
@@ -6053,6 +6093,8 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
TrailingReturnType = ParseTrailingReturnType(Range);
EndLoc = Range.getEnd();
}
+ } else if (standardAttributesAllowed()) {
+ MaybeParseCXX11Attributes(FnAttrs);
}
}
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp
index 2301284b7f43b..44e7a3512098b 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp
@@ -77,9 +77,10 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(unsigned Context,
ParsedAttributesWithRange attrs(AttrFactory);
SourceLocation attrLoc;
if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) {
- if (!getLangOpts().CPlusPlus1z)
- Diag(Tok.getLocation(), diag::warn_cxx14_compat_attribute)
- << 0 /*namespace*/;
+ Diag(Tok.getLocation(), getLangOpts().CPlusPlus17
+ ? diag::warn_cxx14_compat_ns_enum_attribute
+ : diag::ext_ns_enum_attribute)
+ << 0 /*namespace*/;
attrLoc = Tok.getLocation();
ParseCXX11Attributes(attrs);
}
@@ -141,7 +142,7 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(unsigned Context,
// Normal namespace definition, not a nested-namespace-definition.
} else if (InlineLoc.isValid()) {
Diag(InlineLoc, diag::err_inline_nested_namespace_definition);
- } else if (getLangOpts().CPlusPlus1z) {
+ } else if (getLangOpts().CPlusPlus17) {
Diag(ExtraNamespaceLoc[0],
diag::warn_cxx14_compat_nested_namespace_definition);
} else {
@@ -604,8 +605,8 @@ bool Parser::ParseUsingDeclarator(unsigned Context, UsingDeclarator &D) {
}
if (TryConsumeToken(tok::ellipsis, D.EllipsisLoc))
- Diag(Tok.getLocation(), getLangOpts().CPlusPlus1z ?
- diag::warn_cxx1z_compat_using_declaration_pack :
+ Diag(Tok.getLocation(), getLangOpts().CPlusPlus17 ?
+ diag::warn_cxx17_compat_using_declaration_pack :
diag::ext_using_declaration_pack);
return false;
@@ -722,8 +723,8 @@ Parser::ParseUsingDeclaration(unsigned Context,
}
if (DeclsInGroup.size() > 1)
- Diag(Tok.getLocation(), getLangOpts().CPlusPlus1z ?
- diag::warn_cxx1z_compat_multi_using_declaration :
+ Diag(Tok.getLocation(), getLangOpts().CPlusPlus17 ?
+ diag::warn_cxx17_compat_multi_using_declaration :
diag::ext_multi_using_declaration);
// Eat ';'.
@@ -850,10 +851,10 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
ExprResult AssertMessage;
if (Tok.is(tok::r_paren)) {
- Diag(Tok, getLangOpts().CPlusPlus1z
+ Diag(Tok, getLangOpts().CPlusPlus17
? diag::warn_cxx14_compat_static_assert_no_message
: diag::ext_static_assert_no_message)
- << (getLangOpts().CPlusPlus1z
+ << (getLangOpts().CPlusPlus17
? FixItHint()
: FixItHint::CreateInsertion(Tok.getLocation(), ", \"\""));
} else {
@@ -2720,10 +2721,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
InClassInitStyle HasInClassInit = ICIS_NoInit;
bool HasStaticInitializer = false;
if (Tok.isOneOf(tok::equal, tok::l_brace) && PureSpecLoc.isInvalid()) {
- if (BitfieldSize.get()) {
- Diag(Tok, diag::err_bitfield_member_init);
- SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);
- } else if (DeclaratorInfo.isDeclarationOfFunction()) {
+ if (DeclaratorInfo.isDeclarationOfFunction()) {
// It's a pure-specifier.
if (!TryConsumePureSpecifier(/*AllowFunctionDefinition*/ false))
// Parse it as an expression so that Sema can diagnose it.
@@ -2734,6 +2732,10 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
DeclSpec::SCS_typedef &&
!DS.isFriendSpecified()) {
// It's a default member initializer.
+ if (BitfieldSize.get())
+ Diag(Tok, getLangOpts().CPlusPlus2a
+ ? diag::warn_cxx17_compat_bitfield_member_init
+ : diag::ext_bitfield_member_init);
HasInClassInit = Tok.is(tok::equal) ? ICIS_CopyInit : ICIS_ListInit;
} else {
HasStaticInitializer = true;
@@ -3193,6 +3195,9 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
}
if (Tok.is(tok::colon)) {
+ ParseScope InheritanceScope(this, getCurScope()->getFlags() |
+ Scope::ClassInheritanceScope);
+
ParseBaseClause(TagDecl);
if (!Tok.is(tok::l_brace)) {
bool SuggestFixIt = false;
@@ -3620,7 +3625,7 @@ static void diagnoseDynamicExceptionSpecification(
if (P.getLangOpts().CPlusPlus11) {
const char *Replacement = IsNoexcept ? "noexcept" : "noexcept(false)";
P.Diag(Range.getBegin(),
- P.getLangOpts().CPlusPlus1z && !IsNoexcept
+ P.getLangOpts().CPlusPlus17 && !IsNoexcept
? diag::ext_dynamic_exception_spec
: diag::warn_exception_spec_deprecated)
<< Range;
@@ -3812,7 +3817,7 @@ IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(SourceLocation &Loc) {
}
static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName,
- IdentifierInfo *ScopeName) {
+ IdentifierInfo *ScopeName) {
switch (AttributeList::getKind(AttrName, ScopeName,
AttributeList::AS_CXX11)) {
case AttributeList::AT_CarriesDependency:
@@ -3851,11 +3856,14 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName,
SourceLocation ScopeLoc) {
assert(Tok.is(tok::l_paren) && "Not a C++11 attribute argument list");
SourceLocation LParenLoc = Tok.getLocation();
+ const LangOptions &LO = getLangOpts();
+ AttributeList::Syntax Syntax =
+ LO.CPlusPlus ? AttributeList::AS_CXX11 : AttributeList::AS_C2x;
// If the attribute isn't known, we will not attempt to parse any
// arguments.
- if (!hasAttribute(AttrSyntax::CXX, ScopeName, AttrName,
- getTargetInfo(), getLangOpts())) {
+ if (!hasAttribute(LO.CPlusPlus ? AttrSyntax::CXX : AttrSyntax::C, ScopeName,
+ AttrName, getTargetInfo(), getLangOpts())) {
// Eat the left paren, then skip to the ending right paren.
ConsumeParen();
SkipUntil(tok::r_paren);
@@ -3866,7 +3874,7 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName,
// GNU-scoped attributes have some special cases to handle GNU-specific
// behaviors.
ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
- ScopeLoc, AttributeList::AS_CXX11, nullptr);
+ ScopeLoc, Syntax, nullptr);
return true;
}
@@ -3875,11 +3883,11 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName,
if (ScopeName && ScopeName->getName() == "clang")
NumArgs =
ParseClangAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
- ScopeLoc, AttributeList::AS_CXX11);
+ ScopeLoc, Syntax);
else
NumArgs =
ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc,
- ScopeName, ScopeLoc, AttributeList::AS_CXX11);
+ ScopeName, ScopeLoc, Syntax);
const AttributeList *Attr = Attrs.getList();
if (Attr && IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName)) {
@@ -3905,7 +3913,7 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName,
return true;
}
-/// ParseCXX11AttributeSpecifier - Parse a C++11 attribute-specifier.
+/// ParseCXX11AttributeSpecifier - Parse a C++11 or C2x attribute-specifier.
///
/// [C++11] attribute-specifier:
/// '[' '[' attribute-list ']' ']'
@@ -3937,8 +3945,8 @@ void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs,
return;
}
- assert(Tok.is(tok::l_square) && NextToken().is(tok::l_square)
- && "Not a C++11 attribute list");
+ assert(Tok.is(tok::l_square) && NextToken().is(tok::l_square) &&
+ "Not a double square bracket attribute list");
Diag(Tok.getLocation(), diag::warn_cxx98_compat_attribute);
@@ -3948,7 +3956,7 @@ void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs,
SourceLocation CommonScopeLoc;
IdentifierInfo *CommonScopeName = nullptr;
if (Tok.is(tok::kw_using)) {
- Diag(Tok.getLocation(), getLangOpts().CPlusPlus1z
+ Diag(Tok.getLocation(), getLangOpts().CPlusPlus17
? diag::warn_cxx14_compat_using_attribute_ns
: diag::ext_using_attribute_ns);
ConsumeToken();
@@ -4014,10 +4022,12 @@ void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs,
ScopeName, ScopeLoc);
if (!AttrParsed)
- attrs.addNew(AttrName,
- SourceRange(ScopeLoc.isValid() ? ScopeLoc : AttrLoc,
- AttrLoc),
- ScopeName, ScopeLoc, nullptr, 0, AttributeList::AS_CXX11);
+ attrs.addNew(
+ AttrName,
+ SourceRange(ScopeLoc.isValid() ? ScopeLoc : AttrLoc, AttrLoc),
+ ScopeName, ScopeLoc, nullptr, 0,
+ getLangOpts().CPlusPlus ? AttributeList::AS_CXX11
+ : AttributeList::AS_C2x);
if (TryConsumeToken(tok::ellipsis))
Diag(Tok, diag::err_cxx11_attribute_forbids_ellipsis)
@@ -4032,13 +4042,13 @@ void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs,
SkipUntil(tok::r_square);
}
-/// ParseCXX11Attributes - Parse a C++11 attribute-specifier-seq.
+/// ParseCXX11Attributes - Parse a C++11 or C2x attribute-specifier-seq.
///
/// attribute-specifier-seq:
/// attribute-specifier-seq[opt] attribute-specifier
void Parser::ParseCXX11Attributes(ParsedAttributesWithRange &attrs,
SourceLocation *endLoc) {
- assert(getLangOpts().CPlusPlus11);
+ assert(standardAttributesAllowed());
SourceLocation StartLoc = Tok.getLocation(), Loc;
if (!endLoc)
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp
index 44b87af01abd0..bc587628c954d 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp
@@ -66,12 +66,16 @@ using namespace clang;
/// shift-expression '<<' additive-expression
/// shift-expression '>>' additive-expression
///
-/// relational-expression: [C99 6.5.8]
+/// compare-expression: [C++20 expr.spaceship]
/// shift-expression
-/// relational-expression '<' shift-expression
-/// relational-expression '>' shift-expression
-/// relational-expression '<=' shift-expression
-/// relational-expression '>=' shift-expression
+/// compare-expression '<=>' shift-expression
+///
+/// relational-expression: [C99 6.5.8]
+/// compare-expression
+/// relational-expression '<' compare-expression
+/// relational-expression '>' compare-expression
+/// relational-expression '<=' compare-expression
+/// relational-expression '>=' compare-expression
///
/// equality-expression: [C99 6.5.9]
/// relational-expression
@@ -266,11 +270,13 @@ bool Parser::diagnoseUnknownTemplateId(ExprResult LHS, SourceLocation Less) {
return false;
}
-static bool isFoldOperator(prec::Level Level) {
- return Level > prec::Unknown && Level != prec::Conditional;
+bool Parser::isFoldOperator(prec::Level Level) const {
+ return Level > prec::Unknown && Level != prec::Conditional &&
+ Level != prec::Spaceship;
}
-static bool isFoldOperator(tok::TokenKind Kind) {
- return isFoldOperator(getBinOpPrecedence(Kind, false, true));
+
+bool Parser::isFoldOperator(tok::TokenKind Kind) const {
+ return isFoldOperator(getBinOpPrecedence(Kind, GreaterThanIsOperator, true));
}
/// \brief Parse a binary expression that starts with \p LHS and has a
@@ -716,6 +722,7 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback {
/// '__is_sealed' [MS]
/// '__is_trivial'
/// '__is_union'
+/// '__has_unique_object_representations'
///
/// [Clang] unary-type-trait:
/// '__is_aggregate'
@@ -798,7 +805,8 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw_true:
case tok::kw_false:
- return ParseCXXBoolLiteral();
+ Res = ParseCXXBoolLiteral();
+ break;
case tok::kw___objc_yes:
case tok::kw___objc_no:
@@ -1229,6 +1237,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw_half:
case tok::kw_float:
case tok::kw_double:
+ case tok::kw__Float16:
case tok::kw___float128:
case tok::kw_void:
case tok::kw_typename:
@@ -2729,7 +2738,7 @@ ExprResult Parser::ParseFoldExpression(ExprResult LHS,
}
}
- Diag(EllipsisLoc, getLangOpts().CPlusPlus1z
+ Diag(EllipsisLoc, getLangOpts().CPlusPlus17
? diag::warn_cxx14_compat_fold_expression
: diag::ext_fold_expression);
@@ -2762,7 +2771,7 @@ ExprResult Parser::ParseFoldExpression(ExprResult LHS,
/// \endverbatim
bool Parser::ParseExpressionList(SmallVectorImpl<Expr *> &Exprs,
SmallVectorImpl<SourceLocation> &CommaLocs,
- std::function<void()> Completer) {
+ llvm::function_ref<void()> Completer) {
bool SawError = false;
while (1) {
if (Tok.is(tok::code_completion)) {
@@ -2881,7 +2890,7 @@ ExprResult Parser::ParseBlockLiteralExpression() {
// allows determining whether a variable reference inside the block is
// within or outside of the block.
ParseScope BlockScope(this, Scope::BlockScope | Scope::FnScope |
- Scope::DeclScope);
+ Scope::CompoundStmtScope | Scope::DeclScope);
// Inform sema that we are starting a block.
Actions.ActOnBlockStart(CaretLoc, getCurScope());
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp
index dcafbadae5c08..959cb7a61d3a7 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp
@@ -249,7 +249,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
if (Tok.is(tok::code_completion)) {
// Code completion for a nested-name-specifier, where the code
- // code completion token follows the '::'.
+ // completion token follows the '::'.
Actions.CodeCompleteQualifiedId(getCurScope(), SS, EnteringContext);
// Include code completion token into the range of the scope otherwise
// when we try to annotate the scope tokens the dangling code completion
@@ -966,6 +966,8 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
// that would be an error.
ParsedType InitCaptureType;
+ if (!Init.isInvalid())
+ Init = Actions.CorrectDelayedTyposInExpr(Init.get());
if (Init.isUsable()) {
// Get the pointer and store it in an lvalue, so we can use it as an
// out argument.
@@ -989,27 +991,34 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
///
/// Returns true if it hit something unexpected.
bool Parser::TryParseLambdaIntroducer(LambdaIntroducer &Intro) {
- TentativeParsingAction PA(*this);
+ {
+ bool SkippedInits = false;
+ TentativeParsingAction PA1(*this);
- bool SkippedInits = false;
- Optional<unsigned> DiagID(ParseLambdaIntroducer(Intro, &SkippedInits));
+ if (ParseLambdaIntroducer(Intro, &SkippedInits)) {
+ PA1.Revert();
+ return true;
+ }
- if (DiagID) {
- PA.Revert();
- return true;
+ if (!SkippedInits) {
+ PA1.Commit();
+ return false;
+ }
+
+ PA1.Revert();
}
- if (SkippedInits) {
- // Parse it again, but this time parse the init-captures too.
- PA.Revert();
- Intro = LambdaIntroducer();
- DiagID = ParseLambdaIntroducer(Intro);
- assert(!DiagID && "parsing lambda-introducer failed on reparse");
+ // Try to parse it again, but this time parse the init-captures too.
+ Intro = LambdaIntroducer();
+ TentativeParsingAction PA2(*this);
+
+ if (!ParseLambdaIntroducer(Intro)) {
+ PA2.Commit();
return false;
}
- PA.Commit();
- return false;
+ PA2.Revert();
+ return true;
}
static void
@@ -1053,8 +1062,8 @@ static void
addConstexprToLambdaDeclSpecifier(Parser &P, SourceLocation ConstexprLoc,
DeclSpec &DS) {
if (ConstexprLoc.isValid()) {
- P.Diag(ConstexprLoc, !P.getLangOpts().CPlusPlus1z
- ? diag::ext_constexpr_on_lambda_cxx1z
+ P.Diag(ConstexprLoc, !P.getLangOpts().CPlusPlus17
+ ? diag::ext_constexpr_on_lambda_cxx17
: diag::warn_cxx14_compat_constexpr_on_lambda);
const char *PrevSpec = nullptr;
unsigned DiagID = 0;
@@ -1281,7 +1290,8 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
// FIXME: Rename BlockScope -> ClosureScope if we decide to continue using
// it.
- unsigned ScopeFlags = Scope::BlockScope | Scope::FnScope | Scope::DeclScope;
+ unsigned ScopeFlags = Scope::BlockScope | Scope::FnScope | Scope::DeclScope |
+ Scope::CompoundStmtScope;
ParseScope BodyScope(this, ScopeFlags);
Actions.ActOnStartOfLambdaDefinition(Intro, D, getCurScope());
@@ -1351,7 +1361,6 @@ ExprResult Parser::ParseCXXCasts() {
if (ExpectAndConsume(tok::greater))
return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << tok::less);
- SourceLocation LParenLoc, RParenLoc;
BalancedDelimiterTracker T(*this, tok::l_paren);
if (T.expectAndConsume(diag::err_expected_lparen_after, CastName))
@@ -1706,6 +1715,8 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
/// type-specifier-seq declarator '=' assignment-expression
/// [C++11] type-specifier-seq declarator '=' initializer-clause
/// [C++11] type-specifier-seq declarator braced-init-list
+/// [Clang] type-specifier-seq ref-qualifier[opt] '[' identifier-list ']'
+/// brace-or-equal-initializer
/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
/// '=' assignment-expression
///
@@ -1751,7 +1762,7 @@ Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt,
}
case ConditionOrInitStatement::InitStmtDecl: {
- Diag(Tok.getLocation(), getLangOpts().CPlusPlus1z
+ Diag(Tok.getLocation(), getLangOpts().CPlusPlus17
? diag::warn_cxx14_compat_init_statement
: diag::ext_init_statement)
<< (CK == Sema::ConditionKind::Switch);
@@ -1925,6 +1936,9 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
case tok::kw_double:
DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID, Policy);
break;
+ case tok::kw__Float16:
+ DS.SetTypeSpecType(DeclSpec::TST_float16, Loc, PrevSpec, DiagID, Policy);
+ break;
case tok::kw___float128:
DS.SetTypeSpecType(DeclSpec::TST_float128, Loc, PrevSpec, DiagID, Policy);
break;
@@ -2172,7 +2186,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
/// ! = < > += -= *= /= %=
/// ^= &= |= << >> >>= <<= == !=
/// <= >= && || ++ -- , ->* ->
-/// () []
+/// () [] <=>
///
/// conversion-function-id: [C++ 12.3.2]
/// operator conversion-type-id
@@ -2468,7 +2482,7 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
/*IsCtorOrDtorName=*/true,
/*NonTrivialTypeSourceInfo=*/true);
Result.setConstructorName(Ty, IdLoc, IdLoc);
- } else if (getLangOpts().CPlusPlus1z &&
+ } else if (getLangOpts().CPlusPlus17 &&
AllowDeductionGuide && SS.isEmpty() &&
Actions.isDeductionGuideName(getCurScope(), *Id, IdLoc,
&TemplateName)) {
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp
index 01b1bf48e4738..fb8624a324b93 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp
@@ -81,8 +81,10 @@ Parser::DeclGroupPtrTy Parser::ParseObjCAtDirectives() {
SingleDecl = ParseObjCPropertyDynamic(AtLoc);
break;
case tok::objc_import:
- if (getLangOpts().Modules || getLangOpts().DebuggerSupport)
- return ParseModuleImport(AtLoc);
+ if (getLangOpts().Modules || getLangOpts().DebuggerSupport) {
+ SingleDecl = ParseModuleImport(AtLoc);
+ break;
+ }
Diag(AtLoc, diag::err_atimport);
SkipUntil(tok::semi);
return Actions.ConvertDeclToDeclGroup(nullptr);
@@ -2478,7 +2480,7 @@ Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) {
operand = Actions.ActOnObjCAtSynchronizedOperand(atLoc, operand.get());
// Parse the compound statement within a new scope.
- ParseScope bodyScope(this, Scope::DeclScope);
+ ParseScope bodyScope(this, Scope::DeclScope | Scope::CompoundStmtScope);
StmtResult body(ParseCompoundStatementBody());
bodyScope.Exit();
@@ -2514,7 +2516,7 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
}
StmtVector CatchStmts;
StmtResult FinallyStmt;
- ParseScope TryScope(this, Scope::DeclScope);
+ ParseScope TryScope(this, Scope::DeclScope | Scope::CompoundStmtScope);
StmtResult TryBody(ParseCompoundStatementBody());
TryScope.Exit();
if (TryBody.isInvalid())
@@ -2535,7 +2537,9 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
ConsumeToken(); // consume catch
if (Tok.is(tok::l_paren)) {
ConsumeParen();
- ParseScope CatchScope(this, Scope::DeclScope|Scope::AtCatchScope);
+ ParseScope CatchScope(this, Scope::DeclScope |
+ Scope::CompoundStmtScope |
+ Scope::AtCatchScope);
if (Tok.isNot(tok::ellipsis)) {
DeclSpec DS(AttrFactory);
ParseDeclarationSpecifiers(DS);
@@ -2579,7 +2583,8 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
} else {
assert(Tok.isObjCAtKeyword(tok::objc_finally) && "Lookahead confused?");
ConsumeToken(); // consume finally
- ParseScope FinallyScope(this, Scope::DeclScope);
+ ParseScope FinallyScope(this,
+ Scope::DeclScope | Scope::CompoundStmtScope);
StmtResult FinallyBody(true);
if (Tok.is(tok::l_brace))
@@ -2616,7 +2621,7 @@ Parser::ParseObjCAutoreleasePoolStmt(SourceLocation atLoc) {
}
// Enter a scope to hold everything within the compound stmt. Compound
// statements can always hold declarations.
- ParseScope BodyScope(this, Scope::DeclScope);
+ ParseScope BodyScope(this, Scope::DeclScope | Scope::CompoundStmtScope);
StmtResult AutoreleasePoolBody(ParseCompoundStatementBody());
@@ -3650,11 +3655,10 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {
assert(Tok.isOneOf(tok::l_brace, tok::kw_try, tok::colon) &&
"Inline objective-c method not starting with '{' or 'try' or ':'");
// Enter a scope for the method or c-function body.
- ParseScope BodyScope(this,
- parseMethod
- ? Scope::ObjCMethodScope|Scope::FnScope|Scope::DeclScope
- : Scope::FnScope|Scope::DeclScope);
-
+ ParseScope BodyScope(this, (parseMethod ? Scope::ObjCMethodScope : 0) |
+ Scope::FnScope | Scope::DeclScope |
+ Scope::CompoundStmtScope);
+
// Tell the actions module that we have entered a method or c-function definition
// with the specified Declarator for the method/function.
if (parseMethod)
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp
index d9a088595ab73..a67a5bbe0deaa 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp
@@ -302,6 +302,7 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
for (auto *D : DRD.get()) {
TentativeParsingAction TPA(*this);
ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
+ Scope::CompoundStmtScope |
Scope::OpenMPDirectiveScope);
// Parse <combiner> expression.
Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
@@ -337,14 +338,24 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
IsCorrect;
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
+ Scope::CompoundStmtScope |
Scope::OpenMPDirectiveScope);
// Parse expression.
- Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(), D);
- InitializerResult = Actions.ActOnFinishFullExpr(
- ParseAssignmentExpression().get(), D->getLocation(),
- /*DiscardedValue=*/true);
+ VarDecl *OmpPrivParm =
+ Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(),
+ D);
+ // Check if initializer is omp_priv <init_expr> or something else.
+ if (Tok.is(tok::identifier) &&
+ Tok.getIdentifierInfo()->isStr("omp_priv")) {
+ ConsumeToken();
+ ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
+ } else {
+ InitializerResult = Actions.ActOnFinishFullExpr(
+ ParseAssignmentExpression().get(), D->getLocation(),
+ /*DiscardedValue=*/true);
+ }
Actions.ActOnOpenMPDeclareReductionInitializerEnd(
- D, InitializerResult.get());
+ D, InitializerResult.get(), OmpPrivParm);
if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
Tok.isNot(tok::annot_pragma_openmp_end)) {
TPA.Commit();
@@ -368,6 +379,72 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
IsCorrect);
}
+void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
+ // Parse declarator '=' initializer.
+ // If a '==' or '+=' is found, suggest a fixit to '='.
+ if (isTokenEqualOrEqualTypo()) {
+ ConsumeToken();
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteInitializer(getCurScope(), OmpPrivParm);
+ Actions.FinalizeDeclaration(OmpPrivParm);
+ cutOffParsing();
+ return;
+ }
+
+ ExprResult Init(ParseInitializer());
+
+ if (Init.isInvalid()) {
+ SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
+ Actions.ActOnInitializerError(OmpPrivParm);
+ } else {
+ Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
+ /*DirectInit=*/false);
+ }
+ } else if (Tok.is(tok::l_paren)) {
+ // Parse C++ direct initializer: '(' expression-list ')'
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ T.consumeOpen();
+
+ ExprVector Exprs;
+ CommaLocsTy CommaLocs;
+
+ if (ParseExpressionList(Exprs, CommaLocs, [this, OmpPrivParm, &Exprs] {
+ Actions.CodeCompleteConstructor(
+ getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(),
+ OmpPrivParm->getLocation(), Exprs);
+ })) {
+ Actions.ActOnInitializerError(OmpPrivParm);
+ SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
+ } else {
+ // Match the ')'.
+ T.consumeClose();
+
+ assert(!Exprs.empty() && Exprs.size() - 1 == CommaLocs.size() &&
+ "Unexpected number of commas!");
+
+ ExprResult Initializer = Actions.ActOnParenListExpr(
+ T.getOpenLocation(), T.getCloseLocation(), Exprs);
+ Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(),
+ /*DirectInit=*/true);
+ }
+ } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
+ // Parse C++0x braced-init-list.
+ Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
+
+ ExprResult Init(ParseBraceInitializer());
+
+ if (Init.isInvalid()) {
+ Actions.ActOnInitializerError(OmpPrivParm);
+ } else {
+ Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
+ /*DirectInit=*/true);
+ }
+ } else {
+ Actions.ActOnUninitializedDecl(OmpPrivParm);
+ }
+}
+
namespace {
/// RAII that recreates function context for correct parsing of clauses of
/// 'declare simd' construct.
@@ -405,8 +482,9 @@ public:
// If the Decl is on a function, add function parameters to the scope.
HasFunScope = D->isFunctionOrFunctionTemplate();
- FnScope = new Parser::ParseScope(&P, Scope::FnScope | Scope::DeclScope,
- HasFunScope);
+ FnScope = new Parser::ParseScope(
+ &P, Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope,
+ HasFunScope);
if (HasFunScope)
Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
}
@@ -682,9 +760,17 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
DKind = ParseOpenMPDirectiveKind(*this);
while (DKind != OMPD_end_declare_target && DKind != OMPD_declare_target &&
Tok.isNot(tok::eof) && Tok.isNot(tok::r_brace)) {
- ParsedAttributesWithRange attrs(AttrFactory);
- MaybeParseCXX11Attributes(attrs);
- ParseExternalDeclaration(attrs);
+ DeclGroupPtrTy Ptr;
+ // Here we expect to see some function declaration.
+ if (AS == AS_none) {
+ assert(TagType == DeclSpec::TST_unspecified);
+ MaybeParseCXX11Attributes(Attrs);
+ ParsingDeclSpec PDS(*this);
+ Ptr = ParseExternalDeclaration(Attrs, &PDS);
+ } else {
+ Ptr =
+ ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
+ }
if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) {
TentativeParsingAction TPA(*this);
ConsumeAnnotationToken();
@@ -813,8 +899,8 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
SmallVector<OMPClause *, 5> Clauses;
SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
FirstClauses(OMPC_unknown + 1);
- unsigned ScopeFlags =
- Scope::FnScope | Scope::DeclScope | Scope::OpenMPDirectiveScope;
+ unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
+ Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
SourceLocation Loc = ConsumeAnnotationToken(), EndLoc;
auto DKind = ParseOpenMPDirectiveKind(*this);
OpenMPDirectiveKind CancelRegion = OMPD_unknown;
@@ -1000,6 +1086,15 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
AssociatedStmt = ParseStatement();
Actions.ActOnFinishOfCompoundStmt();
AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
+ } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
+ DKind == OMPD_target_exit_data) {
+ Sema::CompoundScopeRAII CompoundScope(Actions);
+ Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
+ Actions.ActOnStartOfCompoundStmt();
+ AssociatedStmt =
+ Actions.ActOnCompoundStmt(Loc, Loc, llvm::None, /*isStmtExpr=*/false);
+ Actions.ActOnFinishOfCompoundStmt();
+ AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
}
Directive = Actions.ActOnOpenMPExecutableDirective(
DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
@@ -1102,7 +1197,8 @@ bool Parser::ParseOpenMPSimpleVarList(
/// simdlen-clause | threads-clause | simd-clause | num_teams-clause |
/// thread_limit-clause | priority-clause | grainsize-clause |
/// nogroup-clause | num_tasks-clause | hint-clause | to-clause |
-/// from-clause | is_device_ptr-clause | task_reduction-clause
+/// from-clause | is_device_ptr-clause | task_reduction-clause |
+/// in_reduction-clause
///
OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
OpenMPClauseKind CKind, bool FirstClause) {
@@ -1221,6 +1317,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_shared:
case OMPC_reduction:
case OMPC_task_reduction:
+ case OMPC_in_reduction:
case OMPC_linear:
case OMPC_aligned:
case OMPC_copyin:
@@ -1586,7 +1683,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
BalancedDelimiterTracker LinearT(*this, tok::l_paren,
tok::annot_pragma_openmp_end);
// Handle reduction-identifier for reduction clause.
- if (Kind == OMPC_reduction || Kind == OMPC_task_reduction) {
+ if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
+ Kind == OMPC_in_reduction) {
ColonProtectionRAIIObject ColonRAII(*this);
if (getLangOpts().CPlusPlus)
ParseOptionalCXXScopeSpecifier(Data.ReductionIdScopeSpec,
@@ -1734,13 +1832,14 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
Diag(Tok, diag::warn_pragma_expected_colon) << "map type";
}
- bool IsComma = (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
- Kind != OMPC_depend && Kind != OMPC_map) ||
- (Kind == OMPC_reduction && !InvalidReductionId) ||
- (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown &&
- (!MapTypeModifierSpecified ||
- Data.MapTypeModifier == OMPC_MAP_always)) ||
- (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown);
+ bool IsComma =
+ (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
+ Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
+ (Kind == OMPC_reduction && !InvalidReductionId) ||
+ (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown &&
+ (!MapTypeModifierSpecified ||
+ Data.MapTypeModifier == OMPC_MAP_always)) ||
+ (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown);
const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
Tok.isNot(tok::annot_pragma_openmp_end))) {
@@ -1796,7 +1895,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
}
/// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
-/// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction' or 'task_reduction'.
+/// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction' or
+/// 'in_reduction'.
///
/// private-clause:
/// 'private' '(' list ')'
@@ -1814,6 +1914,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
/// 'reduction' '(' reduction-identifier ':' list ')'
/// task_reduction-clause:
/// 'task_reduction' '(' reduction-identifier ':' list ')'
+/// in_reduction-clause:
+/// 'in_reduction' '(' reduction-identifier ':' list ')'
/// copyprivate-clause:
/// 'copyprivate' '(' list ')'
/// flush-clause:
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp
index 262743756a6b8..198d5c6e9cb03 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp
@@ -422,15 +422,20 @@ void Parser::HandlePragmaPack() {
assert(Tok.is(tok::annot_pragma_pack));
PragmaPackInfo *Info =
static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
- SourceLocation PragmaLoc = ConsumeAnnotationToken();
+ SourceLocation PragmaLoc = Tok.getLocation();
ExprResult Alignment;
if (Info->Alignment.is(tok::numeric_constant)) {
Alignment = Actions.ActOnNumericConstant(Info->Alignment);
- if (Alignment.isInvalid())
+ if (Alignment.isInvalid()) {
+ ConsumeAnnotationToken();
return;
+ }
}
Actions.ActOnPragmaPack(PragmaLoc, Info->Action, Info->SlotLabel,
Alignment.get());
+ // Consume the token after processing the pragma to enable pragma-specific
+ // #include warnings.
+ ConsumeAnnotationToken();
}
void Parser::HandlePragmaMSStruct() {
@@ -528,7 +533,8 @@ StmtResult Parser::HandlePragmaCaptured()
SourceLocation Loc = Tok.getLocation();
- ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope);
+ ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope |
+ Scope::CompoundStmtScope);
Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
/*NumParams=*/1);
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp
index b1fbb20c721bd..3f25610f4471f 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp
@@ -453,9 +453,10 @@ StmtResult Parser::ParseSEHTryBlock() {
if (Tok.isNot(tok::l_brace))
return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
- StmtResult TryBlock(ParseCompoundStatement(/*isStmtExpr=*/false,
- Scope::DeclScope | Scope::SEHTryScope));
- if(TryBlock.isInvalid())
+ StmtResult TryBlock(ParseCompoundStatement(
+ /*isStmtExpr=*/false,
+ Scope::DeclScope | Scope::CompoundStmtScope | Scope::SEHTryScope));
+ if (TryBlock.isInvalid())
return TryBlock;
StmtResult Handler;
@@ -840,7 +841,8 @@ StmtResult Parser::ParseDefaultStatement() {
}
StmtResult Parser::ParseCompoundStatement(bool isStmtExpr) {
- return ParseCompoundStatement(isStmtExpr, Scope::DeclScope);
+ return ParseCompoundStatement(isStmtExpr,
+ Scope::DeclScope | Scope::CompoundStmtScope);
}
/// ParseCompoundStatement - Parse a "{}" block.
@@ -1126,7 +1128,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
bool IsConstexpr = false;
if (Tok.is(tok::kw_constexpr)) {
- Diag(Tok, getLangOpts().CPlusPlus1z ? diag::warn_cxx14_compat_constexpr_if
+ Diag(Tok, getLangOpts().CPlusPlus17 ? diag::warn_cxx14_compat_constexpr_if
: diag::ext_constexpr_if);
IsConstexpr = true;
ConsumeToken();
@@ -1477,6 +1479,9 @@ StmtResult Parser::ParseDoStatement() {
DiagnoseAndSkipCXX11Attributes();
ExprResult Cond = ParseExpression();
+ // Correct the typos in condition before closing the scope.
+ if (Cond.isUsable())
+ Cond = Actions.CorrectDelayedTyposInExpr(Cond);
T.consumeClose();
DoScope.Exit();
@@ -1608,7 +1613,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
ForRangeInit.RangeExpr = ParseExpression();
Diag(Loc, diag::err_for_range_identifier)
- << ((getLangOpts().CPlusPlus11 && !getLangOpts().CPlusPlus1z)
+ << ((getLangOpts().CPlusPlus11 && !getLangOpts().CPlusPlus17)
? FixItHint::CreateInsertion(Loc, "auto &&")
: FixItHint());
@@ -2085,9 +2090,10 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry) {
if (Tok.isNot(tok::l_brace))
return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
- StmtResult TryBlock(ParseCompoundStatement(/*isStmtExpr=*/false,
- Scope::DeclScope | Scope::TryScope |
- (FnTry ? Scope::FnTryCatchScope : 0)));
+ StmtResult TryBlock(ParseCompoundStatement(
+ /*isStmtExpr=*/false, Scope::DeclScope | Scope::TryScope |
+ Scope::CompoundStmtScope |
+ (FnTry ? Scope::FnTryCatchScope : 0)));
if (TryBlock.isInvalid())
return TryBlock;
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp
index d6f16bb0cb79e..d81029e279740 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp
@@ -54,54 +54,13 @@ public:
assert(AsmToks.size() == AsmTokOffsets.size());
}
- void *LookupInlineAsmIdentifier(StringRef &LineBuf,
- llvm::InlineAsmIdentifierInfo &Info,
- bool IsUnevaluatedContext) override {
- // Collect the desired tokens.
- SmallVector<Token, 16> LineToks;
- const Token *FirstOrigToken = nullptr;
- findTokensForString(LineBuf, LineToks, FirstOrigToken);
-
- unsigned NumConsumedToks;
- ExprResult Result = TheParser.ParseMSAsmIdentifier(
- LineToks, NumConsumedToks, &Info, IsUnevaluatedContext);
-
- // If we consumed the entire line, tell MC that.
- // Also do this if we consumed nothing as a way of reporting failure.
- if (NumConsumedToks == 0 || NumConsumedToks == LineToks.size()) {
- // By not modifying LineBuf, we're implicitly consuming it all.
-
- // Otherwise, consume up to the original tokens.
- } else {
- assert(FirstOrigToken && "not using original tokens?");
-
- // Since we're using original tokens, apply that offset.
- assert(FirstOrigToken[NumConsumedToks].getLocation() ==
- LineToks[NumConsumedToks].getLocation());
- unsigned FirstIndex = FirstOrigToken - AsmToks.begin();
- unsigned LastIndex = FirstIndex + NumConsumedToks - 1;
-
- // The total length we've consumed is the relative offset
- // of the last token we consumed plus its length.
- unsigned TotalOffset =
- (AsmTokOffsets[LastIndex] + AsmToks[LastIndex].getLength() -
- AsmTokOffsets[FirstIndex]);
- LineBuf = LineBuf.substr(0, TotalOffset);
- }
-
- // Initialize the "decl" with the lookup result.
- Info.OpDecl = static_cast<void *>(Result.get());
- return Info.OpDecl;
- }
+ void LookupInlineAsmIdentifier(StringRef &LineBuf,
+ llvm::InlineAsmIdentifierInfo &Info,
+ bool IsUnevaluatedContext) override;
StringRef LookupInlineAsmLabel(StringRef Identifier, llvm::SourceMgr &LSM,
llvm::SMLoc Location,
- bool Create) override {
- SourceLocation Loc = translateLocation(LSM, Location);
- LabelDecl *Label =
- TheParser.getActions().GetOrCreateMSAsmLabel(Identifier, Loc, Create);
- return Label->getMSAsmLabel();
- }
+ bool Create) override;
bool LookupInlineAsmField(StringRef Base, StringRef Member,
unsigned &Offset) override {
@@ -116,78 +75,133 @@ public:
private:
/// Collect the appropriate tokens for the given string.
void findTokensForString(StringRef Str, SmallVectorImpl<Token> &TempToks,
- const Token *&FirstOrigToken) const {
- // For now, assert that the string we're working with is a substring
- // of what we gave to MC. This lets us use the original tokens.
- assert(!std::less<const char *>()(Str.begin(), AsmString.begin()) &&
- !std::less<const char *>()(AsmString.end(), Str.end()));
+ const Token *&FirstOrigToken) const;
- // Try to find a token whose offset matches the first token.
- unsigned FirstCharOffset = Str.begin() - AsmString.begin();
- const unsigned *FirstTokOffset = std::lower_bound(
- AsmTokOffsets.begin(), AsmTokOffsets.end(), FirstCharOffset);
+ SourceLocation translateLocation(const llvm::SourceMgr &LSM,
+ llvm::SMLoc SMLoc);
- // For now, assert that the start of the string exactly
- // corresponds to the start of a token.
- assert(*FirstTokOffset == FirstCharOffset);
+ void handleDiagnostic(const llvm::SMDiagnostic &D);
+};
+}
- // Use all the original tokens for this line. (We assume the
- // end of the line corresponds cleanly to a token break.)
- unsigned FirstTokIndex = FirstTokOffset - AsmTokOffsets.begin();
- FirstOrigToken = &AsmToks[FirstTokIndex];
- unsigned LastCharOffset = Str.end() - AsmString.begin();
- for (unsigned i = FirstTokIndex, e = AsmTokOffsets.size(); i != e; ++i) {
- if (AsmTokOffsets[i] >= LastCharOffset)
- break;
- TempToks.push_back(AsmToks[i]);
- }
+void ClangAsmParserCallback::LookupInlineAsmIdentifier(
+ StringRef &LineBuf, llvm::InlineAsmIdentifierInfo &Info,
+ bool IsUnevaluatedContext) {
+ // Collect the desired tokens.
+ SmallVector<Token, 16> LineToks;
+ const Token *FirstOrigToken = nullptr;
+ findTokensForString(LineBuf, LineToks, FirstOrigToken);
+
+ unsigned NumConsumedToks;
+ ExprResult Result = TheParser.ParseMSAsmIdentifier(LineToks, NumConsumedToks,
+ IsUnevaluatedContext);
+
+ // If we consumed the entire line, tell MC that.
+ // Also do this if we consumed nothing as a way of reporting failure.
+ if (NumConsumedToks == 0 || NumConsumedToks == LineToks.size()) {
+ // By not modifying LineBuf, we're implicitly consuming it all.
+
+ // Otherwise, consume up to the original tokens.
+ } else {
+ assert(FirstOrigToken && "not using original tokens?");
+
+ // Since we're using original tokens, apply that offset.
+ assert(FirstOrigToken[NumConsumedToks].getLocation() ==
+ LineToks[NumConsumedToks].getLocation());
+ unsigned FirstIndex = FirstOrigToken - AsmToks.begin();
+ unsigned LastIndex = FirstIndex + NumConsumedToks - 1;
+
+ // The total length we've consumed is the relative offset
+ // of the last token we consumed plus its length.
+ unsigned TotalOffset =
+ (AsmTokOffsets[LastIndex] + AsmToks[LastIndex].getLength() -
+ AsmTokOffsets[FirstIndex]);
+ LineBuf = LineBuf.substr(0, TotalOffset);
}
- SourceLocation translateLocation(const llvm::SourceMgr &LSM, llvm::SMLoc SMLoc) {
- // Compute an offset into the inline asm buffer.
- // FIXME: This isn't right if .macro is involved (but hopefully, no
- // real-world code does that).
- const llvm::MemoryBuffer *LBuf =
- LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(SMLoc));
- unsigned Offset = SMLoc.getPointer() - LBuf->getBufferStart();
+ // Initialize Info with the lookup result.
+ if (!Result.isUsable())
+ return;
+ TheParser.getActions().FillInlineAsmIdentifierInfo(Result.get(), Info);
+}
- // Figure out which token that offset points into.
- const unsigned *TokOffsetPtr =
- std::lower_bound(AsmTokOffsets.begin(), AsmTokOffsets.end(), Offset);
- unsigned TokIndex = TokOffsetPtr - AsmTokOffsets.begin();
- unsigned TokOffset = *TokOffsetPtr;
+StringRef ClangAsmParserCallback::LookupInlineAsmLabel(StringRef Identifier,
+ llvm::SourceMgr &LSM,
+ llvm::SMLoc Location,
+ bool Create) {
+ SourceLocation Loc = translateLocation(LSM, Location);
+ LabelDecl *Label =
+ TheParser.getActions().GetOrCreateMSAsmLabel(Identifier, Loc, Create);
+ return Label->getMSAsmLabel();
+}
- // If we come up with an answer which seems sane, use it; otherwise,
- // just point at the __asm keyword.
- // FIXME: Assert the answer is sane once we handle .macro correctly.
- SourceLocation Loc = AsmLoc;
- if (TokIndex < AsmToks.size()) {
- const Token &Tok = AsmToks[TokIndex];
- Loc = Tok.getLocation();
- Loc = Loc.getLocWithOffset(Offset - TokOffset);
- }
- return Loc;
+void ClangAsmParserCallback::findTokensForString(
+ StringRef Str, SmallVectorImpl<Token> &TempToks,
+ const Token *&FirstOrigToken) const {
+ // For now, assert that the string we're working with is a substring
+ // of what we gave to MC. This lets us use the original tokens.
+ assert(!std::less<const char *>()(Str.begin(), AsmString.begin()) &&
+ !std::less<const char *>()(AsmString.end(), Str.end()));
+
+ // Try to find a token whose offset matches the first token.
+ unsigned FirstCharOffset = Str.begin() - AsmString.begin();
+ const unsigned *FirstTokOffset = std::lower_bound(
+ AsmTokOffsets.begin(), AsmTokOffsets.end(), FirstCharOffset);
+
+ // For now, assert that the start of the string exactly
+ // corresponds to the start of a token.
+ assert(*FirstTokOffset == FirstCharOffset);
+
+ // Use all the original tokens for this line. (We assume the
+ // end of the line corresponds cleanly to a token break.)
+ unsigned FirstTokIndex = FirstTokOffset - AsmTokOffsets.begin();
+ FirstOrigToken = &AsmToks[FirstTokIndex];
+ unsigned LastCharOffset = Str.end() - AsmString.begin();
+ for (unsigned i = FirstTokIndex, e = AsmTokOffsets.size(); i != e; ++i) {
+ if (AsmTokOffsets[i] >= LastCharOffset)
+ break;
+ TempToks.push_back(AsmToks[i]);
}
+}
+
+SourceLocation
+ClangAsmParserCallback::translateLocation(const llvm::SourceMgr &LSM,
+ llvm::SMLoc SMLoc) {
+ // Compute an offset into the inline asm buffer.
+ // FIXME: This isn't right if .macro is involved (but hopefully, no
+ // real-world code does that).
+ const llvm::MemoryBuffer *LBuf =
+ LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(SMLoc));
+ unsigned Offset = SMLoc.getPointer() - LBuf->getBufferStart();
- void handleDiagnostic(const llvm::SMDiagnostic &D) {
- const llvm::SourceMgr &LSM = *D.getSourceMgr();
- SourceLocation Loc = translateLocation(LSM, D.getLoc());
- TheParser.Diag(Loc, diag::err_inline_ms_asm_parsing) << D.getMessage();
+ // Figure out which token that offset points into.
+ const unsigned *TokOffsetPtr =
+ std::lower_bound(AsmTokOffsets.begin(), AsmTokOffsets.end(), Offset);
+ unsigned TokIndex = TokOffsetPtr - AsmTokOffsets.begin();
+ unsigned TokOffset = *TokOffsetPtr;
+
+ // If we come up with an answer which seems sane, use it; otherwise,
+ // just point at the __asm keyword.
+ // FIXME: Assert the answer is sane once we handle .macro correctly.
+ SourceLocation Loc = AsmLoc;
+ if (TokIndex < AsmToks.size()) {
+ const Token &Tok = AsmToks[TokIndex];
+ Loc = Tok.getLocation();
+ Loc = Loc.getLocWithOffset(Offset - TokOffset);
}
-};
+ return Loc;
+}
+
+void ClangAsmParserCallback::handleDiagnostic(const llvm::SMDiagnostic &D) {
+ const llvm::SourceMgr &LSM = *D.getSourceMgr();
+ SourceLocation Loc = translateLocation(LSM, D.getLoc());
+ TheParser.Diag(Loc, diag::err_inline_ms_asm_parsing) << D.getMessage();
}
/// Parse an identifier in an MS-style inline assembly block.
-///
-/// \param CastInfo - a void* so that we don't have to teach Parser.h
-/// about the actual type.
ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks,
unsigned &NumLineToksConsumed,
- void *CastInfo,
bool IsUnevaluatedContext) {
- llvm::InlineAsmIdentifierInfo &Info =
- *(llvm::InlineAsmIdentifierInfo *)CastInfo;
-
// Push a fake token on the end so that we don't overrun the token
// stream. We use ';' because it expression-parsing should never
// overrun it.
@@ -227,7 +241,7 @@ ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks,
/*AllowDeductionGuide=*/false,
/*ObjectType=*/nullptr, TemplateKWLoc, Id);
// Perform the lookup.
- Result = Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id, Info,
+ Result = Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id,
IsUnevaluatedContext);
}
// While the next two tokens are 'period' 'identifier', repeatedly parse it as
@@ -241,7 +255,7 @@ ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks,
IdentifierInfo *Id = Tok.getIdentifierInfo();
ConsumeToken(); // Consume the identifier.
Result = Actions.LookupInlineAsmVarDeclField(Result.get(), Id->getName(),
- Info, Tok.getLocation());
+ Tok.getLocation());
}
// Figure out how many tokens we are into LineToks.
@@ -564,7 +578,7 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) {
if (buildMSAsmString(PP, AsmLoc, AsmToks, TokOffsets, AsmString))
return StmtError();
- TargetOptions TO = Actions.Context.getTargetInfo().getTargetOpts();
+ const TargetOptions &TO = Actions.Context.getTargetInfo().getTargetOpts();
std::string FeaturesStr =
llvm::join(TO.Features.begin(), TO.Features.end(), ",");
@@ -578,8 +592,7 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) {
llvm::SourceMgr TempSrcMgr;
llvm::MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &TempSrcMgr);
- MOFI->InitMCObjectFileInfo(TheTriple, /*PIC*/ false, llvm::CodeModel::Default,
- Ctx);
+ MOFI->InitMCObjectFileInfo(TheTriple, /*PIC*/ false, Ctx);
std::unique_ptr<llvm::MemoryBuffer> Buffer =
llvm::MemoryBuffer::getMemBuffer(AsmString, "<MS inline asm>");
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp
index 944cd775d52a4..6df9df804fd7e 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp
@@ -112,7 +112,7 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
// Parse the '<' template-parameter-list '>'
SourceLocation LAngleLoc, RAngleLoc;
- SmallVector<Decl*, 4> TemplateParams;
+ SmallVector<NamedDecl*, 4> TemplateParams;
if (ParseTemplateParameters(CurTemplateDepthTracker.getDepth(),
TemplateParams, LAngleLoc, RAngleLoc)) {
// Skip until the semi-colon or a '}'.
@@ -197,10 +197,11 @@ Parser::ParseSingleDeclarationAfterTemplate(
MaybeParseCXX11Attributes(prefixAttrs);
if (Tok.is(tok::kw_using)) {
- // FIXME: We should return the DeclGroup to the caller.
- ParseUsingDirectiveOrDeclaration(Context, TemplateInfo, DeclEnd,
- prefixAttrs);
- return nullptr;
+ auto usingDeclPtr = ParseUsingDirectiveOrDeclaration(Context, TemplateInfo, DeclEnd,
+ prefixAttrs);
+ if (!usingDeclPtr || !usingDeclPtr.get().isSingleDecl())
+ return nullptr;
+ return usingDeclPtr.get().getSingleDecl();
}
// Parse the declaration specifiers, stealing any diagnostics from
@@ -329,10 +330,9 @@ Parser::ParseSingleDeclarationAfterTemplate(
/// that enclose this template parameter list.
///
/// \returns true if an error occurred, false otherwise.
-bool Parser::ParseTemplateParameters(unsigned Depth,
- SmallVectorImpl<Decl*> &TemplateParams,
- SourceLocation &LAngleLoc,
- SourceLocation &RAngleLoc) {
+bool Parser::ParseTemplateParameters(
+ unsigned Depth, SmallVectorImpl<NamedDecl *> &TemplateParams,
+ SourceLocation &LAngleLoc, SourceLocation &RAngleLoc) {
// Get the template parameter list.
if (!TryConsumeToken(tok::less, LAngleLoc)) {
Diag(Tok.getLocation(), diag::err_expected_less_after) << "template";
@@ -370,11 +370,12 @@ bool Parser::ParseTemplateParameters(unsigned Depth,
/// template-parameter-list ',' template-parameter
bool
Parser::ParseTemplateParameterList(unsigned Depth,
- SmallVectorImpl<Decl*> &TemplateParams) {
+ SmallVectorImpl<NamedDecl*> &TemplateParams) {
while (1) {
+ // FIXME: ParseTemplateParameter should probably just return a NamedDecl.
if (Decl *TmpParam
= ParseTemplateParameter(Depth, TemplateParams.size())) {
- TemplateParams.push_back(TmpParam);
+ TemplateParams.push_back(dyn_cast<NamedDecl>(TmpParam));
} else {
// If we failed to parse a template parameter, skip until we find
// a comma or closing brace.
@@ -569,7 +570,7 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
// Handle the template <...> part.
SourceLocation TemplateLoc = ConsumeToken();
- SmallVector<Decl*,8> TemplateParams;
+ SmallVector<NamedDecl*,8> TemplateParams;
SourceLocation LAngleLoc, RAngleLoc;
{
ParseScope TemplateParmScope(this, Scope::TemplateParamScope);
@@ -589,10 +590,10 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
const Token &Next = Tok.is(tok::kw_struct) ? NextToken() : Tok;
if (Tok.is(tok::kw_typename)) {
Diag(Tok.getLocation(),
- getLangOpts().CPlusPlus1z
+ getLangOpts().CPlusPlus17
? diag::warn_cxx14_compat_template_template_param_typename
: diag::ext_template_template_param_typename)
- << (!getLangOpts().CPlusPlus1z
+ << (!getLangOpts().CPlusPlus17
? FixItHint::CreateReplacement(Tok.getLocation(), "class")
: FixItHint());
} else if (Next.isOneOf(tok::identifier, tok::comma, tok::greater,
@@ -1023,8 +1024,8 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
? OO_None
: TemplateName.OperatorFunctionId.Operator;
- TemplateIdAnnotation *TemplateId = TemplateIdAnnotation::Create(
- SS, TemplateKWLoc, TemplateNameLoc, TemplateII, OpKind, Template, TNK,
+ TemplateIdAnnotation *TemplateId = TemplateIdAnnotation::Create(
+ SS, TemplateKWLoc, TemplateNameLoc, TemplateII, OpKind, Template, TNK,
LAngleLoc, RAngleLoc, TemplateArgs, TemplateIds);
Tok.setAnnotationValue(TemplateId);
@@ -1380,7 +1381,8 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) {
// Parse the method body. Function body parsing code is similar enough
// to be re-used for method bodies as well.
- ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope);
+ ParseScope FnScope(this, Scope::FnScope | Scope::DeclScope |
+ Scope::CompoundStmtScope);
// Recreate the containing function DeclContext.
Sema::ContextRAII FunctionSavedContext(Actions,
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp
index d6684c39aa734..5c206f4eab90b 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp
@@ -1026,6 +1026,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
case tok::kw_char:
case tok::kw_const:
case tok::kw_double:
+ case tok::kw__Float16:
case tok::kw___float128:
case tok::kw_enum:
case tok::kw_half:
@@ -1298,11 +1299,9 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
// 'friend'
// 'typedef'
// 'constexpr'
- // 'concept'
case tok::kw_friend:
case tok::kw_typedef:
case tok::kw_constexpr:
- case tok::kw_concept:
// storage-class-specifier
case tok::kw_register:
case tok::kw_static:
@@ -1510,6 +1509,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
case tok::kw_half:
case tok::kw_float:
case tok::kw_double:
+ case tok::kw__Float16:
case tok::kw___float128:
case tok::kw_void:
case tok::annot_decltype:
@@ -1600,6 +1600,7 @@ bool Parser::isCXXDeclarationSpecifierAType() {
case tok::kw_half:
case tok::kw_float:
case tok::kw_double:
+ case tok::kw__Float16:
case tok::kw___float128:
case tok::kw_void:
case tok::kw___unknown_anytype:
diff --git a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp
index 1ed7ef9663589..72d653797c60a 100644
--- a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp
@@ -556,10 +556,6 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
HandlePragmaUnused();
return false;
- case tok::kw_import:
- Result = ParseModuleImport(SourceLocation());
- return false;
-
case tok::kw_export:
if (NextToken().isNot(tok::kw_module))
break;
@@ -637,6 +633,9 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
/// ';'
///
/// [C++0x/GNU] 'extern' 'template' declaration
+///
+/// [Modules-TS] module-import-declaration
+///
Parser::DeclGroupPtrTy
Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
ParsingDeclSpec *DS) {
@@ -753,11 +752,20 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
SingleDecl = ParseObjCMethodDefinition();
break;
case tok::code_completion:
- Actions.CodeCompleteOrdinaryName(getCurScope(),
- CurParsedObjCImpl? Sema::PCC_ObjCImplementation
- : Sema::PCC_Namespace);
+ if (CurParsedObjCImpl) {
+ // Code-complete Objective-C methods even without leading '-'/'+' prefix.
+ Actions.CodeCompleteObjCMethodDecl(getCurScope(),
+ /*IsInstanceMethod=*/None,
+ /*ReturnType=*/nullptr);
+ }
+ Actions.CodeCompleteOrdinaryName(
+ getCurScope(),
+ CurParsedObjCImpl ? Sema::PCC_ObjCImplementation : Sema::PCC_Namespace);
cutOffParsing();
return nullptr;
+ case tok::kw_import:
+ SingleDecl = ParseModuleImport(SourceLocation());
+ break;
case tok::kw_export:
if (getLangOpts().ModulesTS) {
SingleDecl = ParseExportDeclaration();
@@ -1073,8 +1081,9 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
TemplateInfo.Kind == ParsedTemplateInfo::Template &&
Actions.canDelayFunctionBody(D)) {
MultiTemplateParamsArg TemplateParameterLists(*TemplateInfo.TemplateParams);
-
- ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope);
+
+ ParseScope BodyScope(this, Scope::FnScope | Scope::DeclScope |
+ Scope::CompoundStmtScope);
Scope *ParentScope = getCurScope()->getParent();
D.setFunctionDefinitionKind(FDK_Definition);
@@ -1104,7 +1113,8 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
(Tok.is(tok::l_brace) || Tok.is(tok::kw_try) ||
Tok.is(tok::colon)) &&
Actions.CurContext->isTranslationUnit()) {
- ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope);
+ ParseScope BodyScope(this, Scope::FnScope | Scope::DeclScope |
+ Scope::CompoundStmtScope);
Scope *ParentScope = getCurScope()->getParent();
D.setFunctionDefinitionKind(FDK_Definition);
@@ -1122,7 +1132,8 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
}
// Enter a scope for the function body.
- ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope);
+ ParseScope BodyScope(this, Scope::FnScope | Scope::DeclScope |
+ Scope::CompoundStmtScope);
// Tell the actions module that we have entered a function definition with the
// specified Declarator for the function.
@@ -2045,7 +2056,7 @@ Parser::DeclGroupPtrTy Parser::ParseModuleDecl() {
SourceLocation StartLoc = Tok.getLocation();
Sema::ModuleDeclKind MDK = TryConsumeToken(tok::kw_export)
- ? Sema::ModuleDeclKind::Module
+ ? Sema::ModuleDeclKind::Interface
: Sema::ModuleDeclKind::Implementation;
assert(Tok.is(tok::kw_module) && "not a module declaration");
@@ -2054,7 +2065,7 @@ Parser::DeclGroupPtrTy Parser::ParseModuleDecl() {
if (Tok.is(tok::identifier) && NextToken().is(tok::identifier) &&
Tok.getIdentifierInfo()->isStr("partition")) {
// If 'partition' is present, this must be a module interface unit.
- if (MDK != Sema::ModuleDeclKind::Module)
+ if (MDK != Sema::ModuleDeclKind::Interface)
Diag(Tok.getLocation(), diag::err_module_implementation_partition)
<< FixItHint::CreateInsertion(ModuleLoc, "export ");
MDK = Sema::ModuleDeclKind::Partition;
@@ -2083,7 +2094,7 @@ Parser::DeclGroupPtrTy Parser::ParseModuleDecl() {
/// '@' 'import' module-name ';'
/// [ModTS] module-import-declaration:
/// 'import' module-name attribute-specifier-seq[opt] ';'
-Parser::DeclGroupPtrTy Parser::ParseModuleImport(SourceLocation AtLoc) {
+Decl *Parser::ParseModuleImport(SourceLocation AtLoc) {
assert((AtLoc.isInvalid() ? Tok.is(tok::kw_import)
: Tok.isObjCAtKeyword(tok::objc_import)) &&
"Improper start to module import");
@@ -2110,7 +2121,7 @@ Parser::DeclGroupPtrTy Parser::ParseModuleImport(SourceLocation AtLoc) {
if (Import.isInvalid())
return nullptr;
- return Actions.ConvertDeclToDeclGroup(Import.get());
+ return Import.get();
}
/// Parse a C++ Modules TS / Objective-C module name (both forms use the same
diff --git a/contrib/llvm/tools/clang/lib/Rewrite/HTMLRewrite.cpp b/contrib/llvm/tools/clang/lib/Rewrite/HTMLRewrite.cpp
index 9e307f31be11c..23d1895e31b4c 100644
--- a/contrib/llvm/tools/clang/lib/Rewrite/HTMLRewrite.cpp
+++ b/contrib/llvm/tools/clang/lib/Rewrite/HTMLRewrite.cpp
@@ -289,6 +289,11 @@ void html::AddHeaderFooterInternalBuiltinCSS(Rewriter &R, FileID FID,
" body { color:#000000; background-color:#ffffff }\n"
" body { font-family:Helvetica, sans-serif; font-size:10pt }\n"
" h1 { font-size:14pt }\n"
+ " .FileName { margin-top: 5px; margin-bottom: 5px; display: inline; }\n"
+ " .FileNav { margin-left: 5px; margin-right: 5px; display: inline; }\n"
+ " .FileNav a { text-decoration:none; font-size: larger; }\n"
+ " .divider { margin-top: 30px; margin-bottom: 30px; height: 15px; }\n"
+ " .divider { background-color: gray; }\n"
" .code { border-collapse:collapse; width:100%; }\n"
" .code { font-family: \"Monospace\", monospace; font-size:10pt }\n"
" .code { line-height: 1.2em }\n"
diff --git a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
index f83baa790b497..0033edf326ac5 100644
--- a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -29,7 +29,7 @@
#include "clang/Analysis/Analyses/ReachableCode.h"
#include "clang/Analysis/Analyses/ThreadSafety.h"
#include "clang/Analysis/Analyses/UninitializedValues.h"
-#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/CFGStmtMap.h"
#include "clang/Basic/SourceLocation.h"
@@ -289,14 +289,14 @@ enum ThrowState {
static bool isThrowCaught(const CXXThrowExpr *Throw,
const CXXCatchStmt *Catch) {
+ const Type *CaughtType = Catch->getCaughtType().getTypePtrOrNull();
+ if (!CaughtType)
+ return true;
const Type *ThrowType = nullptr;
if (Throw->getSubExpr())
ThrowType = Throw->getSubExpr()->getType().getTypePtrOrNull();
if (!ThrowType)
return false;
- const Type *CaughtType = Catch->getCaughtType().getTypePtrOrNull();
- if (!CaughtType)
- return true;
if (ThrowType->isReferenceType())
ThrowType = ThrowType->castAs<ReferenceType>()
->getPointeeType()
@@ -361,8 +361,7 @@ static bool hasThrowOutNonThrowingFunc(SourceLocation &OpLoc, CFG *BodyCFG) {
SmallVector<CFGBlock *, 16> Stack;
Stack.push_back(&BodyCFG->getEntry());
while (!Stack.empty()) {
- CFGBlock *CurBlock = Stack.back();
- Stack.pop_back();
+ CFGBlock *CurBlock = Stack.pop_back_val();
unsigned ID = CurBlock->getBlockID();
ThrowState CurState = States[ID];
@@ -426,7 +425,7 @@ static void checkThrowInNonThrowingFunc(Sema &S, const FunctionDecl *FD,
static bool isNoexcept(const FunctionDecl *FD) {
const auto *FPT = FD->getType()->castAs<FunctionProtoType>();
- if (FPT->isNothrow(FD->getASTContext()))
+ if (FPT->isNothrow(FD->getASTContext()) || FD->hasAttr<NoThrowAttr>())
return true;
return false;
}
@@ -1276,7 +1275,7 @@ static StringRef getFallthroughAttrSpelling(Preprocessor &PP,
tok::r_square, tok::r_square
};
- bool PreferClangAttr = !PP.getLangOpts().CPlusPlus1z;
+ bool PreferClangAttr = !PP.getLangOpts().CPlusPlus17;
StringRef MacroName;
if (PreferClangAttr)
@@ -1292,16 +1291,15 @@ static StringRef getFallthroughAttrSpelling(Preprocessor &PP,
static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC,
bool PerFunction) {
- // Only perform this analysis when using C++11. There is no good workflow
- // for this warning when not using C++11. There is no good way to silence
- // the warning (no attribute is available) unless we are using C++11's support
- // for generalized attributes. Once could use pragmas to silence the warning,
- // but as a general solution that is gross and not in the spirit of this
- // warning.
+ // Only perform this analysis when using [[]] attributes. There is no good
+ // workflow for this warning when not using C++11. There is no good way to
+ // silence the warning (no attribute is available) unless we are using
+ // [[]] attributes. One could use pragmas to silence the warning, but as a
+ // general solution that is gross and not in the spirit of this warning.
//
- // NOTE: This an intermediate solution. There are on-going discussions on
+ // NOTE: This an intermediate solution. There are on-going discussions on
// how to properly support this warning outside of C++11 with an annotation.
- if (!AC.getASTContext().getLangOpts().CPlusPlus11)
+ if (!AC.getASTContext().getLangOpts().DoubleSquareBracketAttributes)
return;
FallthroughMapper FM(S);
@@ -2082,10 +2080,10 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
// time.
DiagnosticsEngine &Diags = S.getDiagnostics();
- // Do not do any analysis for declarations in system headers if we are
- // going to just ignore them.
- if (Diags.getSuppressSystemWarnings() &&
- S.SourceMgr.isInSystemHeader(D->getLocation()))
+ // Do not do any analysis if we are going to just ignore them.
+ if (Diags.getIgnoreAllWarnings() ||
+ (Diags.getSuppressSystemWarnings() &&
+ S.SourceMgr.isInSystemHeader(D->getLocation())))
return;
// For code in dependent contexts, we'll do this at instantiation time.
diff --git a/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp b/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp
index 724db456785fb..14d334746f1fd 100644
--- a/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp
@@ -114,7 +114,8 @@ static StringRef normalizeAttrName(StringRef AttrName, StringRef ScopeName,
// Normalize the attribute name, __foo__ becomes foo. This is only allowable
// for GNU attributes.
bool IsGNU = SyntaxUsed == AttributeList::AS_GNU ||
- (SyntaxUsed == AttributeList::AS_CXX11 && ScopeName == "gnu");
+ ((SyntaxUsed == AttributeList::AS_CXX11 ||
+ SyntaxUsed == AttributeList::AS_C2x) && ScopeName == "gnu");
if (IsGNU && AttrName.size() >= 4 && AttrName.startswith("__") &&
AttrName.endswith("__"))
AttrName = AttrName.slice(2, AttrName.size() - 2);
@@ -135,7 +136,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name,
// Ensure that in the case of C++11 attributes, we look for '::foo' if it is
// unscoped.
- if (ScopeName || SyntaxUsed == AS_CXX11)
+ if (ScopeName || SyntaxUsed == AS_CXX11 || SyntaxUsed == AS_C2x)
FullName += "::";
FullName += AttrName;
diff --git a/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp b/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp
index f5b0104462f78..542b65327b7d2 100644
--- a/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp
@@ -613,24 +613,20 @@ void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) {
///
/// If the name needs to be constructed as a string, that string will be
/// saved into Saved and the returned StringRef will refer to it.
-static StringRef getOrderedName(const CodeCompletionResult &R,
- std::string &Saved) {
- switch (R.Kind) {
- case CodeCompletionResult::RK_Keyword:
- return R.Keyword;
-
- case CodeCompletionResult::RK_Pattern:
- return R.Pattern->getTypedText();
-
- case CodeCompletionResult::RK_Macro:
- return R.Macro->getName();
-
- case CodeCompletionResult::RK_Declaration:
+StringRef CodeCompletionResult::getOrderedName(std::string &Saved) const {
+ switch (Kind) {
+ case RK_Keyword:
+ return Keyword;
+ case RK_Pattern:
+ return Pattern->getTypedText();
+ case RK_Macro:
+ return Macro->getName();
+ case RK_Declaration:
// Handle declarations below.
break;
}
- DeclarationName Name = R.Declaration->getDeclName();
+ DeclarationName Name = Declaration->getDeclName();
// If the name is a simple identifier (by far the common case), or a
// zero-argument selector, just return a reference to that identifier.
@@ -648,8 +644,8 @@ static StringRef getOrderedName(const CodeCompletionResult &R,
bool clang::operator<(const CodeCompletionResult &X,
const CodeCompletionResult &Y) {
std::string XSaved, YSaved;
- StringRef XStr = getOrderedName(X, XSaved);
- StringRef YStr = getOrderedName(Y, YSaved);
+ StringRef XStr = X.getOrderedName(XSaved);
+ StringRef YStr = Y.getOrderedName(YSaved);
int cmp = XStr.compare_lower(YStr);
if (cmp)
return cmp < 0;
diff --git a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
index e4e84fcec954b..6fe2dcc9895fb 100644
--- a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
@@ -336,6 +336,7 @@ bool Declarator::isDeclarationOfFunction() const {
case TST_decimal32:
case TST_decimal64:
case TST_double:
+ case TST_Float16:
case TST_float128:
case TST_enum:
case TST_error:
@@ -505,6 +506,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T,
case DeclSpec::TST_half: return "half";
case DeclSpec::TST_float: return "float";
case DeclSpec::TST_double: return "double";
+ case DeclSpec::TST_float16: return "_Float16";
case DeclSpec::TST_float128: return "__float128";
case DeclSpec::TST_bool: return Policy.Bool ? "bool" : "_Bool";
case DeclSpec::TST_decimal32: return "_Decimal32";
@@ -967,18 +969,6 @@ bool DeclSpec::SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec,
return false;
}
-bool DeclSpec::SetConceptSpec(SourceLocation Loc, const char *&PrevSpec,
- unsigned &DiagID) {
- if (Concept_specified) {
- DiagID = diag::ext_duplicate_declspec;
- PrevSpec = "concept";
- return true;
- }
- Concept_specified = true;
- ConceptLoc = Loc;
- return false;
-}
-
void DeclSpec::SaveWrittenBuiltinSpecs() {
writtenBS.Sign = getTypeSpecSign();
writtenBS.Width = getTypeSpecWidth();
diff --git a/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp
index b7e343c647183..77ace0cfa579f 100644
--- a/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp
@@ -19,8 +19,6 @@ using namespace clang;
///\brief Constructs a new multiplexing external sema source and appends the
/// given element to it.
///
-///\param[in] source - An ExternalSemaSource.
-///
MultiplexExternalSemaSource::MultiplexExternalSemaSource(ExternalSemaSource &s1,
ExternalSemaSource &s2){
Sources.push_back(&s1);
diff --git a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
index a18f71422fde6..4e57e5ef81c6f 100644
--- a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
@@ -70,6 +70,49 @@ void Sema::ActOnTranslationUnitScope(Scope *S) {
PushDeclContext(S, Context.getTranslationUnitDecl());
}
+namespace clang {
+namespace sema {
+
+class SemaPPCallbacks : public PPCallbacks {
+ Sema *S = nullptr;
+ llvm::SmallVector<SourceLocation, 8> IncludeStack;
+
+public:
+ void set(Sema &S) { this->S = &S; }
+
+ void reset() { S = nullptr; }
+
+ virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType,
+ FileID PrevFID) override {
+ if (!S)
+ return;
+ switch (Reason) {
+ case EnterFile: {
+ SourceManager &SM = S->getSourceManager();
+ SourceLocation IncludeLoc = SM.getIncludeLoc(SM.getFileID(Loc));
+ if (IncludeLoc.isValid()) {
+ IncludeStack.push_back(IncludeLoc);
+ S->DiagnoseNonDefaultPragmaPack(
+ Sema::PragmaPackDiagnoseKind::NonDefaultStateAtInclude, IncludeLoc);
+ }
+ break;
+ }
+ case ExitFile:
+ if (!IncludeStack.empty())
+ S->DiagnoseNonDefaultPragmaPack(
+ Sema::PragmaPackDiagnoseKind::ChangedStateAtExit,
+ IncludeStack.pop_back_val());
+ break;
+ default:
+ break;
+ }
+ }
+};
+
+} // end namespace sema
+} // end namespace clang
+
Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
TranslationUnitKind TUKind, CodeCompleteConsumer *CodeCompleter)
: ExternalSource(nullptr), isMultiplexExternalSource(false),
@@ -122,6 +165,12 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
// Initilization of data sharing attributes stack for OpenMP
InitDataSharingAttributesStack();
+
+ std::unique_ptr<sema::SemaPPCallbacks> Callbacks =
+ llvm::make_unique<sema::SemaPPCallbacks>();
+ SemaPPCallbackHandler = Callbacks.get();
+ PP.addPPCallbacks(std::move(Callbacks));
+ SemaPPCallbackHandler->set(*this);
}
void Sema::addImplicitTypedef(StringRef Name, QualType T) {
@@ -306,6 +355,10 @@ Sema::~Sema() {
// Destroys data sharing attributes stack for OpenMP
DestroyDataSharingAttributesStack();
+ // Detach from the PP callback handler which outlives Sema since it's owned
+ // by the preprocessor.
+ SemaPPCallbackHandler->reset();
+
assert(DelayedTypos.empty() && "Uncorrected typos!");
}
@@ -383,14 +436,26 @@ void Sema::diagnoseNullableToNonnullConversion(QualType DstType,
}
void Sema::diagnoseZeroToNullptrConversion(CastKind Kind, const Expr* E) {
- if (Kind != CK_NullToPointer && Kind != CK_NullToMemberPointer)
- return;
- if (E->getType()->isNullPtrType())
+ if (Diags.isIgnored(diag::warn_zero_as_null_pointer_constant,
+ E->getLocStart()))
return;
// nullptr only exists from C++11 on, so don't warn on its absence earlier.
if (!getLangOpts().CPlusPlus11)
return;
+ if (Kind != CK_NullToPointer && Kind != CK_NullToMemberPointer)
+ return;
+ if (E->IgnoreParenImpCasts()->getType()->isNullPtrType())
+ return;
+
+ // If it is a macro from system header, and if the macro name is not "NULL",
+ // do not warn.
+ SourceLocation MaybeMacroLoc = E->getLocStart();
+ if (Diags.getSuppressSystemWarnings() &&
+ SourceMgr.isInSystemMacro(MaybeMacroLoc) &&
+ !findMacroSpelling(MaybeMacroLoc, "NULL"))
+ return;
+
Diag(E->getLocStart(), diag::warn_zero_as_null_pointer_constant)
<< FixItHint::CreateReplacement(E->getSourceRange(), "nullptr");
}
@@ -464,7 +529,7 @@ CastKind Sema::ScalarTypeToBooleanCastKind(QualType ScalarTy) {
case Type::STK_IntegralComplex: return CK_IntegralComplexToBoolean;
case Type::STK_FloatingComplex: return CK_FloatingComplexToBoolean;
}
- return CK_Invalid;
+ llvm_unreachable("unknown scalar type kind");
}
/// \brief Used to prune the decls of Sema's UnusedFileScopedDecls vector.
@@ -529,6 +594,23 @@ static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) {
return false;
}
+static bool isFunctionOrVarDeclExternC(NamedDecl *ND) {
+ if (auto *FD = dyn_cast<FunctionDecl>(ND))
+ return FD->isExternC();
+ return cast<VarDecl>(ND)->isExternC();
+}
+
+/// Determine whether ND is an external-linkage function or variable whose
+/// type has no linkage.
+bool Sema::isExternalWithNoLinkageType(ValueDecl *VD) {
+ // Note: it's not quite enough to check whether VD has UniqueExternalLinkage,
+ // because we also want to catch the case where its type has VisibleNoLinkage,
+ // which does not affect the linkage of VD.
+ return getLangOpts().CPlusPlus && VD->hasExternalFormalLinkage() &&
+ !isExternalFormalLinkage(VD->getType()->getLinkage()) &&
+ !isFunctionOrVarDeclExternC(VD);
+}
+
/// Obtains a sorted list of functions and variables that are undefined but
/// ODR-used.
void Sema::getUndefinedButUsed(
@@ -545,17 +627,27 @@ void Sema::getUndefinedButUsed(
if (isa<CXXDeductionGuideDecl>(ND))
continue;
+ if (ND->hasAttr<DLLImportAttr>() || ND->hasAttr<DLLExportAttr>()) {
+ // An exported function will always be emitted when defined, so even if
+ // the function is inline, it doesn't have to be emitted in this TU. An
+ // imported function implies that it has been exported somewhere else.
+ continue;
+ }
+
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
if (FD->isDefined())
continue;
if (FD->isExternallyVisible() &&
+ !isExternalWithNoLinkageType(FD) &&
!FD->getMostRecentDecl()->isInlined())
continue;
} else {
auto *VD = cast<VarDecl>(ND);
if (VD->hasDefinition() != VarDecl::DeclarationOnly)
continue;
- if (VD->isExternallyVisible() && !VD->getMostRecentDecl()->isInline())
+ if (VD->isExternallyVisible() &&
+ !isExternalWithNoLinkageType(VD) &&
+ !VD->getMostRecentDecl()->isInline())
continue;
}
@@ -573,33 +665,43 @@ static void checkUndefinedButUsed(Sema &S) {
S.getUndefinedButUsed(Undefined);
if (Undefined.empty()) return;
- for (SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> >::iterator
- I = Undefined.begin(), E = Undefined.end(); I != E; ++I) {
- NamedDecl *ND = I->first;
+ for (auto Undef : Undefined) {
+ ValueDecl *VD = cast<ValueDecl>(Undef.first);
+ SourceLocation UseLoc = Undef.second;
- if (ND->hasAttr<DLLImportAttr>() || ND->hasAttr<DLLExportAttr>()) {
- // An exported function will always be emitted when defined, so even if
- // the function is inline, it doesn't have to be emitted in this TU. An
- // imported function implies that it has been exported somewhere else.
- continue;
- }
-
- if (!ND->isExternallyVisible()) {
- S.Diag(ND->getLocation(), diag::warn_undefined_internal)
- << isa<VarDecl>(ND) << ND;
- } else if (auto *FD = dyn_cast<FunctionDecl>(ND)) {
+ if (S.isExternalWithNoLinkageType(VD)) {
+ // C++ [basic.link]p8:
+ // A type without linkage shall not be used as the type of a variable
+ // or function with external linkage unless
+ // -- the entity has C language linkage
+ // -- the entity is not odr-used or is defined in the same TU
+ //
+ // As an extension, accept this in cases where the type is externally
+ // visible, since the function or variable actually can be defined in
+ // another translation unit in that case.
+ S.Diag(VD->getLocation(), isExternallyVisible(VD->getType()->getLinkage())
+ ? diag::ext_undefined_internal_type
+ : diag::err_undefined_internal_type)
+ << isa<VarDecl>(VD) << VD;
+ } else if (!VD->isExternallyVisible()) {
+ // FIXME: We can promote this to an error. The function or variable can't
+ // be defined anywhere else, so the program must necessarily violate the
+ // one definition rule.
+ S.Diag(VD->getLocation(), diag::warn_undefined_internal)
+ << isa<VarDecl>(VD) << VD;
+ } else if (auto *FD = dyn_cast<FunctionDecl>(VD)) {
(void)FD;
assert(FD->getMostRecentDecl()->isInlined() &&
"used object requires definition but isn't inline or internal?");
// FIXME: This is ill-formed; we should reject.
- S.Diag(ND->getLocation(), diag::warn_undefined_inline) << ND;
+ S.Diag(VD->getLocation(), diag::warn_undefined_inline) << VD;
} else {
- assert(cast<VarDecl>(ND)->getMostRecentDecl()->isInline() &&
+ assert(cast<VarDecl>(VD)->getMostRecentDecl()->isInline() &&
"used var requires definition but isn't inline or internal?");
- S.Diag(ND->getLocation(), diag::err_undefined_inline_var) << ND;
+ S.Diag(VD->getLocation(), diag::err_undefined_inline_var) << VD;
}
- if (I->second.isValid())
- S.Diag(I->second, diag::note_used_here);
+ if (UseLoc.isValid())
+ S.Diag(UseLoc, diag::note_used_here);
}
S.UndefinedButUsed.clear();
@@ -635,7 +737,8 @@ static bool MethodsAndNestedClassesComplete(const CXXRecordDecl *RD,
E = RD->decls_end();
I != E && Complete; ++I) {
if (const CXXMethodDecl *M = dyn_cast<CXXMethodDecl>(*I))
- Complete = M->isDefined() || (M->isPure() && !isa<CXXDestructorDecl>(M));
+ Complete = M->isDefined() || M->isDefaulted() ||
+ (M->isPure() && !isa<CXXDestructorDecl>(M));
else if (const FunctionTemplateDecl *F = dyn_cast<FunctionTemplateDecl>(*I))
// If the template function is marked as late template parsed at this
// point, it has not been instantiated and therefore we have not
@@ -713,10 +816,24 @@ void Sema::emitAndClearUnusedLocalTypedefWarnings() {
/// declarations.
void Sema::ActOnStartOfTranslationUnit() {
if (getLangOpts().ModulesTS) {
+ SourceLocation StartOfTU =
+ SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
+
// We start in the global module; all those declarations are implicitly
// module-private (though they do not have module linkage).
- Context.getTranslationUnitDecl()->setModuleOwnershipKind(
- Decl::ModuleOwnershipKind::ModulePrivate);
+ auto &Map = PP.getHeaderSearchInfo().getModuleMap();
+ auto *GlobalModule = Map.createGlobalModuleForInterfaceUnit(StartOfTU);
+ assert(GlobalModule && "module creation should not fail");
+
+ // Enter the scope of the global module.
+ ModuleScopes.push_back({});
+ ModuleScopes.back().Module = GlobalModule;
+ VisibleModules.setVisible(GlobalModule, StartOfTU);
+
+ // All declarations created from now on are owned by the global module.
+ auto *TU = Context.getTranslationUnitDecl();
+ TU->setModuleOwnershipKind(Decl::ModuleOwnershipKind::Visible);
+ TU->setLocalOwningModule(GlobalModule);
}
}
@@ -769,6 +886,7 @@ void Sema::ActOnEndOfTranslationUnit() {
CheckDelayedMemberExceptionSpecs();
}
+ DiagnoseUnterminatedPragmaPack();
DiagnoseUnterminatedPragmaAttribute();
// All delayed member exception specs should be checked or we end up accepting
@@ -825,6 +943,17 @@ void Sema::ActOnEndOfTranslationUnit() {
}
if (TUKind == TU_Module) {
+ // If we are building a module interface unit, we need to have seen the
+ // module declaration by now.
+ if (getLangOpts().getCompilingModule() ==
+ LangOptions::CMK_ModuleInterface &&
+ ModuleScopes.back().Module->Kind != Module::ModuleInterfaceUnit) {
+ // FIXME: Make a better guess as to where to put the module declaration.
+ Diag(getSourceManager().getLocForStartOfFile(
+ getSourceManager().getMainFileID()),
+ diag::err_module_declaration_missing);
+ }
+
// If we are building a module, resolve all of the exported declarations
// now.
if (Module *CurrentModule = PP.getCurrentModule()) {
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp
index 8c13ead644574..4ba2a317e1f97 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp
@@ -61,6 +61,17 @@ void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {
RD->addAttr(MaxFieldAlignmentAttr::CreateImplicit(Context,
Alignment * 8));
}
+ if (PackIncludeStack.empty())
+ return;
+ // The #pragma pack affected a record in an included file, so Clang should
+ // warn when that pragma was written in a file that included the included
+ // file.
+ for (auto &PackedInclude : llvm::reverse(PackIncludeStack)) {
+ if (PackedInclude.CurrentPragmaLocation != PackStack.CurrentPragmaLocation)
+ break;
+ if (PackedInclude.HasNonDefaultValue)
+ PackedInclude.ShouldWarnOnInclude = true;
+ }
}
void Sema::AddMsStructLayoutForRecord(RecordDecl *RD) {
@@ -202,6 +213,61 @@ void Sema::ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action,
PackStack.Act(PragmaLoc, Action, SlotLabel, AlignmentVal);
}
+void Sema::DiagnoseNonDefaultPragmaPack(PragmaPackDiagnoseKind Kind,
+ SourceLocation IncludeLoc) {
+ if (Kind == PragmaPackDiagnoseKind::NonDefaultStateAtInclude) {
+ SourceLocation PrevLocation = PackStack.CurrentPragmaLocation;
+ // Warn about non-default alignment at #includes (without redundant
+ // warnings for the same directive in nested includes).
+ // The warning is delayed until the end of the file to avoid warnings
+ // for files that don't have any records that are affected by the modified
+ // alignment.
+ bool HasNonDefaultValue =
+ PackStack.hasValue() &&
+ (PackIncludeStack.empty() ||
+ PackIncludeStack.back().CurrentPragmaLocation != PrevLocation);
+ PackIncludeStack.push_back(
+ {PackStack.CurrentValue,
+ PackStack.hasValue() ? PrevLocation : SourceLocation(),
+ HasNonDefaultValue, /*ShouldWarnOnInclude*/ false});
+ return;
+ }
+
+ assert(Kind == PragmaPackDiagnoseKind::ChangedStateAtExit && "invalid kind");
+ PackIncludeState PrevPackState = PackIncludeStack.pop_back_val();
+ if (PrevPackState.ShouldWarnOnInclude) {
+ // Emit the delayed non-default alignment at #include warning.
+ Diag(IncludeLoc, diag::warn_pragma_pack_non_default_at_include);
+ Diag(PrevPackState.CurrentPragmaLocation, diag::note_pragma_pack_here);
+ }
+ // Warn about modified alignment after #includes.
+ if (PrevPackState.CurrentValue != PackStack.CurrentValue) {
+ Diag(IncludeLoc, diag::warn_pragma_pack_modified_after_include);
+ Diag(PackStack.CurrentPragmaLocation, diag::note_pragma_pack_here);
+ }
+}
+
+void Sema::DiagnoseUnterminatedPragmaPack() {
+ if (PackStack.Stack.empty())
+ return;
+ bool IsInnermost = true;
+ for (const auto &StackSlot : llvm::reverse(PackStack.Stack)) {
+ Diag(StackSlot.PragmaPushLocation, diag::warn_pragma_pack_no_pop_eof);
+ // The user might have already reset the alignment, so suggest replacing
+ // the reset with a pop.
+ if (IsInnermost && PackStack.CurrentValue == PackStack.DefaultValue) {
+ DiagnosticBuilder DB = Diag(PackStack.CurrentPragmaLocation,
+ diag::note_pragma_pack_pop_instead_reset);
+ SourceLocation FixItLoc = Lexer::findLocationAfterToken(
+ PackStack.CurrentPragmaLocation, tok::l_paren, SourceMgr, LangOpts,
+ /*SkipTrailing=*/false);
+ if (FixItLoc.isValid())
+ DB << FixItHint::CreateInsertion(FixItLoc, "pop");
+ }
+ IsInnermost = false;
+ }
+}
+
void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) {
MSStructPragmaOn = (Kind == PMSST_ON);
}
@@ -249,7 +315,8 @@ void Sema::PragmaStack<ValueType>::Act(SourceLocation PragmaLocation,
return;
}
if (Action & PSK_Push)
- Stack.push_back(Slot(StackSlotLabel, CurrentValue, CurrentPragmaLocation));
+ Stack.emplace_back(StackSlotLabel, CurrentValue, CurrentPragmaLocation,
+ PragmaLocation);
else if (Action & PSK_Pop) {
if (!StackSlotLabel.empty()) {
// If we've got a label, try to find it and jump there.
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp
index d603101c3fd9c..ad6348685b64e 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp
@@ -2458,24 +2458,17 @@ void CastOperation::CheckCStyleCast() {
// GCC's cast to union extension.
if (DestRecordTy && DestRecordTy->getDecl()->isUnion()) {
RecordDecl *RD = DestRecordTy->getDecl();
- RecordDecl::field_iterator Field, FieldEnd;
- for (Field = RD->field_begin(), FieldEnd = RD->field_end();
- Field != FieldEnd; ++Field) {
- if (Self.Context.hasSameUnqualifiedType(Field->getType(), SrcType) &&
- !Field->isUnnamedBitfield()) {
- Self.Diag(OpRange.getBegin(), diag::ext_typecheck_cast_to_union)
- << SrcExpr.get()->getSourceRange();
- break;
- }
- }
- if (Field == FieldEnd) {
+ if (CastExpr::getTargetFieldForToUnionCast(RD, SrcType)) {
+ Self.Diag(OpRange.getBegin(), diag::ext_typecheck_cast_to_union)
+ << SrcExpr.get()->getSourceRange();
+ Kind = CK_ToUnion;
+ return;
+ } else {
Self.Diag(OpRange.getBegin(), diag::err_typecheck_cast_to_union_no_type)
<< SrcType << SrcExpr.get()->getSourceRange();
SrcExpr = ExprError();
return;
}
- Kind = CK_ToUnion;
- return;
}
// OpenCL v2.0 s6.13.10 - Allow casts from '0' to event_t type.
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
index b2223b7550614..94070bb9c9aa1 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
@@ -1,4 +1,4 @@
-//===--- SemaChecking.cpp - Extra Semantic Checking -----------------------===//
+//===- SemaChecking.cpp - Extra Semantic Checking -------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,34 +12,88 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/AttrIterator.h"
#include "clang/AST/CharUnits.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclarationName.h"
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExprOpenMP.h"
-#include "clang/AST/StmtCXX.h"
-#include "clang/AST/StmtObjC.h"
+#include "clang/AST/NSAPI.h"
+#include "clang/AST/OperationKinds.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/AST/UnresolvedSet.h"
#include "clang/Analysis/Analyses/FormatString.h"
+#include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/OpenCLOptions.h"
+#include "clang/Basic/OperatorKinds.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Basic/SyncScope.h"
#include "clang/Basic/TargetBuiltins.h"
+#include "clang/Basic/TargetCXXABI.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TypeTraits.h"
#include "clang/Lex/Lexer.h" // TODO: Extract static functions to fix layering.
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Ownership.h"
+#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaInternal.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallBitVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/AtomicOrdering.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Locale.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <functional>
+#include <limits>
+#include <string>
+#include <tuple>
+#include <utility>
using namespace clang;
using namespace sema;
@@ -98,6 +152,28 @@ static bool SemaBuiltinAnnotation(Sema &S, CallExpr *TheCall) {
return false;
}
+static bool SemaBuiltinMSVCAnnotation(Sema &S, CallExpr *TheCall) {
+ // We need at least one argument.
+ if (TheCall->getNumArgs() < 1) {
+ S.Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args_at_least)
+ << 0 << 1 << TheCall->getNumArgs()
+ << TheCall->getCallee()->getSourceRange();
+ return true;
+ }
+
+ // All arguments should be wide string literals.
+ for (Expr *Arg : TheCall->arguments()) {
+ auto *Literal = dyn_cast<StringLiteral>(Arg->IgnoreParenCasts());
+ if (!Literal || !Literal->isWide()) {
+ S.Diag(Arg->getLocStart(), diag::err_msvc_annotation_wide_str)
+ << Arg->getSourceRange();
+ return true;
+ }
+ }
+
+ return false;
+}
+
/// Check that the argument to __builtin_addressof is a glvalue, and set the
/// result type to the corresponding pointer type.
static bool SemaBuiltinAddressof(Sema &S, CallExpr *TheCall) {
@@ -299,6 +375,41 @@ static bool checkOpenCLBlockArgs(Sema &S, Expr *BlockArg) {
return IllegalParams;
}
+static bool checkOpenCLSubgroupExt(Sema &S, CallExpr *Call) {
+ if (!S.getOpenCLOptions().isEnabled("cl_khr_subgroups")) {
+ S.Diag(Call->getLocStart(), diag::err_opencl_requires_extension)
+ << 1 << Call->getDirectCallee() << "cl_khr_subgroups";
+ return true;
+ }
+ return false;
+}
+
+static bool SemaOpenCLBuiltinNDRangeAndBlock(Sema &S, CallExpr *TheCall) {
+ if (checkArgCount(S, TheCall, 2))
+ return true;
+
+ if (checkOpenCLSubgroupExt(S, TheCall))
+ return true;
+
+ // First argument is an ndrange_t type.
+ Expr *NDRangeArg = TheCall->getArg(0);
+ if (NDRangeArg->getType().getUnqualifiedType().getAsString() != "ndrange_t") {
+ S.Diag(NDRangeArg->getLocStart(),
+ diag::err_opencl_builtin_expected_type)
+ << TheCall->getDirectCallee() << "'ndrange_t'";
+ return true;
+ }
+
+ Expr *BlockArg = TheCall->getArg(1);
+ if (!isBlockPointer(BlockArg)) {
+ S.Diag(BlockArg->getLocStart(),
+ diag::err_opencl_builtin_expected_type)
+ << TheCall->getDirectCallee() << "block";
+ return true;
+ }
+ return checkOpenCLBlockArgs(S, BlockArg);
+}
+
/// OpenCL C v2.0, s6.13.17.6 - Check the argument to the
/// get_kernel_work_group_size
/// and get_kernel_preferred_work_group_size_multiple builtin functions.
@@ -580,7 +691,7 @@ static bool SemaBuiltinRWPipe(Sema &S, CallExpr *Call) {
// OpenCL v2.0 s6.13.16.2 - The built-in read/write
// functions have two forms.
switch (Call->getNumArgs()) {
- case 2: {
+ case 2:
if (checkOpenCLPipeArg(S, Call))
return true;
// The call with 2 arguments should be
@@ -588,7 +699,7 @@ static bool SemaBuiltinRWPipe(Sema &S, CallExpr *Call) {
// Check packet type T.
if (checkOpenCLPipePacketType(S, Call, 1))
return true;
- } break;
+ break;
case 4: {
if (checkOpenCLPipeArg(S, Call))
@@ -647,6 +758,11 @@ static bool SemaBuiltinReserveRWPipe(Sema &S, CallExpr *Call) {
return true;
}
+ // Since return type of reserve_read/write_pipe built-in function is
+ // reserve_id_t, which is not defined in the builtin def file , we used int
+ // as return type and need to override the return type of these functions.
+ Call->setType(S.Context.OCLReserveIDTy);
+
return false;
}
@@ -690,6 +806,7 @@ static bool SemaBuiltinPipePackets(Sema &S, CallExpr *Call) {
return false;
}
+
// \brief OpenCL v2.0 s6.13.9 - Address space qualifier functions.
// \brief Performs semantic analysis for the to_global/local/private call.
// \param S Reference to the semantic analyzer.
@@ -721,8 +838,11 @@ static bool SemaOpenCLBuiltinToAddr(Sema &S, unsigned BuiltinID,
case Builtin::BIto_local:
Qual.setAddressSpace(LangAS::opencl_local);
break;
+ case Builtin::BIto_private:
+ Qual.setAddressSpace(LangAS::opencl_private);
+ break;
default:
- Qual.removeAddressSpace();
+ llvm_unreachable("Invalid builtin function");
}
Call->setType(S.Context.getPointerType(S.Context.getQualifiedType(
RT.getUnqualifiedType(), Qual)));
@@ -770,7 +890,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
switch (Context.getTargetInfo().getTriple().getArch()) {
case llvm::Triple::arm:
case llvm::Triple::thumb:
- if (SemaBuiltinVAStartARM(TheCall))
+ if (SemaBuiltinVAStartARMMicrosoft(TheCall))
return ExprError();
break;
default:
@@ -839,7 +959,6 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
if (checkArgCount(*this, TheCall, 1))
return true;
break;
-
case Builtin::BI__builtin_classify_type:
if (checkArgCount(*this, TheCall, 1)) return true;
TheCall->setType(Context.IntTy);
@@ -959,6 +1078,10 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
case Builtin::BI##ID: \
return SemaAtomicOpsOverloaded(TheCallResult, AtomicExpr::AO##ID);
#include "clang/Basic/Builtins.def"
+ case Builtin::BI__annotation:
+ if (SemaBuiltinMSVCAnnotation(*this, TheCall))
+ return ExprError();
+ break;
case Builtin::BI__builtin_annotation:
if (SemaBuiltinAnnotation(*this, TheCall))
return ExprError();
@@ -1048,22 +1171,26 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
case Builtin::BIreserve_write_pipe:
case Builtin::BIwork_group_reserve_read_pipe:
case Builtin::BIwork_group_reserve_write_pipe:
+ if (SemaBuiltinReserveRWPipe(*this, TheCall))
+ return ExprError();
+ break;
case Builtin::BIsub_group_reserve_read_pipe:
case Builtin::BIsub_group_reserve_write_pipe:
- if (SemaBuiltinReserveRWPipe(*this, TheCall))
+ if (checkOpenCLSubgroupExt(*this, TheCall) ||
+ SemaBuiltinReserveRWPipe(*this, TheCall))
return ExprError();
- // Since return type of reserve_read/write_pipe built-in function is
- // reserve_id_t, which is not defined in the builtin def file , we used int
- // as return type and need to override the return type of these functions.
- TheCall->setType(Context.OCLReserveIDTy);
break;
case Builtin::BIcommit_read_pipe:
case Builtin::BIcommit_write_pipe:
case Builtin::BIwork_group_commit_read_pipe:
case Builtin::BIwork_group_commit_write_pipe:
+ if (SemaBuiltinCommitRWPipe(*this, TheCall))
+ return ExprError();
+ break;
case Builtin::BIsub_group_commit_read_pipe:
case Builtin::BIsub_group_commit_write_pipe:
- if (SemaBuiltinCommitRWPipe(*this, TheCall))
+ if (checkOpenCLSubgroupExt(*this, TheCall) ||
+ SemaBuiltinCommitRWPipe(*this, TheCall))
return ExprError();
break;
case Builtin::BIget_pipe_num_packets:
@@ -1088,11 +1215,16 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
if (SemaOpenCLBuiltinKernelWorkGroupSize(*this, TheCall))
return ExprError();
break;
+ break;
+ case Builtin::BIget_kernel_max_sub_group_size_for_ndrange:
+ case Builtin::BIget_kernel_sub_group_count_for_ndrange:
+ if (SemaOpenCLBuiltinNDRangeAndBlock(*this, TheCall))
+ return ExprError();
+ break;
case Builtin::BI__builtin_os_log_format:
case Builtin::BI__builtin_os_log_format_buffer_size:
- if (SemaBuiltinOSLogFormat(TheCall)) {
+ if (SemaBuiltinOSLogFormat(TheCall))
return ExprError();
- }
break;
}
@@ -1422,21 +1554,26 @@ bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
// For intrinsics which take an immediate value as part of the instruction,
// range check them here.
- unsigned i = 0, l = 0, u = 0;
+ // FIXME: VFP Intrinsics should error if VFP not present.
switch (BuiltinID) {
default: return false;
- case ARM::BI__builtin_arm_ssat: i = 1; l = 1; u = 31; break;
- case ARM::BI__builtin_arm_usat: i = 1; u = 31; break;
+ case ARM::BI__builtin_arm_ssat:
+ return SemaBuiltinConstantArgRange(TheCall, 1, 1, 32);
+ case ARM::BI__builtin_arm_usat:
+ return SemaBuiltinConstantArgRange(TheCall, 1, 0, 31);
+ case ARM::BI__builtin_arm_ssat16:
+ return SemaBuiltinConstantArgRange(TheCall, 1, 1, 16);
+ case ARM::BI__builtin_arm_usat16:
+ return SemaBuiltinConstantArgRange(TheCall, 1, 0, 15);
case ARM::BI__builtin_arm_vcvtr_f:
- case ARM::BI__builtin_arm_vcvtr_d: i = 1; u = 1; break;
+ case ARM::BI__builtin_arm_vcvtr_d:
+ return SemaBuiltinConstantArgRange(TheCall, 1, 0, 1);
case ARM::BI__builtin_arm_dmb:
case ARM::BI__builtin_arm_dsb:
case ARM::BI__builtin_arm_isb:
- case ARM::BI__builtin_arm_dbg: l = 0; u = 15; break;
+ case ARM::BI__builtin_arm_dbg:
+ return SemaBuiltinConstantArgRange(TheCall, 0, 0, 15);
}
-
- // FIXME: VFP Intrinsics should error if VFP not present.
- return SemaBuiltinConstantArgRange(TheCall, i, l, u + l);
}
bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID,
@@ -1790,6 +1927,26 @@ static bool SemaBuiltinCpuSupports(Sema &S, CallExpr *TheCall) {
return false;
}
+/// SemaBuiltinCpuIs - Handle __builtin_cpu_is(char *).
+/// This checks that the target supports __builtin_cpu_is and
+/// that the string argument is constant and valid.
+static bool SemaBuiltinCpuIs(Sema &S, CallExpr *TheCall) {
+ Expr *Arg = TheCall->getArg(0);
+
+ // Check if the argument is a string literal.
+ if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts()))
+ return S.Diag(TheCall->getLocStart(), diag::err_expr_not_string_literal)
+ << Arg->getSourceRange();
+
+ // Check the contents of the string.
+ StringRef Feature =
+ cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString();
+ if (!S.Context.getTargetInfo().validateCpuIs(Feature))
+ return S.Diag(TheCall->getLocStart(), diag::err_invalid_cpu_is)
+ << Arg->getSourceRange();
+ return false;
+}
+
// Check if the rounding mode is legal.
bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) {
// Indicates if this instruction has rounding control or just SAE.
@@ -2103,6 +2260,9 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
if (BuiltinID == X86::BI__builtin_cpu_supports)
return SemaBuiltinCpuSupports(*this, TheCall);
+ if (BuiltinID == X86::BI__builtin_cpu_is)
+ return SemaBuiltinCpuIs(*this, TheCall);
+
// If the intrinsic has rounding or SAE make sure its valid.
if (CheckX86BuiltinRoundingOrSAE(BuiltinID, TheCall))
return true;
@@ -2209,7 +2369,10 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
i = 1; l = -128; u = 255;
break;
case X86::BI__builtin_ia32_vcvtps2ph:
+ case X86::BI__builtin_ia32_vcvtps2ph_mask:
case X86::BI__builtin_ia32_vcvtps2ph256:
+ case X86::BI__builtin_ia32_vcvtps2ph256_mask:
+ case X86::BI__builtin_ia32_vcvtps2ph512_mask:
case X86::BI__builtin_ia32_rndscaleps_128_mask:
case X86::BI__builtin_ia32_rndscalepd_128_mask:
case X86::BI__builtin_ia32_rndscaleps_256_mask:
@@ -2402,6 +2565,7 @@ bool Sema::GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx) {
}
return false;
}
+
/// \brief Diagnose use of %s directive in an NSString which is being passed
/// as formatting string to formatting method.
static void
@@ -2595,7 +2759,7 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
// Type safety checking.
if (FDecl) {
for (const auto *I : FDecl->specific_attrs<ArgumentWithTypeTagAttr>())
- CheckArgumentWithTypeTag(I, Args.data());
+ CheckArgumentWithTypeTag(I, Args, Loc);
}
}
@@ -2734,15 +2898,18 @@ static bool isValidOrderingForOp(int64_t Ordering, AtomicExpr::AtomicOp Op) {
auto OrderingCABI = (llvm::AtomicOrderingCABI)Ordering;
switch (Op) {
case AtomicExpr::AO__c11_atomic_init:
+ case AtomicExpr::AO__opencl_atomic_init:
llvm_unreachable("There is no ordering argument for an init");
case AtomicExpr::AO__c11_atomic_load:
+ case AtomicExpr::AO__opencl_atomic_load:
case AtomicExpr::AO__atomic_load_n:
case AtomicExpr::AO__atomic_load:
return OrderingCABI != llvm::AtomicOrderingCABI::release &&
OrderingCABI != llvm::AtomicOrderingCABI::acq_rel;
case AtomicExpr::AO__c11_atomic_store:
+ case AtomicExpr::AO__opencl_atomic_store:
case AtomicExpr::AO__atomic_store:
case AtomicExpr::AO__atomic_store_n:
return OrderingCABI != llvm::AtomicOrderingCABI::consume &&
@@ -2759,27 +2926,39 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
CallExpr *TheCall = cast<CallExpr>(TheCallResult.get());
DeclRefExpr *DRE =cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());
- // All these operations take one of the following forms:
+ // All the non-OpenCL operations take one of the following forms.
+ // The OpenCL operations take the __c11 forms with one extra argument for
+ // synchronization scope.
enum {
// C __c11_atomic_init(A *, C)
Init,
+
// C __c11_atomic_load(A *, int)
Load,
+
// void __atomic_load(A *, CP, int)
LoadCopy,
+
// void __atomic_store(A *, CP, int)
Copy,
+
// C __c11_atomic_add(A *, M, int)
Arithmetic,
+
// C __atomic_exchange_n(A *, CP, int)
Xchg,
+
// void __atomic_exchange(A *, C *, CP, int)
GNUXchg,
+
// bool __c11_atomic_compare_exchange_strong(A *, C *, CP, int, int)
C11CmpXchg,
+
// bool __atomic_compare_exchange(A *, C *, CP, bool, int, int)
GNUCmpXchg
} Form = Init;
+
+ const unsigned NumForm = GNUCmpXchg + 1;
const unsigned NumArgs[] = { 2, 2, 3, 3, 3, 3, 4, 5, 6 };
const unsigned NumVals[] = { 1, 0, 1, 1, 1, 1, 2, 2, 3 };
// where:
@@ -2789,12 +2968,18 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
// M is C if C is an integer, and ptrdiff_t if C is a pointer, and
// the int parameters are for orderings.
+ static_assert(sizeof(NumArgs)/sizeof(NumArgs[0]) == NumForm
+ && sizeof(NumVals)/sizeof(NumVals[0]) == NumForm,
+ "need to update code for modified forms");
static_assert(AtomicExpr::AO__c11_atomic_init == 0 &&
AtomicExpr::AO__c11_atomic_fetch_xor + 1 ==
AtomicExpr::AO__atomic_load,
"need to update code for modified C11 atomics");
- bool IsC11 = Op >= AtomicExpr::AO__c11_atomic_init &&
- Op <= AtomicExpr::AO__c11_atomic_fetch_xor;
+ bool IsOpenCL = Op >= AtomicExpr::AO__opencl_atomic_init &&
+ Op <= AtomicExpr::AO__opencl_atomic_fetch_max;
+ bool IsC11 = (Op >= AtomicExpr::AO__c11_atomic_init &&
+ Op <= AtomicExpr::AO__c11_atomic_fetch_xor) ||
+ IsOpenCL;
bool IsN = Op == AtomicExpr::AO__atomic_load_n ||
Op == AtomicExpr::AO__atomic_store_n ||
Op == AtomicExpr::AO__atomic_exchange_n ||
@@ -2803,10 +2988,12 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
switch (Op) {
case AtomicExpr::AO__c11_atomic_init:
+ case AtomicExpr::AO__opencl_atomic_init:
Form = Init;
break;
case AtomicExpr::AO__c11_atomic_load:
+ case AtomicExpr::AO__opencl_atomic_load:
case AtomicExpr::AO__atomic_load_n:
Form = Load;
break;
@@ -2816,6 +3003,7 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
break;
case AtomicExpr::AO__c11_atomic_store:
+ case AtomicExpr::AO__opencl_atomic_store:
case AtomicExpr::AO__atomic_store:
case AtomicExpr::AO__atomic_store_n:
Form = Copy;
@@ -2823,6 +3011,10 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
case AtomicExpr::AO__c11_atomic_fetch_add:
case AtomicExpr::AO__c11_atomic_fetch_sub:
+ case AtomicExpr::AO__opencl_atomic_fetch_add:
+ case AtomicExpr::AO__opencl_atomic_fetch_sub:
+ case AtomicExpr::AO__opencl_atomic_fetch_min:
+ case AtomicExpr::AO__opencl_atomic_fetch_max:
case AtomicExpr::AO__atomic_fetch_add:
case AtomicExpr::AO__atomic_fetch_sub:
case AtomicExpr::AO__atomic_add_fetch:
@@ -2832,6 +3024,9 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
case AtomicExpr::AO__c11_atomic_fetch_and:
case AtomicExpr::AO__c11_atomic_fetch_or:
case AtomicExpr::AO__c11_atomic_fetch_xor:
+ case AtomicExpr::AO__opencl_atomic_fetch_and:
+ case AtomicExpr::AO__opencl_atomic_fetch_or:
+ case AtomicExpr::AO__opencl_atomic_fetch_xor:
case AtomicExpr::AO__atomic_fetch_and:
case AtomicExpr::AO__atomic_fetch_or:
case AtomicExpr::AO__atomic_fetch_xor:
@@ -2844,6 +3039,7 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
break;
case AtomicExpr::AO__c11_atomic_exchange:
+ case AtomicExpr::AO__opencl_atomic_exchange:
case AtomicExpr::AO__atomic_exchange_n:
Form = Xchg;
break;
@@ -2854,6 +3050,8 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
+ case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:
+ case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:
Form = C11CmpXchg;
break;
@@ -2863,16 +3061,19 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
break;
}
+ unsigned AdjustedNumArgs = NumArgs[Form];
+ if (IsOpenCL && Op != AtomicExpr::AO__opencl_atomic_init)
+ ++AdjustedNumArgs;
// Check we have the right number of arguments.
- if (TheCall->getNumArgs() < NumArgs[Form]) {
+ if (TheCall->getNumArgs() < AdjustedNumArgs) {
Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
- << 0 << NumArgs[Form] << TheCall->getNumArgs()
+ << 0 << AdjustedNumArgs << TheCall->getNumArgs()
<< TheCall->getCallee()->getSourceRange();
return ExprError();
- } else if (TheCall->getNumArgs() > NumArgs[Form]) {
- Diag(TheCall->getArg(NumArgs[Form])->getLocStart(),
+ } else if (TheCall->getNumArgs() > AdjustedNumArgs) {
+ Diag(TheCall->getArg(AdjustedNumArgs)->getLocStart(),
diag::err_typecheck_call_too_many_args)
- << 0 << NumArgs[Form] << TheCall->getNumArgs()
+ << 0 << AdjustedNumArgs << TheCall->getNumArgs()
<< TheCall->getCallee()->getSourceRange();
return ExprError();
}
@@ -2900,9 +3101,11 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
<< Ptr->getType() << Ptr->getSourceRange();
return ExprError();
}
- if (AtomTy.isConstQualified()) {
+ if (AtomTy.isConstQualified() ||
+ AtomTy.getAddressSpace() == LangAS::opencl_constant) {
Diag(DRE->getLocStart(), diag::err_atomic_op_needs_non_const_atomic)
- << Ptr->getType() << Ptr->getSourceRange();
+ << (AtomTy.isConstQualified() ? 0 : 1) << Ptr->getType()
+ << Ptr->getSourceRange();
return ExprError();
}
ValType = AtomTy->getAs<AtomicType>()->getValueType();
@@ -2971,7 +3174,8 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
ValType.removeLocalVolatile();
ValType.removeLocalConst();
QualType ResultType = ValType;
- if (Form == Copy || Form == LoadCopy || Form == GNUXchg || Form == Init)
+ if (Form == Copy || Form == LoadCopy || Form == GNUXchg ||
+ Form == Init)
ResultType = Context.VoidTy;
else if (Form == C11CmpXchg || Form == GNUCmpXchg)
ResultType = Context.BoolTy;
@@ -2985,7 +3189,7 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
// The first argument --- the pointer --- has a fixed type; we
// deduce the types of the rest of the arguments accordingly. Walk
// the remaining arguments, converting them to the deduced value type.
- for (unsigned i = 1; i != NumArgs[Form]; ++i) {
+ for (unsigned i = 1; i != TheCall->getNumArgs(); ++i) {
QualType Ty;
if (i < NumVals[Form] + 1) {
switch (i) {
@@ -3006,7 +3210,7 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
// Treat this argument as _Nonnull as we want to show a warning if
// NULL is passed into it.
CheckNonNullArgument(*this, ValArg, DRE->getLocStart());
- unsigned AS = 0;
+ LangAS AS = LangAS::Default;
// Keep address space of non-atomic pointer type.
if (const PointerType *PtrTy =
ValArg->getType()->getAs<PointerType>()) {
@@ -3027,7 +3231,7 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
break;
}
} else {
- // The order(s) are always converted to int.
+ // The order(s) and scope are always converted to int.
Ty = Context.IntTy;
}
@@ -3088,15 +3292,30 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
<< SubExprs[1]->getSourceRange();
}
+ if (auto ScopeModel = AtomicExpr::getScopeModel(Op)) {
+ auto *Scope = TheCall->getArg(TheCall->getNumArgs() - 1);
+ llvm::APSInt Result(32);
+ if (Scope->isIntegerConstantExpr(Result, Context) &&
+ !ScopeModel->isValid(Result.getZExtValue())) {
+ Diag(Scope->getLocStart(), diag::err_atomic_op_has_invalid_synch_scope)
+ << Scope->getSourceRange();
+ }
+ SubExprs.push_back(Scope);
+ }
+
AtomicExpr *AE = new (Context) AtomicExpr(TheCall->getCallee()->getLocStart(),
SubExprs, ResultType, Op,
TheCall->getRParenLoc());
if ((Op == AtomicExpr::AO__c11_atomic_load ||
- (Op == AtomicExpr::AO__c11_atomic_store)) &&
+ Op == AtomicExpr::AO__c11_atomic_store ||
+ Op == AtomicExpr::AO__opencl_atomic_load ||
+ Op == AtomicExpr::AO__opencl_atomic_store ) &&
Context.AtomicUsesUnsupportedLibcall(AE))
- Diag(AE->getLocStart(), diag::err_atomic_load_store_uses_lib) <<
- ((Op == AtomicExpr::AO__c11_atomic_load) ? 0 : 1);
+ Diag(AE->getLocStart(), diag::err_atomic_load_store_uses_lib)
+ << ((Op == AtomicExpr::AO__c11_atomic_load ||
+ Op == AtomicExpr::AO__opencl_atomic_load)
+ ? 0 : 1);
return AE;
}
@@ -3631,7 +3850,7 @@ static bool checkVAStartABI(Sema &S, unsigned BuiltinID, Expr *Fn) {
bool IsWindows = TT.isOSWindows();
bool IsMSVAStart = BuiltinID == Builtin::BI__builtin_ms_va_start;
if (IsX64 || IsAArch64) {
- clang::CallingConv CC = CC_C;
+ CallingConv CC = CC_C;
if (const FunctionDecl *FD = S.getCurFunctionDecl())
CC = FD->getType()->getAs<FunctionType>()->getCallConv();
if (IsMSVAStart) {
@@ -3778,7 +3997,7 @@ bool Sema::SemaBuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall) {
return false;
}
-bool Sema::SemaBuiltinVAStartARM(CallExpr *Call) {
+bool Sema::SemaBuiltinVAStartARMMicrosoft(CallExpr *Call) {
// void __va_start(va_list *ap, const char *named_addr, size_t slot_size,
// const char *named_addr);
@@ -3797,23 +4016,33 @@ bool Sema::SemaBuiltinVAStartARM(CallExpr *Call) {
if (checkVAStartIsInVariadicFunction(*this, Func))
return true;
- const struct {
- unsigned ArgNo;
- QualType Type;
- } ArgumentTypes[] = {
- { 1, Context.getPointerType(Context.CharTy.withConst()) },
- { 2, Context.getSizeType() },
- };
+ // __va_start on Windows does not validate the parameter qualifiers
- for (const auto &AT : ArgumentTypes) {
- const Expr *Arg = Call->getArg(AT.ArgNo)->IgnoreParens();
- if (Arg->getType().getCanonicalType() == AT.Type.getCanonicalType())
- continue;
- Diag(Arg->getLocStart(), diag::err_typecheck_convert_incompatible)
- << Arg->getType() << AT.Type << 1 /* different class */
- << 0 /* qualifier difference */ << 3 /* parameter mismatch */
- << AT.ArgNo + 1 << Arg->getType() << AT.Type;
- }
+ const Expr *Arg1 = Call->getArg(1)->IgnoreParens();
+ const Type *Arg1Ty = Arg1->getType().getCanonicalType().getTypePtr();
+
+ const Expr *Arg2 = Call->getArg(2)->IgnoreParens();
+ const Type *Arg2Ty = Arg2->getType().getCanonicalType().getTypePtr();
+
+ const QualType &ConstCharPtrTy =
+ Context.getPointerType(Context.CharTy.withConst());
+ if (!Arg1Ty->isPointerType() ||
+ Arg1Ty->getPointeeType().withoutLocalFastQualifiers() != Context.CharTy)
+ Diag(Arg1->getLocStart(), diag::err_typecheck_convert_incompatible)
+ << Arg1->getType() << ConstCharPtrTy
+ << 1 /* different class */
+ << 0 /* qualifier difference */
+ << 3 /* parameter mismatch */
+ << 2 << Arg1->getType() << ConstCharPtrTy;
+
+ const QualType SizeTy = Context.getSizeType();
+ if (Arg2Ty->getCanonicalTypeInternal().withoutLocalFastQualifiers() != SizeTy)
+ Diag(Arg2->getLocStart(), diag::err_typecheck_convert_incompatible)
+ << Arg2->getType() << SizeTy
+ << 1 /* different class */
+ << 0 /* qualifier difference */
+ << 3 /* parameter mismatch */
+ << 3 << Arg2->getType() << SizeTy;
return false;
}
@@ -4143,9 +4372,9 @@ bool Sema::SemaBuiltinAllocaWithAlign(CallExpr *TheCall) {
<< (unsigned)Context.getCharWidth()
<< Arg->getSourceRange();
- if (Result > INT32_MAX)
+ if (Result > std::numeric_limits<int32_t>::max())
return Diag(TheCall->getLocStart(), diag::err_alignment_too_big)
- << INT32_MAX
+ << std::numeric_limits<int32_t>::max()
<< Arg->getSourceRange();
}
@@ -4410,7 +4639,6 @@ bool Sema::SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall,
if (!ValidString)
return Diag(TheCall->getLocStart(), diag::err_arm_invalid_specialreg)
<< Arg->getSourceRange();
-
} else if (IsAArch64Builtin && Fields.size() == 1) {
// If the register name is one of those that appear in the condition below
// and the special register builtin being used is one of the write builtins,
@@ -4464,13 +4692,15 @@ bool Sema::SemaBuiltinSetjmp(CallExpr *TheCall) {
}
namespace {
+
class UncoveredArgHandler {
enum { Unknown = -1, AllCovered = -2 };
- signed FirstUncoveredArg;
+
+ signed FirstUncoveredArg = Unknown;
SmallVector<const Expr *, 4> DiagnosticExprs;
public:
- UncoveredArgHandler() : FirstUncoveredArg(Unknown) { }
+ UncoveredArgHandler() = default;
bool hasUncoveredArg() const {
return (FirstUncoveredArg >= 0);
@@ -4514,7 +4744,8 @@ enum StringLiteralCheckType {
SLCT_UncheckedLiteral,
SLCT_CheckedLiteral
};
-} // end anonymous namespace
+
+} // namespace
static void sumOffsets(llvm::APSInt &Offset, llvm::APSInt Addend,
BinaryOperatorKind BinOpKind,
@@ -4547,7 +4778,8 @@ static void sumOffsets(llvm::APSInt &Offset, llvm::APSInt Addend,
// We add an offset to a pointer here so we should support an offset as big as
// possible.
if (Ov) {
- assert(BitWidth <= UINT_MAX / 2 && "index (intermediate) result too big");
+ assert(BitWidth <= std::numeric_limits<unsigned>::max() / 2 &&
+ "index (intermediate) result too big");
Offset = Offset.sext(2 * BitWidth);
sumOffsets(Offset, Addend, BinOpKind, AddendIsRight);
return;
@@ -4557,6 +4789,7 @@ static void sumOffsets(llvm::APSInt &Offset, llvm::APSInt Addend,
}
namespace {
+
// This is a wrapper class around StringLiteral to support offsetted string
// literals as format strings. It takes the offset into account when returning
// the string and its length or the source locations to display notes correctly.
@@ -4575,6 +4808,7 @@ class FormatStringLiteral {
unsigned getByteLength() const {
return FExpr->getByteLength() - getCharByteWidth() * Offset;
}
+
unsigned getLength() const { return FExpr->getLength() - Offset; }
unsigned getCharByteWidth() const { return FExpr->getCharByteWidth(); }
@@ -4600,9 +4834,11 @@ class FormatStringLiteral {
SourceLocation getLocStart() const LLVM_READONLY {
return FExpr->getLocStart().getLocWithOffset(Offset);
}
+
SourceLocation getLocEnd() const LLVM_READONLY { return FExpr->getLocEnd(); }
};
-} // end anonymous namespace
+
+} // namespace
static void CheckFormatString(Sema &S, const FormatStringLiteral *FExpr,
const Expr *OrigFormatExpr,
@@ -4689,10 +4925,9 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args,
return (CheckLeft && Left < Right) ? Left : Right;
}
- case Stmt::ImplicitCastExprClass: {
+ case Stmt::ImplicitCastExprClass:
E = cast<ImplicitCastExpr>(E)->getSubExpr();
goto tryAgain;
- }
case Stmt::OpaqueValueExprClass:
if (const Expr *src = cast<OpaqueValueExpr>(E)->getSourceExpr()) {
@@ -4881,7 +5116,7 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args,
case Stmt::UnaryOperatorClass: {
const UnaryOperator *UnaOp = cast<UnaryOperator>(E);
auto ASE = dyn_cast<ArraySubscriptExpr>(UnaOp->getSubExpr());
- if (UnaOp->getOpcode() == clang::UO_AddrOf && ASE) {
+ if (UnaOp->getOpcode() == UO_AddrOf && ASE) {
llvm::APSInt IndexResult;
if (ASE->getRHS()->EvaluateAsInt(IndexResult, S.Context)) {
sumOffsets(Offset, IndexResult, BO_Add, /*RHS is int*/ true);
@@ -5014,6 +5249,7 @@ bool Sema::CheckFormatArguments(ArrayRef<const Expr *> Args,
}
namespace {
+
class CheckFormatHandler : public analyze_format_string::FormatStringHandler {
protected:
Sema &S;
@@ -5027,8 +5263,8 @@ protected:
ArrayRef<const Expr *> Args;
unsigned FormatIdx;
llvm::SmallBitVector CoveredArgs;
- bool usesPositionalArgs;
- bool atFirstArg;
+ bool usesPositionalArgs = false;
+ bool atFirstArg = true;
bool inFunctionCall;
Sema::VariadicCallType CallType;
llvm::SmallBitVector &CheckedVarArgs;
@@ -5046,7 +5282,6 @@ public:
: S(s), FExpr(fexpr), OrigFormatExpr(origFormatExpr), FSType(type),
FirstDataArg(firstDataArg), NumDataArgs(numDataArgs), Beg(beg),
HasVAListArg(hasVAListArg), Args(Args), FormatIdx(formatIdx),
- usesPositionalArgs(false), atFirstArg(true),
inFunctionCall(inFunctionCall), CallType(callType),
CheckedVarArgs(CheckedVarArgs), UncoveredArg(UncoveredArg) {
CoveredArgs.resize(numDataArgs);
@@ -5116,7 +5351,8 @@ protected:
bool IsStringLocation, Range StringRange,
ArrayRef<FixItHint> Fixit = None);
};
-} // end anonymous namespace
+
+} // namespace
SourceRange CheckFormatHandler::getFormatStringRange() {
return OrigFormatExpr->getSourceRange();
@@ -5470,6 +5706,7 @@ void CheckFormatHandler::EmitFormatDiagnostic(
//===--- CHECK: Printf format string checking ------------------------------===//
namespace {
+
class CheckPrintfHandler : public CheckFormatHandler {
public:
CheckPrintfHandler(Sema &s, const FormatStringLiteral *fexpr,
@@ -5534,7 +5771,8 @@ public:
const char *conversionPosition)
override;
};
-} // end anonymous namespace
+
+} // namespace
bool CheckPrintfHandler::HandleInvalidPrintfConversionSpecifier(
const analyze_printf::PrintfSpecifier &FS,
@@ -5652,10 +5890,6 @@ void CheckPrintfHandler::HandleIgnoredFlag(
getSpecifierRange(ignoredFlag.getPosition(), 1)));
}
-// void EmitFormatDiagnostic(PartialDiagnostic PDiag, SourceLocation StringLoc,
-// bool IsStringLocation, Range StringRange,
-// ArrayRef<FixItHint> Fixit = None);
-
void CheckPrintfHandler::HandleEmptyObjCModifierFlag(const char *startFlag,
unsigned flagLen) {
// Warn about an empty flag.
@@ -5722,7 +5956,8 @@ CXXRecordMembersNamed(StringRef Name, Sema &S, QualType Ty) {
/// FIXME: This returns the wrong results in some cases (if cv-qualifiers don't
/// allow the call, or if it would be ambiguous).
bool Sema::hasCStrMethod(const Expr *E) {
- typedef llvm::SmallPtrSet<CXXMethodDecl*, 1> MethodSet;
+ using MethodSet = llvm::SmallPtrSet<CXXMethodDecl *, 1>;
+
MethodSet Results =
CXXRecordMembersNamed<CXXMethodDecl>("c_str", *this, E->getType());
for (MethodSet::iterator MI = Results.begin(), ME = Results.end();
@@ -5737,7 +5972,7 @@ bool Sema::hasCStrMethod(const Expr *E) {
// Returns true when a c_str() conversion method is found.
bool CheckPrintfHandler::checkForCStrMembers(
const analyze_printf::ArgType &AT, const Expr *E) {
- typedef llvm::SmallPtrSet<CXXMethodDecl*, 1> MethodSet;
+ using MethodSet = llvm::SmallPtrSet<CXXMethodDecl *, 1>;
MethodSet Results =
CXXRecordMembersNamed<CXXMethodDecl>("c_str", S, E->getType());
@@ -5765,7 +6000,8 @@ CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier
const char *startSpecifier,
unsigned specifierLen) {
using namespace analyze_format_string;
- using namespace analyze_printf;
+ using namespace analyze_printf;
+
const PrintfConversionSpecifier &CS = FS.getConversionSpecifier();
if (FS.consumesDataArgument()) {
@@ -6009,9 +6245,9 @@ shouldNotPrintDirectly(const ASTContext &Context,
while (const TypedefType *UserTy = TyTy->getAs<TypedefType>()) {
StringRef Name = UserTy->getDecl()->getName();
QualType CastTy = llvm::StringSwitch<QualType>(Name)
- .Case("CFIndex", Context.LongTy)
- .Case("NSInteger", Context.LongTy)
- .Case("NSUInteger", Context.UnsignedLongTy)
+ .Case("CFIndex", Context.getNSIntegerType())
+ .Case("NSInteger", Context.getNSIntegerType())
+ .Case("NSUInteger", Context.getNSUIntegerType())
.Case("SInt32", Context.IntTy)
.Case("UInt32", Context.UnsignedIntTy)
.Default(QualType());
@@ -6063,6 +6299,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
const Expr *E) {
using namespace analyze_format_string;
using namespace analyze_printf;
+
// Now type check the data expression that matches the
// format specifier.
const analyze_printf::ArgType &AT = FS.getArgType(S.Context, isObjCContext());
@@ -6200,7 +6437,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
CastFix << ")";
SmallVector<FixItHint,4> Hints;
- if (!AT.matchesType(S.Context, IntendedTy))
+ if (!AT.matchesType(S.Context, IntendedTy) || ShouldNotPrintDirectly)
Hints.push_back(FixItHint::CreateReplacement(SpecRange, os.str()));
if (const CStyleCastExpr *CCast = dyn_cast<CStyleCastExpr>(E)) {
@@ -6315,6 +6552,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
//===--- CHECK: Scanf format string checking ------------------------------===//
namespace {
+
class CheckScanfHandler : public CheckFormatHandler {
public:
CheckScanfHandler(Sema &s, const FormatStringLiteral *fexpr,
@@ -6341,7 +6579,8 @@ public:
void HandleIncompleteScanList(const char *start, const char *end) override;
};
-} // end anonymous namespace
+
+} // namespace
void CheckScanfHandler::HandleIncompleteScanList(const char *start,
const char *end) {
@@ -6354,7 +6593,6 @@ bool CheckScanfHandler::HandleInvalidScanfConversionSpecifier(
const analyze_scanf::ScanfSpecifier &FS,
const char *startSpecifier,
unsigned specifierLen) {
-
const analyze_scanf::ScanfConversionSpecifier &CS =
FS.getConversionSpecifier();
@@ -7041,8 +7279,8 @@ static bool CheckMemorySizeofForComparison(Sema &S, const Expr *E,
if (!Size)
return false;
- // if E is binop and op is >, <, >=, <=, ==, &&, ||:
- if (!Size->isComparisonOp() && !Size->isEqualityOp() && !Size->isLogicalOp())
+ // if E is binop and op is <=>, >, <, >=, <=, ==, &&, ||:
+ if (!Size->isComparisonOp() && !Size->isLogicalOp())
return false;
SourceRange SizeRange = Size->getSourceRange();
@@ -7096,7 +7334,7 @@ static const CXXRecordDecl *getContainedDynamicClass(QualType T,
static const Expr *getSizeOfExprArg(const Expr *E) {
if (const UnaryExprOrTypeTraitExpr *SizeOf =
dyn_cast<UnaryExprOrTypeTraitExpr>(E))
- if (SizeOf->getKind() == clang::UETT_SizeOf && !SizeOf->isArgumentType())
+ if (SizeOf->getKind() == UETT_SizeOf && !SizeOf->isArgumentType())
return SizeOf->getArgumentExpr()->IgnoreParenImpCasts();
return nullptr;
@@ -7106,7 +7344,7 @@ static const Expr *getSizeOfExprArg(const Expr *E) {
static QualType getSizeOfArgType(const Expr *E) {
if (const UnaryExprOrTypeTraitExpr *SizeOf =
dyn_cast<UnaryExprOrTypeTraitExpr>(E))
- if (SizeOf->getKind() == clang::UETT_SizeOf)
+ if (SizeOf->getKind() == UETT_SizeOf)
return SizeOf->getTypeOfArgument();
return QualType();
@@ -7294,7 +7532,7 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
static const Expr *ignoreLiteralAdditions(const Expr *Ex, ASTContext &Ctx) {
Ex = Ex->IgnoreParenCasts();
- for (;;) {
+ while (true) {
const BinaryOperator * BO = dyn_cast<BinaryOperator>(Ex);
if (!BO || !BO->isAdditiveOp())
break;
@@ -7512,7 +7750,6 @@ static const Expr *EvalAddr(const Expr *E,
static void
CheckReturnStackAddr(Sema &S, Expr *RetValExp, QualType lhsType,
SourceLocation ReturnLoc) {
-
const Expr *stackE = nullptr;
SmallVector<const DeclRefExpr *, 8> refVars;
@@ -7997,8 +8234,7 @@ struct IntRange {
bool NonNegative;
IntRange(unsigned Width, bool NonNegative)
- : Width(Width), NonNegative(NonNegative)
- {}
+ : Width(Width), NonNegative(NonNegative) {}
/// Returns the range of the bool type.
static IntRange forBoolType() {
@@ -8022,11 +8258,19 @@ struct IntRange {
if (const AtomicType *AT = dyn_cast<AtomicType>(T))
T = AT->getValueType().getTypePtr();
- // For enum types, use the known bit width of the enumerators.
- if (const EnumType *ET = dyn_cast<EnumType>(T)) {
+ if (!C.getLangOpts().CPlusPlus) {
+ // For enum types in C code, use the underlying datatype.
+ if (const EnumType *ET = dyn_cast<EnumType>(T))
+ T = ET->getDecl()->getIntegerType().getDesugaredType(C).getTypePtr();
+ } else if (const EnumType *ET = dyn_cast<EnumType>(T)) {
+ // For enum types in C++, use the known bit width of the enumerators.
EnumDecl *Enum = ET->getDecl();
- if (!Enum->isCompleteDefinition())
- return IntRange(C.getIntWidth(QualType(T, 0)), false);
+ // In C++11, enums can have a fixed underlying type. Use this type to
+ // compute the range.
+ if (Enum->isFixed()) {
+ return IntRange(C.getIntWidth(QualType(T, 0)),
+ !ET->isSignedIntegerOrEnumerationType());
+ }
unsigned NumPositive = Enum->getNumPositiveBits();
unsigned NumNegative = Enum->getNumNegativeBits();
@@ -8080,7 +8324,10 @@ struct IntRange {
}
};
-IntRange GetValueRange(ASTContext &C, llvm::APSInt &value, unsigned MaxWidth) {
+} // namespace
+
+static IntRange GetValueRange(ASTContext &C, llvm::APSInt &value,
+ unsigned MaxWidth) {
if (value.isSigned() && value.isNegative())
return IntRange(value.getMinSignedBits(), false);
@@ -8092,8 +8339,8 @@ IntRange GetValueRange(ASTContext &C, llvm::APSInt &value, unsigned MaxWidth) {
return IntRange(value.getActiveBits(), true);
}
-IntRange GetValueRange(ASTContext &C, APValue &result, QualType Ty,
- unsigned MaxWidth) {
+static IntRange GetValueRange(ASTContext &C, APValue &result, QualType Ty,
+ unsigned MaxWidth) {
if (result.isInt())
return GetValueRange(C, result.getInt(), MaxWidth);
@@ -8121,7 +8368,7 @@ IntRange GetValueRange(ASTContext &C, APValue &result, QualType Ty,
return IntRange(MaxWidth, Ty->isUnsignedIntegerOrEnumerationType());
}
-QualType GetExprType(const Expr *E) {
+static QualType GetExprType(const Expr *E) {
QualType Ty = E->getType();
if (const AtomicType *AtomicRHS = Ty->getAs<AtomicType>())
Ty = AtomicRHS->getValueType();
@@ -8132,7 +8379,7 @@ QualType GetExprType(const Expr *E) {
/// range of values it might take.
///
/// \param MaxWidth - the width to which the value will be truncated
-IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth) {
+static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth) {
E = E->IgnoreParens();
// Try a full evaluation first.
@@ -8186,6 +8433,8 @@ IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth) {
if (const auto *BO = dyn_cast<BinaryOperator>(E)) {
switch (BO->getOpcode()) {
+ case BO_Cmp:
+ llvm_unreachable("builtin <=> should have class type");
// Boolean-valued operations are single-bit and positive.
case BO_LAnd:
@@ -8350,16 +8599,16 @@ IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth) {
return IntRange::forValueOfType(C, GetExprType(E));
}
-IntRange GetExprRange(ASTContext &C, const Expr *E) {
+static IntRange GetExprRange(ASTContext &C, const Expr *E) {
return GetExprRange(C, E, C.getIntWidth(GetExprType(E)));
}
/// Checks whether the given value, which currently has the given
/// source semantics, has the same value when coerced through the
/// target semantics.
-bool IsSameFloatAfterCast(const llvm::APFloat &value,
- const llvm::fltSemantics &Src,
- const llvm::fltSemantics &Tgt) {
+static bool IsSameFloatAfterCast(const llvm::APFloat &value,
+ const llvm::fltSemantics &Src,
+ const llvm::fltSemantics &Tgt) {
llvm::APFloat truncated = value;
bool ignored;
@@ -8374,9 +8623,9 @@ bool IsSameFloatAfterCast(const llvm::APFloat &value,
/// target semantics.
///
/// The value might be a vector of floats (or a complex number).
-bool IsSameFloatAfterCast(const APValue &value,
- const llvm::fltSemantics &Src,
- const llvm::fltSemantics &Tgt) {
+static bool IsSameFloatAfterCast(const APValue &value,
+ const llvm::fltSemantics &Src,
+ const llvm::fltSemantics &Tgt) {
if (value.isFloat())
return IsSameFloatAfterCast(value.getFloat(), Src, Tgt);
@@ -8392,249 +8641,234 @@ bool IsSameFloatAfterCast(const APValue &value,
IsSameFloatAfterCast(value.getComplexFloatImag(), Src, Tgt));
}
-void AnalyzeImplicitConversions(Sema &S, Expr *E, SourceLocation CC);
+static void AnalyzeImplicitConversions(Sema &S, Expr *E, SourceLocation CC);
-bool IsZero(Sema &S, Expr *E) {
+static bool IsEnumConstOrFromMacro(Sema &S, Expr *E) {
// Suppress cases where we are comparing against an enum constant.
if (const DeclRefExpr *DR =
dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
if (isa<EnumConstantDecl>(DR->getDecl()))
- return false;
+ return true;
// Suppress cases where the '0' value is expanded from a macro.
if (E->getLocStart().isMacroID())
- return false;
+ return true;
- llvm::APSInt Value;
- return E->isIntegerConstantExpr(Value, S.Context) && Value == 0;
+ return false;
}
-bool HasEnumType(Expr *E) {
- // Strip off implicit integral promotions.
- while (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
- if (ICE->getCastKind() != CK_IntegralCast &&
- ICE->getCastKind() != CK_NoOp)
- break;
- E = ICE->getSubExpr();
- }
-
- return E->getType()->isEnumeralType();
+static bool isKnownToHaveUnsignedValue(Expr *E) {
+ return E->getType()->isIntegerType() &&
+ (!E->getType()->isSignedIntegerType() ||
+ !E->IgnoreParenImpCasts()->getType()->isSignedIntegerType());
}
-void CheckTrivialUnsignedComparison(Sema &S, BinaryOperator *E) {
- // Disable warning in template instantiations.
- if (S.inTemplateInstantiation())
- return;
+namespace {
+/// The promoted range of values of a type. In general this has the
+/// following structure:
+///
+/// |-----------| . . . |-----------|
+/// ^ ^ ^ ^
+/// Min HoleMin HoleMax Max
+///
+/// ... where there is only a hole if a signed type is promoted to unsigned
+/// (in which case Min and Max are the smallest and largest representable
+/// values).
+struct PromotedRange {
+ // Min, or HoleMax if there is a hole.
+ llvm::APSInt PromotedMin;
+ // Max, or HoleMin if there is a hole.
+ llvm::APSInt PromotedMax;
- BinaryOperatorKind op = E->getOpcode();
- if (E->isValueDependent())
- return;
+ PromotedRange(IntRange R, unsigned BitWidth, bool Unsigned) {
+ if (R.Width == 0)
+ PromotedMin = PromotedMax = llvm::APSInt(BitWidth, Unsigned);
+ else if (R.Width >= BitWidth && !Unsigned) {
+ // Promotion made the type *narrower*. This happens when promoting
+ // a < 32-bit unsigned / <= 32-bit signed bit-field to 'signed int'.
+ // Treat all values of 'signed int' as being in range for now.
+ PromotedMin = llvm::APSInt::getMinValue(BitWidth, Unsigned);
+ PromotedMax = llvm::APSInt::getMaxValue(BitWidth, Unsigned);
+ } else {
+ PromotedMin = llvm::APSInt::getMinValue(R.Width, R.NonNegative)
+ .extOrTrunc(BitWidth);
+ PromotedMin.setIsUnsigned(Unsigned);
- if (op == BO_LT && IsZero(S, E->getRHS())) {
- S.Diag(E->getOperatorLoc(), diag::warn_lunsigned_always_true_comparison)
- << "< 0" << "false" << HasEnumType(E->getLHS())
- << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
- } else if (op == BO_GE && IsZero(S, E->getRHS())) {
- S.Diag(E->getOperatorLoc(), diag::warn_lunsigned_always_true_comparison)
- << ">= 0" << "true" << HasEnumType(E->getLHS())
- << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
- } else if (op == BO_GT && IsZero(S, E->getLHS())) {
- S.Diag(E->getOperatorLoc(), diag::warn_runsigned_always_true_comparison)
- << "0 >" << "false" << HasEnumType(E->getRHS())
- << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
- } else if (op == BO_LE && IsZero(S, E->getLHS())) {
- S.Diag(E->getOperatorLoc(), diag::warn_runsigned_always_true_comparison)
- << "0 <=" << "true" << HasEnumType(E->getRHS())
- << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
+ PromotedMax = llvm::APSInt::getMaxValue(R.Width, R.NonNegative)
+ .extOrTrunc(BitWidth);
+ PromotedMax.setIsUnsigned(Unsigned);
+ }
}
-}
-
-void DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E, Expr *Constant,
- Expr *Other, const llvm::APSInt &Value,
- bool RhsConstant) {
- // Disable warning in template instantiations.
- if (S.inTemplateInstantiation())
- return;
- // TODO: Investigate using GetExprRange() to get tighter bounds
- // on the bit ranges.
- QualType OtherT = Other->getType();
- if (const auto *AT = OtherT->getAs<AtomicType>())
- OtherT = AT->getValueType();
- IntRange OtherRange = IntRange::forValueOfType(S.Context, OtherT);
- unsigned OtherWidth = OtherRange.Width;
+ // Determine whether this range is contiguous (has no hole).
+ bool isContiguous() const { return PromotedMin <= PromotedMax; }
- bool OtherIsBooleanType = Other->isKnownToHaveBooleanValue();
+ // Where a constant value is within the range.
+ enum ComparisonResult {
+ LT = 0x1,
+ LE = 0x2,
+ GT = 0x4,
+ GE = 0x8,
+ EQ = 0x10,
+ NE = 0x20,
+ InRangeFlag = 0x40,
- // 0 values are handled later by CheckTrivialUnsignedComparison().
- if ((Value == 0) && (!OtherIsBooleanType))
- return;
+ Less = LE | LT | NE,
+ Min = LE | InRangeFlag,
+ InRange = InRangeFlag,
+ Max = GE | InRangeFlag,
+ Greater = GE | GT | NE,
- BinaryOperatorKind op = E->getOpcode();
- bool IsTrue = true;
+ OnlyValue = LE | GE | EQ | InRangeFlag,
+ InHole = NE
+ };
- // Used for diagnostic printout.
- enum {
- LiteralConstant = 0,
- CXXBoolLiteralTrue,
- CXXBoolLiteralFalse
- } LiteralOrBoolConstant = LiteralConstant;
+ ComparisonResult compare(const llvm::APSInt &Value) const {
+ assert(Value.getBitWidth() == PromotedMin.getBitWidth() &&
+ Value.isUnsigned() == PromotedMin.isUnsigned());
+ if (!isContiguous()) {
+ assert(Value.isUnsigned() && "discontiguous range for signed compare");
+ if (Value.isMinValue()) return Min;
+ if (Value.isMaxValue()) return Max;
+ if (Value >= PromotedMin) return InRange;
+ if (Value <= PromotedMax) return InRange;
+ return InHole;
+ }
- if (!OtherIsBooleanType) {
- QualType ConstantT = Constant->getType();
- QualType CommonT = E->getLHS()->getType();
+ switch (llvm::APSInt::compareValues(Value, PromotedMin)) {
+ case -1: return Less;
+ case 0: return PromotedMin == PromotedMax ? OnlyValue : Min;
+ case 1:
+ switch (llvm::APSInt::compareValues(Value, PromotedMax)) {
+ case -1: return InRange;
+ case 0: return Max;
+ case 1: return Greater;
+ }
+ }
- if (S.Context.hasSameUnqualifiedType(OtherT, ConstantT))
- return;
- assert((OtherT->isIntegerType() && ConstantT->isIntegerType()) &&
- "comparison with non-integer type");
+ llvm_unreachable("impossible compare result");
+ }
- bool ConstantSigned = ConstantT->isSignedIntegerType();
- bool CommonSigned = CommonT->isSignedIntegerType();
+ static llvm::Optional<StringRef>
+ constantValue(BinaryOperatorKind Op, ComparisonResult R, bool ConstantOnRHS) {
+ if (Op == BO_Cmp) {
+ ComparisonResult LTFlag = LT, GTFlag = GT;
+ if (ConstantOnRHS) std::swap(LTFlag, GTFlag);
- bool EqualityOnly = false;
+ if (R & EQ) return StringRef("'std::strong_ordering::equal'");
+ if (R & LTFlag) return StringRef("'std::strong_ordering::less'");
+ if (R & GTFlag) return StringRef("'std::strong_ordering::greater'");
+ return llvm::None;
+ }
- if (CommonSigned) {
- // The common type is signed, therefore no signed to unsigned conversion.
- if (!OtherRange.NonNegative) {
- // Check that the constant is representable in type OtherT.
- if (ConstantSigned) {
- if (OtherWidth >= Value.getMinSignedBits())
- return;
- } else { // !ConstantSigned
- if (OtherWidth >= Value.getActiveBits() + 1)
- return;
- }
- } else { // !OtherSigned
- // Check that the constant is representable in type OtherT.
- // Negative values are out of range.
- if (ConstantSigned) {
- if (Value.isNonNegative() && OtherWidth >= Value.getActiveBits())
- return;
- } else { // !ConstantSigned
- if (OtherWidth >= Value.getActiveBits())
- return;
- }
- }
- } else { // !CommonSigned
- if (OtherRange.NonNegative) {
- if (OtherWidth >= Value.getActiveBits())
- return;
- } else { // OtherSigned
- assert(!ConstantSigned &&
- "Two signed types converted to unsigned types.");
- // Check to see if the constant is representable in OtherT.
- if (OtherWidth > Value.getActiveBits())
- return;
- // Check to see if the constant is equivalent to a negative value
- // cast to CommonT.
- if (S.Context.getIntWidth(ConstantT) ==
- S.Context.getIntWidth(CommonT) &&
- Value.isNegative() && Value.getMinSignedBits() <= OtherWidth)
- return;
- // The constant value rests between values that OtherT can represent
- // after conversion. Relational comparison still works, but equality
- // comparisons will be tautological.
- EqualityOnly = true;
+ ComparisonResult TrueFlag, FalseFlag;
+ if (Op == BO_EQ) {
+ TrueFlag = EQ;
+ FalseFlag = NE;
+ } else if (Op == BO_NE) {
+ TrueFlag = NE;
+ FalseFlag = EQ;
+ } else {
+ if ((Op == BO_LT || Op == BO_GE) ^ ConstantOnRHS) {
+ TrueFlag = LT;
+ FalseFlag = GE;
+ } else {
+ TrueFlag = GT;
+ FalseFlag = LE;
}
+ if (Op == BO_GE || Op == BO_LE)
+ std::swap(TrueFlag, FalseFlag);
}
+ if (R & TrueFlag)
+ return StringRef("true");
+ if (R & FalseFlag)
+ return StringRef("false");
+ return llvm::None;
+ }
+};
+}
- bool PositiveConstant = !ConstantSigned || Value.isNonNegative();
+static bool HasEnumType(Expr *E) {
+ // Strip off implicit integral promotions.
+ while (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
+ if (ICE->getCastKind() != CK_IntegralCast &&
+ ICE->getCastKind() != CK_NoOp)
+ break;
+ E = ICE->getSubExpr();
+ }
- if (op == BO_EQ || op == BO_NE) {
- IsTrue = op == BO_NE;
- } else if (EqualityOnly) {
- return;
- } else if (RhsConstant) {
- if (op == BO_GT || op == BO_GE)
- IsTrue = !PositiveConstant;
- else // op == BO_LT || op == BO_LE
- IsTrue = PositiveConstant;
- } else {
- if (op == BO_LT || op == BO_LE)
- IsTrue = !PositiveConstant;
- else // op == BO_GT || op == BO_GE
- IsTrue = PositiveConstant;
- }
- } else {
- // Other isKnownToHaveBooleanValue
- enum CompareBoolWithConstantResult { AFals, ATrue, Unkwn };
- enum ConstantValue { LT_Zero, Zero, One, GT_One, SizeOfConstVal };
- enum ConstantSide { Lhs, Rhs, SizeOfConstSides };
+ return E->getType()->isEnumeralType();
+}
- static const struct LinkedConditions {
- CompareBoolWithConstantResult BO_LT_OP[SizeOfConstSides][SizeOfConstVal];
- CompareBoolWithConstantResult BO_GT_OP[SizeOfConstSides][SizeOfConstVal];
- CompareBoolWithConstantResult BO_LE_OP[SizeOfConstSides][SizeOfConstVal];
- CompareBoolWithConstantResult BO_GE_OP[SizeOfConstSides][SizeOfConstVal];
- CompareBoolWithConstantResult BO_EQ_OP[SizeOfConstSides][SizeOfConstVal];
- CompareBoolWithConstantResult BO_NE_OP[SizeOfConstSides][SizeOfConstVal];
+static int classifyConstantValue(Expr *Constant) {
+ // The values of this enumeration are used in the diagnostics
+ // diag::warn_out_of_range_compare and diag::warn_tautological_bool_compare.
+ enum ConstantValueKind {
+ Miscellaneous = 0,
+ LiteralTrue,
+ LiteralFalse
+ };
+ if (auto *BL = dyn_cast<CXXBoolLiteralExpr>(Constant))
+ return BL->getValue() ? ConstantValueKind::LiteralTrue
+ : ConstantValueKind::LiteralFalse;
+ return ConstantValueKind::Miscellaneous;
+}
- } TruthTable = {
- // Constant on LHS. | Constant on RHS. |
- // LT_Zero| Zero | One |GT_One| LT_Zero| Zero | One |GT_One|
- { { ATrue, Unkwn, AFals, AFals }, { AFals, AFals, Unkwn, ATrue } },
- { { AFals, AFals, Unkwn, ATrue }, { ATrue, Unkwn, AFals, AFals } },
- { { ATrue, ATrue, Unkwn, AFals }, { AFals, Unkwn, ATrue, ATrue } },
- { { AFals, Unkwn, ATrue, ATrue }, { ATrue, ATrue, Unkwn, AFals } },
- { { AFals, Unkwn, Unkwn, AFals }, { AFals, Unkwn, Unkwn, AFals } },
- { { ATrue, Unkwn, Unkwn, ATrue }, { ATrue, Unkwn, Unkwn, ATrue } }
- };
+static bool CheckTautologicalComparison(Sema &S, BinaryOperator *E,
+ Expr *Constant, Expr *Other,
+ const llvm::APSInt &Value,
+ bool RhsConstant) {
+ if (S.inTemplateInstantiation())
+ return false;
- bool ConstantIsBoolLiteral = isa<CXXBoolLiteralExpr>(Constant);
+ Expr *OriginalOther = Other;
- enum ConstantValue ConstVal = Zero;
- if (Value.isUnsigned() || Value.isNonNegative()) {
- if (Value == 0) {
- LiteralOrBoolConstant =
- ConstantIsBoolLiteral ? CXXBoolLiteralFalse : LiteralConstant;
- ConstVal = Zero;
- } else if (Value == 1) {
- LiteralOrBoolConstant =
- ConstantIsBoolLiteral ? CXXBoolLiteralTrue : LiteralConstant;
- ConstVal = One;
- } else {
- LiteralOrBoolConstant = LiteralConstant;
- ConstVal = GT_One;
- }
- } else {
- ConstVal = LT_Zero;
- }
+ Constant = Constant->IgnoreParenImpCasts();
+ Other = Other->IgnoreParenImpCasts();
- CompareBoolWithConstantResult CmpRes;
+ // Suppress warnings on tautological comparisons between values of the same
+ // enumeration type. There are only two ways we could warn on this:
+ // - If the constant is outside the range of representable values of
+ // the enumeration. In such a case, we should warn about the cast
+ // to enumeration type, not about the comparison.
+ // - If the constant is the maximum / minimum in-range value. For an
+ // enumeratin type, such comparisons can be meaningful and useful.
+ if (Constant->getType()->isEnumeralType() &&
+ S.Context.hasSameUnqualifiedType(Constant->getType(), Other->getType()))
+ return false;
- switch (op) {
- case BO_LT:
- CmpRes = TruthTable.BO_LT_OP[RhsConstant][ConstVal];
- break;
- case BO_GT:
- CmpRes = TruthTable.BO_GT_OP[RhsConstant][ConstVal];
- break;
- case BO_LE:
- CmpRes = TruthTable.BO_LE_OP[RhsConstant][ConstVal];
- break;
- case BO_GE:
- CmpRes = TruthTable.BO_GE_OP[RhsConstant][ConstVal];
- break;
- case BO_EQ:
- CmpRes = TruthTable.BO_EQ_OP[RhsConstant][ConstVal];
- break;
- case BO_NE:
- CmpRes = TruthTable.BO_NE_OP[RhsConstant][ConstVal];
- break;
- default:
- CmpRes = Unkwn;
- break;
- }
+ // TODO: Investigate using GetExprRange() to get tighter bounds
+ // on the bit ranges.
+ QualType OtherT = Other->getType();
+ if (const auto *AT = OtherT->getAs<AtomicType>())
+ OtherT = AT->getValueType();
+ IntRange OtherRange = IntRange::forValueOfType(S.Context, OtherT);
- if (CmpRes == AFals) {
- IsTrue = false;
- } else if (CmpRes == ATrue) {
- IsTrue = true;
- } else {
- return;
- }
- }
+ // Whether we're treating Other as being a bool because of the form of
+ // expression despite it having another type (typically 'int' in C).
+ bool OtherIsBooleanDespiteType =
+ !OtherT->isBooleanType() && Other->isKnownToHaveBooleanValue();
+ if (OtherIsBooleanDespiteType)
+ OtherRange = IntRange::forBoolType();
+
+ // Determine the promoted range of the other type and see if a comparison of
+ // the constant against that range is tautological.
+ PromotedRange OtherPromotedRange(OtherRange, Value.getBitWidth(),
+ Value.isUnsigned());
+ auto Cmp = OtherPromotedRange.compare(Value);
+ auto Result = PromotedRange::constantValue(E->getOpcode(), Cmp, RhsConstant);
+ if (!Result)
+ return false;
+
+ // Suppress the diagnostic for an in-range comparison if the constant comes
+ // from a macro or enumerator. We don't want to diagnose
+ //
+ // some_long_value <= INT_MAX
+ //
+ // when sizeof(int) == sizeof(long).
+ bool InRange = Cmp & PromotedRange::InRangeFlag;
+ if (InRange && IsEnumConstOrFromMacro(S, Constant))
+ return false;
// If this is a comparison to an enum constant, include that
// constant in the diagnostic.
@@ -8642,6 +8876,7 @@ void DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E, Expr *Constant,
if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Constant))
ED = dyn_cast<EnumConstantDecl>(DR->getDecl());
+ // Should be enough for uint128 (39 decimal digits)
SmallString<64> PrettySourceValue;
llvm::raw_svector_ostream OS(PrettySourceValue);
if (ED)
@@ -8649,17 +8884,35 @@ void DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E, Expr *Constant,
else
OS << Value;
- S.DiagRuntimeBehavior(
- E->getOperatorLoc(), E,
- S.PDiag(diag::warn_out_of_range_compare)
- << OS.str() << LiteralOrBoolConstant
- << OtherT << (OtherIsBooleanType && !OtherT->isBooleanType()) << IsTrue
- << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange());
+ // FIXME: We use a somewhat different formatting for the in-range cases and
+ // cases involving boolean values for historical reasons. We should pick a
+ // consistent way of presenting these diagnostics.
+ if (!InRange || Other->isKnownToHaveBooleanValue()) {
+ S.DiagRuntimeBehavior(
+ E->getOperatorLoc(), E,
+ S.PDiag(!InRange ? diag::warn_out_of_range_compare
+ : diag::warn_tautological_bool_compare)
+ << OS.str() << classifyConstantValue(Constant)
+ << OtherT << OtherIsBooleanDespiteType << *Result
+ << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange());
+ } else {
+ unsigned Diag = (isKnownToHaveUnsignedValue(OriginalOther) && Value == 0)
+ ? (HasEnumType(OriginalOther)
+ ? diag::warn_unsigned_enum_always_true_comparison
+ : diag::warn_unsigned_always_true_comparison)
+ : diag::warn_tautological_constant_compare;
+
+ S.Diag(E->getOperatorLoc(), Diag)
+ << RhsConstant << OtherT << E->getOpcodeStr() << OS.str() << *Result
+ << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
+ }
+
+ return true;
}
/// Analyze the operands of the given comparison. Implements the
/// fallback case from AnalyzeComparison.
-void AnalyzeImpConvsInComparison(Sema &S, BinaryOperator *E) {
+static void AnalyzeImpConvsInComparison(Sema &S, BinaryOperator *E) {
AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc());
AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc());
}
@@ -8667,7 +8920,7 @@ void AnalyzeImpConvsInComparison(Sema &S, BinaryOperator *E) {
/// \brief Implements -Wsign-compare.
///
/// \param E the binary operator to check for warnings
-void AnalyzeComparison(Sema &S, BinaryOperator *E) {
+static void AnalyzeComparison(Sema &S, BinaryOperator *E) {
// The type the comparison is being performed in.
QualType T = E->getLHS()->getType();
@@ -8680,39 +8933,45 @@ void AnalyzeComparison(Sema &S, BinaryOperator *E) {
if (E->isValueDependent())
return AnalyzeImpConvsInComparison(S, E);
- Expr *LHS = E->getLHS()->IgnoreParenImpCasts();
- Expr *RHS = E->getRHS()->IgnoreParenImpCasts();
-
- bool IsComparisonConstant = false;
-
- // Check whether an integer constant comparison results in a value
- // of 'true' or 'false'.
+ Expr *LHS = E->getLHS();
+ Expr *RHS = E->getRHS();
+
if (T->isIntegralType(S.Context)) {
llvm::APSInt RHSValue;
- bool IsRHSIntegralLiteral =
- RHS->isIntegerConstantExpr(RHSValue, S.Context);
llvm::APSInt LHSValue;
- bool IsLHSIntegralLiteral =
- LHS->isIntegerConstantExpr(LHSValue, S.Context);
- if (IsRHSIntegralLiteral && !IsLHSIntegralLiteral)
- DiagnoseOutOfRangeComparison(S, E, RHS, LHS, RHSValue, true);
- else if (!IsRHSIntegralLiteral && IsLHSIntegralLiteral)
- DiagnoseOutOfRangeComparison(S, E, LHS, RHS, LHSValue, false);
- else
- IsComparisonConstant =
- (IsRHSIntegralLiteral && IsLHSIntegralLiteral);
- } else if (!T->hasUnsignedIntegerRepresentation())
- IsComparisonConstant = E->isIntegerConstantExpr(S.Context);
-
- // We don't do anything special if this isn't an unsigned integral
- // comparison: we're only interested in integral comparisons, and
- // signed comparisons only happen in cases we don't care to warn about.
- //
- // We also don't care about value-dependent expressions or expressions
- // whose result is a constant.
- if (!T->hasUnsignedIntegerRepresentation() || IsComparisonConstant)
+
+ bool IsRHSIntegralLiteral = RHS->isIntegerConstantExpr(RHSValue, S.Context);
+ bool IsLHSIntegralLiteral = LHS->isIntegerConstantExpr(LHSValue, S.Context);
+
+ // We don't care about expressions whose result is a constant.
+ if (IsRHSIntegralLiteral && IsLHSIntegralLiteral)
+ return AnalyzeImpConvsInComparison(S, E);
+
+ // We only care about expressions where just one side is literal
+ if (IsRHSIntegralLiteral ^ IsLHSIntegralLiteral) {
+ // Is the constant on the RHS or LHS?
+ const bool RhsConstant = IsRHSIntegralLiteral;
+ Expr *Const = RhsConstant ? RHS : LHS;
+ Expr *Other = RhsConstant ? LHS : RHS;
+ const llvm::APSInt &Value = RhsConstant ? RHSValue : LHSValue;
+
+ // Check whether an integer constant comparison results in a value
+ // of 'true' or 'false'.
+ if (CheckTautologicalComparison(S, E, Const, Other, Value, RhsConstant))
+ return AnalyzeImpConvsInComparison(S, E);
+ }
+ }
+
+ if (!T->hasUnsignedIntegerRepresentation()) {
+ // We don't do anything special if this isn't an unsigned integral
+ // comparison: we're only interested in integral comparisons, and
+ // signed comparisons only happen in cases we don't care to warn about.
return AnalyzeImpConvsInComparison(S, E);
-
+ }
+
+ LHS = LHS->IgnoreParenImpCasts();
+ RHS = RHS->IgnoreParenImpCasts();
+
// Check to see if one of the (unmodified) operands is of different
// signedness.
Expr *signedOperand, *unsignedOperand;
@@ -8725,7 +8984,6 @@ void AnalyzeComparison(Sema &S, BinaryOperator *E) {
signedOperand = RHS;
unsignedOperand = LHS;
} else {
- CheckTrivialUnsignedComparison(S, E);
return AnalyzeImpConvsInComparison(S, E);
}
@@ -8737,11 +8995,9 @@ void AnalyzeComparison(Sema &S, BinaryOperator *E) {
AnalyzeImplicitConversions(S, LHS, E->getOperatorLoc());
AnalyzeImplicitConversions(S, RHS, E->getOperatorLoc());
- // If the signed range is non-negative, -Wsign-compare won't fire,
- // but we should still check for comparisons which are always true
- // or false.
+ // If the signed range is non-negative, -Wsign-compare won't fire.
if (signedRange.NonNegative)
- return CheckTrivialUnsignedComparison(S, E);
+ return;
// For (in)equality comparisons, if the unsigned operand is a
// constant which cannot collide with a overflowed signed operand,
@@ -8768,8 +9024,8 @@ void AnalyzeComparison(Sema &S, BinaryOperator *E) {
/// Analyzes an attempt to assign the given value to a bitfield.
///
/// Returns true if there was something fishy about the attempt.
-bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init,
- SourceLocation InitLoc) {
+static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init,
+ SourceLocation InitLoc) {
assert(Bitfield->isBitField());
if (Bitfield->isInvalidDecl())
return false;
@@ -8899,7 +9155,7 @@ bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init,
/// Analyze the given simple or compound assignment for warning-worthy
/// operations.
-void AnalyzeAssignment(Sema &S, BinaryOperator *E) {
+static void AnalyzeAssignment(Sema &S, BinaryOperator *E) {
// Just recurse on the LHS.
AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc());
@@ -8918,9 +9174,9 @@ void AnalyzeAssignment(Sema &S, BinaryOperator *E) {
}
/// Diagnose an implicit cast; purely a helper for CheckImplicitConversion.
-void DiagnoseImpCast(Sema &S, Expr *E, QualType SourceType, QualType T,
- SourceLocation CContext, unsigned diag,
- bool pruneControlFlow = false) {
+static void DiagnoseImpCast(Sema &S, Expr *E, QualType SourceType, QualType T,
+ SourceLocation CContext, unsigned diag,
+ bool pruneControlFlow = false) {
if (pruneControlFlow) {
S.DiagRuntimeBehavior(E->getExprLoc(), E,
S.PDiag(diag)
@@ -8933,16 +9189,16 @@ void DiagnoseImpCast(Sema &S, Expr *E, QualType SourceType, QualType T,
}
/// Diagnose an implicit cast; purely a helper for CheckImplicitConversion.
-void DiagnoseImpCast(Sema &S, Expr *E, QualType T, SourceLocation CContext,
- unsigned diag, bool pruneControlFlow = false) {
+static void DiagnoseImpCast(Sema &S, Expr *E, QualType T,
+ SourceLocation CContext,
+ unsigned diag, bool pruneControlFlow = false) {
DiagnoseImpCast(S, E, E->getType(), T, CContext, diag, pruneControlFlow);
}
/// Diagnose an implicit cast from a floating point value to an integer value.
-void DiagnoseFloatingImpCast(Sema &S, Expr *E, QualType T,
-
- SourceLocation CContext) {
+static void DiagnoseFloatingImpCast(Sema &S, Expr *E, QualType T,
+ SourceLocation CContext) {
const bool IsBool = T->isSpecificBuiltinType(BuiltinType::Bool);
const bool PruneWarnings = S.inTemplateInstantiation();
@@ -9032,7 +9288,8 @@ void DiagnoseFloatingImpCast(Sema &S, Expr *E, QualType T,
}
}
-std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) {
+static std::string PrettyPrintInRange(const llvm::APSInt &Value,
+ IntRange Range) {
if (!Range.Width) return "0";
llvm::APSInt ValueInRange = Value;
@@ -9041,7 +9298,7 @@ std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) {
return ValueInRange.toString(10);
}
-bool IsImplicitBoolFloatConversion(Sema &S, Expr *Ex, bool ToBool) {
+static bool IsImplicitBoolFloatConversion(Sema &S, Expr *Ex, bool ToBool) {
if (!isa<ImplicitCastExpr>(Ex))
return false;
@@ -9060,8 +9317,8 @@ bool IsImplicitBoolFloatConversion(Sema &S, Expr *Ex, bool ToBool) {
FloatCandidateBT && (FloatCandidateBT->isFloatingPoint()));
}
-void CheckImplicitArgumentConversions(Sema &S, CallExpr *TheCall,
- SourceLocation CC) {
+static void CheckImplicitArgumentConversions(Sema &S, CallExpr *TheCall,
+ SourceLocation CC) {
unsigned NumArgs = TheCall->getNumArgs();
for (unsigned i = 0; i < NumArgs; ++i) {
Expr *CurrA = TheCall->getArg(i);
@@ -9081,7 +9338,8 @@ void CheckImplicitArgumentConversions(Sema &S, CallExpr *TheCall,
}
}
-void DiagnoseNullConversion(Sema &S, Expr *E, QualType T, SourceLocation CC) {
+static void DiagnoseNullConversion(Sema &S, Expr *E, QualType T,
+ SourceLocation CC) {
if (S.Diags.isIgnored(diag::warn_impcast_null_pointer_to_integer,
E->getExprLoc()))
return;
@@ -9125,20 +9383,24 @@ void DiagnoseNullConversion(Sema &S, Expr *E, QualType T, SourceLocation CC) {
return;
S.Diag(Loc, diag::warn_impcast_null_pointer_to_integer)
- << (NullKind == Expr::NPCK_CXX11_nullptr) << T << clang::SourceRange(CC)
+ << (NullKind == Expr::NPCK_CXX11_nullptr) << T << SourceRange(CC)
<< FixItHint::CreateReplacement(Loc,
S.getFixItZeroLiteralForType(T, Loc));
}
-void checkObjCArrayLiteral(Sema &S, QualType TargetType,
- ObjCArrayLiteral *ArrayLiteral);
-void checkObjCDictionaryLiteral(Sema &S, QualType TargetType,
- ObjCDictionaryLiteral *DictionaryLiteral);
+static void checkObjCArrayLiteral(Sema &S, QualType TargetType,
+ ObjCArrayLiteral *ArrayLiteral);
+
+static void
+checkObjCDictionaryLiteral(Sema &S, QualType TargetType,
+ ObjCDictionaryLiteral *DictionaryLiteral);
/// Check a single element within a collection literal against the
/// target element type.
-void checkObjCCollectionLiteralElement(Sema &S, QualType TargetElementType,
- Expr *Element, unsigned ElementKind) {
+static void checkObjCCollectionLiteralElement(Sema &S,
+ QualType TargetElementType,
+ Expr *Element,
+ unsigned ElementKind) {
// Skip a bitcast to 'id' or qualified 'id'.
if (auto ICE = dyn_cast<ImplicitCastExpr>(Element)) {
if (ICE->getCastKind() == CK_BitCast &&
@@ -9167,8 +9429,8 @@ void checkObjCCollectionLiteralElement(Sema &S, QualType TargetElementType,
/// Check an Objective-C array literal being converted to the given
/// target type.
-void checkObjCArrayLiteral(Sema &S, QualType TargetType,
- ObjCArrayLiteral *ArrayLiteral) {
+static void checkObjCArrayLiteral(Sema &S, QualType TargetType,
+ ObjCArrayLiteral *ArrayLiteral) {
if (!S.NSArrayDecl)
return;
@@ -9195,8 +9457,9 @@ void checkObjCArrayLiteral(Sema &S, QualType TargetType,
/// Check an Objective-C dictionary literal being converted to the given
/// target type.
-void checkObjCDictionaryLiteral(Sema &S, QualType TargetType,
- ObjCDictionaryLiteral *DictionaryLiteral) {
+static void
+checkObjCDictionaryLiteral(Sema &S, QualType TargetType,
+ ObjCDictionaryLiteral *DictionaryLiteral) {
if (!S.NSDictionaryDecl)
return;
@@ -9224,8 +9487,8 @@ void checkObjCDictionaryLiteral(Sema &S, QualType TargetType,
// Helper function to filter out cases for constant width constant conversion.
// Don't warn on char array initialization or for non-decimal values.
-bool isSameWidthConstantConversion(Sema &S, Expr *E, QualType T,
- SourceLocation CC) {
+static bool isSameWidthConstantConversion(Sema &S, Expr *E, QualType T,
+ SourceLocation CC) {
// If initializing from a constant, and the constant starts with '0',
// then it is a binary, octal, or hexadecimal. Allow these constants
// to fill all the bits, even if there is a sign change.
@@ -9248,8 +9511,9 @@ bool isSameWidthConstantConversion(Sema &S, Expr *E, QualType T,
return true;
}
-void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
- SourceLocation CC, bool *ICContext = nullptr) {
+static void
+CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC,
+ bool *ICContext = nullptr) {
if (E->isTypeDependent() || E->isValueDependent()) return;
const Type *Source = S.Context.getCanonicalType(E->getType()).getTypePtr();
@@ -9316,10 +9580,13 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
// Strip complex types.
if (isa<ComplexType>(Source)) {
if (!isa<ComplexType>(Target)) {
- if (S.SourceMgr.isInSystemMacro(CC))
+ if (S.SourceMgr.isInSystemMacro(CC) || Target->isBooleanType())
return;
- return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_complex_scalar);
+ return DiagnoseImpCast(S, E, T, CC,
+ S.getLangOpts().CPlusPlus
+ ? diag::err_impcast_complex_scalar
+ : diag::warn_impcast_complex_scalar);
}
Source = cast<ComplexType>(Source)->getElementType().getTypePtr();
@@ -9514,11 +9781,11 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
}
}
-void CheckConditionalOperator(Sema &S, ConditionalOperator *E,
- SourceLocation CC, QualType T);
+static void CheckConditionalOperator(Sema &S, ConditionalOperator *E,
+ SourceLocation CC, QualType T);
-void CheckConditionalOperand(Sema &S, Expr *E, QualType T,
- SourceLocation CC, bool &ICContext) {
+static void CheckConditionalOperand(Sema &S, Expr *E, QualType T,
+ SourceLocation CC, bool &ICContext) {
E = E->IgnoreParenImpCasts();
if (isa<ConditionalOperator>(E))
@@ -9529,8 +9796,8 @@ void CheckConditionalOperand(Sema &S, Expr *E, QualType T,
return CheckImplicitConversion(S, E, T, CC, &ICContext);
}
-void CheckConditionalOperator(Sema &S, ConditionalOperator *E,
- SourceLocation CC, QualType T) {
+static void CheckConditionalOperator(Sema &S, ConditionalOperator *E,
+ SourceLocation CC, QualType T) {
AnalyzeImplicitConversions(S, E->getCond(), E->getQuestionLoc());
bool Suspicious = false;
@@ -9559,7 +9826,7 @@ void CheckConditionalOperator(Sema &S, ConditionalOperator *E,
/// CheckBoolLikeConversion - Check conversion of given expression to boolean.
/// Input argument E is a logical expression.
-void CheckBoolLikeConversion(Sema &S, Expr *E, SourceLocation CC) {
+static void CheckBoolLikeConversion(Sema &S, Expr *E, SourceLocation CC) {
if (S.getLangOpts().Bool)
return;
CheckImplicitConversion(S, E->IgnoreParenImpCasts(), S.Context.BoolTy, CC);
@@ -9568,7 +9835,8 @@ void CheckBoolLikeConversion(Sema &S, Expr *E, SourceLocation CC) {
/// AnalyzeImplicitConversions - Find and report any interesting
/// implicit conversions in the given expression. There are a couple
/// of competing diagnostics here, -Wconversion and -Wsign-compare.
-void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) {
+static void AnalyzeImplicitConversions(Sema &S, Expr *OrigE,
+ SourceLocation CC) {
QualType T = OrigE->getType();
Expr *E = OrigE->IgnoreParenImpCasts();
@@ -9661,8 +9929,6 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) {
::CheckBoolLikeConversion(S, U->getSubExpr(), CC);
}
-} // end anonymous namespace
-
/// Diagnose integer type and any valid implicit convertion to it.
static bool checkOpenCLEnqueueIntType(Sema &S, Expr *E, const QualType &IntT) {
// Taking into account implicit conversions,
@@ -9968,10 +10234,11 @@ void Sema::CheckForIntOverflow (Expr *E) {
}
namespace {
+
/// \brief Visitor for expressions which looks for unsequenced operations on the
/// same object.
class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
- typedef EvaluatedExprVisitor<SequenceChecker> Base;
+ using Base = EvaluatedExprVisitor<SequenceChecker>;
/// \brief A tree of sequenced regions within an expression. Two regions are
/// unsequenced if one is an ancestor or a descendent of the other. When we
@@ -9990,11 +10257,14 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
/// \brief A region within an expression which may be sequenced with respect
/// to some other region.
class Seq {
- explicit Seq(unsigned N) : Index(N) {}
- unsigned Index;
friend class SequenceTree;
+
+ unsigned Index = 0;
+
+ explicit Seq(unsigned N) : Index(N) {}
+
public:
- Seq() : Index(0) {}
+ Seq() = default;
};
SequenceTree() { Values.push_back(Value(0)); }
@@ -10038,16 +10308,18 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
};
/// An object for which we can track unsequenced uses.
- typedef NamedDecl *Object;
+ using Object = NamedDecl *;
/// Different flavors of object usage which we track. We only track the
/// least-sequenced usage of each kind.
enum UsageKind {
/// A read of an object. Multiple unsequenced reads are OK.
UK_Use,
+
/// A modification of an object which is sequenced before the value
/// computation of the expression, such as ++n in C++.
UK_ModAsValue,
+
/// A modification of an object which is not sequenced before the value
/// computation of the expression, such as n++.
UK_ModAsSideEffect,
@@ -10056,29 +10328,37 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
};
struct Usage {
- Usage() : Use(nullptr), Seq() {}
- Expr *Use;
+ Expr *Use = nullptr;
SequenceTree::Seq Seq;
+
+ Usage() = default;
};
struct UsageInfo {
- UsageInfo() : Diagnosed(false) {}
Usage Uses[UK_Count];
+
/// Have we issued a diagnostic for this variable already?
- bool Diagnosed;
+ bool Diagnosed = false;
+
+ UsageInfo() = default;
};
- typedef llvm::SmallDenseMap<Object, UsageInfo, 16> UsageInfoMap;
+ using UsageInfoMap = llvm::SmallDenseMap<Object, UsageInfo, 16>;
Sema &SemaRef;
+
/// Sequenced regions within the expression.
SequenceTree Tree;
+
/// Declaration modifications and references which we have seen.
UsageInfoMap UsageMap;
+
/// The region we are currently within.
SequenceTree::Seq Region;
+
/// Filled in with declarations which were modified as a side-effect
/// (that is, post-increment operations).
- SmallVectorImpl<std::pair<Object, Usage> > *ModAsSideEffect;
+ SmallVectorImpl<std::pair<Object, Usage>> *ModAsSideEffect = nullptr;
+
/// Expressions to check later. We defer checking these to reduce
/// stack usage.
SmallVectorImpl<Expr *> &WorkList;
@@ -10093,6 +10373,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
: Self(Self), OldModAsSideEffect(Self.ModAsSideEffect) {
Self.ModAsSideEffect = &ModAsSideEffect;
}
+
~SequencedSubexpression() {
for (auto &M : llvm::reverse(ModAsSideEffect)) {
UsageInfo &U = Self.UsageMap[M.first];
@@ -10105,7 +10386,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
SequenceChecker &Self;
SmallVector<std::pair<Object, Usage>, 4> ModAsSideEffect;
- SmallVectorImpl<std::pair<Object, Usage> > *OldModAsSideEffect;
+ SmallVectorImpl<std::pair<Object, Usage>> *OldModAsSideEffect;
};
/// RAII object wrapping the visitation of a subexpression which we might
@@ -10115,9 +10396,10 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
class EvaluationTracker {
public:
EvaluationTracker(SequenceChecker &Self)
- : Self(Self), Prev(Self.EvalTracker), EvalOK(true) {
+ : Self(Self), Prev(Self.EvalTracker) {
Self.EvalTracker = this;
}
+
~EvaluationTracker() {
Self.EvalTracker = Prev;
if (Prev)
@@ -10134,8 +10416,8 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
private:
SequenceChecker &Self;
EvaluationTracker *Prev;
- bool EvalOK;
- } *EvalTracker;
+ bool EvalOK = true;
+ } *EvalTracker = nullptr;
/// \brief Find the object which is produced by the specified expression,
/// if any.
@@ -10169,6 +10451,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
U.Seq = Region;
}
}
+
/// \brief Check whether a modification or use conflicts with a prior usage.
void checkUsage(Object O, UsageInfo &UI, Expr *Ref, UsageKind OtherKind,
bool IsModMod) {
@@ -10196,6 +10479,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
// Uses conflict with other modifications.
checkUsage(O, U, Use, UK_ModAsValue, false);
}
+
void notePostUse(Object O, Expr *Use) {
UsageInfo &U = UsageMap[O];
checkUsage(O, U, Use, UK_ModAsSideEffect, false);
@@ -10208,6 +10492,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
checkUsage(O, U, Mod, UK_ModAsValue, true);
checkUsage(O, U, Mod, UK_Use, false);
}
+
void notePostMod(Object O, Expr *Use, UsageKind UK) {
UsageInfo &U = UsageMap[O];
checkUsage(O, U, Use, UK_ModAsSideEffect, true);
@@ -10216,8 +10501,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
public:
SequenceChecker(Sema &S, Expr *E, SmallVectorImpl<Expr *> &WorkList)
- : Base(S.Context), SemaRef(S), Region(Tree.root()),
- ModAsSideEffect(nullptr), WorkList(WorkList), EvalTracker(nullptr) {
+ : Base(S.Context), SemaRef(S), Region(Tree.root()), WorkList(WorkList) {
Visit(E);
}
@@ -10451,7 +10735,8 @@ public:
Tree.merge(Elts[I]);
}
};
-} // end anonymous namespace
+
+} // namespace
void Sema::CheckUnsequencedOperations(Expr *E) {
SmallVector<Expr *, 8> WorkList;
@@ -10868,19 +11153,22 @@ void Sema::CheckArrayAccess(const Expr *expr) {
//===--- CHECK: Objective-C retain cycles ----------------------------------//
namespace {
- struct RetainCycleOwner {
- RetainCycleOwner() : Variable(nullptr), Indirect(false) {}
- VarDecl *Variable;
- SourceRange Range;
- SourceLocation Loc;
- bool Indirect;
- void setLocsFrom(Expr *e) {
- Loc = e->getExprLoc();
- Range = e->getSourceRange();
- }
- };
-} // end anonymous namespace
+struct RetainCycleOwner {
+ VarDecl *Variable = nullptr;
+ SourceRange Range;
+ SourceLocation Loc;
+ bool Indirect = false;
+
+ RetainCycleOwner() = default;
+
+ void setLocsFrom(Expr *e) {
+ Loc = e->getExprLoc();
+ Range = e->getSourceRange();
+ }
+};
+
+} // namespace
/// Consider whether capturing the given variable can possibly lead to
/// a retain cycle.
@@ -10977,15 +11265,16 @@ static bool findRetainCycleOwner(Sema &S, Expr *e, RetainCycleOwner &owner) {
}
namespace {
+
struct FindCaptureVisitor : EvaluatedExprVisitor<FindCaptureVisitor> {
- FindCaptureVisitor(ASTContext &Context, VarDecl *variable)
- : EvaluatedExprVisitor<FindCaptureVisitor>(Context),
- Context(Context), Variable(variable), Capturer(nullptr),
- VarWillBeReased(false) {}
ASTContext &Context;
VarDecl *Variable;
- Expr *Capturer;
- bool VarWillBeReased;
+ Expr *Capturer = nullptr;
+ bool VarWillBeReased = false;
+
+ FindCaptureVisitor(ASTContext &Context, VarDecl *variable)
+ : EvaluatedExprVisitor<FindCaptureVisitor>(Context),
+ Context(Context), Variable(variable) {}
void VisitDeclRefExpr(DeclRefExpr *ref) {
if (ref->getDecl() == Variable && !Capturer)
@@ -11010,6 +11299,7 @@ namespace {
if (OVE->getSourceExpr())
Visit(OVE->getSourceExpr());
}
+
void VisitBinaryOperator(BinaryOperator *BinOp) {
if (!Variable || VarWillBeReased || BinOp->getOpcode() != BO_Assign)
return;
@@ -11026,7 +11316,8 @@ namespace {
}
}
};
-} // end anonymous namespace
+
+} // namespace
/// Check whether the given argument is a block which captures a
/// variable.
@@ -11283,9 +11574,15 @@ void Sema::checkRetainCycles(ObjCMessageExpr *msg) {
}
// Check whether the receiver is captured by any of the arguments.
- for (unsigned i = 0, e = msg->getNumArgs(); i != e; ++i)
- if (Expr *capturer = findCapturingExpr(*this, msg->getArg(i), owner))
+ const ObjCMethodDecl *MD = msg->getMethodDecl();
+ for (unsigned i = 0, e = msg->getNumArgs(); i != e; ++i) {
+ if (Expr *capturer = findCapturingExpr(*this, msg->getArg(i), owner)) {
+ // noescape blocks should not be retained by the method.
+ if (MD && MD->parameters()[i]->hasAttr<NoEscapeAttr>())
+ continue;
return diagnoseRetainCycle(*this, capturer, owner);
+ }
+ }
}
/// Check a property assign to see if it's likely to cause a retain cycle.
@@ -11433,16 +11730,14 @@ void Sema::checkUnsafeExprAssigns(SourceLocation Loc,
//===--- CHECK: Empty statement body (-Wempty-body) ---------------------===//
-namespace {
-bool ShouldDiagnoseEmptyStmtBody(const SourceManager &SourceMgr,
- SourceLocation StmtLoc,
- const NullStmt *Body) {
+static bool ShouldDiagnoseEmptyStmtBody(const SourceManager &SourceMgr,
+ SourceLocation StmtLoc,
+ const NullStmt *Body) {
// Do not warn if the body is a macro that expands to nothing, e.g:
//
// #define CALL(x)
// if (condition)
// CALL(0);
- //
if (Body->hasLeadingEmptyMacro())
return false;
@@ -11465,7 +11760,6 @@ bool ShouldDiagnoseEmptyStmtBody(const SourceManager &SourceMgr,
return true;
}
-} // end anonymous namespace
void Sema::DiagnoseEmptyStmtBody(SourceLocation StmtLoc,
const Stmt *Body,
@@ -11577,9 +11871,7 @@ void Sema::DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr,
return;
// Check for a call to std::move
- const FunctionDecl *FD = CE->getDirectCallee();
- if (!FD || !FD->isInStdNamespace() || !FD->getIdentifier() ||
- !FD->getIdentifier()->isStr("move"))
+ if (!CE->isCallToStdMove())
return;
// Get argument from std::move
@@ -11647,12 +11939,10 @@ void Sema::DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr,
//===--- Layout compatibility ----------------------------------------------//
-namespace {
-
-bool isLayoutCompatible(ASTContext &C, QualType T1, QualType T2);
+static bool isLayoutCompatible(ASTContext &C, QualType T1, QualType T2);
/// \brief Check if two enumeration types are layout-compatible.
-bool isLayoutCompatible(ASTContext &C, EnumDecl *ED1, EnumDecl *ED2) {
+static bool isLayoutCompatible(ASTContext &C, EnumDecl *ED1, EnumDecl *ED2) {
// C++11 [dcl.enum] p8:
// Two enumeration types are layout-compatible if they have the same
// underlying type.
@@ -11661,7 +11951,8 @@ bool isLayoutCompatible(ASTContext &C, EnumDecl *ED1, EnumDecl *ED2) {
}
/// \brief Check if two fields are layout-compatible.
-bool isLayoutCompatible(ASTContext &C, FieldDecl *Field1, FieldDecl *Field2) {
+static bool isLayoutCompatible(ASTContext &C, FieldDecl *Field1,
+ FieldDecl *Field2) {
if (!isLayoutCompatible(C, Field1->getType(), Field2->getType()))
return false;
@@ -11682,9 +11973,8 @@ bool isLayoutCompatible(ASTContext &C, FieldDecl *Field1, FieldDecl *Field2) {
/// \brief Check if two standard-layout structs are layout-compatible.
/// (C++11 [class.mem] p17)
-bool isLayoutCompatibleStruct(ASTContext &C,
- RecordDecl *RD1,
- RecordDecl *RD2) {
+static bool isLayoutCompatibleStruct(ASTContext &C, RecordDecl *RD1,
+ RecordDecl *RD2) {
// If both records are C++ classes, check that base classes match.
if (const CXXRecordDecl *D1CXX = dyn_cast<CXXRecordDecl>(RD1)) {
// If one of records is a CXXRecordDecl we are in C++ mode,
@@ -11727,9 +12017,8 @@ bool isLayoutCompatibleStruct(ASTContext &C,
/// \brief Check if two standard-layout unions are layout-compatible.
/// (C++11 [class.mem] p18)
-bool isLayoutCompatibleUnion(ASTContext &C,
- RecordDecl *RD1,
- RecordDecl *RD2) {
+static bool isLayoutCompatibleUnion(ASTContext &C, RecordDecl *RD1,
+ RecordDecl *RD2) {
llvm::SmallPtrSet<FieldDecl *, 8> UnmatchedFields;
for (auto *Field2 : RD2->fields())
UnmatchedFields.insert(Field2);
@@ -11754,7 +12043,8 @@ bool isLayoutCompatibleUnion(ASTContext &C,
return UnmatchedFields.empty();
}
-bool isLayoutCompatible(ASTContext &C, RecordDecl *RD1, RecordDecl *RD2) {
+static bool isLayoutCompatible(ASTContext &C, RecordDecl *RD1,
+ RecordDecl *RD2) {
if (RD1->isUnion() != RD2->isUnion())
return false;
@@ -11765,7 +12055,7 @@ bool isLayoutCompatible(ASTContext &C, RecordDecl *RD1, RecordDecl *RD2) {
}
/// \brief Check if two types are layout-compatible in C++11 sense.
-bool isLayoutCompatible(ASTContext &C, QualType T1, QualType T2) {
+static bool isLayoutCompatible(ASTContext &C, QualType T1, QualType T2) {
if (T1.isNull() || T2.isNull())
return false;
@@ -11799,11 +12089,9 @@ bool isLayoutCompatible(ASTContext &C, QualType T1, QualType T2) {
return false;
}
-} // end anonymous namespace
//===--- CHECK: pointer_with_type_tag attribute: datatypes should match ----//
-namespace {
/// \brief Given a type tag expression find the type tag itself.
///
/// \param TypeExpr Type tag expression, as it appears in user's code.
@@ -11811,8 +12099,8 @@ namespace {
/// \param VD Declaration of an identifier that appears in a type tag.
///
/// \param MagicValue Type tag magic value.
-bool FindTypeTagExpr(const Expr *TypeExpr, const ASTContext &Ctx,
- const ValueDecl **VD, uint64_t *MagicValue) {
+static bool FindTypeTagExpr(const Expr *TypeExpr, const ASTContext &Ctx,
+ const ValueDecl **VD, uint64_t *MagicValue) {
while(true) {
if (!TypeExpr)
return false;
@@ -11887,7 +12175,7 @@ bool FindTypeTagExpr(const Expr *TypeExpr, const ASTContext &Ctx,
/// \param TypeInfo Information about the corresponding C type.
///
/// \returns true if the corresponding C type was found.
-bool GetMatchingCType(
+static bool GetMatchingCType(
const IdentifierInfo *ArgumentKind,
const Expr *TypeExpr, const ASTContext &Ctx,
const llvm::DenseMap<Sema::TypeTagMagicValue,
@@ -11930,7 +12218,6 @@ bool GetMatchingCType(
TypeInfo = I->second;
return true;
}
-} // end anonymous namespace
void Sema::RegisterTypeTagForDatatype(const IdentifierInfo *ArgumentKind,
uint64_t MagicValue, QualType Type,
@@ -11945,8 +12232,7 @@ void Sema::RegisterTypeTagForDatatype(const IdentifierInfo *ArgumentKind,
TypeTagData(Type, LayoutCompatible, MustBeNull);
}
-namespace {
-bool IsSameCharType(QualType T1, QualType T2) {
+static bool IsSameCharType(QualType T1, QualType T2) {
const BuiltinType *BT1 = T1->getAs<BuiltinType>();
if (!BT1)
return false;
@@ -11963,13 +12249,20 @@ bool IsSameCharType(QualType T1, QualType T2) {
(T1Kind == BuiltinType::Char_U && T2Kind == BuiltinType::UChar) ||
(T1Kind == BuiltinType::Char_S && T2Kind == BuiltinType::SChar);
}
-} // end anonymous namespace
void Sema::CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr,
- const Expr * const *ExprArgs) {
+ const ArrayRef<const Expr *> ExprArgs,
+ SourceLocation CallSiteLoc) {
const IdentifierInfo *ArgumentKind = Attr->getArgumentKind();
bool IsPointerAttr = Attr->getIsPointer();
+ // Retrieve the argument representing the 'type_tag'.
+ if (Attr->getTypeTagIdx() >= ExprArgs.size()) {
+ // Add 1 to display the user's specified value.
+ Diag(CallSiteLoc, diag::err_tag_index_out_of_range)
+ << 0 << Attr->getTypeTagIdx() + 1;
+ return;
+ }
const Expr *TypeTagExpr = ExprArgs[Attr->getTypeTagIdx()];
bool FoundWrongKind;
TypeTagData TypeInfo;
@@ -11983,6 +12276,13 @@ void Sema::CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr,
return;
}
+ // Retrieve the argument representing the 'arg_idx'.
+ if (Attr->getArgumentIdx() >= ExprArgs.size()) {
+ // Add 1 to display the user's specified value.
+ Diag(CallSiteLoc, diag::err_tag_index_out_of_range)
+ << 1 << Attr->getArgumentIdx() + 1;
+ return;
+ }
const Expr *ArgumentExpr = ExprArgs[Attr->getArgumentIdx()];
if (IsPointerAttr) {
// Skip implicit cast of pointer to `void *' (as a function argument).
@@ -12074,8 +12374,9 @@ void Sema::DiscardMisalignedMemberAddress(const Type *T, Expr *E) {
MisalignedMember(Op));
if (MA != MisalignedMembers.end() &&
(T->isIntegerType() ||
- (T->isPointerType() &&
- Context.getTypeAlignInChars(T->getPointeeType()) <= MA->Alignment)))
+ (T->isPointerType() && (T->getPointeeType()->isIncompleteType() ||
+ Context.getTypeAlignInChars(
+ T->getPointeeType()) <= MA->Alignment))))
MisalignedMembers.erase(MA);
}
}
@@ -12192,8 +12493,8 @@ void Sema::RefersToMemberWithReducedAlignment(
void Sema::CheckAddressOfPackedMember(Expr *rhs) {
using namespace std::placeholders;
+
RefersToMemberWithReducedAlignment(
rhs, std::bind(&Sema::AddPotentialMisalignedMembers, std::ref(*this), _1,
_2, _3, _4));
}
-
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp
index 4de7d422072da..834e149d1af4c 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp
@@ -10,10 +10,11 @@
// This file defines the code-completion semantic actions.
//
//===----------------------------------------------------------------------===//
-#include "clang/Sema/SemaInternal.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/QualTypeNames.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/MacroInfo.h"
@@ -23,6 +24,7 @@
#include "clang/Sema/Overload.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/SmallPtrSet.h"
@@ -46,7 +48,7 @@ namespace {
/// the result set (when it returns true) and which declarations should be
/// filtered out (returns false).
typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const;
-
+
typedef CodeCompletionResult Result;
private:
@@ -741,8 +743,18 @@ unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) {
}
const DeclContext *DC = ND->getDeclContext()->getRedeclContext();
- if (DC->isRecord() || isa<ObjCContainerDecl>(DC))
+ if (DC->isRecord() || isa<ObjCContainerDecl>(DC)) {
+ // Explicit destructor calls are very rare.
+ if (isa<CXXDestructorDecl>(ND))
+ return CCP_Unlikely;
+ // Explicit operator and conversion function calls are also very rare.
+ auto DeclNameKind = ND->getDeclName().getNameKind();
+ if (DeclNameKind == DeclarationName::CXXOperatorName ||
+ DeclNameKind == DeclarationName::CXXLiteralOperatorName ||
+ DeclNameKind == DeclarationName::CXXConversionFunctionName)
+ return CCP_Unlikely;
return CCP_MemberDeclaration;
+ }
// Content-based decisions.
if (isa<EnumConstantDecl>(ND))
@@ -1070,9 +1082,16 @@ bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
/// ordinary name lookup but is not a type name.
bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
ND = cast<NamedDecl>(ND->getUnderlyingDecl());
- if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
+ if (isa<TypeDecl>(ND))
return false;
-
+ // Objective-C interfaces names are not filtered by this method because they
+ // can be used in a class property expression. We can still filter out
+ // @class declarations though.
+ if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {
+ if (!ID->getDefinition())
+ return false;
+ }
+
unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
if (SemaRef.getLangOpts().CPlusPlus)
IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
@@ -1484,6 +1503,7 @@ static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
Policy.AnonymousTagLocations = false;
Policy.SuppressStrongLifetime = true;
Policy.SuppressUnwrittenScope = true;
+ Policy.SuppressScope = true;
return Policy;
}
@@ -1647,21 +1667,23 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
if (CCC == Sema::PCC_Class) {
AddTypedefResult(Results);
+ bool IsNotInheritanceScope =
+ !(S->getFlags() & Scope::ClassInheritanceScope);
// public:
Builder.AddTypedTextChunk("public");
- if (Results.includeCodePatterns())
+ if (IsNotInheritanceScope && Results.includeCodePatterns())
Builder.AddChunk(CodeCompletionString::CK_Colon);
Results.AddResult(Result(Builder.TakeString()));
// protected:
Builder.AddTypedTextChunk("protected");
- if (Results.includeCodePatterns())
+ if (IsNotInheritanceScope && Results.includeCodePatterns())
Builder.AddChunk(CodeCompletionString::CK_Colon);
Results.AddResult(Result(Builder.TakeString()));
// private:
Builder.AddTypedTextChunk("private");
- if (Results.includeCodePatterns())
+ if (IsNotInheritanceScope && Results.includeCodePatterns())
Builder.AddChunk(CodeCompletionString::CK_Colon);
Results.AddResult(Result(Builder.TakeString()));
}
@@ -2126,9 +2148,10 @@ static void AddResultTypeChunk(ASTContext &Context,
T = Method->getSendResultType(BaseType);
else
T = Method->getReturnType();
- } else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
+ } else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND)) {
T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
- else if (isa<UnresolvedUsingValueDecl>(ND)) {
+ T = clang::TypeName::getFullyQualifiedType(T, Context);
+ } else if (isa<UnresolvedUsingValueDecl>(ND)) {
/* Do nothing: ignore unresolved using declarations*/
} else if (const ObjCIvarDecl *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
if (!BaseType.isNull())
@@ -3355,12 +3378,9 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
return;
PrintingPolicy Policy = getCompletionPrintingPolicy(S);
- for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
- MEnd = Method->end_overridden_methods();
- M != MEnd; ++M) {
+ for (const CXXMethodDecl *Overridden : Method->overridden_methods()) {
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
- const CXXMethodDecl *Overridden = *M;
if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
continue;
@@ -4282,13 +4302,17 @@ static void mergeCandidatesWithResults(Sema &SemaRef,
std::stable_sort(
CandidateSet.begin(), CandidateSet.end(),
[&](const OverloadCandidate &X, const OverloadCandidate &Y) {
- return isBetterOverloadCandidate(SemaRef, X, Y, Loc);
+ return isBetterOverloadCandidate(SemaRef, X, Y, Loc,
+ CandidateSet.getKind());
});
// Add the remaining viable overload candidates as code-completion results.
- for (auto &Candidate : CandidateSet)
+ for (auto &Candidate : CandidateSet) {
+ if (Candidate.Function && Candidate.Function->isDeleted())
+ continue;
if (Candidate.Viable)
Results.push_back(ResultCandidate(Candidate.Function));
+ }
}
}
@@ -4379,9 +4403,11 @@ void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) {
ArgExprs.append(Args.begin(), Args.end());
UnresolvedSet<8> Decls;
Decls.append(UME->decls_begin(), UME->decls_end());
+ const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase();
AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs,
/*SuppressUsedConversions=*/false,
- /*PartialOverloading=*/true);
+ /*PartialOverloading=*/true,
+ FirstArgumentIsBase);
} else {
FunctionDecl *FD = nullptr;
if (auto MCE = dyn_cast<MemberExpr>(NakedFn))
@@ -4574,9 +4600,19 @@ void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
bool EnteringContext) {
- if (!SS.getScopeRep() || !CodeCompleter)
+ if (SS.isEmpty() || !CodeCompleter)
return;
+ // We want to keep the scope specifier even if it's invalid (e.g. the scope
+ // "a::b::" is not corresponding to any context/namespace in the AST), since
+ // it can be useful for global code completion which have information about
+ // contexts/symbols that are not in the AST.
+ if (SS.isInvalid()) {
+ CodeCompletionContext CC(CodeCompletionContext::CCC_Name);
+ CC.setCXXScopeSpecifier(SS);
+ HandleCodeCompleteResults(this, CodeCompleter, CC, nullptr, 0);
+ return;
+ }
// Always pretend to enter a context to ensure that a dependent type
// resolves to a dependent record.
DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true);
@@ -4592,7 +4628,7 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Name);
Results.EnterNewScope();
-
+
// The "template" keyword can follow "::" in the grammar, but only
// put it into the grammar if the nested-name-specifier is dependent.
NestedNameSpecifier *NNS = SS.getScopeRep();
@@ -4606,16 +4642,21 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
// qualified-id completions.
if (!EnteringContext)
MaybeAddOverrideCalls(*this, Ctx, Results);
- Results.ExitScope();
-
- CodeCompletionDeclConsumer Consumer(Results, CurContext);
- LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer,
- /*IncludeGlobalScope=*/true,
- /*IncludeDependentBases=*/true);
+ Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter,
- Results.getCompletionContext(),
- Results.data(),Results.size());
+ if (CodeCompleter->includeNamespaceLevelDecls() ||
+ (!Ctx->isNamespace() && !Ctx->isTranslationUnit())) {
+ CodeCompletionDeclConsumer Consumer(Results, CurContext);
+ LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer,
+ /*IncludeGlobalScope=*/true,
+ /*IncludeDependentBases=*/true);
+ }
+
+ auto CC = Results.getCompletionContext();
+ CC.setCXXScopeSpecifier(SS);
+
+ HandleCodeCompleteResults(this, CodeCompleter, CC, Results.data(),
+ Results.size());
}
void Sema::CodeCompleteUsing(Scope *S) {
@@ -6630,7 +6671,7 @@ typedef llvm::DenseMap<
/// indexed by selector so they can be easily found.
static void FindImplementableMethods(ASTContext &Context,
ObjCContainerDecl *Container,
- bool WantInstanceMethods,
+ Optional<bool> WantInstanceMethods,
QualType ReturnType,
KnownMethodsMap &KnownMethods,
bool InOriginalClass = true) {
@@ -6701,7 +6742,7 @@ static void FindImplementableMethods(ASTContext &Context,
// we want the methods from this container to override any methods
// we've previously seen with the same selector.
for (auto *M : Container->methods()) {
- if (M->isInstanceMethod() == WantInstanceMethods) {
+ if (!WantInstanceMethods || M->isInstanceMethod() == *WantInstanceMethods) {
if (!ReturnType.isNull() &&
!Context.hasSameUnqualifiedType(ReturnType, M->getReturnType()))
continue;
@@ -7373,8 +7414,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
}
}
-void Sema::CodeCompleteObjCMethodDecl(Scope *S,
- bool IsInstanceMethod,
+void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
ParsedType ReturnTy) {
// Determine the return type of the method we're declaring, if
// provided.
@@ -7429,7 +7469,13 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
ObjCMethodDecl *Method = M->second.getPointer();
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
-
+
+ // Add the '-'/'+' prefix if it wasn't provided yet.
+ if (!IsInstanceMethod) {
+ Builder.AddTextChunk(Method->isInstanceMethod() ? "-" : "+");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ }
+
// If the result type was not already provided, add it to the
// pattern as (type).
if (ReturnType.isNull()) {
@@ -7531,11 +7577,13 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
if (IFace)
for (auto *Cat : IFace->visible_categories())
Containers.push_back(Cat);
-
- for (unsigned I = 0, N = Containers.size(); I != N; ++I)
- for (auto *P : Containers[I]->instance_properties())
- AddObjCKeyValueCompletions(P, IsInstanceMethod, ReturnType, Context,
- KnownSelectors, Results);
+
+ if (IsInstanceMethod) {
+ for (unsigned I = 0, N = Containers.size(); I != N; ++I)
+ for (auto *P : Containers[I]->instance_properties())
+ AddObjCKeyValueCompletions(P, *IsInstanceMethod, ReturnType, Context,
+ KnownSelectors, Results);
+ }
}
Results.ExitScope();
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCoroutine.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCoroutine.cpp
index dc7d8e4e9cec3..e6b640f878c2b 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCoroutine.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCoroutine.cpp
@@ -363,6 +363,32 @@ static ExprResult buildMemberCall(Sema &S, Expr *Base, SourceLocation Loc,
return S.ActOnCallExpr(nullptr, Result.get(), Loc, Args, Loc, nullptr);
}
+// See if return type is coroutine-handle and if so, invoke builtin coro-resume
+// on its address. This is to enable experimental support for coroutine-handle
+// returning await_suspend that results in a guranteed tail call to the target
+// coroutine.
+static Expr *maybeTailCall(Sema &S, QualType RetType, Expr *E,
+ SourceLocation Loc) {
+ if (RetType->isReferenceType())
+ return nullptr;
+ Type const *T = RetType.getTypePtr();
+ if (!T->isClassType() && !T->isStructureType())
+ return nullptr;
+
+ // FIXME: Add convertability check to coroutine_handle<>. Possibly via
+ // EvaluateBinaryTypeTrait(BTT_IsConvertible, ...) which is at the moment
+ // a private function in SemaExprCXX.cpp
+
+ ExprResult AddressExpr = buildMemberCall(S, E, Loc, "address", None);
+ if (AddressExpr.isInvalid())
+ return nullptr;
+
+ Expr *JustAddress = AddressExpr.get();
+ // FIXME: Check that the type of AddressExpr is void*
+ return buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_resume,
+ JustAddress);
+}
+
/// Build calls to await_ready, await_suspend, and await_resume for a co_await
/// expression.
static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, VarDecl *CoroPromise,
@@ -412,16 +438,21 @@ static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, VarDecl *CoroPromise,
// - await-suspend is the expression e.await_suspend(h), which shall be
// a prvalue of type void or bool.
QualType RetType = AwaitSuspend->getCallReturnType(S.Context);
- // non-class prvalues always have cv-unqualified types
- QualType AdjRetType = RetType.getUnqualifiedType();
- if (RetType->isReferenceType() ||
- (AdjRetType != S.Context.BoolTy && AdjRetType != S.Context.VoidTy)) {
- S.Diag(AwaitSuspend->getCalleeDecl()->getLocation(),
- diag::err_await_suspend_invalid_return_type)
- << RetType;
- S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)
- << AwaitSuspend->getDirectCallee();
- Calls.IsInvalid = true;
+
+ // Experimental support for coroutine_handle returning await_suspend.
+ if (Expr *TailCallSuspend = maybeTailCall(S, RetType, AwaitSuspend, Loc))
+ Calls.Results[ACT::ACT_Suspend] = TailCallSuspend;
+ else {
+ // non-class prvalues always have cv-unqualified types
+ if (RetType->isReferenceType() ||
+ (!RetType->isBooleanType() && !RetType->isVoidType())) {
+ S.Diag(AwaitSuspend->getCalleeDecl()->getLocation(),
+ diag::err_await_suspend_invalid_return_type)
+ << RetType;
+ S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)
+ << AwaitSuspend->getDirectCallee();
+ Calls.IsInvalid = true;
+ }
}
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
index 59c10128f9087..ec5ca69735683 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
@@ -132,6 +132,7 @@ bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const {
case tok::kw_half:
case tok::kw_float:
case tok::kw_double:
+ case tok::kw__Float16:
case tok::kw___float128:
case tok::kw_wchar_t:
case tok::kw_bool:
@@ -280,7 +281,7 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
IdentifierInfo **CorrectedII) {
// FIXME: Consider allowing this outside C++1z mode as an extension.
bool AllowDeducedTemplate = IsClassTemplateDeductionContext &&
- getLangOpts().CPlusPlus1z && !IsCtorOrDtorName &&
+ getLangOpts().CPlusPlus17 && !IsCtorOrDtorName &&
!isClassName && !HasTrailingDot;
// Determine where we will perform name lookup.
@@ -1447,6 +1448,46 @@ void Sema::FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S,
F.done();
}
+/// We've determined that \p New is a redeclaration of \p Old. Check that they
+/// have compatible owning modules.
+bool Sema::CheckRedeclarationModuleOwnership(NamedDecl *New, NamedDecl *Old) {
+ // FIXME: The Modules TS is not clear about how friend declarations are
+ // to be treated. It's not meaningful to have different owning modules for
+ // linkage in redeclarations of the same entity, so for now allow the
+ // redeclaration and change the owning modules to match.
+ if (New->getFriendObjectKind() &&
+ Old->getOwningModuleForLinkage() != New->getOwningModuleForLinkage()) {
+ New->setLocalOwningModule(Old->getOwningModule());
+ makeMergedDefinitionVisible(New);
+ return false;
+ }
+
+ Module *NewM = New->getOwningModule();
+ Module *OldM = Old->getOwningModule();
+ if (NewM == OldM)
+ return false;
+
+ // FIXME: Check proclaimed-ownership-declarations here too.
+ bool NewIsModuleInterface = NewM && NewM->Kind == Module::ModuleInterfaceUnit;
+ bool OldIsModuleInterface = OldM && OldM->Kind == Module::ModuleInterfaceUnit;
+ if (NewIsModuleInterface || OldIsModuleInterface) {
+ // C++ Modules TS [basic.def.odr] 6.2/6.7 [sic]:
+ // if a declaration of D [...] appears in the purview of a module, all
+ // other such declarations shall appear in the purview of the same module
+ Diag(New->getLocation(), diag::err_mismatched_owning_module)
+ << New
+ << NewIsModuleInterface
+ << (NewIsModuleInterface ? NewM->getFullModuleName() : "")
+ << OldIsModuleInterface
+ << (OldIsModuleInterface ? OldM->getFullModuleName() : "");
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+ New->setInvalidDecl();
+ return true;
+ }
+
+ return false;
+}
+
static bool isUsingDecl(NamedDecl *D) {
return isa<UsingShadowDecl>(D) ||
isa<UnresolvedUsingTypenameDecl>(D) ||
@@ -1682,7 +1723,8 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
dyn_cast<CXXConstructExpr>(Init);
if (Construct && !Construct->isElidable()) {
CXXConstructorDecl *CD = Construct->getConstructor();
- if (!CD->isTrivial() && !RD->hasAttr<WarnUnusedAttr>())
+ if (!CD->isTrivial() && !RD->hasAttr<WarnUnusedAttr>() &&
+ (VD->getInit()->isValueDependent() || !VD->evaluateValue()))
return false;
}
}
@@ -2623,6 +2665,16 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
}
}
+ // This redeclaration adds a section attribute.
+ if (New->hasAttr<SectionAttr>() && !Old->hasAttr<SectionAttr>()) {
+ if (auto *VD = dyn_cast<VarDecl>(New)) {
+ if (VD->isThisDeclarationADefinition() == VarDecl::DeclarationOnly) {
+ Diag(New->getLocation(), diag::warn_attribute_section_on_redeclaration);
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+ }
+ }
+ }
+
if (!Old->hasAttrs())
return;
@@ -2951,6 +3003,9 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
New->dropAttr<InternalLinkageAttr>();
}
+ if (CheckRedeclarationModuleOwnership(New, Old))
+ return true;
+
if (!getLangOpts().CPlusPlus) {
bool OldOvl = Old->hasAttr<OverloadableAttr>();
if (OldOvl != New->hasAttr<OverloadableAttr>() && !Old->isImplicit()) {
@@ -3526,8 +3581,6 @@ void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod,
ni = newMethod->param_begin(), ne = newMethod->param_end();
ni != ne && oi != oe; ++ni, ++oi)
mergeParamDeclAttributes(*ni, *oi, *this);
-
- CheckObjCMethodOverride(newMethod, oldMethod);
}
static void diagnoseVarDeclTypeMismatch(Sema &S, VarDecl *New, VarDecl* Old) {
@@ -3820,6 +3873,9 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
return New->setInvalidDecl();
}
+ if (CheckRedeclarationModuleOwnership(New, Old))
+ return;
+
// Variables with external linkage are analyzed in FinalizeDeclaratorGroup.
// FIXME: The test for external storage here seems wrong? We still
@@ -3843,7 +3899,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
}
}
- // If this redeclaration makes the function inline, we may need to add it to
+ // If this redeclaration makes the variable inline, we may need to add it to
// UndefinedButUsed.
if (!Old->isInline() && New->isInline() && Old->isUsed(false) &&
!Old->getDefinition() && !New->isThisDeclarationADefinition())
@@ -4143,7 +4199,7 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
if (DS.isInlineSpecified())
Diag(DS.getInlineSpecLoc(), diag::err_inline_non_function)
- << getLangOpts().CPlusPlus1z;
+ << getLangOpts().CPlusPlus17;
if (DS.isConstexprSpecified()) {
// C++0x [dcl.constexpr]p1: constexpr can only be applied to declarations
@@ -4157,14 +4213,6 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
return TagD;
}
- if (DS.isConceptSpecified()) {
- // C++ Concepts TS [dcl.spec.concept]p1: A concept definition refers to
- // either a function concept and its definition or a variable concept and
- // its initializer.
- Diag(DS.getConceptSpecLoc(), diag::err_concept_wrong_decl_kind);
- return TagD;
- }
-
DiagnoseFunctionSpecifiers(DS);
if (DS.isFriendSpecified()) {
@@ -4371,7 +4419,7 @@ static bool CheckAnonMemberRedeclaration(Sema &SemaRef,
SourceLocation NameLoc,
bool IsUnion) {
LookupResult R(SemaRef, Name, NameLoc, Sema::LookupMemberName,
- Sema::ForRedeclaration);
+ Sema::ForVisibleRedeclaration);
if (!SemaRef.LookupName(R, S)) return false;
// Pick a representative declaration.
@@ -5305,19 +5353,12 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
QualType R = TInfo->getType();
- if (!R->isFunctionType() && DiagnoseClassNameShadow(DC, NameInfo))
- // If this is a typedef, we'll end up spewing multiple diagnostics.
- // Just return early; it's safer. If this is a function, let the
- // "constructor cannot have a return type" diagnostic handle it.
- if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
- return nullptr;
-
if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo,
UPPC_DeclarationType))
D.setInvalidType();
LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
- ForRedeclaration);
+ forRedeclarationInCurContext());
// See if this is a redefinition of a variable in the same scope.
if (!D.getCXXScopeSpec().isSet()) {
@@ -5343,8 +5384,10 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static)
CreateBuiltins = true;
- if (IsLinkageLookup)
+ if (IsLinkageLookup) {
Previous.clear(LookupRedeclarationWithLinkage);
+ Previous.setRedeclarationKind(ForExternalRedeclaration);
+ }
LookupName(Previous, S, CreateBuiltins);
} else { // Something like "int foo::x;"
@@ -5390,12 +5433,17 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
Previous.clear();
}
+ if (!R->isFunctionType() && DiagnoseClassNameShadow(DC, NameInfo))
+ // Forget that the previous declaration is the injected-class-name.
+ Previous.clear();
+
// In C++, the previous declaration we find might be a tag type
// (class or enum). In this case, the new declaration will hide the
- // tag type. Note that this does does not apply if we're declaring a
- // typedef (C++ [dcl.typedef]p4).
+ // tag type. Note that this applies to functions, function templates, and
+ // variables, but not to typedefs (C++ [dcl.typedef]p4) or variable templates.
if (Previous.isSingleTagDecl() &&
- D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef)
+ D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
+ (TemplateParamLists.size() == 0 || R->isFunctionType()))
Previous.clear();
// Check that there are no default arguments other than in the parameters
@@ -5403,23 +5451,6 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
if (getLangOpts().CPlusPlus)
CheckExtraCXXDefaultArguments(D);
- if (D.getDeclSpec().isConceptSpecified()) {
- // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be
- // applied only to the definition of a function template or variable
- // template, declared in namespace scope
- if (!TemplateParamLists.size()) {
- Diag(D.getDeclSpec().getConceptSpecLoc(),
- diag:: err_concept_wrong_decl_kind);
- return nullptr;
- }
-
- if (!DC->getRedeclContext()->isFileContext()) {
- Diag(D.getIdentifierLoc(),
- diag::err_concept_decls_may_only_appear_in_namespace_scope);
- return nullptr;
- }
- }
-
NamedDecl *New;
bool AddToScope = true;
@@ -5634,13 +5665,10 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (D.getDeclSpec().isInlineSpecified())
Diag(D.getDeclSpec().getInlineSpecLoc(), diag::err_inline_non_function)
- << getLangOpts().CPlusPlus1z;
+ << getLangOpts().CPlusPlus17;
if (D.getDeclSpec().isConstexprSpecified())
Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr)
<< 1;
- if (D.getDeclSpec().isConceptSpecified())
- Diag(D.getDeclSpec().getConceptSpecLoc(),
- diag::err_concept_wrong_decl_kind);
if (D.getName().Kind != UnqualifiedId::IK_Identifier) {
if (D.getName().Kind == UnqualifiedId::IK_DeductionGuideName)
@@ -5919,7 +5947,7 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
NamedDecl *NewDecl,
bool IsSpecialization,
bool IsDefinition) {
- if (OldDecl->isInvalidDecl())
+ if (OldDecl->isInvalidDecl() || NewDecl->isInvalidDecl())
return;
bool IsTemplate = false;
@@ -6025,13 +6053,30 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
NewDecl->dropAttr<DLLImportAttr>();
}
} else if (IsInline && OldImportAttr && !IsMicrosoft) {
- // In MinGW, seeing a function declared inline drops the dllimport attribute.
+ // In MinGW, seeing a function declared inline drops the dllimport
+ // attribute.
OldDecl->dropAttr<DLLImportAttr>();
NewDecl->dropAttr<DLLImportAttr>();
S.Diag(NewDecl->getLocation(),
diag::warn_dllimport_dropped_from_inline_function)
<< NewDecl << OldImportAttr;
}
+
+ // A specialization of a class template member function is processed here
+ // since it's a redeclaration. If the parent class is dllexport, the
+ // specialization inherits that attribute. This doesn't happen automatically
+ // since the parent class isn't instantiated until later.
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewDecl)) {
+ if (MD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization &&
+ !NewImportAttr && !NewExportAttr) {
+ if (const DLLExportAttr *ParentExportAttr =
+ MD->getParent()->getAttr<DLLExportAttr>()) {
+ DLLExportAttr *NewAttr = ParentExportAttr->clone(S.Context);
+ NewAttr->setInherited(true);
+ NewDecl->addAttr(NewAttr);
+ }
+ }
+ }
}
/// Given that we are within the definition of the given function,
@@ -6253,7 +6298,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
// The event type cannot be used with the __local, __constant and __global
// address space qualifiers.
if (R->isEventT()) {
- if (R.getAddressSpace()) {
+ if (R.getAddressSpace() != LangAS::opencl_private) {
Diag(D.getLocStart(), diag::err_event_t_addr_space_qual);
D.setInvalidType();
}
@@ -6289,7 +6334,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
// Suppress the warning in system macros, it's used in macros in some
// popular C system headers, such as in glibc's htonl() macro.
Diag(D.getDeclSpec().getStorageClassSpecLoc(),
- getLangOpts().CPlusPlus1z ? diag::ext_register_storage_class
+ getLangOpts().CPlusPlus17 ? diag::ext_register_storage_class
: diag::warn_deprecated_register)
<< FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
}
@@ -6477,49 +6522,9 @@ NamedDecl *Sema::ActOnVariableDeclarator(
// C++1z [dcl.spec.constexpr]p1:
// A static data member declared with the constexpr specifier is
// implicitly an inline variable.
- if (NewVD->isStaticDataMember() && getLangOpts().CPlusPlus1z)
+ if (NewVD->isStaticDataMember() && getLangOpts().CPlusPlus17)
NewVD->setImplicitlyInline();
}
-
- if (D.getDeclSpec().isConceptSpecified()) {
- if (VarTemplateDecl *VTD = NewVD->getDescribedVarTemplate())
- VTD->setConcept();
-
- // C++ Concepts TS [dcl.spec.concept]p2: A concept definition shall not
- // be declared with the thread_local, inline, friend, or constexpr
- // specifiers, [...]
- if (D.getDeclSpec().getThreadStorageClassSpec() == TSCS_thread_local) {
- Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
- diag::err_concept_decl_invalid_specifiers)
- << 0 << 0;
- NewVD->setInvalidDecl(true);
- }
-
- if (D.getDeclSpec().isConstexprSpecified()) {
- Diag(D.getDeclSpec().getConstexprSpecLoc(),
- diag::err_concept_decl_invalid_specifiers)
- << 0 << 3;
- NewVD->setInvalidDecl(true);
- }
-
- // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be
- // applied only to the definition of a function template or variable
- // template, declared in namespace scope.
- if (IsVariableTemplateSpecialization) {
- Diag(D.getDeclSpec().getConceptSpecLoc(),
- diag::err_concept_specified_specialization)
- << (IsPartialSpecialization ? 2 : 1);
- }
-
- // C++ Concepts TS [dcl.spec.concept]p6: A variable concept has the
- // following restrictions:
- // - The declared type shall have the type bool.
- if (!Context.hasSameType(NewVD->getType(), Context.BoolTy) &&
- !NewVD->isInvalidDecl()) {
- Diag(D.getIdentifierLoc(), diag::err_variable_concept_bool_decl);
- NewVD->setInvalidDecl(true);
- }
- }
}
if (D.getDeclSpec().isInlineSpecified()) {
@@ -6533,7 +6538,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
<< FixItHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc());
} else {
Diag(D.getDeclSpec().getInlineSpecLoc(),
- getLangOpts().CPlusPlus1z ? diag::warn_cxx14_compat_inline_variable
+ getLangOpts().CPlusPlus17 ? diag::warn_cxx14_compat_inline_variable
: diag::ext_inline_variable);
NewVD->setInlineSpecified();
}
@@ -6770,25 +6775,6 @@ NamedDecl *Sema::ActOnVariableDeclarator(
if (!IsVariableTemplateSpecialization)
D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous));
- // C++ Concepts TS [dcl.spec.concept]p7: A program shall not declare [...]
- // an explicit specialization (14.8.3) or a partial specialization of a
- // concept definition.
- if (IsVariableTemplateSpecialization &&
- !D.getDeclSpec().isConceptSpecified() && !Previous.empty() &&
- Previous.isSingleResult()) {
- NamedDecl *PreviousDecl = Previous.getFoundDecl();
- if (VarTemplateDecl *VarTmpl = dyn_cast<VarTemplateDecl>(PreviousDecl)) {
- if (VarTmpl->isConcept()) {
- Diag(NewVD->getLocation(), diag::err_concept_specialized)
- << 1 /*variable*/
- << (IsPartialSpecialization ? 2 /*partially specialized*/
- : 1 /*explicitly specialized*/);
- Diag(VarTmpl->getLocation(), diag::note_previous_declaration);
- NewVD->setInvalidDecl();
- }
- }
- }
-
if (NewTemplate) {
VarTemplateDecl *PrevVarTemplate =
NewVD->getPreviousDecl()
@@ -7087,7 +7073,7 @@ void Sema::CheckShadow(Scope *S, VarDecl *D) {
return;
LookupResult R(*this, D->getDeclName(), D->getLocation(),
- Sema::LookupOrdinaryName, Sema::ForRedeclaration);
+ Sema::LookupOrdinaryName, Sema::ForVisibleRedeclaration);
LookupName(R, S);
if (NamedDecl *ShadowedDecl = getShadowedDeclaration(D, R))
CheckShadow(D, ShadowedDecl, R);
@@ -7260,8 +7246,8 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
// This includes arrays of objects with address space qualifiers, but not
// automatic variables that point to other address spaces.
// ISO/IEC TR 18037 S5.1.2
- if (!getLangOpts().OpenCL
- && NewVD->hasLocalStorage() && T.getAddressSpace() != 0) {
+ if (!getLangOpts().OpenCL && NewVD->hasLocalStorage() &&
+ T.getAddressSpace() != LangAS::Default) {
Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl) << 0;
NewVD->setInvalidDecl();
return;
@@ -7356,7 +7342,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
return;
}
}
- } else if (T.getAddressSpace() != LangAS::Default) {
+ } else if (T.getAddressSpace() != LangAS::opencl_private) {
// Do not allow other address spaces on automatic variable.
Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl) << 1;
NewVD->setInvalidDecl();
@@ -7531,16 +7517,14 @@ enum OverrideErrorKind { OEK_All, OEK_NonDeleted, OEK_Deleted };
static void ReportOverrides(Sema& S, unsigned DiagID, const CXXMethodDecl *MD,
OverrideErrorKind OEK = OEK_All) {
S.Diag(MD->getLocation(), DiagID) << MD->getDeclName();
- for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
- E = MD->end_overridden_methods();
- I != E; ++I) {
+ for (const CXXMethodDecl *O : MD->overridden_methods()) {
// This check (& the OEK parameter) could be replaced by a predicate, but
// without lambdas that would be overkill. This is still nicer than writing
// out the diag loop 3 times.
if ((OEK == OEK_All) ||
- (OEK == OEK_NonDeleted && !(*I)->isDeleted()) ||
- (OEK == OEK_Deleted && (*I)->isDeleted()))
- S.Diag((*I)->getLocation(), diag::note_overridden_virtual_function);
+ (OEK == OEK_NonDeleted && !O->isDeleted()) ||
+ (OEK == OEK_Deleted && O->isDeleted()))
+ S.Diag(O->getLocation(), diag::note_overridden_virtual_function);
}
}
@@ -7663,7 +7647,7 @@ static NamedDecl *DiagnoseInvalidRedeclaration(
LookupResult Prev(SemaRef, Name, NewFD->getLocation(),
IsLocalFriend ? Sema::LookupLocalFriendName
: Sema::LookupOrdinaryName,
- Sema::ForRedeclaration);
+ Sema::ForVisibleRedeclaration);
NewFD->setInvalidDecl();
if (IsLocalFriend)
@@ -7991,7 +7975,8 @@ static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) {
if (PointeeType->isPointerType())
return PtrPtrKernelParam;
if (PointeeType.getAddressSpace() == LangAS::opencl_generic ||
- PointeeType.getAddressSpace() == 0)
+ PointeeType.getAddressSpace() == LangAS::opencl_private ||
+ PointeeType.getAddressSpace() == LangAS::Default)
return InvalidAddrSpacePtrKernelParam;
return PtrKernelParam;
}
@@ -8241,7 +8226,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
bool isVirtual = D.getDeclSpec().isVirtualSpecified();
bool isExplicit = D.getDeclSpec().isExplicitSpecified();
bool isConstexpr = D.getDeclSpec().isConstexprSpecified();
- bool isConcept = D.getDeclSpec().isConceptSpecified();
isFriend = D.getDeclSpec().isFriendSpecified();
if (isFriend && !isInline && D.isFunctionDefinition()) {
// C++ [class.friend]p5
@@ -8453,89 +8437,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_constexpr_dtor);
}
- if (isConcept) {
- // This is a function concept.
- if (FunctionTemplateDecl *FTD = NewFD->getDescribedFunctionTemplate())
- FTD->setConcept();
-
- // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be
- // applied only to the definition of a function template [...]
- if (!D.isFunctionDefinition()) {
- Diag(D.getDeclSpec().getConceptSpecLoc(),
- diag::err_function_concept_not_defined);
- NewFD->setInvalidDecl();
- }
-
- // C++ Concepts TS [dcl.spec.concept]p1: [...] A function concept shall
- // have no exception-specification and is treated as if it were specified
- // with noexcept(true) (15.4). [...]
- if (const FunctionProtoType *FPT = R->getAs<FunctionProtoType>()) {
- if (FPT->hasExceptionSpec()) {
- SourceRange Range;
- if (D.isFunctionDeclarator())
- Range = D.getFunctionTypeInfo().getExceptionSpecRange();
- Diag(NewFD->getLocation(), diag::err_function_concept_exception_spec)
- << FixItHint::CreateRemoval(Range);
- NewFD->setInvalidDecl();
- } else {
- Context.adjustExceptionSpec(NewFD, EST_BasicNoexcept);
- }
-
- // C++ Concepts TS [dcl.spec.concept]p5: A function concept has the
- // following restrictions:
- // - The declared return type shall have the type bool.
- if (!Context.hasSameType(FPT->getReturnType(), Context.BoolTy)) {
- Diag(D.getIdentifierLoc(), diag::err_function_concept_bool_ret);
- NewFD->setInvalidDecl();
- }
-
- // C++ Concepts TS [dcl.spec.concept]p5: A function concept has the
- // following restrictions:
- // - The declaration's parameter list shall be equivalent to an empty
- // parameter list.
- if (FPT->getNumParams() > 0 || FPT->isVariadic())
- Diag(NewFD->getLocation(), diag::err_function_concept_with_params);
- }
-
- // C++ Concepts TS [dcl.spec.concept]p2: Every concept definition is
- // implicity defined to be a constexpr declaration (implicitly inline)
- NewFD->setImplicitlyInline();
-
- // C++ Concepts TS [dcl.spec.concept]p2: A concept definition shall not
- // be declared with the thread_local, inline, friend, or constexpr
- // specifiers, [...]
- if (isInline) {
- Diag(D.getDeclSpec().getInlineSpecLoc(),
- diag::err_concept_decl_invalid_specifiers)
- << 1 << 1;
- NewFD->setInvalidDecl(true);
- }
-
- if (isFriend) {
- Diag(D.getDeclSpec().getFriendSpecLoc(),
- diag::err_concept_decl_invalid_specifiers)
- << 1 << 2;
- NewFD->setInvalidDecl(true);
- }
-
- if (isConstexpr) {
- Diag(D.getDeclSpec().getConstexprSpecLoc(),
- diag::err_concept_decl_invalid_specifiers)
- << 1 << 3;
- NewFD->setInvalidDecl(true);
- }
-
- // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be
- // applied only to the definition of a function template or variable
- // template, declared in namespace scope.
- if (isFunctionTemplateSpecialization) {
- Diag(D.getDeclSpec().getConceptSpecLoc(),
- diag::err_concept_specified_specialization) << 1;
- NewFD->setInvalidDecl(true);
- return NewFD;
- }
- }
-
// If __module_private__ was specified, mark the function accordingly.
if (D.getDeclSpec().isModulePrivateSpecified()) {
if (isFunctionTemplateSpecialization) {
@@ -8760,10 +8661,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (getLangOpts().OpenCL) {
// OpenCL v1.1 s6.5: Using an address space qualifier in a function return
// type declaration will generate a compilation error.
- unsigned AddressSpace = NewFD->getReturnType().getAddressSpace();
- if (AddressSpace == LangAS::opencl_local ||
- AddressSpace == LangAS::opencl_global ||
- AddressSpace == LangAS::opencl_constant) {
+ LangAS AddressSpace = NewFD->getReturnType().getAddressSpace();
+ if (AddressSpace != LangAS::Default) {
Diag(NewFD->getLocation(),
diag::err_opencl_return_value_with_address_space);
NewFD->setInvalidDecl();
@@ -8890,10 +8789,10 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
diag::ext_function_specialization_in_class :
diag::err_function_specialization_in_class)
<< NewFD->getDeclName();
- } else if (CheckFunctionTemplateSpecialization(NewFD,
- (HasExplicitTemplateArgs ? &TemplateArgs
- : nullptr),
- Previous))
+ } else if (!NewFD->isInvalidDecl() &&
+ CheckFunctionTemplateSpecialization(
+ NewFD, (HasExplicitTemplateArgs ? &TemplateArgs : nullptr),
+ Previous))
NewFD->setInvalidDecl();
// C++ [dcl.stc]p1:
@@ -9529,7 +9428,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
// return type. (Exception specifications on the function itself are OK in
// most cases, and exception specifications are not permitted in most other
// contexts where they could make it into a mangling.)
- if (!getLangOpts().CPlusPlus1z && !NewFD->getPrimaryTemplate()) {
+ if (!getLangOpts().CPlusPlus17 && !NewFD->getPrimaryTemplate()) {
auto HasNoexcept = [&](QualType T) -> bool {
// Strip off declarator chunks that could be between us and a function
// type. We don't need to look far, exception specifications are very
@@ -9552,7 +9451,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
AnyNoexcept |= HasNoexcept(T);
if (AnyNoexcept)
Diag(NewFD->getLocation(),
- diag::warn_cxx1z_compat_exception_spec_in_signature)
+ diag::warn_cxx17_compat_exception_spec_in_signature)
<< NewFD;
}
@@ -9601,6 +9500,13 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) {
assert(T->isFunctionType() && "function decl is not of function type");
const FunctionType* FT = T->castAs<FunctionType>();
+ // Set default calling convention for main()
+ if (FT->getCallConv() != CC_C) {
+ FT = Context.adjustFunctionType(FT, FT->getExtInfo().withCallingConv(CC_C));
+ FD->setType(QualType(FT, 0));
+ T = Context.getCanonicalType(FD->getType());
+ }
+
if (getLangOpts().GNUMode && !getLangOpts().CPlusPlus) {
// In C with GNU extensions we allow main() to have non-integer return
// type, but we should warn about the extension, and we disable the
@@ -10000,14 +9906,9 @@ namespace {
void VisitCallExpr(CallExpr *E) {
// Treat std::move as a use.
- if (E->getNumArgs() == 1) {
- if (FunctionDecl *FD = E->getDirectCallee()) {
- if (FD->isInStdNamespace() && FD->getIdentifier() &&
- FD->getIdentifier()->isStr("move")) {
- HandleValue(E->getArg(0));
- return;
- }
- }
+ if (E->isCallToStdMove()) {
+ HandleValue(E->getArg(0));
+ return;
}
Inherited::VisitCallExpr(E);
@@ -10737,7 +10638,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
if (Var->isStaticDataMember()) {
// C++1z removes the relevant rule; the in-class declaration is always
// a definition there.
- if (!getLangOpts().CPlusPlus1z) {
+ if (!getLangOpts().CPlusPlus17) {
Diag(Var->getLocation(),
diag::err_constexpr_static_mem_var_requires_init)
<< Var->getDeclName();
@@ -10751,17 +10652,6 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
}
}
- // C++ Concepts TS [dcl.spec.concept]p1: [...] A variable template
- // definition having the concept specifier is called a variable concept. A
- // concept definition refers to [...] a variable concept and its initializer.
- if (VarTemplateDecl *VTD = Var->getDescribedVarTemplate()) {
- if (VTD->isConcept()) {
- Diag(Var->getLocation(), diag::err_var_concept_not_initialized);
- Var->setInvalidDecl();
- return;
- }
- }
-
// OpenCL v1.1 s6.5.3: variables declared in the constant address space must
// be initialized.
if (!Var->isInvalidDecl() &&
@@ -11651,6 +11541,14 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
StorageClass SC = SC_None;
if (DS.getStorageClassSpec() == DeclSpec::SCS_register) {
SC = SC_Register;
+ // In C++11, the 'register' storage class specifier is deprecated.
+ // In C++17, it is not allowed, but we tolerate it as an extension.
+ if (getLangOpts().CPlusPlus11) {
+ Diag(DS.getStorageClassSpecLoc(),
+ getLangOpts().CPlusPlus17 ? diag::ext_register_storage_class
+ : diag::warn_deprecated_register)
+ << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc());
+ }
} else if (getLangOpts().CPlusPlus &&
DS.getStorageClassSpec() == DeclSpec::SCS_auto) {
SC = SC_Auto;
@@ -11665,12 +11563,10 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
<< DeclSpec::getSpecifierName(TSCS);
if (DS.isInlineSpecified())
Diag(DS.getInlineSpecLoc(), diag::err_inline_non_function)
- << getLangOpts().CPlusPlus1z;
+ << getLangOpts().CPlusPlus17;
if (DS.isConstexprSpecified())
Diag(DS.getConstexprSpecLoc(), diag::err_invalid_constexpr)
<< 0;
- if (DS.isConceptSpecified())
- Diag(DS.getConceptSpecLoc(), diag::err_concept_wrong_decl_kind);
DiagnoseFunctionSpecifiers(DS);
@@ -11704,7 +11600,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
// Check for redeclaration of parameters, e.g. int foo(int x, int x);
if (II) {
LookupResult R(*this, II, D.getIdentifierLoc(), LookupOrdinaryName,
- ForRedeclaration);
+ ForVisibleRedeclaration);
LookupName(R, S);
if (R.isSingleResult()) {
NamedDecl *PrevDecl = R.getFoundDecl();
@@ -11873,13 +11769,13 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc,
// duration shall not be qualified by an address-space qualifier."
// Since all parameters have automatic store duration, they can not have
// an address space.
- if (T.getAddressSpace() != 0) {
- // OpenCL allows function arguments declared to be an array of a type
- // to be qualified with an address space.
- if (!(getLangOpts().OpenCL && T->isArrayType())) {
- Diag(NameLoc, diag::err_arg_with_address_space);
- New->setInvalidDecl();
- }
+ if (T.getAddressSpace() != LangAS::Default &&
+ // OpenCL allows function arguments declared to be an array of a type
+ // to be qualified with an address space.
+ !(getLangOpts().OpenCL &&
+ (T->isArrayType() || T.getAddressSpace() == LangAS::opencl_private))) {
+ Diag(NameLoc, diag::err_arg_with_address_space);
+ New->setInvalidDecl();
}
return New;
@@ -12346,18 +12242,6 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
}
}
- // The only way to be included in UndefinedButUsed is if there is an
- // ODR use before the definition. Avoid the expensive map lookup if this
- // is the first declaration.
- if (!FD->isFirstDecl() && FD->getPreviousDecl()->isUsed()) {
- if (!FD->isExternallyVisible())
- UndefinedButUsed.erase(FD);
- else if (FD->isInlined() &&
- !LangOpts.GNUInline &&
- (!FD->getPreviousDecl()->hasAttr<GNUInlineAttr>()))
- UndefinedButUsed.erase(FD);
- }
-
// If the function implicitly returns zero (like 'main') or is naked,
// don't complain about missing return statements.
if (FD->hasImplicitReturnZero() || FD->hasAttr<NakedAttr>())
@@ -12621,28 +12505,50 @@ void Sema::ActOnFinishDelayedAttribute(Scope *S, Decl *D,
/// call, forming a call to an implicitly defined function (per C99 6.5.1p2).
NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
IdentifierInfo &II, Scope *S) {
+ Scope *BlockScope = S;
+ while (!BlockScope->isCompoundStmtScope() && BlockScope->getParent())
+ BlockScope = BlockScope->getParent();
+
// Before we produce a declaration for an implicitly defined
// function, see whether there was a locally-scoped declaration of
// this name as a function or variable. If so, use that
// (non-visible) declaration, and complain about it.
- if (NamedDecl *ExternCPrev = findLocallyScopedExternCDecl(&II)) {
- Diag(Loc, diag::warn_use_out_of_scope_declaration) << ExternCPrev;
- Diag(ExternCPrev->getLocation(), diag::note_previous_declaration);
- return ExternCPrev;
+ NamedDecl *ExternCPrev = findLocallyScopedExternCDecl(&II);
+ if (ExternCPrev) {
+ // We still need to inject the function into the enclosing block scope so
+ // that later (non-call) uses can see it.
+ PushOnScopeChains(ExternCPrev, BlockScope, /*AddToContext*/false);
+
+ // C89 footnote 38:
+ // If in fact it is not defined as having type "function returning int",
+ // the behavior is undefined.
+ if (!isa<FunctionDecl>(ExternCPrev) ||
+ !Context.typesAreCompatible(
+ cast<FunctionDecl>(ExternCPrev)->getType(),
+ Context.getFunctionNoProtoType(Context.IntTy))) {
+ Diag(Loc, diag::ext_use_out_of_scope_declaration)
+ << ExternCPrev << !getLangOpts().C99;
+ Diag(ExternCPrev->getLocation(), diag::note_previous_declaration);
+ return ExternCPrev;
+ }
}
// Extension in C99. Legal in C90, but warn about it.
+ // OpenCL v2.0 s6.9.u - Implicit function declaration is not supported.
unsigned diag_id;
if (II.getName().startswith("__builtin_"))
diag_id = diag::warn_builtin_unknown;
- // OpenCL v2.0 s6.9.u - Implicit function declaration is not supported.
- else if (getLangOpts().OpenCL)
- diag_id = diag::err_opencl_implicit_function_decl;
- else if (getLangOpts().C99)
+ else if (getLangOpts().C99 || getLangOpts().OpenCL)
diag_id = diag::ext_implicit_function_decl;
else
diag_id = diag::warn_implicit_function_decl;
- Diag(Loc, diag_id) << &II;
+ Diag(Loc, diag_id) << &II << getLangOpts().OpenCL;
+
+ // If we found a prior declaration of this function, don't bother building
+ // another one. We've already pushed that one into scope, so there's nothing
+ // more to do.
+ if (ExternCPrev)
+ return ExternCPrev;
// Because typo correction is expensive, only do it if the implicit
// function declaration is going to be treated as an error.
@@ -12694,16 +12600,10 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
SourceLocation());
D.SetIdentifier(&II, Loc);
- // Insert this function into translation-unit scope.
-
- DeclContext *PrevDC = CurContext;
- CurContext = Context.getTranslationUnitDecl();
-
- FunctionDecl *FD = cast<FunctionDecl>(ActOnDeclarator(TUScope, D));
+ // Insert this function into the enclosing block scope.
+ FunctionDecl *FD = cast<FunctionDecl>(ActOnDeclarator(BlockScope, D));
FD->setImplicit();
- CurContext = PrevDC;
-
AddKnownFunctionAttributes(FD);
return FD;
@@ -12752,15 +12652,33 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
FD->getLocation()));
}
- // Mark const if we don't care about errno and that is the only
- // thing preventing the function from being const. This allows
- // IRgen to use LLVM intrinsics for such functions.
- if (!getLangOpts().MathErrno &&
- Context.BuiltinInfo.isConstWithoutErrno(BuiltinID)) {
- if (!FD->hasAttr<ConstAttr>())
+ // Mark const if we don't care about errno and that is the only thing
+ // preventing the function from being const. This allows IRgen to use LLVM
+ // intrinsics for such functions.
+ if (!getLangOpts().MathErrno && !FD->hasAttr<ConstAttr>() &&
+ Context.BuiltinInfo.isConstWithoutErrno(BuiltinID))
+ FD->addAttr(ConstAttr::CreateImplicit(Context, FD->getLocation()));
+
+ // We make "fma" on GNU or Windows const because we know it does not set
+ // errno in those environments even though it could set errno based on the
+ // C standard.
+ const llvm::Triple &Trip = Context.getTargetInfo().getTriple();
+ if ((Trip.isGNUEnvironment() || Trip.isOSMSVCRT()) &&
+ !FD->hasAttr<ConstAttr>()) {
+ switch (BuiltinID) {
+ case Builtin::BI__builtin_fma:
+ case Builtin::BI__builtin_fmaf:
+ case Builtin::BI__builtin_fmal:
+ case Builtin::BIfma:
+ case Builtin::BIfmaf:
+ case Builtin::BIfmal:
FD->addAttr(ConstAttr::CreateImplicit(Context, FD->getLocation()));
+ break;
+ default:
+ break;
+ }
}
-
+
if (Context.BuiltinInfo.isReturnsTwice(BuiltinID) &&
!FD->hasAttr<ReturnsTwiceAttr>())
FD->addAttr(ReturnsTwiceAttr::CreateImplicit(Context,
@@ -13260,7 +13178,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
bool isStdBadAlloc = false;
bool isStdAlignValT = false;
- RedeclarationKind Redecl = ForRedeclaration;
+ RedeclarationKind Redecl = forRedeclarationInCurContext();
if (TUK == TUK_Friend || TUK == TUK_Reference)
Redecl = NotForRedeclaration;
@@ -13538,10 +13456,10 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// type declared by an elaborated-type-specifier. In C that is not correct
// and we should instead merge compatible types found by lookup.
if (getLangOpts().CPlusPlus) {
- Previous.setRedeclarationKind(ForRedeclaration);
+ Previous.setRedeclarationKind(forRedeclarationInCurContext());
LookupQualifiedName(Previous, SearchDC);
} else {
- Previous.setRedeclarationKind(ForRedeclaration);
+ Previous.setRedeclarationKind(forRedeclarationInCurContext());
LookupName(Previous, S);
}
}
@@ -13941,6 +13859,13 @@ CreateNewDecl:
Invalid = true;
}
+ if (!Invalid && getLangOpts().CPlusPlus && TUK == TUK_Definition &&
+ DC->getDeclKind() == Decl::Enum) {
+ Diag(New->getLocation(), diag::err_type_defined_in_enum)
+ << Context.getTagDeclType(New);
+ Invalid = true;
+ }
+
// Maybe add qualifier info.
if (SS.isNotEmpty()) {
if (SS.isSet()) {
@@ -14032,6 +13957,9 @@ CreateNewDecl:
if (!Invalid && SearchDC->isRecord())
SetMemberAccessSpecifier(New, PrevDecl, AS);
+ if (PrevDecl)
+ CheckRedeclarationModuleOwnership(New, PrevDecl);
+
if (TUK == TUK_Definition)
New->startDefinition();
@@ -14358,7 +14286,9 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,
}
// TR 18037 does not allow fields to be declared with address spaces.
- if (T.getQualifiers().hasAddressSpace()) {
+ if (T.getQualifiers().hasAddressSpace() ||
+ T->isDependentAddressSpaceType() ||
+ T->getBaseElementTypeUnsafe()->isDependentAddressSpaceType()) {
Diag(Loc, diag::err_field_with_address_space);
D.setInvalidType();
}
@@ -14375,7 +14305,7 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,
if (D.getDeclSpec().isInlineSpecified())
Diag(D.getDeclSpec().getInlineSpecLoc(), diag::err_inline_non_function)
- << getLangOpts().CPlusPlus1z;
+ << getLangOpts().CPlusPlus17;
if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec())
Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
diag::err_invalid_thread)
@@ -14383,7 +14313,8 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,
// Check to see if this name was declared as a member previously
NamedDecl *PrevDecl = nullptr;
- LookupResult Previous(*this, II, Loc, LookupMemberName, ForRedeclaration);
+ LookupResult Previous(*this, II, Loc, LookupMemberName,
+ ForVisibleRedeclaration);
LookupName(Previous, S);
switch (Previous.getResultKind()) {
case LookupResult::Found:
@@ -14771,7 +14702,7 @@ Decl *Sema::ActOnIvar(Scope *S,
if (II) {
NamedDecl *PrevDecl = LookupSingleName(S, II, Loc, LookupMemberName,
- ForRedeclaration);
+ ForVisibleRedeclaration);
if (PrevDecl && isDeclInScope(PrevDecl, EnclosingContext, S)
&& !isa<TagDecl>(PrevDecl)) {
Diag(Loc, diag::err_duplicate_member) << II;
@@ -14913,6 +14844,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
// possibly recursively, a member that is such a structure)
// shall not be a member of a structure or an element of an
// array.
+ bool IsLastField = (i + 1 == Fields.end());
if (FDTy->isFunctionType()) {
// Field declared as a function.
Diag(FD->getLocation(), diag::err_field_declared_as_function)
@@ -14920,60 +14852,70 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
FD->setInvalidDecl();
EnclosingDecl->setInvalidDecl();
continue;
- } else if (FDTy->isIncompleteArrayType() && Record &&
- ((i + 1 == Fields.end() && !Record->isUnion()) ||
- ((getLangOpts().MicrosoftExt ||
- getLangOpts().CPlusPlus) &&
- (i + 1 == Fields.end() || Record->isUnion())))) {
- // Flexible array member.
- // Microsoft and g++ is more permissive regarding flexible array.
- // It will accept flexible array in union and also
- // as the sole element of a struct/class.
- unsigned DiagID = 0;
- if (Record->isUnion())
- DiagID = getLangOpts().MicrosoftExt
- ? diag::ext_flexible_array_union_ms
- : getLangOpts().CPlusPlus
- ? diag::ext_flexible_array_union_gnu
- : diag::err_flexible_array_union;
- else if (NumNamedMembers < 1)
- DiagID = getLangOpts().MicrosoftExt
- ? diag::ext_flexible_array_empty_aggregate_ms
- : getLangOpts().CPlusPlus
- ? diag::ext_flexible_array_empty_aggregate_gnu
- : diag::err_flexible_array_empty_aggregate;
+ } else if (FDTy->isIncompleteArrayType() &&
+ (Record || isa<ObjCContainerDecl>(EnclosingDecl))) {
+ if (Record) {
+ // Flexible array member.
+ // Microsoft and g++ is more permissive regarding flexible array.
+ // It will accept flexible array in union and also
+ // as the sole element of a struct/class.
+ unsigned DiagID = 0;
+ if (!Record->isUnion() && !IsLastField) {
+ Diag(FD->getLocation(), diag::err_flexible_array_not_at_end)
+ << FD->getDeclName() << FD->getType() << Record->getTagKind();
+ Diag((*(i + 1))->getLocation(), diag::note_next_field_declaration);
+ FD->setInvalidDecl();
+ EnclosingDecl->setInvalidDecl();
+ continue;
+ } else if (Record->isUnion())
+ DiagID = getLangOpts().MicrosoftExt
+ ? diag::ext_flexible_array_union_ms
+ : getLangOpts().CPlusPlus
+ ? diag::ext_flexible_array_union_gnu
+ : diag::err_flexible_array_union;
+ else if (NumNamedMembers < 1)
+ DiagID = getLangOpts().MicrosoftExt
+ ? diag::ext_flexible_array_empty_aggregate_ms
+ : getLangOpts().CPlusPlus
+ ? diag::ext_flexible_array_empty_aggregate_gnu
+ : diag::err_flexible_array_empty_aggregate;
- if (DiagID)
- Diag(FD->getLocation(), DiagID) << FD->getDeclName()
- << Record->getTagKind();
- // While the layout of types that contain virtual bases is not specified
- // by the C++ standard, both the Itanium and Microsoft C++ ABIs place
- // virtual bases after the derived members. This would make a flexible
- // array member declared at the end of an object not adjacent to the end
- // of the type.
- if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Record))
- if (RD->getNumVBases() != 0)
- Diag(FD->getLocation(), diag::err_flexible_array_virtual_base)
+ if (DiagID)
+ Diag(FD->getLocation(), DiagID) << FD->getDeclName()
+ << Record->getTagKind();
+ // While the layout of types that contain virtual bases is not specified
+ // by the C++ standard, both the Itanium and Microsoft C++ ABIs place
+ // virtual bases after the derived members. This would make a flexible
+ // array member declared at the end of an object not adjacent to the end
+ // of the type.
+ if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Record))
+ if (RD->getNumVBases() != 0)
+ Diag(FD->getLocation(), diag::err_flexible_array_virtual_base)
+ << FD->getDeclName() << Record->getTagKind();
+ if (!getLangOpts().C99)
+ Diag(FD->getLocation(), diag::ext_c99_flexible_array_member)
<< FD->getDeclName() << Record->getTagKind();
- if (!getLangOpts().C99)
- Diag(FD->getLocation(), diag::ext_c99_flexible_array_member)
- << FD->getDeclName() << Record->getTagKind();
- // If the element type has a non-trivial destructor, we would not
- // implicitly destroy the elements, so disallow it for now.
- //
- // FIXME: GCC allows this. We should probably either implicitly delete
- // the destructor of the containing class, or just allow this.
- QualType BaseElem = Context.getBaseElementType(FD->getType());
- if (!BaseElem->isDependentType() && BaseElem.isDestructedType()) {
- Diag(FD->getLocation(), diag::err_flexible_array_has_nontrivial_dtor)
- << FD->getDeclName() << FD->getType();
- FD->setInvalidDecl();
- EnclosingDecl->setInvalidDecl();
- continue;
+ // If the element type has a non-trivial destructor, we would not
+ // implicitly destroy the elements, so disallow it for now.
+ //
+ // FIXME: GCC allows this. We should probably either implicitly delete
+ // the destructor of the containing class, or just allow this.
+ QualType BaseElem = Context.getBaseElementType(FD->getType());
+ if (!BaseElem->isDependentType() && BaseElem.isDestructedType()) {
+ Diag(FD->getLocation(), diag::err_flexible_array_has_nontrivial_dtor)
+ << FD->getDeclName() << FD->getType();
+ FD->setInvalidDecl();
+ EnclosingDecl->setInvalidDecl();
+ continue;
+ }
+ // Okay, we have a legal flexible array member at the end of the struct.
+ Record->setHasFlexibleArrayMember(true);
+ } else {
+ // In ObjCContainerDecl ivars with incomplete array type are accepted,
+ // unless they are followed by another ivar. That check is done
+ // elsewhere, after synthesized ivars are known.
}
- // Okay, we have a legal flexible array member at the end of the struct.
- Record->setHasFlexibleArrayMember(true);
} else if (!FDTy->isDependentType() &&
RequireCompleteType(FD->getLocation(), FD->getType(),
diag::err_field_incomplete)) {
@@ -14990,7 +14932,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
// If this is a struct/class and this is not the last element, reject
// it. Note that GCC supports variable sized arrays in the middle of
// structures.
- if (i + 1 != Fields.end())
+ if (!IsLastField)
Diag(FD->getLocation(), diag::ext_variable_sized_type_in_struct)
<< FD->getDeclName() << FD->getType();
else {
@@ -15137,8 +15079,10 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(Record)) {
auto *Dtor = CXXRecord->getDestructor();
if (Dtor && Dtor->isImplicit() &&
- ShouldDeleteSpecialMember(Dtor, CXXDestructor))
+ ShouldDeleteSpecialMember(Dtor, CXXDestructor)) {
+ CXXRecord->setImplicitDestructorIsDeleted();
SetDeclDeleted(Dtor, CXXRecord->getLocation());
+ }
}
if (Record->hasAttrs()) {
@@ -15271,7 +15215,8 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
static bool isRepresentableIntegerValue(ASTContext &Context,
llvm::APSInt &Value,
QualType T) {
- assert(T->isIntegralType(Context) && "Integral type required!");
+ assert((T->isIntegralType(Context) || T->isEnumeralType()) &&
+ "Integral type required!");
unsigned BitWidth = Context.getIntWidth(T);
if (Value.isUnsigned() || Value.isNonNegative()) {
@@ -15287,7 +15232,8 @@ static bool isRepresentableIntegerValue(ASTContext &Context,
static QualType getNextLargerIntegralType(ASTContext &Context, QualType T) {
// FIXME: Int128/UInt128 support, which also needs to be introduced into
// enum checking below.
- assert(T->isIntegralType(Context) && "Integral type required!");
+ assert((T->isIntegralType(Context) ||
+ T->isEnumeralType()) && "Integral type required!");
const unsigned NumTypes = 4;
QualType SignedIntegralTypes[NumTypes] = {
Context.ShortTy, Context.IntTy, Context.LongTy, Context.LongLongTy
@@ -15326,7 +15272,6 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
if (Enum->isDependentType() || Val->isTypeDependent())
EltTy = Context.DependentTy;
else {
- SourceLocation ExpLoc;
if (getLangOpts().CPlusPlus11 && Enum->isFixed() &&
!getLangOpts().MSVCCompat) {
// C++11 [dcl.enum]p5: If the underlying type is fixed, [...] the
@@ -15491,7 +15436,7 @@ Sema::SkipBodyInfo Sema::shouldSkipAnonEnumBody(Scope *S, IdentifierInfo *II,
// determine if we should merge the definition with an existing one and
// skip the body.
NamedDecl *PrevDecl = LookupSingleName(S, II, IILoc, LookupOrdinaryName,
- ForRedeclaration);
+ forRedeclarationInCurContext());
auto *PrevECD = dyn_cast_or_null<EnumConstantDecl>(PrevDecl);
if (!PrevECD)
return SkipBodyInfo();
@@ -15522,7 +15467,7 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
// Verify that there isn't already something declared with this name in this
// scope.
NamedDecl *PrevDecl = LookupSingleName(S, Id, IdLoc, LookupOrdinaryName,
- ForRedeclaration);
+ ForVisibleRedeclaration);
if (PrevDecl && PrevDecl->isTemplateParameter()) {
// Maybe we will complain about the shadowed template parameter.
DiagnoseTemplateParameterShadow(IdLoc, PrevDecl);
@@ -15549,8 +15494,7 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
// enum constant will 'hide' the tag.
assert((getLangOpts().CPlusPlus || !isa<TagDecl>(PrevDecl)) &&
"Received TagDecl when not in C++!");
- if (!isa<TagDecl>(PrevDecl) && isDeclInScope(PrevDecl, CurContext, S) &&
- shouldLinkPossiblyHiddenDecl(PrevDecl, New)) {
+ if (!isa<TagDecl>(PrevDecl) && isDeclInScope(PrevDecl, CurContext, S)) {
if (isa<EnumConstantDecl>(PrevDecl))
Diag(IdLoc, diag::err_redefinition_of_enumerator) << Id;
else
@@ -16043,7 +15987,7 @@ static void checkModuleImportContext(Sema &S, Module *M,
DC = LSD->getParent();
}
- while (isa<LinkageSpecDecl>(DC))
+ while (isa<LinkageSpecDecl>(DC) || isa<ExportDecl>(DC))
DC = DC->getParent();
if (!isa<TranslationUnitDecl>(DC)) {
@@ -16064,6 +16008,9 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc,
SourceLocation ModuleLoc,
ModuleDeclKind MDK,
ModuleIdPath Path) {
+ assert(getLangOpts().ModulesTS &&
+ "should only have module decl in modules TS");
+
// A module implementation unit requires that we are not compiling a module
// of any kind. A module interface unit requires that we are not compiling a
// module map.
@@ -16080,6 +16027,7 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc,
// implementation unit. That indicates the 'export' is missing.
Diag(ModuleLoc, diag::err_module_interface_implementation_mismatch)
<< FixItHint::CreateInsertion(ModuleLoc, "export ");
+ MDK = ModuleDeclKind::Interface;
break;
case LangOptions::CMK_ModuleMap:
@@ -16087,9 +16035,19 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc,
return nullptr;
}
+ assert(ModuleScopes.size() == 1 && "expected to be at global module scope");
+
// FIXME: Most of this work should be done by the preprocessor rather than
// here, in order to support macro import.
+ // Only one module-declaration is permitted per source file.
+ if (ModuleScopes.back().Module->Kind == Module::ModuleInterfaceUnit) {
+ Diag(ModuleLoc, diag::err_module_redeclaration);
+ Diag(VisibleModules.getImportLoc(ModuleScopes.back().Module),
+ diag::note_prev_module_declaration);
+ return nullptr;
+ }
+
// Flatten the dots in a module name. Unlike Clang's hierarchical module map
// modules, the dots here are just another character that can appear in a
// module name.
@@ -16100,8 +16058,6 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc,
ModuleName += Piece.first->getName();
}
- // FIXME: If we've already seen a module-declaration, report an error.
-
// If a module name was explicitly specified on the command line, it must be
// correct.
if (!getLangOpts().CurrentModule.empty() &&
@@ -16117,9 +16073,7 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc,
Module *Mod;
switch (MDK) {
- case ModuleDeclKind::Module: {
- // FIXME: Check we're not in a submodule.
-
+ case ModuleDeclKind::Interface: {
// We can't have parsed or imported a definition of this module or parsed a
// module map defining it already.
if (auto *M = Map.findModule(ModuleName)) {
@@ -16129,11 +16083,13 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc,
else if (const auto *FE = M->getASTFile())
Diag(M->DefinitionLoc, diag::note_prev_module_definition_from_ast_file)
<< FE->getName();
- return nullptr;
+ Mod = M;
+ break;
}
// Create a Module for the module that we're defining.
- Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName);
+ Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName,
+ ModuleScopes.front().Module);
assert(Mod && "module creation should not fail");
break;
}
@@ -16147,21 +16103,26 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc,
PP.getIdentifierInfo(ModuleName), Path[0].second);
Mod = getModuleLoader().loadModule(ModuleLoc, Path, Module::AllVisible,
/*IsIncludeDirective=*/false);
- if (!Mod)
- return nullptr;
+ if (!Mod) {
+ Diag(ModuleLoc, diag::err_module_not_defined) << ModuleName;
+ // Create an empty module interface unit for error recovery.
+ Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName,
+ ModuleScopes.front().Module);
+ }
break;
}
- // Enter the semantic scope of the module.
- ModuleScopes.push_back({});
+ // Switch from the global module to the named module.
ModuleScopes.back().Module = Mod;
- ModuleScopes.back().OuterVisibleModules = std::move(VisibleModules);
+ ModuleScopes.back().ModuleInterface = MDK != ModuleDeclKind::Implementation;
VisibleModules.setVisible(Mod, ModuleLoc);
// From now on, we have an owning module for all declarations we see.
// However, those declarations are module-private unless explicitly
// exported.
- Context.getTranslationUnitDecl()->setLocalOwningModule(Mod);
+ auto *TU = Context.getTranslationUnitDecl();
+ TU->setModuleOwnershipKind(Decl::ModuleOwnershipKind::ModulePrivate);
+ TU->setLocalOwningModule(Mod);
// FIXME: Create a ModuleDecl.
return nullptr;
@@ -16204,12 +16165,17 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc,
IdentifierLocs.push_back(Path[I].second);
}
- TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl();
- ImportDecl *Import = ImportDecl::Create(Context, TU, StartLoc,
+ ImportDecl *Import = ImportDecl::Create(Context, CurContext, StartLoc,
Mod, IdentifierLocs);
if (!ModuleScopes.empty())
Context.addModuleInitializer(ModuleScopes.back().Module, Import);
- TU->addDecl(Import);
+ CurContext->addDecl(Import);
+
+ // Re-export the module if needed.
+ if (Import->isExported() &&
+ !ModuleScopes.empty() && ModuleScopes.back().ModuleInterface)
+ getCurrentModule()->Exports.emplace_back(Mod, false);
+
return Import;
}
@@ -16339,8 +16305,7 @@ Decl *Sema::ActOnStartExportDecl(Scope *S, SourceLocation ExportLoc,
// C++ Modules TS draft:
// An export-declaration shall appear in the purview of a module other than
// the global module.
- if (ModuleScopes.empty() || !ModuleScopes.back().Module ||
- ModuleScopes.back().Module->Kind != Module::ModuleInterfaceUnit)
+ if (ModuleScopes.empty() || !ModuleScopes.back().ModuleInterface)
Diag(ExportLoc, diag::err_export_not_in_module_interface);
// An export-declaration [...] shall not contain more than one
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
index 2a310bf41c703..676d00357c960 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
@@ -540,14 +540,13 @@ static bool isCapabilityExpr(Sema &S, const Expr *Ex) {
// a DeclRefExpr is found, its type should be checked to determine whether it
// is a capability or not.
- if (const auto *E = dyn_cast<DeclRefExpr>(Ex))
- return typeHasCapability(S, E->getType());
- else if (const auto *E = dyn_cast<CastExpr>(Ex))
+ if (const auto *E = dyn_cast<CastExpr>(Ex))
return isCapabilityExpr(S, E->getSubExpr());
else if (const auto *E = dyn_cast<ParenExpr>(Ex))
return isCapabilityExpr(S, E->getSubExpr());
else if (const auto *E = dyn_cast<UnaryOperator>(Ex)) {
- if (E->getOpcode() == UO_LNot)
+ if (E->getOpcode() == UO_LNot || E->getOpcode() == UO_AddrOf ||
+ E->getOpcode() == UO_Deref)
return isCapabilityExpr(S, E->getSubExpr());
return false;
} else if (const auto *E = dyn_cast<BinaryOperator>(Ex)) {
@@ -557,7 +556,7 @@ static bool isCapabilityExpr(Sema &S, const Expr *Ex) {
return false;
}
- return false;
+ return typeHasCapability(S, Ex->getType());
}
/// \brief Checks that all attribute arguments, starting from Sidx, resolve to
@@ -1304,14 +1303,28 @@ static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
TD->addAttr(::new (S.Context) PackedAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
- // Report warning about changed offset in the newer compiler versions.
- if (!FD->getType()->isDependentType() &&
- !FD->getType()->isIncompleteType() && FD->isBitField() &&
- S.Context.getTypeAlign(FD->getType()) <= 8)
- S.Diag(Attr.getLoc(), diag::warn_attribute_packed_for_bitfield);
+ bool BitfieldByteAligned = (!FD->getType()->isDependentType() &&
+ !FD->getType()->isIncompleteType() &&
+ FD->isBitField() &&
+ S.Context.getTypeAlign(FD->getType()) <= 8);
+
+ if (S.getASTContext().getTargetInfo().getTriple().isPS4()) {
+ if (BitfieldByteAligned)
+ // The PS4 target needs to maintain ABI backwards compatibility.
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type)
+ << Attr.getName() << FD->getType();
+ else
+ FD->addAttr(::new (S.Context) PackedAttr(
+ Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ } else {
+ // Report warning about changed offset in the newer compiler versions.
+ if (BitfieldByteAligned)
+ S.Diag(Attr.getLoc(), diag::warn_attribute_packed_for_bitfield);
+
+ FD->addAttr(::new (S.Context) PackedAttr(
+ Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ }
- FD->addAttr(::new (S.Context) PackedAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
} else
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
}
@@ -1517,6 +1530,22 @@ static void handleReturnsNonNullAttr(Sema &S, Decl *D,
Attr.getAttributeSpellingListIndex()));
}
+static void handleNoEscapeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ if (D->isInvalidDecl())
+ return;
+
+ // noescape only applies to pointer types.
+ QualType T = cast<ParmVarDecl>(D)->getType();
+ if (!S.isValidPointerAttrType(T, /* RefOkay */ true)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_pointers_only)
+ << Attr.getName() << Attr.getRange() << 0;
+ return;
+ }
+
+ D->addAttr(::new (S.Context) NoEscapeAttr(
+ Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+}
+
static void handleAssumeAlignedAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
Expr *E = Attr.getArgAsExpr(0),
@@ -1939,20 +1968,20 @@ static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
Attr.getAttributeSpellingListIndex()));
}
-static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &attr) {
+static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &Attrs) {
if (hasDeclarator(D)) return;
- if (S.CheckNoReturnAttr(attr))
+ if (S.CheckNoReturnAttr(Attrs))
return;
if (!isa<ObjCMethodDecl>(D)) {
- S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << attr.getName() << ExpectedFunctionOrMethod;
+ S.Diag(Attrs.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attrs.getName() << ExpectedFunctionOrMethod;
return;
}
D->addAttr(::new (S.Context) NoReturnAttr(
- attr.getRange(), S.Context, attr.getAttributeSpellingListIndex()));
+ Attrs.getRange(), S.Context, Attrs.getAttributeSpellingListIndex()));
}
static void handleNoCallerSavedRegsAttr(Sema &S, Decl *D,
@@ -1964,9 +1993,9 @@ static void handleNoCallerSavedRegsAttr(Sema &S, Decl *D,
Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
}
-bool Sema::CheckNoReturnAttr(const AttributeList &attr) {
- if (!checkAttributeNumArgs(*this, attr, 0)) {
- attr.setInvalid();
+bool Sema::CheckNoReturnAttr(const AttributeList &Attrs) {
+ if (!checkAttributeNumArgs(*this, Attrs, 0)) {
+ Attrs.setInvalid();
return true;
}
@@ -2122,10 +2151,10 @@ static void handleUsedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
static void handleUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- bool IsCXX1zAttr = Attr.isCXX11Attribute() && !Attr.getScopeName();
+ bool IsCXX17Attr = Attr.isCXX11Attribute() && !Attr.getScopeName();
- if (IsCXX1zAttr && isa<VarDecl>(D)) {
- // The C++1z spelling of this attribute cannot be applied to a static data
+ if (IsCXX17Attr && isa<VarDecl>(D)) {
+ // The C++17 spelling of this attribute cannot be applied to a static data
// member per [dcl.attr.unused]p2.
if (cast<VarDecl>(D)->isStaticDataMember()) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
@@ -2134,10 +2163,10 @@ static void handleUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
}
- // If this is spelled as the standard C++1z attribute, but not in C++1z, warn
+ // If this is spelled as the standard C++17 attribute, but not in C++17, warn
// about using it as an extension.
- if (!S.getLangOpts().CPlusPlus1z && IsCXX1zAttr)
- S.Diag(Attr.getLoc(), diag::ext_cxx1z_attr) << Attr.getName();
+ if (!S.getLangOpts().CPlusPlus17 && IsCXX17Attr)
+ S.Diag(Attr.getLoc(), diag::ext_cxx17_attr) << Attr.getName();
D->addAttr(::new (S.Context) UnusedAttr(
Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
@@ -2831,11 +2860,11 @@ static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr)
return;
}
- // If this is spelled as the standard C++1z attribute, but not in C++1z, warn
+ // If this is spelled as the standard C++17 attribute, but not in C++17, warn
// about using it as an extension.
- if (!S.getLangOpts().CPlusPlus1z && Attr.isCXX11Attribute() &&
+ if (!S.getLangOpts().CPlusPlus17 && Attr.isCXX11Attribute() &&
!Attr.getScopeName())
- S.Diag(Attr.getLoc(), diag::ext_cxx1z_attr) << Attr.getName();
+ S.Diag(Attr.getLoc(), diag::ext_cxx17_attr) << Attr.getName();
D->addAttr(::new (S.Context)
WarnUnusedResultAttr(Attr.getRange(), S.Context,
@@ -2993,22 +3022,43 @@ static void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) {
D->addAttr(NewAttr);
}
-// Check for things we'd like to warn about, no errors or validation for now.
-// TODO: Validation should use a backend target library that specifies
-// the allowable subtarget features and cpus. We could use something like a
-// TargetCodeGenInfo hook here to do validation.
-void Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) {
+// Check for things we'd like to warn about. Multiversioning issues are
+// handled later in the process, once we know how many exist.
+bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) {
+ enum FirstParam { Unsupported, Duplicate };
+ enum SecondParam { None, Architecture };
for (auto Str : {"tune=", "fpmath="})
if (AttrStr.find(Str) != StringRef::npos)
- Diag(LiteralLoc, diag::warn_unsupported_target_attribute) << Str;
+ return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
+ << Unsupported << None << Str;
+
+ TargetAttr::ParsedTargetAttr ParsedAttrs = TargetAttr::parse(AttrStr);
+
+ if (!ParsedAttrs.Architecture.empty() &&
+ !Context.getTargetInfo().isValidCPUName(ParsedAttrs.Architecture))
+ return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
+ << Unsupported << Architecture << ParsedAttrs.Architecture;
+
+ if (ParsedAttrs.DuplicateArchitecture)
+ return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
+ << Duplicate << None << "arch=";
+
+ for (const auto &Feature : ParsedAttrs.Features) {
+ auto CurFeature = StringRef(Feature).drop_front(); // remove + or -.
+ if (!Context.getTargetInfo().isValidFeatureName(CurFeature))
+ return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
+ << Unsupported << None << CurFeature;
+ }
+
+ return true;
}
static void handleTargetAttr(Sema &S, Decl *D, const AttributeList &Attr) {
StringRef Str;
SourceLocation LiteralLoc;
- if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &LiteralLoc))
+ if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &LiteralLoc) ||
+ !S.checkTargetAttr(LiteralLoc, Str))
return;
- S.checkTargetAttr(LiteralLoc, Str);
unsigned Index = Attr.getAttributeSpellingListIndex();
TargetAttr *NewAttr =
::new (S.Context) TargetAttr(Attr.getRange(), S.Context, Str, Index);
@@ -3016,12 +3066,6 @@ static void handleTargetAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- VarDecl *VD = cast<VarDecl>(D);
- if (!VD->hasLocalStorage()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
- return;
- }
-
Expr *E = Attr.getArgAsExpr(0);
SourceLocation Loc = E->getExprLoc();
FunctionDecl *FD = nullptr;
@@ -3064,7 +3108,7 @@ static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// We're currently more strict than GCC about what function types we accept.
// If this ever proves to be a problem it should be easy to fix.
- QualType Ty = S.Context.getPointerType(VD->getType());
+ QualType Ty = S.Context.getPointerType(cast<VarDecl>(D)->getType());
QualType ParamTy = FD->getParamDecl(0)->getType();
if (S.CheckAssignmentConstraints(FD->getParamDecl(0)->getLocation(),
ParamTy, Ty) != Sema::Compatible) {
@@ -4252,24 +4296,24 @@ static void handleSuppressAttr(Sema &S, Decl *D, const AttributeList &Attr) {
DiagnosticIdentifiers.size(), Attr.getAttributeSpellingListIndex()));
}
-bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,
+bool Sema::CheckCallingConvAttr(const AttributeList &Attrs, CallingConv &CC,
const FunctionDecl *FD) {
- if (attr.isInvalid())
+ if (Attrs.isInvalid())
return true;
- if (attr.hasProcessingCache()) {
- CC = (CallingConv) attr.getProcessingCache();
+ if (Attrs.hasProcessingCache()) {
+ CC = (CallingConv) Attrs.getProcessingCache();
return false;
}
- unsigned ReqArgs = attr.getKind() == AttributeList::AT_Pcs ? 1 : 0;
- if (!checkAttributeNumArgs(*this, attr, ReqArgs)) {
- attr.setInvalid();
+ unsigned ReqArgs = Attrs.getKind() == AttributeList::AT_Pcs ? 1 : 0;
+ if (!checkAttributeNumArgs(*this, Attrs, ReqArgs)) {
+ Attrs.setInvalid();
return true;
}
// TODO: diagnose uses of these conventions on the wrong target.
- switch (attr.getKind()) {
+ switch (Attrs.getKind()) {
case AttributeList::AT_CDecl: CC = CC_C; break;
case AttributeList::AT_FastCall: CC = CC_X86FastCall; break;
case AttributeList::AT_StdCall: CC = CC_X86StdCall; break;
@@ -4288,8 +4332,8 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,
break;
case AttributeList::AT_Pcs: {
StringRef StrRef;
- if (!checkStringLiteralArgumentAttr(attr, 0, StrRef)) {
- attr.setInvalid();
+ if (!checkStringLiteralArgumentAttr(Attrs, 0, StrRef)) {
+ Attrs.setInvalid();
return true;
}
if (StrRef == "aapcs") {
@@ -4300,8 +4344,8 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,
break;
}
- attr.setInvalid();
- Diag(attr.getLoc(), diag::err_invalid_pcs);
+ Attrs.setInvalid();
+ Diag(Attrs.getLoc(), diag::err_invalid_pcs);
return true;
}
case AttributeList::AT_IntelOclBicc: CC = CC_IntelOclBicc; break;
@@ -4314,7 +4358,7 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,
TargetInfo::CallingConvCheckResult A = TI.checkCallingConvention(CC);
if (A != TargetInfo::CCCR_OK) {
if (A == TargetInfo::CCCR_Warning)
- Diag(attr.getLoc(), diag::warn_cconv_ignored) << attr.getName();
+ Diag(Attrs.getLoc(), diag::warn_cconv_ignored) << Attrs.getName();
// This convention is not valid for the target. Use the default function or
// method calling convention.
@@ -4326,7 +4370,7 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,
CC = Context.getDefaultCallingConvention(IsVariadic, IsCXXMethod);
}
- attr.setProcessingCache((unsigned) CC);
+ Attrs.setProcessingCache((unsigned) CC);
return false;
}
@@ -4334,7 +4378,7 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,
static bool isValidSwiftContextType(QualType type) {
if (!type->hasPointerRepresentation())
return type->isDependentType();
- return type->getPointeeType().getAddressSpace() == 0;
+ return type->getPointeeType().getAddressSpace() == LangAS::Default;
}
/// Pointers and references in the default address space.
@@ -4346,7 +4390,7 @@ static bool isValidSwiftIndirectResultType(QualType type) {
} else {
return type->isDependentType();
}
- return type.getAddressSpace() == 0;
+ return type.getAddressSpace() == LangAS::Default;
}
/// Pointers and references to pointers in the default address space.
@@ -4363,10 +4407,10 @@ static bool isValidSwiftErrorResultType(QualType type) {
return isValidSwiftContextType(type);
}
-static void handleParameterABIAttr(Sema &S, Decl *D, const AttributeList &attr,
- ParameterABI abi) {
- S.AddParameterABIAttr(attr.getRange(), D, abi,
- attr.getAttributeSpellingListIndex());
+static void handleParameterABIAttr(Sema &S, Decl *D, const AttributeList &Attrs,
+ ParameterABI Abi) {
+ S.AddParameterABIAttr(Attrs.getRange(), D, Abi,
+ Attrs.getAttributeSpellingListIndex());
}
void Sema::AddParameterABIAttr(SourceRange range, Decl *D, ParameterABI abi,
@@ -4807,11 +4851,11 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D,
}
static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D,
- const AttributeList &attr) {
+ const AttributeList &Attrs) {
const int EP_ObjCMethod = 1;
const int EP_ObjCProperty = 2;
- SourceLocation loc = attr.getLoc();
+ SourceLocation loc = Attrs.getLoc();
QualType resultType;
if (isa<ObjCMethodDecl>(D))
resultType = cast<ObjCMethodDecl>(D)->getReturnType();
@@ -4822,7 +4866,7 @@ static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D,
(!resultType->isPointerType() || resultType->isObjCRetainableType())) {
S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_return_type)
<< SourceRange(loc)
- << attr.getName()
+ << Attrs.getName()
<< (isa<ObjCMethodDecl>(D) ? EP_ObjCMethod : EP_ObjCProperty)
<< /*non-retainable pointer*/ 2;
@@ -4831,29 +4875,29 @@ static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D,
}
D->addAttr(::new (S.Context) ObjCReturnsInnerPointerAttr(
- attr.getRange(), S.Context, attr.getAttributeSpellingListIndex()));
+ Attrs.getRange(), S.Context, Attrs.getAttributeSpellingListIndex()));
}
static void handleObjCRequiresSuperAttr(Sema &S, Decl *D,
- const AttributeList &attr) {
+ const AttributeList &Attrs) {
ObjCMethodDecl *method = cast<ObjCMethodDecl>(D);
DeclContext *DC = method->getDeclContext();
if (const ObjCProtocolDecl *PDecl = dyn_cast_or_null<ObjCProtocolDecl>(DC)) {
S.Diag(D->getLocStart(), diag::warn_objc_requires_super_protocol)
- << attr.getName() << 0;
+ << Attrs.getName() << 0;
S.Diag(PDecl->getLocation(), diag::note_protocol_decl);
return;
}
if (method->getMethodFamily() == OMF_dealloc) {
S.Diag(D->getLocStart(), diag::warn_objc_requires_super_protocol)
- << attr.getName() << 1;
+ << Attrs.getName() << 1;
return;
}
method->addAttr(::new (S.Context)
- ObjCRequiresSuperAttr(attr.getRange(), S.Context,
- attr.getAttributeSpellingListIndex()));
+ ObjCRequiresSuperAttr(Attrs.getRange(), S.Context,
+ Attrs.getAttributeSpellingListIndex()));
}
static void handleCFAuditedTransferAttr(Sema &S, Decl *D,
@@ -5665,8 +5709,12 @@ static void handleCapabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) {
static void handleAssertCapabilityAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
+ SmallVector<Expr*, 1> Args;
+ if (!checkLockFunAttrCommon(S, D, Attr, Args))
+ return;
+
D->addAttr(::new (S.Context) AssertCapabilityAttr(Attr.getRange(), S.Context,
- Attr.getArgAsExpr(0),
+ Args.data(), Args.size(),
Attr.getAttributeSpellingListIndex()));
}
@@ -5965,6 +6013,14 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_NoMicroMips:
handleSimpleAttribute<NoMicroMipsAttr>(S, D, Attr);
break;
+ case AttributeList::AT_MipsLongCall:
+ handleSimpleAttributeWithExclusions<MipsLongCallAttr, MipsShortCallAttr>(
+ S, D, Attr);
+ break;
+ case AttributeList::AT_MipsShortCall:
+ handleSimpleAttributeWithExclusions<MipsShortCallAttr, MipsLongCallAttr>(
+ S, D, Attr);
+ break;
case AttributeList::AT_AMDGPUFlatWorkGroupSize:
handleAMDGPUFlatWorkGroupSizeAttr(S, D, Attr);
break;
@@ -6120,6 +6176,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_ReturnsNonNull:
handleReturnsNonNullAttr(S, D, Attr);
break;
+ case AttributeList::AT_NoEscape:
+ handleNoEscapeAttr(S, D, Attr);
+ break;
case AttributeList::AT_AssumeAligned:
handleAssumeAlignedAttr(S, D, Attr);
break;
@@ -7003,6 +7062,49 @@ static NamedDecl *findEnclosingDeclToAnnotate(Decl *OrigCtx) {
return dyn_cast<NamedDecl>(OrigCtx);
}
+namespace {
+
+struct AttributeInsertion {
+ StringRef Prefix;
+ SourceLocation Loc;
+ StringRef Suffix;
+
+ static AttributeInsertion createInsertionAfter(const NamedDecl *D) {
+ return {" ", D->getLocEnd(), ""};
+ }
+ static AttributeInsertion createInsertionAfter(SourceLocation Loc) {
+ return {" ", Loc, ""};
+ }
+ static AttributeInsertion createInsertionBefore(const NamedDecl *D) {
+ return {"", D->getLocStart(), "\n"};
+ }
+};
+
+} // end anonymous namespace
+
+/// Returns a source location in which it's appropriate to insert a new
+/// attribute for the given declaration \D.
+static Optional<AttributeInsertion>
+createAttributeInsertion(const NamedDecl *D, const SourceManager &SM,
+ const LangOptions &LangOpts) {
+ if (isa<ObjCPropertyDecl>(D))
+ return AttributeInsertion::createInsertionAfter(D);
+ if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ if (MD->hasBody())
+ return None;
+ return AttributeInsertion::createInsertionAfter(D);
+ }
+ if (const auto *TD = dyn_cast<TagDecl>(D)) {
+ SourceLocation Loc =
+ Lexer::getLocForEndOfToken(TD->getInnerLocStart(), 0, SM, LangOpts);
+ if (Loc.isInvalid())
+ return None;
+ // Insert after the 'struct'/whatever keyword.
+ return AttributeInsertion::createInsertionAfter(Loc);
+ }
+ return AttributeInsertion::createInsertionBefore(D);
+}
+
/// Actually emit an availability diagnostic for a reference to an unavailable
/// decl.
///
@@ -7038,7 +7140,83 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
if (!ShouldDiagnoseAvailabilityInContext(S, K, DeclVersion, Ctx))
return;
+ // The declaration can have multiple availability attributes, we are looking
+ // at one of them.
+ const AvailabilityAttr *A = getAttrForPlatform(S.Context, OffendingDecl);
+ if (A && A->isInherited()) {
+ for (const Decl *Redecl = OffendingDecl->getMostRecentDecl(); Redecl;
+ Redecl = Redecl->getPreviousDecl()) {
+ const AvailabilityAttr *AForRedecl =
+ getAttrForPlatform(S.Context, Redecl);
+ if (AForRedecl && !AForRedecl->isInherited()) {
+ // If D is a declaration with inherited attributes, the note should
+ // point to the declaration with actual attributes.
+ NoteLocation = Redecl->getLocation();
+ break;
+ }
+ }
+ }
+
switch (K) {
+ case AR_NotYetIntroduced: {
+ // We would like to emit the diagnostic even if -Wunguarded-availability is
+ // not specified for deployment targets >= to iOS 11 or equivalent or
+ // for declarations that were introduced in iOS 11 (macOS 10.13, ...) or
+ // later.
+ const AvailabilityAttr *AA =
+ getAttrForPlatform(S.getASTContext(), OffendingDecl);
+ VersionTuple Introduced = AA->getIntroduced();
+
+ bool UseNewWarning = shouldDiagnoseAvailabilityByDefault(
+ S.Context, S.Context.getTargetInfo().getPlatformMinVersion(),
+ Introduced);
+ unsigned Warning = UseNewWarning ? diag::warn_unguarded_availability_new
+ : diag::warn_unguarded_availability;
+
+ S.Diag(Loc, Warning)
+ << OffendingDecl
+ << AvailabilityAttr::getPrettyPlatformName(
+ S.getASTContext().getTargetInfo().getPlatformName())
+ << Introduced.getAsString();
+
+ S.Diag(OffendingDecl->getLocation(), diag::note_availability_specified_here)
+ << OffendingDecl << /* partial */ 3;
+
+ if (const auto *Enclosing = findEnclosingDeclToAnnotate(Ctx)) {
+ if (auto *TD = dyn_cast<TagDecl>(Enclosing))
+ if (TD->getDeclName().isEmpty()) {
+ S.Diag(TD->getLocation(),
+ diag::note_decl_unguarded_availability_silence)
+ << /*Anonymous*/ 1 << TD->getKindName();
+ return;
+ }
+ auto FixitNoteDiag =
+ S.Diag(Enclosing->getLocation(),
+ diag::note_decl_unguarded_availability_silence)
+ << /*Named*/ 0 << Enclosing;
+ // Don't offer a fixit for declarations with availability attributes.
+ if (Enclosing->hasAttr<AvailabilityAttr>())
+ return;
+ if (!S.getPreprocessor().isMacroDefined("API_AVAILABLE"))
+ return;
+ Optional<AttributeInsertion> Insertion = createAttributeInsertion(
+ Enclosing, S.getSourceManager(), S.getLangOpts());
+ if (!Insertion)
+ return;
+ std::string PlatformName =
+ AvailabilityAttr::getPlatformNameSourceSpelling(
+ S.getASTContext().getTargetInfo().getPlatformName())
+ .lower();
+ std::string Introduced =
+ OffendingDecl->getVersionIntroduced().getAsString();
+ FixitNoteDiag << FixItHint::CreateInsertion(
+ Insertion->Loc,
+ (llvm::Twine(Insertion->Prefix) + "API_AVAILABLE(" + PlatformName +
+ "(" + Introduced + "))" + Insertion->Suffix)
+ .str());
+ }
+ return;
+ }
case AR_Deprecated:
diag = !ObjCPropertyAccess ? diag::warn_deprecated
: diag::warn_property_method_deprecated;
@@ -7046,8 +7224,8 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
diag_fwdclass_message = diag::warn_deprecated_fwdclass_message;
property_note_select = /* deprecated */ 0;
available_here_select_kind = /* deprecated */ 2;
- if (const auto *attr = OffendingDecl->getAttr<DeprecatedAttr>())
- NoteLocation = attr->getLocation();
+ if (const auto *Attr = OffendingDecl->getAttr<DeprecatedAttr>())
+ NoteLocation = Attr->getLocation();
break;
case AR_Unavailable:
@@ -7058,8 +7236,8 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
property_note_select = /* unavailable */ 1;
available_here_select_kind = /* unavailable */ 0;
- if (auto attr = OffendingDecl->getAttr<UnavailableAttr>()) {
- if (attr->isImplicit() && attr->getImplicitReason()) {
+ if (auto Attr = OffendingDecl->getAttr<UnavailableAttr>()) {
+ if (Attr->isImplicit() && Attr->getImplicitReason()) {
// Most of these failures are due to extra restrictions in ARC;
// reflect that in the primary diagnostic when applicable.
auto flagARCError = [&] {
@@ -7069,7 +7247,7 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
diag = diag::err_unavailable_in_arc;
};
- switch (attr->getImplicitReason()) {
+ switch (Attr->getImplicitReason()) {
case UnavailableAttr::IR_None: break;
case UnavailableAttr::IR_ARCForbiddenType:
@@ -7103,28 +7281,6 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
}
break;
- case AR_NotYetIntroduced: {
- // We would like to emit the diagnostic even if -Wunguarded-availability is
- // not specified for deployment targets >= to iOS 11 or equivalent or
- // for declarations that were introduced in iOS 11 (macOS 10.13, ...) or
- // later.
- const AvailabilityAttr *AA =
- getAttrForPlatform(S.getASTContext(), OffendingDecl);
- VersionTuple Introduced = AA->getIntroduced();
- bool NewWarning = shouldDiagnoseAvailabilityByDefault(
- S.Context, S.Context.getTargetInfo().getPlatformMinVersion(),
- Introduced);
- diag = NewWarning ? diag::warn_partial_availability_new
- : diag::warn_partial_availability;
- diag_message = NewWarning ? diag::warn_partial_message_new
- : diag::warn_partial_message;
- diag_fwdclass_message = NewWarning ? diag::warn_partial_fwdclass_message_new
- : diag::warn_partial_fwdclass_message;
- property_note_select = /* partial */ 2;
- available_here_select_kind = /* partial */ 3;
- break;
- }
-
case AR_Available:
llvm_unreachable("Warning for availability of available declaration?");
}
@@ -7132,10 +7288,10 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
CharSourceRange UseRange;
StringRef Replacement;
if (K == AR_Deprecated) {
- if (auto attr = OffendingDecl->getAttr<DeprecatedAttr>())
- Replacement = attr->getReplacement();
- if (auto attr = getAttrForPlatform(S.Context, OffendingDecl))
- Replacement = attr->getReplacement();
+ if (auto Attr = OffendingDecl->getAttr<DeprecatedAttr>())
+ Replacement = Attr->getReplacement();
+ if (auto Attr = getAttrForPlatform(S.Context, OffendingDecl))
+ Replacement = Attr->getReplacement();
if (!Replacement.empty())
UseRange =
@@ -7163,38 +7319,8 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
S.Diag(UnknownObjCClass->getLocation(), diag::note_forward_class);
}
- // The declaration can have multiple availability attributes, we are looking
- // at one of them.
- const AvailabilityAttr *A = getAttrForPlatform(S.Context, OffendingDecl);
- if (A && A->isInherited()) {
- for (const Decl *Redecl = OffendingDecl->getMostRecentDecl(); Redecl;
- Redecl = Redecl->getPreviousDecl()) {
- const AvailabilityAttr *AForRedecl = getAttrForPlatform(S.Context,
- Redecl);
- if (AForRedecl && !AForRedecl->isInherited()) {
- // If D is a declaration with inherited attributes, the note should
- // point to the declaration with actual attributes.
- S.Diag(Redecl->getLocation(), diag_available_here) << OffendingDecl
- << available_here_select_kind;
- break;
- }
- }
- }
- else
- S.Diag(NoteLocation, diag_available_here)
- << OffendingDecl << available_here_select_kind;
-
- if (K == AR_NotYetIntroduced)
- if (const auto *Enclosing = findEnclosingDeclToAnnotate(Ctx)) {
- if (auto *TD = dyn_cast<TagDecl>(Enclosing))
- if (TD->getDeclName().isEmpty()) {
- S.Diag(TD->getLocation(), diag::note_partial_availability_silence)
- << /*Anonymous*/1 << TD->getKindName();
- return;
- }
- S.Diag(Enclosing->getLocation(), diag::note_partial_availability_silence)
- << /*Named*/0 << Enclosing;
- }
+ S.Diag(NoteLocation, diag_available_here)
+ << OffendingDecl << available_here_select_kind;
}
static void handleDelayedAvailabilityCheck(Sema &S, DelayedDiagnostic &DD,
@@ -7399,6 +7525,10 @@ public:
bool TraverseLambdaExpr(LambdaExpr *E) { return true; }
+ // for 'case X:' statements, don't bother looking at the 'X'; it can't lead
+ // to any useful diagnostics.
+ bool TraverseCaseStmt(CaseStmt *CS) { return TraverseStmt(CS->getSubStmt()); }
+
bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *PRE) {
if (PRE->isClassReceiver())
DiagnoseDeclAvailability(PRE->getClassReceiver(), PRE->getReceiverLocation());
@@ -7581,8 +7711,7 @@ bool DiagnoseUnguardedAvailability::TraverseIfStmt(IfStmt *If) {
// If we're using the '*' case here or if this check is redundant, then we
// use the enclosing version to check both branches.
if (CondVersion.empty() || CondVersion <= AvailabilityStack.back())
- return Base::TraverseStmt(If->getThen()) &&
- Base::TraverseStmt(If->getElse());
+ return TraverseStmt(If->getThen()) && TraverseStmt(If->getElse());
} else {
// This isn't an availability checking 'if', we can just continue.
return Base::TraverseIfStmt(If);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
index 48f698cfe71e3..96472a0a70fe7 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
@@ -143,7 +143,7 @@ namespace {
if (Lambda->capture_begin() == Lambda->capture_end())
return false;
- return S->Diag(Lambda->getLocStart(),
+ return S->Diag(Lambda->getLocStart(),
diag::err_lambda_capture_default_arg);
}
}
@@ -167,6 +167,9 @@ Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc,
if (ComputedEST == EST_None)
return;
+ if (EST == EST_None && Method->hasAttr<NoThrowAttr>())
+ EST = EST_BasicNoexcept;
+
switch(EST) {
// If this function can throw any exceptions, make a note of that.
case EST_MSAny:
@@ -276,18 +279,18 @@ Sema::SetParamDefaultArgument(ParmVarDecl *Param, Expr *Arg,
// Okay: add the default argument to the parameter
Param->setDefaultArg(Arg);
- // We have already instantiated this parameter; provide each of the
+ // We have already instantiated this parameter; provide each of the
// instantiations with the uninstantiated default argument.
UnparsedDefaultArgInstantiationsMap::iterator InstPos
= UnparsedDefaultArgInstantiations.find(Param);
if (InstPos != UnparsedDefaultArgInstantiations.end()) {
for (unsigned I = 0, N = InstPos->second.size(); I != N; ++I)
InstPos->second[I]->setUninstantiatedDefaultArg(Arg);
-
+
// We're done tracking this parameter's instantiations.
UnparsedDefaultArgInstantiations.erase(InstPos);
}
-
+
return false;
}
@@ -524,8 +527,8 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
Invalid = false;
}
}
-
- // FIXME: If we knew where the '=' was, we could easily provide a fix-it
+
+ // FIXME: If we knew where the '=' was, we could easily provide a fix-it
// hint here. Alternatively, we could walk the type-source information
// for NewParam to find the last source location in the type... but it
// isn't worth the effort right now. This is the kind of test case that
@@ -535,7 +538,7 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
// void g(int (*fp)(int) = &f);
Diag(NewParam->getLocation(), DiagDefaultParamID)
<< NewParam->getDefaultArgRange();
-
+
// Look for the function declaration where the default argument was
// actually written, which may be a declaration prior to Old.
for (auto Older = PrevForDefaultArgs;
@@ -581,9 +584,9 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
// or a definition for one of the following explicit specializations:
// - the explicit specialization of a function template;
// - the explicit specialization of a member function template;
- // - the explicit specialization of a member function of a class
+ // - the explicit specialization of a member function of a class
// template where the class template specialization to which the
- // member function specialization belongs is implicitly
+ // member function specialization belongs is implicitly
// instantiated.
Diag(NewParam->getLocation(), diag::err_template_spec_default_arg)
<< (New->getTemplateSpecializationKind() ==TSK_ExplicitSpecialization)
@@ -591,16 +594,16 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
<< NewParam->getDefaultArgRange();
} else if (New->getDeclContext()->isDependentContext()) {
// C++ [dcl.fct.default]p6 (DR217):
- // Default arguments for a member function of a class template shall
- // be specified on the initial declaration of the member function
+ // Default arguments for a member function of a class template shall
+ // be specified on the initial declaration of the member function
// within the class template.
//
- // Reading the tea leaves a bit in DR217 and its reference to DR205
- // leads me to the conclusion that one cannot add default function
- // arguments for an out-of-line definition of a member function of a
+ // Reading the tea leaves a bit in DR217 and its reference to DR205
+ // leads me to the conclusion that one cannot add default function
+ // arguments for an out-of-line definition of a member function of a
// dependent type.
int WhichKind = 2;
- if (CXXRecordDecl *Record
+ if (CXXRecordDecl *Record
= dyn_cast<CXXRecordDecl>(New->getDeclContext())) {
if (Record->getDescribedClassTemplate())
WhichKind = 0;
@@ -609,8 +612,8 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
else
WhichKind = 2;
}
-
- Diag(NewParam->getLocation(),
+
+ Diag(NewParam->getLocation(),
diag::err_param_default_argument_member_template_redecl)
<< WhichKind
<< NewParam->getDefaultArgRange();
@@ -689,8 +692,9 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D,
assert(D.isDecompositionDeclarator());
const DecompositionDeclarator &Decomp = D.getDecompositionDeclarator();
- // The syntax only allows a decomposition declarator as a simple-declaration
- // or a for-range-declaration, but we parse it in more cases than that.
+ // The syntax only allows a decomposition declarator as a simple-declaration,
+ // a for-range-declaration, or a condition in Clang, but we parse it in more
+ // cases than that.
if (!D.mayHaveDecompositionDeclarator()) {
Diag(Decomp.getLSquareLoc(), diag::err_decomp_decl_context)
<< Decomp.getSourceRange();
@@ -705,9 +709,12 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D,
return nullptr;
}
- Diag(Decomp.getLSquareLoc(), getLangOpts().CPlusPlus1z
- ? diag::warn_cxx14_compat_decomp_decl
- : diag::ext_decomp_decl)
+ Diag(Decomp.getLSquareLoc(),
+ !getLangOpts().CPlusPlus17
+ ? diag::ext_decomp_decl
+ : D.getContext() == Declarator::ConditionContext
+ ? diag::ext_decomp_decl_cond
+ : diag::warn_cxx14_compat_decomp_decl)
<< Decomp.getSourceRange();
// The semantic context is always just the current context.
@@ -787,7 +794,7 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D,
// Check for name conflicts.
DeclarationNameInfo NameInfo(B.Name, B.NameLoc);
LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
- ForRedeclaration);
+ ForVisibleRedeclaration);
LookupName(Previous, S,
/*CreateBuiltins*/DC->getRedeclContext()->isTranslationUnit());
@@ -819,7 +826,8 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D,
// is unnamed.
DeclarationNameInfo NameInfo((IdentifierInfo *)nullptr,
Decomp.getLSquareLoc());
- LookupResult Previous(*this, NameInfo, LookupOrdinaryName, ForRedeclaration);
+ LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
+ ForVisibleRedeclaration);
// Build the variable that holds the non-decomposed object.
bool AddToScope = true;
@@ -2151,7 +2159,7 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
return nullptr;
}
- if (EllipsisLoc.isValid() &&
+ if (EllipsisLoc.isValid() &&
!TInfo->getType()->containsUnexpandedParameterPack()) {
Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
<< TInfo->getTypeLoc().getSourceRange();
@@ -2300,10 +2308,10 @@ Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
GetTypeFromParser(basetype, &TInfo);
if (EllipsisLoc.isInvalid() &&
- DiagnoseUnexpandedParameterPack(SpecifierRange.getBegin(), TInfo,
+ DiagnoseUnexpandedParameterPack(SpecifierRange.getBegin(), TInfo,
UPPC_BaseType))
return true;
-
+
if (CXXBaseSpecifier *BaseSpec = CheckBaseSpecifier(Class, SpecifierRange,
Virtual, Access, TInfo,
EllipsisLoc))
@@ -2387,11 +2395,11 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class,
// Note this base's direct & indirect bases, if there could be ambiguity.
if (Bases.size() > 1)
NoteIndirectBases(Context, IndirectBaseTypes, NewBaseType);
-
+
if (const RecordType *Record = NewBaseType->getAs<RecordType>()) {
const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
if (Class->isInterface() &&
- (!RD->isInterface() ||
+ (!RD->isInterfaceLike() ||
KnownBase->getAccessSpecifier() != AS_public)) {
// The Microsoft extension __interface does not permit bases that
// are not themselves public interfaces.
@@ -2408,7 +2416,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class,
// Attach the remaining base class specifiers to the derived class.
Class->setBases(Bases.data(), NumGoodBases);
-
+
for (unsigned idx = 0; idx < NumGoodBases; ++idx) {
// Check whether this direct base is inaccessible due to ambiguity.
QualType BaseType = Bases[idx]->getType();
@@ -2460,7 +2468,7 @@ bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base) {
CXXRecordDecl *DerivedRD = Derived->getAsCXXRecordDecl();
if (!DerivedRD)
return false;
-
+
CXXRecordDecl *BaseRD = Base->getAsCXXRecordDecl();
if (!BaseRD)
return false;
@@ -2474,7 +2482,7 @@ bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base) {
// to be able to use the inheritance relationship?
if (!isCompleteType(Loc, Derived) && !DerivedRD->isBeingDefined())
return false;
-
+
return DerivedRD->isDerivedFrom(BaseRD);
}
@@ -2484,28 +2492,23 @@ bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base,
CXXBasePaths &Paths) {
if (!getLangOpts().CPlusPlus)
return false;
-
+
CXXRecordDecl *DerivedRD = Derived->getAsCXXRecordDecl();
if (!DerivedRD)
return false;
-
+
CXXRecordDecl *BaseRD = Base->getAsCXXRecordDecl();
if (!BaseRD)
return false;
-
+
if (!isCompleteType(Loc, Derived) && !DerivedRD->isBeingDefined())
return false;
-
+
return DerivedRD->isDerivedFrom(BaseRD, Paths);
}
-void Sema::BuildBasePathArray(const CXXBasePaths &Paths,
- CXXCastPath &BasePathArray) {
- assert(BasePathArray.empty() && "Base path array must be empty!");
- assert(Paths.isRecordingPaths() && "Must record paths!");
-
- const CXXBasePath &Path = Paths.front();
-
+static void BuildBasePathArray(const CXXBasePath &Path,
+ CXXCastPath &BasePathArray) {
// We first go backward and check if we have a virtual base.
// FIXME: It would be better if CXXBasePath had the base specifier for
// the nearest virtual base.
@@ -2522,6 +2525,13 @@ void Sema::BuildBasePathArray(const CXXBasePaths &Paths,
BasePathArray.push_back(const_cast<CXXBaseSpecifier*>(Path[I].Base));
}
+
+void Sema::BuildBasePathArray(const CXXBasePaths &Paths,
+ CXXCastPath &BasePathArray) {
+ assert(BasePathArray.empty() && "Base path array must be empty!");
+ assert(Paths.isRecordingPaths() && "Must record paths!");
+ return ::BuildBasePathArray(Paths.front(), BasePathArray);
+}
/// CheckDerivedToBaseConversion - Check whether the Derived-to-Base
/// conversion (where Derived and Base are class types) is
/// well-formed, meaning that the conversion is unambiguous (and
@@ -2549,30 +2559,48 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
/*DetectVirtual=*/false);
bool DerivationOkay = IsDerivedFrom(Loc, Derived, Base, Paths);
- assert(DerivationOkay &&
- "Can only be used with a derived-to-base conversion");
- (void)DerivationOkay;
-
- if (!Paths.isAmbiguous(Context.getCanonicalType(Base).getUnqualifiedType())) {
+ if (!DerivationOkay)
+ return true;
+
+ const CXXBasePath *Path = nullptr;
+ if (!Paths.isAmbiguous(Context.getCanonicalType(Base).getUnqualifiedType()))
+ Path = &Paths.front();
+
+ // For MSVC compatibility, check if Derived directly inherits from Base. Clang
+ // warns about this hierarchy under -Winaccessible-base, but MSVC allows the
+ // user to access such bases.
+ if (!Path && getLangOpts().MSVCCompat) {
+ for (const CXXBasePath &PossiblePath : Paths) {
+ if (PossiblePath.size() == 1) {
+ Path = &PossiblePath;
+ if (AmbigiousBaseConvID)
+ Diag(Loc, diag::ext_ms_ambiguous_direct_base)
+ << Base << Derived << Range;
+ break;
+ }
+ }
+ }
+
+ if (Path) {
if (!IgnoreAccess) {
// Check that the base class can be accessed.
- switch (CheckBaseClassAccess(Loc, Base, Derived, Paths.front(),
- InaccessibleBaseID)) {
- case AR_inaccessible:
- return true;
- case AR_accessible:
- case AR_dependent:
- case AR_delayed:
- break;
+ switch (
+ CheckBaseClassAccess(Loc, Base, Derived, *Path, InaccessibleBaseID)) {
+ case AR_inaccessible:
+ return true;
+ case AR_accessible:
+ case AR_dependent:
+ case AR_delayed:
+ break;
}
}
-
+
// Build a base path if necessary.
if (BasePath)
- BuildBasePathArray(Paths, *BasePath);
+ ::BuildBasePathArray(*Path, *BasePath);
return false;
}
-
+
if (AmbigiousBaseConvID) {
// We know that the derived-to-base conversion is ambiguous, and
// we're going to produce a diagnostic. Perform the derived-to-base
@@ -2637,7 +2665,7 @@ std::string Sema::getAmbiguousPathsDisplayString(CXXBasePaths &Paths) {
PathDisplayStr += " -> " + Element->Base->getType().getAsString();
}
}
-
+
return PathDisplayStr;
}
@@ -2720,8 +2748,7 @@ void Sema::CheckOverrideControl(NamedDecl *D) {
// If a function is marked with the virt-specifier override and
// does not override a member function of a base class, the program is
// ill-formed.
- bool HasOverriddenMethods =
- MD->begin_overridden_methods() != MD->end_overridden_methods();
+ bool HasOverriddenMethods = MD->size_overridden_methods() != 0;
if (MD->hasAttr<OverrideAttr>() && !HasOverriddenMethods)
Diag(MD->getLocation(), diag::err_function_marked_override_not_overriding)
<< MD->getDeclName();
@@ -2860,6 +2887,8 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
assert(!DS.isFriendSpecified());
bool isFunc = D.isDeclarationOfFunction();
+ AttributeList *MSPropertyAttr =
+ getMSPropertyAttr(D.getDeclSpec().getAttributes().getList());
if (cast<CXXRecordDecl>(CurContext)->isInterface()) {
// The Microsoft extension __interface only permits public member functions
@@ -2867,8 +2896,11 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
// functions, static methods and data members.
unsigned InvalidDecl;
bool ShowDeclName = true;
- if (!isFunc)
- InvalidDecl = (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) ? 0 : 1;
+ if (!isFunc &&
+ (DS.getStorageClassSpec() == DeclSpec::SCS_typedef || MSPropertyAttr))
+ InvalidDecl = 0;
+ else if (!isFunc)
+ InvalidDecl = 1;
else if (AS != AS_public)
InvalidDecl = 2;
else if (DS.getStorageClassSpec() == DeclSpec::SCS_static)
@@ -3016,12 +3048,10 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
else
Diag(D.getIdentifierLoc(), diag::err_member_qualification)
<< Name << SS.getRange();
-
+
SS.clear();
}
- AttributeList *MSPropertyAttr =
- getMSPropertyAttr(D.getDeclSpec().getAttributes().getList());
if (MSPropertyAttr) {
Member = HandleMSProperty(S, cast<CXXRecordDecl>(CurContext), Loc, D,
BitWidth, InitStyle, AS, MSPropertyAttr);
@@ -3390,14 +3420,9 @@ namespace {
void VisitCallExpr(CallExpr *E) {
// Treat std::move as a use.
- if (E->getNumArgs() == 1) {
- if (FunctionDecl *FD = E->getDirectCallee()) {
- if (FD->isInStdNamespace() && FD->getIdentifier() &&
- FD->getIdentifier()->isStr("move")) {
- HandleValue(E->getArg(0), false /*AddressOf*/);
- return;
- }
- }
+ if (E->isCallToStdMove()) {
+ HandleValue(E->getArg(0), /*AddressOf=*/false);
+ return;
}
Inherited::VisitCallExpr(E);
@@ -3585,7 +3610,7 @@ void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D,
/// \brief Find the direct and/or virtual base specifiers that
/// correspond to the given base type, for use in base initialization
/// within a constructor.
-static bool FindBaseInitializer(Sema &SemaRef,
+static bool FindBaseInitializer(Sema &SemaRef,
CXXRecordDecl *ClassDecl,
QualType BaseType,
const CXXBaseSpecifier *&DirectBaseSpec,
@@ -3769,7 +3794,7 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
if (SS.isSet() && isDependentScopeSpecifier(SS)) {
bool NotUnknownSpecialization = false;
DeclContext *DC = computeDeclContext(SS, false);
- if (CXXRecordDecl *Record = dyn_cast_or_null<CXXRecordDecl>(DC))
+ if (CXXRecordDecl *Record = dyn_cast_or_null<CXXRecordDecl>(DC))
NotUnknownSpecialization = !Record->hasAnyDependentBases();
if (!NotUnknownSpecialization) {
@@ -3813,7 +3838,7 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
} else if (TypeDecl *Type = Corr.getCorrectionDeclAs<TypeDecl>()) {
const CXXBaseSpecifier *DirectBaseSpec;
const CXXBaseSpecifier *VirtualBaseSpec;
- if (FindBaseInitializer(*this, ClassDecl,
+ if (FindBaseInitializer(*this, ClassDecl,
Context.getTypeDeclType(Type),
DirectBaseSpec, VirtualBaseSpec)) {
// We have found a direct or virtual base class with a
@@ -4038,7 +4063,7 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init,
if (CurContext->isDependentContext())
DelegationInit = Init;
- return new (Context) CXXCtorInitializer(Context, TInfo, InitRange.getBegin(),
+ return new (Context) CXXCtorInitializer(Context, TInfo, InitRange.getBegin(),
DelegationInit.getAs<Expr>(),
InitRange.getEnd());
}
@@ -4083,12 +4108,12 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
// Check for direct and virtual base classes.
const CXXBaseSpecifier *DirectBaseSpec = nullptr;
const CXXBaseSpecifier *VirtualBaseSpec = nullptr;
- if (!Dependent) {
+ if (!Dependent) {
if (Context.hasSameUnqualifiedType(QualType(ClassDecl->getTypeForDecl(),0),
BaseType))
return BuildDelegatingInitializer(BaseTInfo, Init, ClassDecl);
- FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec,
+ FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec,
VirtualBaseSpec);
// C++ [base.class.init]p2:
@@ -4208,7 +4233,7 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
IsInheritedVirtualBase);
ExprResult BaseInit;
-
+
switch (ImplicitInitKind) {
case IIK_Inherit:
case IIK_Default: {
@@ -4225,7 +4250,7 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
ParmVarDecl *Param = Constructor->getParamDecl(0);
QualType ParamType = Param->getType().getNonReferenceType();
- Expr *CopyCtorArg =
+ Expr *CopyCtorArg =
DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(),
SourceLocation(), Param, false,
Constructor->getLocation(), ParamType,
@@ -4234,8 +4259,8 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
SemaRef.MarkDeclRefReferenced(cast<DeclRefExpr>(CopyCtorArg));
// Cast to the base class to avoid ambiguities.
- QualType ArgTy =
- SemaRef.Context.getQualifiedType(BaseSpec->getType().getUnqualifiedType(),
+ QualType ArgTy =
+ SemaRef.Context.getQualifiedType(BaseSpec->getType().getUnqualifiedType(),
ParamType.getQualifiers());
if (Moving) {
@@ -4261,10 +4286,10 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
BaseInit = SemaRef.MaybeCreateExprWithCleanups(BaseInit);
if (BaseInit.isInvalid())
return true;
-
+
CXXBaseInit =
new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context,
- SemaRef.Context.getTrivialTypeSourceInfo(BaseSpec->getType(),
+ SemaRef.Context.getTrivialTypeSourceInfo(BaseSpec->getType(),
SourceLocation()),
BaseSpec->isVirtual(),
SourceLocation(),
@@ -4298,8 +4323,8 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
// Suppress copying zero-width bitfields.
if (Field->isBitField() && Field->getBitWidthValue(SemaRef.Context) == 0)
return false;
-
- Expr *MemberExprBase =
+
+ Expr *MemberExprBase =
DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(),
SourceLocation(), Param, false,
Loc, ParamType, VK_LValue, nullptr);
@@ -4317,7 +4342,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
MemberLookup.addDecl(Indirect ? cast<ValueDecl>(Indirect)
: cast<ValueDecl>(Field), AS_public);
MemberLookup.resolveKind();
- ExprResult CtorArg
+ ExprResult CtorArg
= SemaRef.BuildMemberReferenceExpr(MemberExprBase,
ParamType, Loc,
/*IsArrow=*/false,
@@ -4346,7 +4371,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
// Direct-initialize to use the copy constructor.
InitializationKind InitKind =
InitializationKind::CreateDirect(Loc, SourceLocation(), SourceLocation());
-
+
Expr *CtorArgE = CtorArg.getAs<Expr>();
InitializationSequence InitSeq(SemaRef, Entity, InitKind, CtorArgE);
ExprResult MemberInit =
@@ -4367,16 +4392,16 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
assert((ImplicitInitKind == IIK_Default || ImplicitInitKind == IIK_Inherit) &&
"Unhandled implicit init kind!");
- QualType FieldBaseElementType =
+ QualType FieldBaseElementType =
SemaRef.Context.getBaseElementType(Field->getType());
-
+
if (FieldBaseElementType->isRecordType()) {
InitializedEntity InitEntity =
Indirect ? InitializedEntity::InitializeMember(Indirect, nullptr,
/*Implicit*/ true)
: InitializedEntity::InitializeMember(Field, nullptr,
/*Implicit*/ true);
- InitializationKind InitKind =
+ InitializationKind InitKind =
InitializationKind::CreateDefault(Loc);
InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, None);
@@ -4386,10 +4411,10 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
MemberInit = SemaRef.MaybeCreateExprWithCleanups(MemberInit);
if (MemberInit.isInvalid())
return true;
-
+
if (Indirect)
CXXMemberInit = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context,
- Indirect, Loc,
+ Indirect, Loc,
Loc,
MemberInit.get(),
Loc);
@@ -4403,9 +4428,9 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
if (!Field->getParent()->isUnion()) {
if (FieldBaseElementType->isReferenceType()) {
- SemaRef.Diag(Constructor->getLocation(),
+ SemaRef.Diag(Constructor->getLocation(),
diag::err_uninitialized_member_in_ctor)
- << (int)Constructor->isImplicit()
+ << (int)Constructor->isImplicit()
<< SemaRef.Context.getTagDeclType(Constructor->getParent())
<< 0 << Field->getDeclName();
SemaRef.Diag(Field->getLocation(), diag::note_declared_at);
@@ -4413,27 +4438,27 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
}
if (FieldBaseElementType.isConstQualified()) {
- SemaRef.Diag(Constructor->getLocation(),
+ SemaRef.Diag(Constructor->getLocation(),
diag::err_uninitialized_member_in_ctor)
- << (int)Constructor->isImplicit()
+ << (int)Constructor->isImplicit()
<< SemaRef.Context.getTagDeclType(Constructor->getParent())
<< 1 << Field->getDeclName();
SemaRef.Diag(Field->getLocation(), diag::note_declared_at);
return true;
}
}
-
+
if (FieldBaseElementType.hasNonTrivialObjCLifetime()) {
// ARC and Weak:
// Default-initialize Objective-C pointers to NULL.
CXXMemberInit
- = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Field,
- Loc, Loc,
- new (SemaRef.Context) ImplicitValueInitExpr(Field->getType()),
+ = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Field,
+ Loc, Loc,
+ new (SemaRef.Context) ImplicitValueInitExpr(Field->getType()),
Loc);
return false;
}
-
+
// Nothing to initialize.
CXXMemberInit = nullptr;
return false;
@@ -4461,13 +4486,13 @@ struct BaseAndFieldInfo {
else
IIK = IIK_Default;
}
-
+
bool isImplicitCopyOrMove() const {
switch (IIK) {
case IIK_Copy:
case IIK_Move:
return true;
-
+
case IIK_Default:
case IIK_Inherit:
return false;
@@ -4534,19 +4559,19 @@ struct BaseAndFieldInfo {
static bool isIncompleteOrZeroLengthArrayType(ASTContext &Context, QualType T) {
if (T->isIncompleteArrayType())
return true;
-
+
while (const ConstantArrayType *ArrayT = Context.getAsConstantArrayType(T)) {
if (!ArrayT->getSize())
return true;
-
+
T = ArrayT->getElementType();
}
-
+
return false;
}
static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info,
- FieldDecl *Field,
+ FieldDecl *Field,
IndirectFieldDecl *Indirect = nullptr) {
if (Field->isInvalidDecl())
return false;
@@ -4659,7 +4684,7 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors,
CXXRecordDecl *ClassDecl = Constructor->getParent()->getDefinition();
if (!ClassDecl)
return true;
-
+
bool HadError = false;
for (unsigned i = 0; i < Initializers.size(); i++) {
@@ -4758,34 +4783,34 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors,
// initialized.
if (F->isUnnamedBitfield())
continue;
-
+
// If we're not generating the implicit copy/move constructor, then we'll
// handle anonymous struct/union fields based on their individual
// indirect fields.
if (F->isAnonymousStructOrUnion() && !Info.isImplicitCopyOrMove())
continue;
-
+
if (CollectFieldInitializer(*this, Info, F))
HadError = true;
continue;
}
-
+
// Beyond this point, we only consider default initialization.
if (Info.isImplicitCopyOrMove())
continue;
-
+
if (auto *F = dyn_cast<IndirectFieldDecl>(Mem)) {
if (F->getType()->isIncompleteArrayType()) {
assert(ClassDecl->hasFlexibleArrayMember() &&
"Incomplete array type is not valid");
continue;
}
-
+
// Initialize each field of an anonymous struct individually.
if (CollectFieldInitializer(*this, Info, F->getAnonField(), F))
HadError = true;
-
- continue;
+
+ continue;
}
}
@@ -4827,7 +4852,7 @@ static const void *GetKeyForMember(ASTContext &Context,
CXXCtorInitializer *Member) {
if (!Member->isAnyMemberInitializer())
return GetKeyForBase(Context, QualType(Member->getBaseClass(), 0));
-
+
return Member->getAnyMember()->getCanonicalDecl();
}
@@ -4838,7 +4863,7 @@ static void DiagnoseBaseOrMemInitializerOrder(
return;
// Don't check initializers order unless the warning is enabled at the
- // location of at least one initializer.
+ // location of at least one initializer.
bool ShouldCheckOrder = false;
for (unsigned InitIndex = 0; InitIndex != Inits.size(); ++InitIndex) {
CXXCtorInitializer *Init = Inits[InitIndex];
@@ -4850,7 +4875,7 @@ static void DiagnoseBaseOrMemInitializerOrder(
}
if (!ShouldCheckOrder)
return;
-
+
// Build the list of bases and members in the order that they'll
// actually be initialized. The explicit initializers should be in
// this same order but may be missing things.
@@ -4873,10 +4898,10 @@ static void DiagnoseBaseOrMemInitializerOrder(
for (auto *Field : ClassDecl->fields()) {
if (Field->isUnnamedBitfield())
continue;
-
+
PopulateKeysForFields(Field, IdealInitKeys);
}
-
+
unsigned NumIdealInits = IdealInitKeys.size();
unsigned IdealIndex = 0;
@@ -4903,7 +4928,7 @@ static void DiagnoseBaseOrMemInitializerOrder(
D << 0 << PrevInit->getAnyMember()->getDeclName();
else
D << 1 << PrevInit->getTypeSourceInfo()->getType();
-
+
if (Init->isAnyMemberInitializer())
D << 0 << Init->getAnyMember()->getDeclName();
else
@@ -4971,7 +4996,7 @@ bool CheckRedundantUnionInit(Sema &S,
S.Diag(En.second->getSourceLocation(), diag::note_previous_initializer)
<< 0 << En.second->getSourceRange();
return true;
- }
+ }
if (!En.first) {
En.first = Child;
En.second = Init;
@@ -5005,7 +5030,7 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
Diag(ColonLoc, diag::err_only_constructors_take_base_inits);
return;
}
-
+
// Mapping for the duplicate initializers check.
// For member initializers, this is keyed with a FieldDecl*.
// For base initializers, this is keyed with a Type*.
@@ -5067,22 +5092,22 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
// field/base declaration. That's probably good; that said, the
// user might reasonably want to know why the destructor is being
// emitted, and we currently don't say.
-
+
// Non-static data members.
for (auto *Field : ClassDecl->fields()) {
if (Field->isInvalidDecl())
continue;
-
+
// Don't destroy incomplete or zero-length arrays.
if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
continue;
QualType FieldType = Context.getBaseElementType(Field->getType());
-
+
const RecordType* RT = FieldType->getAs<RecordType>();
if (!RT)
continue;
-
+
CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
if (FieldClassDecl->isInvalidDecl())
continue;
@@ -5137,14 +5162,14 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
<< Base.getType()
<< Base.getSourceRange(),
Context.getTypeDeclType(ClassDecl));
-
+
MarkFunctionReferenced(Location, Dtor);
DiagnoseUseOfDecl(Dtor, Location);
}
if (!VisitVirtualBases)
return;
-
+
// Virtual bases.
for (const auto &VBase : ClassDecl->vbases()) {
// Bases are always records in a well-formed non-dependent class.
@@ -5241,12 +5266,12 @@ void Sema::DiagnoseAbstractType(const CXXRecordDecl *RD) {
// Keep a set of seen pure methods so we won't diagnose the same method
// more than once.
llvm::SmallPtrSet<const CXXMethodDecl *, 8> SeenPureMethods;
-
- for (CXXFinalOverriderMap::iterator M = FinalOverriders.begin(),
+
+ for (CXXFinalOverriderMap::iterator M = FinalOverriders.begin(),
MEnd = FinalOverriders.end();
- M != MEnd;
+ M != MEnd;
++M) {
- for (OverridingMethods::iterator SO = M->second.begin(),
+ for (OverridingMethods::iterator SO = M->second.begin(),
SOEnd = M->second.end();
SO != SOEnd; ++SO) {
// C++ [class.abstract]p4:
@@ -5254,7 +5279,7 @@ void Sema::DiagnoseAbstractType(const CXXRecordDecl *RD) {
// pure virtual function for which the final overrider is pure
// virtual.
- //
+ //
if (SO->second.size() != 1)
continue;
@@ -5264,8 +5289,8 @@ void Sema::DiagnoseAbstractType(const CXXRecordDecl *RD) {
if (!SeenPureMethods.insert(SO->second.front().Method).second)
continue;
- Diag(SO->second.front().Method->getLocation(),
- diag::note_pure_virtual_function)
+ Diag(SO->second.front().Method->getLocation(),
+ diag::note_pure_virtual_function)
<< SO->second.front().Method->getDeclName() << RD->getDeclName();
}
}
@@ -5745,7 +5770,7 @@ static bool computeCanPassInRegisters(Sema &S, CXXRecordDecl *D) {
!D->defaultedCopyConstructorIsDeleted()) {
if (!D->hasTrivialCopyConstructor())
return false;
- HasNonDeletedCopyOrMove = true;
+ HasNonDeletedCopyOrMove = true;
}
if (S.getLangOpts().CPlusPlus11 && D->needsImplicitMoveConstructor() &&
@@ -5787,7 +5812,7 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
AbstractUsageInfo Info(*this, Record);
CheckAbstractClassUsage(Info, Record);
}
-
+
// If this is not an aggregate type and has no user-declared constructor,
// complain about any non-static data members of reference or const scalar
// type, since they will never get initializers.
@@ -5806,7 +5831,7 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
<< Record->getTagKind() << Record;
Complained = true;
}
-
+
Diag(F->getLocation(), diag::note_refconst_member_not_initialized)
<< F->getType()->isReferenceType()
<< F->getDeclName();
@@ -5816,12 +5841,12 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
if (Record->getIdentifier()) {
// C++ [class.mem]p13:
- // If T is the name of a class, then each of the following shall have a
+ // If T is the name of a class, then each of the following shall have a
// name different from T:
// - every member of every anonymous union that is a member of class T.
//
// C++ [class.mem]p14:
- // In addition, if class T has a user-declared constructor (12.1), every
+ // In addition, if class T has a user-declared constructor (12.1), every
// non-static data member of class T shall have a name different from T.
DeclContext::lookup_result R = Record->lookup(Record->getDeclName());
for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E;
@@ -7398,10 +7423,8 @@ private:
const llvm::SmallPtrSetImpl<const CXXMethodDecl *> &Methods) {
if (MD->size_overridden_methods() == 0)
return Methods.count(MD->getCanonicalDecl());
- for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
- E = MD->end_overridden_methods();
- I != E; ++I)
- if (CheckMostOverridenMethods(*I, Methods))
+ for (const CXXMethodDecl *O : MD->overridden_methods())
+ if (CheckMostOverridenMethods(O, Methods))
return true;
return false;
}
@@ -7459,10 +7482,9 @@ static void AddMostOverridenMethods(const CXXMethodDecl *MD,
llvm::SmallPtrSetImpl<const CXXMethodDecl *>& Methods) {
if (MD->size_overridden_methods() == 0)
Methods.insert(MD->getCanonicalDecl());
- for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
- E = MD->end_overridden_methods();
- I != E; ++I)
- AddMostOverridenMethods(*I, Methods);
+ else
+ for (const CXXMethodDecl *O : MD->overridden_methods())
+ AddMostOverridenMethods(O, Methods);
}
/// \brief Check if a method overloads virtual methods in a base class without
@@ -7821,11 +7843,11 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R,
// A constructor shall not be declared with a ref-qualifier.
if (FTI.hasRefQualifier()) {
Diag(FTI.getRefQualifierLoc(), diag::err_ref_qualifier_constructor)
- << FTI.RefQualifierIsLValueRef
+ << FTI.RefQualifierIsLValueRef
<< FixItHint::CreateRemoval(FTI.getRefQualifierLoc());
D.setInvalidType();
}
-
+
// Rebuild the function type "R" without any type qualifiers (in
// case any of the errors above fired) and with "void" as the
// return type, since constructors don't have return types.
@@ -7864,8 +7886,8 @@ void Sema::CheckConstructor(CXXConstructorDecl *Constructor) {
QualType ClassTy = Context.getTagDeclType(ClassDecl);
if (Context.getCanonicalType(ParamType).getUnqualifiedType() == ClassTy) {
SourceLocation ParamLoc = Constructor->getParamDecl(0)->getLocation();
- const char *ConstRef
- = Constructor->getParamDecl(0)->getIdentifier() ? "const &"
+ const char *ConstRef
+ = Constructor->getParamDecl(0)->getIdentifier() ? "const &"
: " const &";
Diag(ParamLoc, diag::err_constructor_byvalue_arg)
<< FixItHint::CreateInsertion(ParamLoc, ConstRef);
@@ -7882,23 +7904,49 @@ void Sema::CheckConstructor(CXXConstructorDecl *Constructor) {
/// on error.
bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) {
CXXRecordDecl *RD = Destructor->getParent();
-
+
if (!Destructor->getOperatorDelete() && Destructor->isVirtual()) {
SourceLocation Loc;
-
+
if (!Destructor->isImplicit())
Loc = Destructor->getLocation();
else
Loc = RD->getLocation();
-
+
// If we have a virtual destructor, look up the deallocation function
if (FunctionDecl *OperatorDelete =
FindDeallocationFunctionForDestructor(Loc, RD)) {
+ Expr *ThisArg = nullptr;
+
+ // If the notional 'delete this' expression requires a non-trivial
+ // conversion from 'this' to the type of a destroying operator delete's
+ // first parameter, perform that conversion now.
+ if (OperatorDelete->isDestroyingOperatorDelete()) {
+ QualType ParamType = OperatorDelete->getParamDecl(0)->getType();
+ if (!declaresSameEntity(ParamType->getAsCXXRecordDecl(), RD)) {
+ // C++ [class.dtor]p13:
+ // ... as if for the expression 'delete this' appearing in a
+ // non-virtual destructor of the destructor's class.
+ ContextRAII SwitchContext(*this, Destructor);
+ ExprResult This =
+ ActOnCXXThis(OperatorDelete->getParamDecl(0)->getLocation());
+ assert(!This.isInvalid() && "couldn't form 'this' expr in dtor?");
+ This = PerformImplicitConversion(This.get(), ParamType, AA_Passing);
+ if (This.isInvalid()) {
+ // FIXME: Register this as a context note so that it comes out
+ // in the right order.
+ Diag(Loc, diag::note_implicit_delete_this_in_destructor_here);
+ return true;
+ }
+ ThisArg = This.get();
+ }
+ }
+
MarkFunctionReferenced(Loc, OperatorDelete);
- Destructor->setOperatorDelete(OperatorDelete);
+ Destructor->setOperatorDelete(OperatorDelete, ThisArg);
}
}
-
+
return false;
}
@@ -7939,7 +7987,7 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,
<< "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
<< SourceRange(D.getIdentifierLoc())
<< FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
-
+
SC = SC_None;
}
if (!D.isInvalidType()) {
@@ -7988,7 +8036,7 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,
<< FixItHint::CreateRemoval(FTI.getRefQualifierLoc());
D.setInvalidType();
}
-
+
// Make sure we don't have any parameters.
if (FTIHasNonVoidParameters(FTI)) {
Diag(D.getIdentifierLoc(), diag::err_destructor_with_params);
@@ -8007,7 +8055,7 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,
// Rebuild the function type "R" without any type qualifiers or
// parameters (in case any of the errors above fired) and with
// "void" as the return type, since destructors don't have return
- // types.
+ // types.
if (!D.isInvalidType())
return R;
@@ -8236,7 +8284,7 @@ Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
if (FunctionTemplateDecl *ConversionTemplate
= Conversion->getDescribedFunctionTemplate())
return ConversionTemplate;
-
+
return Conversion;
}
@@ -8294,8 +8342,7 @@ void Sema::CheckDeductionGuideDeclarator(Declarator &D, QualType &R,
// We leave 'friend' and 'virtual' to be rejected in the normal way.
if (DS.hasTypeSpecifier() || DS.getTypeQualifiers() ||
DS.getStorageClassSpecLoc().isValid() || DS.isInlineSpecified() ||
- DS.isNoreturnSpecified() || DS.isConstexprSpecified() ||
- DS.isConceptSpecified()) {
+ DS.isNoreturnSpecified() || DS.isConstexprSpecified()) {
BadSpecifierDiagnoser Diagnoser(
*this, D.getIdentifierLoc(),
diag::err_deduction_guide_invalid_specifier);
@@ -8308,9 +8355,7 @@ void Sema::CheckDeductionGuideDeclarator(Declarator &D, QualType &R,
Diagnoser.check(DS.getInlineSpecLoc(), "inline");
Diagnoser.check(DS.getNoreturnSpecLoc(), "_Noreturn");
Diagnoser.check(DS.getConstexprSpecLoc(), "constexpr");
- Diagnoser.check(DS.getConceptSpecLoc(), "concept");
DS.ClearConstexprSpec();
- DS.ClearConceptSpec();
Diagnoser.check(DS.getConstSpecLoc(), "const");
Diagnoser.check(DS.getRestrictSpecLoc(), "__restrict");
@@ -8464,7 +8509,8 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
// Since namespace names are unique in their scope, and we don't
// look through using directives, just look for any ordinary names
// as if by qualified name lookup.
- LookupResult R(*this, II, IdentLoc, LookupOrdinaryName, ForRedeclaration);
+ LookupResult R(*this, II, IdentLoc, LookupOrdinaryName,
+ ForExternalRedeclaration);
LookupQualifiedName(R, CurContext->getRedeclContext());
NamedDecl *PrevDecl =
R.isSingleResult() ? R.getRepresentativeDecl() : nullptr;
@@ -8495,7 +8541,7 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
}
} else {
// Anonymous namespaces.
-
+
// Determine whether the parent already has an anonymous namespace.
DeclContext *Parent = CurContext->getRedeclContext();
if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(Parent)) {
@@ -8509,12 +8555,12 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
DiagnoseNamespaceInlineMismatch(*this, NamespaceLoc, NamespaceLoc, II,
&IsInline, PrevNS);
}
-
+
NamespaceDecl *Namespc = NamespaceDecl::Create(Context, CurContext, IsInline,
StartLoc, Loc, II, PrevNS);
if (IsInvalid)
Namespc->setInvalidDecl();
-
+
ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList);
AddPragmaAttributes(DeclRegionScope, Namespc);
@@ -8526,7 +8572,7 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
StdNamespace = Namespc;
if (AddToKnown)
KnownNamespaces[Namespc] = false;
-
+
if (II) {
PushOnScopeChains(Namespc, DeclRegionScope);
} else {
@@ -8627,12 +8673,12 @@ NamespaceDecl *Sema::lookupStdExperimentalNamespace() {
return StdExperimentalNamespaceCache;
}
-/// \brief Retrieve the special "std" namespace, which may require us to
+/// \brief Retrieve the special "std" namespace, which may require us to
/// implicitly define the namespace.
NamespaceDecl *Sema::getOrCreateStdNamespace() {
if (!StdNamespace) {
// The "std" namespace has not yet been defined, so build one implicitly.
- StdNamespace = NamespaceDecl::Create(Context,
+ StdNamespace = NamespaceDecl::Create(Context,
Context.getTranslationUnitDecl(),
/*Inline=*/false,
SourceLocation(), SourceLocation(),
@@ -8845,7 +8891,7 @@ Decl *Sema::ActOnUsingDirective(Scope *S,
NestedNameSpecifier *Qualifier = nullptr;
if (SS.isSet())
Qualifier = SS.getScopeRep();
-
+
// Lookup namespace name.
LookupResult R(*this, NamespcName, IdentLoc, LookupNamespaceName);
LookupParsedName(R, S, &SS);
@@ -8854,18 +8900,18 @@ Decl *Sema::ActOnUsingDirective(Scope *S,
if (R.empty()) {
R.clear();
- // Allow "using namespace std;" or "using namespace ::std;" even if
+ // Allow "using namespace std;" or "using namespace ::std;" even if
// "std" hasn't been defined yet, for GCC compatibility.
if ((!Qualifier || Qualifier->getKind() == NestedNameSpecifier::Global) &&
NamespcName->isStr("std")) {
Diag(IdentLoc, diag::ext_using_undefined_std);
R.addDecl(getOrCreateStdNamespace());
R.resolveKind();
- }
+ }
// Otherwise, attempt typo correction.
else TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, NamespcName);
}
-
+
if (!R.empty()) {
NamedDecl *Named = R.getRepresentativeDecl();
NamespaceDecl *NS = R.getAsSingle<NamespaceDecl>();
@@ -8946,7 +8992,7 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
case UnqualifiedId::IK_LiteralOperatorId:
case UnqualifiedId::IK_ConversionFunctionId:
break;
-
+
case UnqualifiedId::IK_ConstructorName:
case UnqualifiedId::IK_ConstructorTemplateId:
// C++11 inheriting constructors.
@@ -9089,7 +9135,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
// If the target happens to be one of the previous declarations, we
// don't have a conflict.
- //
+ //
// FIXME: but we might be increasing its access, in which case we
// should redeclare it.
NamedDecl *NonTag = nullptr, *Tag = nullptr;
@@ -9401,7 +9447,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
// Do the redeclaration lookup in the current scope.
LookupResult Previous(*this, UsingName, LookupUsingDeclName,
- ForRedeclaration);
+ ForVisibleRedeclaration);
Previous.setHideTags(false);
if (S) {
LookupName(Previous, S);
@@ -9464,7 +9510,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
IdentLoc, NameInfo.getName(),
EllipsisLoc);
} else {
- D = UnresolvedUsingValueDecl::Create(Context, CurContext, UsingLoc,
+ D = UnresolvedUsingValueDecl::Create(Context, CurContext, UsingLoc,
QualifierLoc, NameInfo, EllipsisLoc);
}
D->setAccess(AS);
@@ -9977,11 +10023,14 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S,
if (DiagnoseUnexpandedParameterPack(Name.StartLocation, TInfo,
UPPC_DeclarationType)) {
Invalid = true;
- TInfo = Context.getTrivialTypeSourceInfo(Context.IntTy,
+ TInfo = Context.getTrivialTypeSourceInfo(Context.IntTy,
TInfo->getTypeLoc().getBeginLoc());
}
- LookupResult Previous(*this, NameInfo, LookupOrdinaryName, ForRedeclaration);
+ LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
+ TemplateParamLists.size()
+ ? forRedeclarationInCurContext()
+ : ForVisibleRedeclaration);
LookupName(Previous, S);
// Warn about shadowing the name of a template parameter.
@@ -10084,8 +10133,10 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S,
if (Invalid)
NewDecl->setInvalidDecl();
- else if (OldDecl)
+ else if (OldDecl) {
NewDecl->setPreviousDecl(OldDecl);
+ CheckRedeclarationModuleOwnership(NewDecl, OldDecl);
+ }
NewND = NewDecl;
} else {
@@ -10126,7 +10177,7 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc,
// Check if we have a previous declaration with the same name.
LookupResult PrevR(*this, Alias, AliasLoc, LookupOrdinaryName,
- ForRedeclaration);
+ ForVisibleRedeclaration);
LookupName(PrevR, S);
// Check we're not shadowing a template parameter.
@@ -10140,7 +10191,7 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc,
/*AllowInlineNamespace*/false);
// Find the previous declaration and check that we can redeclare it.
- NamespaceAliasDecl *Prev = nullptr;
+ NamespaceAliasDecl *Prev = nullptr;
if (PrevR.isSingleResult()) {
NamedDecl *PrevDecl = PrevR.getRepresentativeDecl();
if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(PrevDecl)) {
@@ -10261,7 +10312,7 @@ ComputeDefaultedSpecialMemberExceptionSpec(
CXXRecordDecl *ClassDecl = MD->getParent();
// C++ [except.spec]p14:
- // An implicitly declared special member function (Clause 12) shall have an
+ // An implicitly declared special member function (Clause 12) shall have an
// exception-specification. [...]
SpecialMemberExceptionSpecInfo Info(S, MD, CSM, ICI, Loc);
if (ClassDecl->isInvalidDecl())
@@ -10339,7 +10390,7 @@ void Sema::CheckImplicitSpecialMemberDeclaration(Scope *S, FunctionDecl *FD) {
// implicit special members with this name.
DeclarationName Name = FD->getDeclName();
LookupResult R(*this, Name, SourceLocation(), LookupOrdinaryName,
- ForRedeclaration);
+ ForExternalRedeclaration);
for (auto *D : FD->getParent()->lookup(Name))
if (auto *Acceptable = R.getAcceptableDecl(D))
R.addDecl(Acceptable);
@@ -11126,7 +11177,7 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
//
// for (__SIZE_TYPE__ i0 = 0; i0 != array-size; ++i0)
//
- // that will copy each of the array elements.
+ // that will copy each of the array elements.
QualType SizeType = S.Context.getSizeType();
// Create the iteration variable.
@@ -11338,7 +11389,7 @@ static void diagnoseDeprecatedCopyOperation(Sema &S, CXXMethodDecl *CopyOp) {
void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
CXXMethodDecl *CopyAssignOperator) {
- assert((CopyAssignOperator->isDefaulted() &&
+ assert((CopyAssignOperator->isDefaulted() &&
CopyAssignOperator->isOverloadedOperator() &&
CopyAssignOperator->getOverloadedOperator() == OO_Equal &&
!CopyAssignOperator->doesThisDeclarationHaveABody() &&
@@ -11372,15 +11423,15 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
// C++0x [class.copy]p30:
// The implicitly-defined or explicitly-defaulted copy assignment operator
- // for a non-union class X performs memberwise copy assignment of its
- // subobjects. The direct base classes of X are assigned first, in the
- // order of their declaration in the base-specifier-list, and then the
- // immediate non-static data members of X are assigned, in the order in
+ // for a non-union class X performs memberwise copy assignment of its
+ // subobjects. The direct base classes of X are assigned first, in the
+ // order of their declaration in the base-specifier-list, and then the
+ // immediate non-static data members of X are assigned, in the order in
// which they were declared in the class definition.
-
+
// The statements that form the synthesized function body.
SmallVector<Stmt*, 8> Statements;
-
+
// The parameter for the "other" object, which we are copying from.
ParmVarDecl *Other = CopyAssignOperator->getParamDecl(0);
Qualifiers OtherQuals = Other->getType().getQualifiers();
@@ -11390,7 +11441,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
OtherRefType = OtherRef->getPointeeType();
OtherQuals = OtherRefType.getQualifiers();
}
-
+
// Our location for everything implicitly-generated.
SourceLocation Loc = CopyAssignOperator->getLocEnd().isValid()
? CopyAssignOperator->getLocEnd()
@@ -11401,7 +11452,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
// Builds the "this" pointer.
ThisBuilder This;
-
+
// Assign base classes.
bool Invalid = false;
for (auto &Base : ClassDecl->bases()) {
@@ -11437,11 +11488,11 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
CopyAssignOperator->setInvalidDecl();
return;
}
-
+
// Success! Record the copy.
Statements.push_back(Copy.getAs<Expr>());
}
-
+
// Assign non-static members.
for (auto *Field : ClassDecl->fields()) {
// FIXME: We should form some kind of AST representation for the implied
@@ -11462,28 +11513,28 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
Invalid = true;
continue;
}
-
+
// Check for members of const-qualified, non-class type.
QualType BaseType = Context.getBaseElementType(Field->getType());
if (!BaseType->getAs<RecordType>() && BaseType.isConstQualified()) {
Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
<< Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName();
Diag(Field->getLocation(), diag::note_declared_at);
- Invalid = true;
+ Invalid = true;
continue;
}
// Suppress assigning zero-width bitfields.
if (Field->isBitField() && Field->getBitWidthValue(Context) == 0)
continue;
-
+
QualType FieldType = Field->getType().getNonReferenceType();
if (FieldType->isIncompleteArrayType()) {
- assert(ClassDecl->hasFlexibleArrayMember() &&
+ assert(ClassDecl->hasFlexibleArrayMember() &&
"Incomplete array type is not valid");
continue;
}
-
+
// Build references to the field in the object we're copying from and to.
CXXScopeSpec SS; // Intentionally empty
LookupResult MemberLookup(*this, Field->getDeclName(), Loc,
@@ -11504,7 +11555,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
CopyAssignOperator->setInvalidDecl();
return;
}
-
+
// Success! Record the copy.
Statements.push_back(Copy.getAs<Stmt>());
}
@@ -11512,7 +11563,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
if (!Invalid) {
// Add a "return *this;"
ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This.build(*this, Loc));
-
+
StmtResult Return = BuildReturnStmt(Loc, ThisObj.get());
if (Return.isInvalid())
Invalid = true;
@@ -11700,7 +11751,7 @@ static void checkMoveAssignmentForRepeatedMove(Sema &S, CXXRecordDecl *Class,
void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
CXXMethodDecl *MoveAssignOperator) {
- assert((MoveAssignOperator->isDefaulted() &&
+ assert((MoveAssignOperator->isDefaulted() &&
MoveAssignOperator->isOverloadedOperator() &&
MoveAssignOperator->getOverloadedOperator() == OO_Equal &&
!MoveAssignOperator->doesThisDeclarationHaveABody() &&
@@ -11714,7 +11765,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
MoveAssignOperator->setInvalidDecl();
return;
}
-
+
// C++0x [class.copy]p28:
// The implicitly-defined or move assignment operator for a non-union class
// X performs memberwise move assignment of its subobjects. The direct base
@@ -11836,21 +11887,21 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
<< Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName();
Diag(Field->getLocation(), diag::note_declared_at);
- Invalid = true;
+ Invalid = true;
continue;
}
// Suppress assigning zero-width bitfields.
if (Field->isBitField() && Field->getBitWidthValue(Context) == 0)
continue;
-
+
QualType FieldType = Field->getType().getNonReferenceType();
if (FieldType->isIncompleteArrayType()) {
- assert(ClassDecl->hasFlexibleArrayMember() &&
+ assert(ClassDecl->hasFlexibleArrayMember() &&
"Incomplete array type is not valid");
continue;
}
-
+
// Build references to the field in the object we're copying from and to.
LookupResult MemberLookup(*this, Field->getDeclName(), Loc,
LookupMemberName);
@@ -12164,26 +12215,26 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion(
SourceLocation CurrentLocation,
CXXConversionDecl *Conv) {
SynthesizedFunctionScope Scope(*this, Conv);
-
+
CXXRecordDecl *Lambda = Conv->getParent();
CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator();
// If we are defining a specialization of a conversion to function-ptr
// cache the deduced template arguments for this specialization
// so that we can use them to retrieve the corresponding call-operator
- // and static-invoker.
+ // and static-invoker.
const TemplateArgumentList *DeducedTemplateArgs = nullptr;
// Retrieve the corresponding call-operator specialization.
if (Lambda->isGenericLambda()) {
assert(Conv->isFunctionTemplateSpecialization());
- FunctionTemplateDecl *CallOpTemplate =
+ FunctionTemplateDecl *CallOpTemplate =
CallOp->getDescribedFunctionTemplate();
DeducedTemplateArgs = Conv->getTemplateSpecializationArgs();
void *InsertPos = nullptr;
FunctionDecl *CallOpSpec = CallOpTemplate->findSpecialization(
DeducedTemplateArgs->asArray(),
InsertPos);
- assert(CallOpSpec &&
+ assert(CallOpSpec &&
"Conversion operator must have a corresponding call operator");
CallOp = cast<CXXMethodDecl>(CallOpSpec);
}
@@ -12199,15 +12250,15 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion(
CXXMethodDecl *Invoker = Lambda->getLambdaStaticInvoker();
// ... and get the corresponding specialization for a generic lambda.
if (Lambda->isGenericLambda()) {
- assert(DeducedTemplateArgs &&
+ assert(DeducedTemplateArgs &&
"Must have deduced template arguments from Conversion Operator");
- FunctionTemplateDecl *InvokeTemplate =
+ FunctionTemplateDecl *InvokeTemplate =
Invoker->getDescribedFunctionTemplate();
void *InsertPos = nullptr;
FunctionDecl *InvokeSpec = InvokeTemplate->findSpecialization(
DeducedTemplateArgs->asArray(),
InsertPos);
- assert(InvokeSpec &&
+ assert(InvokeSpec &&
"Must have a corresponding static invoker specialization");
Invoker = cast<CXXMethodDecl>(InvokeSpec);
}
@@ -12222,13 +12273,13 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion(
Conv->markUsed(Context);
Conv->setReferenced();
-
+
// Fill in the __invoke function with a dummy implementation. IR generation
// will fill in the actual details.
Invoker->markUsed(Context);
Invoker->setReferenced();
Invoker->setBody(new (Context) CompoundStmt(Conv->getLocation()));
-
+
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(Conv);
L->CompletedImplicitDefinition(Invoker);
@@ -12239,16 +12290,16 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion(
void Sema::DefineImplicitLambdaToBlockPointerConversion(
SourceLocation CurrentLocation,
- CXXConversionDecl *Conv)
+ CXXConversionDecl *Conv)
{
assert(!Conv->getParent()->isGenericLambda());
SynthesizedFunctionScope Scope(*this, Conv);
-
+
// Copy-initialize the lambda object as needed to capture it.
Expr *This = ActOnCXXThis(CurrentLocation).get();
Expr *DerefThis =CreateBuiltinUnaryOp(CurrentLocation, UO_Deref, This).get();
-
+
ExprResult BuildBlock = BuildBlockForLambdaConversion(CurrentLocation,
Conv->getLocation(),
Conv, DerefThis);
@@ -12283,29 +12334,29 @@ void Sema::DefineImplicitLambdaToBlockPointerConversion(
Conv->getLocation(),
Conv->getLocation()));
Conv->markUsed(Context);
-
+
// We're done; notify the mutation listener, if any.
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(Conv);
}
}
-/// \brief Determine whether the given list arguments contains exactly one
+/// \brief Determine whether the given list arguments contains exactly one
/// "real" (non-default) argument.
static bool hasOneRealArgument(MultiExprArg Args) {
switch (Args.size()) {
case 0:
return false;
-
+
default:
if (!Args[1]->isDefaultArgument())
return false;
-
+
// fall through
case 1:
return !Args[0]->isDefaultArgument();
}
-
+
return false;
}
@@ -12362,7 +12413,7 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
if (auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>(FoundDecl)) {
Constructor = findInheritingConstructor(ConstructLoc, Constructor, Shadow);
if (DiagnoseUseOfDecl(Constructor, ConstructLoc))
- return ExprError();
+ return ExprError();
}
return BuildCXXConstructExpr(
@@ -12439,7 +12490,8 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) {
assert(Pattern && "We must have set the Pattern!");
}
- if (InstantiateInClassInitializer(Loc, Field, Pattern,
+ if (!Pattern->hasInClassInitializer() ||
+ InstantiateInClassInitializer(Loc, Field, Pattern,
getTemplateInstantiationArgs(Field))) {
// Don't diagnose this again.
Field->setInvalidDecl();
@@ -12505,7 +12557,7 @@ void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) {
/// to form a proper call to this constructor.
///
/// \returns true if an error occurred, false otherwise.
-bool
+bool
Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor,
MultiExprArg ArgsPtr,
SourceLocation Loc,
@@ -12516,7 +12568,7 @@ Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor,
unsigned NumArgs = ArgsPtr.size();
Expr **Args = ArgsPtr.data();
- const FunctionProtoType *Proto
+ const FunctionProtoType *Proto
= Constructor->getType()->getAs<FunctionProtoType>();
assert(Proto && "Constructor without a prototype?");
unsigned NumParams = Proto->getNumParams();
@@ -12527,7 +12579,7 @@ Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor,
else
ConvertedArgs.reserve(NumArgs);
- VariadicCallType CallType =
+ VariadicCallType CallType =
Proto->isVariadic() ? VariadicConstructor : VariadicDoesNotApply;
SmallVector<Expr *, 8> AllArgs;
bool Invalid = GatherArgumentsForCall(Loc, Constructor,
@@ -12548,22 +12600,22 @@ Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor,
}
static inline bool
-CheckOperatorNewDeleteDeclarationScope(Sema &SemaRef,
+CheckOperatorNewDeleteDeclarationScope(Sema &SemaRef,
const FunctionDecl *FnDecl) {
const DeclContext *DC = FnDecl->getDeclContext()->getRedeclContext();
if (isa<NamespaceDecl>(DC)) {
- return SemaRef.Diag(FnDecl->getLocation(),
+ return SemaRef.Diag(FnDecl->getLocation(),
diag::err_operator_new_delete_declared_in_namespace)
<< FnDecl->getDeclName();
}
-
- if (isa<TranslationUnitDecl>(DC) &&
+
+ if (isa<TranslationUnitDecl>(DC) &&
FnDecl->getStorageClass() == SC_Static) {
return SemaRef.Diag(FnDecl->getLocation(),
diag::err_operator_new_delete_declared_static)
<< FnDecl->getDeclName();
}
-
+
return false;
}
@@ -12585,21 +12637,21 @@ CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl,
// Check that the result type is what we expect.
if (SemaRef.Context.getCanonicalType(ResultType) != ExpectedResultType)
return SemaRef.Diag(FnDecl->getLocation(),
- diag::err_operator_new_delete_invalid_result_type)
+ diag::err_operator_new_delete_invalid_result_type)
<< FnDecl->getDeclName() << ExpectedResultType;
-
+
// A function template must have at least 2 parameters.
if (FnDecl->getDescribedFunctionTemplate() && FnDecl->getNumParams() < 2)
return SemaRef.Diag(FnDecl->getLocation(),
diag::err_operator_new_delete_template_too_few_parameters)
<< FnDecl->getDeclName();
-
+
// The function decl must have at least 1 parameter.
if (FnDecl->getNumParams() == 0)
return SemaRef.Diag(FnDecl->getLocation(),
diag::err_operator_new_delete_too_few_parameters)
<< FnDecl->getDeclName();
-
+
// Check the first parameter type is not dependent.
QualType FirstParamType = FnDecl->getParamDecl(0)->getType();
if (FirstParamType->isDependentType())
@@ -12607,11 +12659,11 @@ CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl,
<< FnDecl->getDeclName() << ExpectedFirstParamType;
// Check that the first parameter type is what we expect.
- if (SemaRef.Context.getCanonicalType(FirstParamType).getUnqualifiedType() !=
+ if (SemaRef.Context.getCanonicalType(FirstParamType).getUnqualifiedType() !=
ExpectedFirstParamType)
return SemaRef.Diag(FnDecl->getLocation(), InvalidParamTypeDiag)
<< FnDecl->getDeclName() << ExpectedFirstParamType;
-
+
return false;
}
@@ -12619,18 +12671,18 @@ static bool
CheckOperatorNewDeclaration(Sema &SemaRef, const FunctionDecl *FnDecl) {
// C++ [basic.stc.dynamic.allocation]p1:
// A program is ill-formed if an allocation function is declared in a
- // namespace scope other than global scope or declared static in global
+ // namespace scope other than global scope or declared static in global
// scope.
if (CheckOperatorNewDeleteDeclarationScope(SemaRef, FnDecl))
return true;
- CanQualType SizeTy =
+ CanQualType SizeTy =
SemaRef.Context.getCanonicalType(SemaRef.Context.getSizeType());
// C++ [basic.stc.dynamic.allocation]p1:
- // The return type shall be void*. The first parameter shall have type
+ // The return type shall be void*. The first parameter shall have type
// std::size_t.
- if (CheckOperatorNewDeleteTypes(SemaRef, FnDecl, SemaRef.Context.VoidPtrTy,
+ if (CheckOperatorNewDeleteTypes(SemaRef, FnDecl, SemaRef.Context.VoidPtrTy,
SizeTy,
diag::err_operator_new_dependent_param_type,
diag::err_operator_new_param_type))
@@ -12650,20 +12702,40 @@ static bool
CheckOperatorDeleteDeclaration(Sema &SemaRef, FunctionDecl *FnDecl) {
// C++ [basic.stc.dynamic.deallocation]p1:
// A program is ill-formed if deallocation functions are declared in a
- // namespace scope other than global scope or declared static in global
+ // namespace scope other than global scope or declared static in global
// scope.
if (CheckOperatorNewDeleteDeclarationScope(SemaRef, FnDecl))
return true;
+ auto *MD = dyn_cast<CXXMethodDecl>(FnDecl);
+
+ // C++ P0722:
+ // Within a class C, the first parameter of a destroying operator delete
+ // shall be of type C *. The first parameter of any other deallocation
+ // function shall be of type void *.
+ CanQualType ExpectedFirstParamType =
+ MD && MD->isDestroyingOperatorDelete()
+ ? SemaRef.Context.getCanonicalType(SemaRef.Context.getPointerType(
+ SemaRef.Context.getRecordType(MD->getParent())))
+ : SemaRef.Context.VoidPtrTy;
+
// C++ [basic.stc.dynamic.deallocation]p2:
- // Each deallocation function shall return void and its first parameter
- // shall be void*.
- if (CheckOperatorNewDeleteTypes(SemaRef, FnDecl, SemaRef.Context.VoidTy,
- SemaRef.Context.VoidPtrTy,
- diag::err_operator_delete_dependent_param_type,
- diag::err_operator_delete_param_type))
+ // Each deallocation function shall return void
+ if (CheckOperatorNewDeleteTypes(
+ SemaRef, FnDecl, SemaRef.Context.VoidTy, ExpectedFirstParamType,
+ diag::err_operator_delete_dependent_param_type,
+ diag::err_operator_delete_param_type))
return true;
+ // C++ P0722:
+ // A destroying operator delete shall be a usual deallocation function.
+ if (MD && !MD->getParent()->isDependentContext() &&
+ MD->isDestroyingOperatorDelete() && !MD->isUsualDeallocationFunction()) {
+ SemaRef.Diag(MD->getLocation(),
+ diag::err_destroying_operator_delete_not_usual);
+ return true;
+ }
+
return false;
}
@@ -12684,7 +12756,7 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) {
// explicitly stated in 3.7.3.
if (Op == OO_Delete || Op == OO_Array_Delete)
return CheckOperatorDeleteDeclaration(*this, FnDecl);
-
+
if (Op == OO_New || Op == OO_Array_New)
return CheckOperatorNewDeclaration(*this, FnDecl);
@@ -13088,7 +13160,7 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S,
IdentifierInfo *Name) {
bool Invalid = false;
QualType ExDeclType = TInfo->getType();
-
+
// Arrays and functions decay.
if (ExDeclType->isArrayType())
ExDeclType = Context.getArrayDecayedType(ExDeclType);
@@ -13152,7 +13224,7 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S,
VarDecl *ExDecl = VarDecl::Create(Context, CurContext, StartLoc, Loc, Name,
ExDeclType, TInfo, SC_None);
ExDecl->setExceptionVariable(true);
-
+
// In ARC, infer 'retaining' for variables of retainable type.
if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(ExDecl))
Invalid = true;
@@ -13193,13 +13265,13 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S,
Expr *init = MaybeCreateExprWithCleanups(construct);
ExDecl->setInit(init);
}
-
+
// And make sure it's destructable.
FinalizeVarWithDestructor(ExDecl, recordType);
}
}
}
-
+
if (Invalid)
ExDecl->setInvalidDecl();
@@ -13215,7 +13287,7 @@ Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
// Check for unexpanded parameter packs.
if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo,
UPPC_ExceptionType)) {
- TInfo = Context.getTrivialTypeSourceInfo(Context.IntTy,
+ TInfo = Context.getTrivialTypeSourceInfo(Context.IntTy,
D.getIdentifierLoc());
Invalid = true;
}
@@ -13223,7 +13295,7 @@ Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
IdentifierInfo *II = D.getIdentifier();
if (NamedDecl *PrevDecl = LookupSingleName(S, II, D.getIdentifierLoc(),
LookupOrdinaryName,
- ForRedeclaration)) {
+ ForVisibleRedeclaration)) {
// The scope should be freshly made just for us. There is just no way
// it contains any previous declaration, except for function parameters in
// a function-try-block's catch statement.
@@ -13300,8 +13372,20 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
llvm::raw_svector_ostream Msg(MsgBuffer);
if (AssertMessage)
AssertMessage->printPretty(Msg, nullptr, getPrintingPolicy());
- Diag(StaticAssertLoc, diag::err_static_assert_failed)
- << !AssertMessage << Msg.str() << AssertExpr->getSourceRange();
+
+ Expr *InnerCond = nullptr;
+ std::string InnerCondDescription;
+ std::tie(InnerCond, InnerCondDescription) =
+ findFailedBooleanCondition(Converted.get(),
+ /*AllowTopLevelCond=*/false);
+ if (InnerCond) {
+ Diag(StaticAssertLoc, diag::err_static_assert_requirement_failed)
+ << InnerCondDescription << !AssertMessage
+ << Msg.str() << InnerCond->getSourceRange();
+ } else {
+ Diag(StaticAssertLoc, diag::err_static_assert_failed)
+ << !AssertMessage << Msg.str() << AssertExpr->getSourceRange();
+ }
Failed = true;
}
}
@@ -13329,10 +13413,10 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart,
SourceLocation FriendLoc,
TypeSourceInfo *TSInfo) {
assert(TSInfo && "NULL TypeSourceInfo for friend type declaration");
-
+
QualType T = TSInfo->getType();
SourceRange TypeRange = TSInfo->getTypeLoc().getLocalSourceRange();
-
+
// C++03 [class.friend]p2:
// An elaborated-type-specifier shall be used in a friend declaration
// for a class.*
@@ -13376,7 +13460,7 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart,
<< T
<< TypeRange;
}
-
+
// C++11 [class.friend]p3:
// A friend declaration that does not declare a function shall have one
// of the following forms:
@@ -13489,9 +13573,9 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
CurContext->addDecl(Friend);
return Friend;
}
-
+
assert(SS.isNotEmpty() && "valid templated tag with no SS and no direct?");
-
+
// Handle the case of a templated-scope friend class. e.g.
@@ -13571,7 +13655,7 @@ Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
<< DS.getSourceRange();
return nullptr;
}
-
+
// C++98 [class.friend]p1: A friend of a class is a function
// or class that is not a member of the class . . .
// This is fixed in DR77, which just barely didn't make the C++03
@@ -13591,7 +13675,7 @@ Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
DS.getFriendSpecLoc());
else
D = CheckFriendTypeDecl(Loc, DS.getFriendSpecLoc(), TSI);
-
+
if (!D)
return nullptr;
@@ -13660,7 +13744,7 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
DeclContext *DC;
Scope *DCScope = S;
LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
- ForRedeclaration);
+ ForExternalRedeclaration);
// There are five cases here.
// - There's no scope specifier and we're in a local class. Only look
@@ -13791,15 +13875,15 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_friend_is_member :
diag::err_friend_is_member);
-
+
if (D.isFunctionDefinition()) {
// C++ [class.friend]p6:
- // A function can be defined in a friend declaration of a class if and
+ // A function can be defined in a friend declaration of a class if and
// only if the class is a non-local class (9.8), the function name is
// unqualified, and the function has namespace scope.
SemaDiagnosticBuilder DB
= Diag(SS.getRange().getBegin(), diag::err_qualified_friend_def);
-
+
DB << SS.getScopeRep();
if (DC->isFileContext())
DB << FixItHint::CreateRemoval(SS.getRange());
@@ -13814,13 +13898,13 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
} else {
if (D.isFunctionDefinition()) {
// C++ [class.friend]p6:
- // A function can be defined in a friend declaration of a class if and
+ // A function can be defined in a friend declaration of a class if and
// only if the class is a non-local class (9.8), the function name is
// unqualified, and the function has namespace scope.
Diag(SS.getRange().getBegin(), diag::err_qualified_friend_def)
<< SS.getScopeRep();
}
-
+
DC = CurContext;
assert(isa<CXXRecordDecl>(DC) && "friend declaration not in class?");
}
@@ -13856,7 +13940,7 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
}
// FIXME: This is an egregious hack to cope with cases where the scope stack
- // does not contain the declaration context, i.e., in an out-of-line
+ // does not contain the declaration context, i.e., in an out-of-line
// definition of a class.
Scope FakeDCScope(S, Scope::DeclScope, Diags);
if (!DCScope) {
@@ -13974,15 +14058,13 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) {
// non-deleted virtual function.
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Fn)) {
bool IssuedDiagnostic = false;
- for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
- E = MD->end_overridden_methods();
- I != E; ++I) {
+ for (const CXXMethodDecl *O : MD->overridden_methods()) {
if (!(*MD->begin_overridden_methods())->isDeleted()) {
if (!IssuedDiagnostic) {
Diag(DelLoc, diag::err_deleted_override) << MD->getDeclName();
IssuedDiagnostic = true;
}
- Diag((*I)->getLocation(), diag::note_overridden_virtual_function);
+ Diag(O->getLocation(), diag::note_overridden_virtual_function);
}
}
// If this function was implicitly deleted because it was defaulted,
@@ -14072,8 +14154,21 @@ void Sema::DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock) {
bool Sema::CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
const CXXMethodDecl *Old) {
- const FunctionType *NewFT = New->getType()->getAs<FunctionType>();
- const FunctionType *OldFT = Old->getType()->getAs<FunctionType>();
+ const auto *NewFT = New->getType()->getAs<FunctionProtoType>();
+ const auto *OldFT = Old->getType()->getAs<FunctionProtoType>();
+
+ if (OldFT->hasExtParameterInfos()) {
+ for (unsigned I = 0, E = OldFT->getNumParams(); I != E; ++I)
+ // A parameter of the overriding method should be annotated with noescape
+ // if the corresponding parameter of the overridden method is annotated.
+ if (OldFT->getExtParameterInfo(I).isNoEscape() &&
+ !NewFT->getExtParameterInfo(I).isNoEscape()) {
+ Diag(New->getParamDecl(I)->getLocation(),
+ diag::warn_overriding_method_missing_noescape);
+ Diag(Old->getParamDecl(I)->getLocation(),
+ diag::note_overridden_marked_noescape);
+ }
+ }
CallingConv NewCC = NewFT->getCallConv(), OldCC = OldFT->getCallConv();
@@ -14231,21 +14326,22 @@ void Sema::ActOnPureSpecifier(Decl *D, SourceLocation ZeroLoc) {
Diag(D->getLocation(), diag::err_illegal_initializer);
}
-/// \brief Determine whether the given declaration is a static data member.
-static bool isStaticDataMember(const Decl *D) {
+/// \brief Determine whether the given declaration is a global variable or
+/// static data member.
+static bool isNonlocalVariable(const Decl *D) {
if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(D))
- return Var->isStaticDataMember();
+ return Var->hasGlobalStorage();
return false;
}
-/// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse
-/// an initializer for the out-of-line declaration 'Dcl'. The scope
-/// is a fresh scope pushed for just this purpose.
+/// Invoked when we are about to parse an initializer for the declaration
+/// 'Dcl'.
///
/// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a
/// static data member of class X, names should be looked up in the scope of
-/// class X.
+/// class X. If the declaration had a scope specifier, a scope will have
+/// been created and passed in for this purpose. Otherwise, S will be null.
void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) {
// If there is no declaration, there was an error parsing it.
if (!D || D->isInvalidDecl())
@@ -14255,28 +14351,27 @@ void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) {
// might not be out of line if the specifier names the current namespace:
// extern int n;
// int ::n = 0;
- if (D->isOutOfLine())
+ if (S && D->isOutOfLine())
EnterDeclaratorContext(S, D->getDeclContext());
// If we are parsing the initializer for a static data member, push a
// new expression evaluation context that is associated with this static
// data member.
- if (isStaticDataMember(D))
+ if (isNonlocalVariable(D))
PushExpressionEvaluationContext(
ExpressionEvaluationContext::PotentiallyEvaluated, D);
}
-/// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an
-/// initializer for the out-of-line declaration 'D'.
+/// Invoked after we are finished parsing an initializer for the declaration D.
void Sema::ActOnCXXExitDeclInitializer(Scope *S, Decl *D) {
// If there is no declaration, there was an error parsing it.
if (!D || D->isInvalidDecl())
return;
- if (isStaticDataMember(D))
+ if (isNonlocalVariable(D))
PopExpressionEvaluationContext();
- if (D->isOutOfLine())
+ if (S && D->isOutOfLine())
ExitDeclaratorContext(S);
}
@@ -14307,7 +14402,7 @@ DeclResult Sema::ActOnCXXConditionDeclaration(Scope *S, Declarator &D) {
void Sema::LoadExternalVTableUses() {
if (!ExternalSource)
return;
-
+
SmallVector<ExternalVTableUse, 4> VTables;
ExternalSource->ReadUsedVTables(VTables);
SmallVector<VTableUse, 4> NewUses;
@@ -14320,11 +14415,11 @@ void Sema::LoadExternalVTableUses() {
Pos->second = true;
continue;
}
-
+
VTablesUsed[VTables[I].Record] = VTables[I].DefinitionRequired;
NewUses.push_back(VTableUse(VTables[I].Record, VTables[I].Location));
}
-
+
VTableUses.insert(VTableUses.begin(), NewUses.begin(), NewUses.end());
}
@@ -14531,17 +14626,17 @@ void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) {
FieldDecl *Field = ivars[i];
if (Field->isInvalidDecl())
continue;
-
+
CXXCtorInitializer *Member;
InitializedEntity InitEntity = InitializedEntity::InitializeMember(Field);
- InitializationKind InitKind =
+ InitializationKind InitKind =
InitializationKind::CreateDefault(ObjCImplementation->getLocation());
InitializationSequence InitSeq(*this, InitEntity, InitKind, None);
ExprResult MemberInit =
InitSeq.Perform(*this, InitEntity, InitKind, None);
MemberInit = MaybeCreateExprWithCleanups(MemberInit);
- // Note, MemberInit could actually come back empty if no initialization
+ // Note, MemberInit could actually come back empty if no initialization
// is required (e.g., because it would call a trivial default constructor)
if (!MemberInit.get() || MemberInit.isInvalid())
continue;
@@ -14552,7 +14647,7 @@ void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) {
MemberInit.getAs<Expr>(),
SourceLocation());
AllToInit.push_back(Member);
-
+
// Be sure that the destructor is accessible and is marked as referenced.
if (const RecordType *RecordTy =
Context.getBaseElementType(Field->getType())
@@ -14564,9 +14659,9 @@ void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) {
PDiag(diag::err_access_dtor_ivar)
<< Context.getBaseElementType(Field->getType()));
}
- }
+ }
}
- ObjCImplementation->setIvarInitializers(Context,
+ ObjCImplementation->setIvarInitializers(Context,
AllToInit.data(), AllToInit.size());
}
}
@@ -14634,7 +14729,7 @@ void DelegatingCycleHelper(CXXConstructorDecl* Ctor,
DelegatingCycleHelper(Target, Valid, Invalid, Current, S);
}
}
-
+
void Sema::CheckDelegatingCtorCycles() {
llvm::SmallSet<CXXConstructorDecl*, 4> Valid, Invalid, Current;
@@ -14655,10 +14750,10 @@ namespace {
/// \brief AST visitor that finds references to the 'this' expression.
class FindCXXThisExpr : public RecursiveASTVisitor<FindCXXThisExpr> {
Sema &S;
-
+
public:
explicit FindCXXThisExpr(Sema &S) : S(S) { }
-
+
bool VisitCXXThisExpr(CXXThisExpr *E) {
S.Diag(E->getLocation(), diag::err_this_static_member_func)
<< E->isImplicit();
@@ -14671,22 +14766,22 @@ bool Sema::checkThisInStaticMemberFunctionType(CXXMethodDecl *Method) {
TypeSourceInfo *TSInfo = Method->getTypeSourceInfo();
if (!TSInfo)
return false;
-
+
TypeLoc TL = TSInfo->getTypeLoc();
FunctionProtoTypeLoc ProtoTL = TL.getAs<FunctionProtoTypeLoc>();
if (!ProtoTL)
return false;
-
+
// C++11 [expr.prim.general]p3:
- // [The expression this] shall not appear before the optional
- // cv-qualifier-seq and it shall not appear within the declaration of a
+ // [The expression this] shall not appear before the optional
+ // cv-qualifier-seq and it shall not appear within the declaration of a
// static member function (although its type and value category are defined
// within a static member function as they are within a non-static member
// function). [ Note: this is because declaration matching does not occur
// until the complete declarator is known. - end note ]
const FunctionProtoType *Proto = ProtoTL.getTypePtr();
FindCXXThisExpr Finder(*this);
-
+
// If the return type came after the cv-qualifier-seq, check it now.
if (Proto->hasTrailingReturn() &&
!Finder.TraverseTypeLoc(ProtoTL.getReturnLoc()))
@@ -14695,7 +14790,7 @@ bool Sema::checkThisInStaticMemberFunctionType(CXXMethodDecl *Method) {
// Check the exception specification.
if (checkThisInStaticMemberFunctionExceptionSpec(Method))
return true;
-
+
return checkThisInStaticMemberFunctionAttributes(Method);
}
@@ -14703,12 +14798,12 @@ bool Sema::checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method) {
TypeSourceInfo *TSInfo = Method->getTypeSourceInfo();
if (!TSInfo)
return false;
-
+
TypeLoc TL = TSInfo->getTypeLoc();
FunctionProtoTypeLoc ProtoTL = TL.getAs<FunctionProtoTypeLoc>();
if (!ProtoTL)
return false;
-
+
const FunctionProtoType *Proto = ProtoTL.getTypePtr();
FindCXXThisExpr Finder(*this);
@@ -14721,12 +14816,12 @@ bool Sema::checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method) {
case EST_MSAny:
case EST_None:
break;
-
+
case EST_ComputedNoexcept:
if (!Finder.TraverseStmt(Proto->getNoexceptExpr()))
return true;
LLVM_FALLTHROUGH;
-
+
case EST_Dynamic:
for (const auto &E : Proto->exceptions()) {
if (!Finder.TraverseType(E))
@@ -14775,13 +14870,13 @@ bool Sema::checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method) {
if (Arg && !Finder.TraverseStmt(Arg))
return true;
-
+
for (unsigned I = 0, N = Args.size(); I != N; ++I) {
if (!Finder.TraverseStmt(Args[I]))
return true;
}
}
-
+
return false;
}
@@ -14832,10 +14927,16 @@ void Sema::checkExceptionSpecification(
return;
}
- if (!NoexceptExpr->isValueDependent())
- NoexceptExpr = VerifyIntegerConstantExpression(NoexceptExpr, nullptr,
- diag::err_noexcept_needs_constant_expression,
- /*AllowFold*/ false).get();
+ if (!NoexceptExpr->isValueDependent()) {
+ ExprResult Result = VerifyIntegerConstantExpression(
+ NoexceptExpr, nullptr, diag::err_noexcept_needs_constant_expression,
+ /*AllowFold*/ false);
+ if (Result.isInvalid()) {
+ ESI.Type = EST_BasicNoexcept;
+ return;
+ }
+ NoexceptExpr = Result.get();
+ }
ESI.NoexceptExpr = NoexceptExpr;
}
return;
@@ -14874,10 +14975,8 @@ void Sema::actOnDelayedExceptionSpecification(Decl *MethodD,
if (Method->isVirtual()) {
// Check overrides, which we previously had to delay.
- for (CXXMethodDecl::method_iterator O = Method->begin_overridden_methods(),
- OEnd = Method->end_overridden_methods();
- O != OEnd; ++O)
- CheckOverridingFunctionExceptionSpec(Method, *O);
+ for (const CXXMethodDecl *O : Method->overridden_methods())
+ CheckOverridingFunctionExceptionSpec(Method, O);
}
}
@@ -14913,7 +15012,7 @@ MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record,
if (D.getDeclSpec().isInlineSpecified())
Diag(D.getDeclSpec().getInlineSpecLoc(), diag::err_inline_non_function)
- << getLangOpts().CPlusPlus1z;
+ << getLangOpts().CPlusPlus17;
if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec())
Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
diag::err_invalid_thread)
@@ -14921,7 +15020,8 @@ MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record,
// Check to see if this name was declared as a member previously
NamedDecl *PrevDecl = nullptr;
- LookupResult Previous(*this, II, Loc, LookupMemberName, ForRedeclaration);
+ LookupResult Previous(*this, II, Loc, LookupMemberName,
+ ForVisibleRedeclaration);
LookupName(Previous, S);
switch (Previous.getResultKind()) {
case LookupResult::Found:
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
index 967573011d0dc..abbdc9574b8ce 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
@@ -157,34 +157,44 @@ void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,
diag::note_related_result_type_overridden);
}
if (getLangOpts().ObjCAutoRefCount) {
- if ((NewMethod->hasAttr<NSReturnsRetainedAttr>() !=
- Overridden->hasAttr<NSReturnsRetainedAttr>())) {
- Diag(NewMethod->getLocation(),
- diag::err_nsreturns_retained_attribute_mismatch) << 1;
- Diag(Overridden->getLocation(), diag::note_previous_decl)
- << "method";
- }
- if ((NewMethod->hasAttr<NSReturnsNotRetainedAttr>() !=
- Overridden->hasAttr<NSReturnsNotRetainedAttr>())) {
- Diag(NewMethod->getLocation(),
- diag::err_nsreturns_retained_attribute_mismatch) << 0;
- Diag(Overridden->getLocation(), diag::note_previous_decl)
- << "method";
+ Diags.setSeverity(diag::warn_nsreturns_retained_attribute_mismatch,
+ diag::Severity::Error, SourceLocation());
+ Diags.setSeverity(diag::warn_nsconsumed_attribute_mismatch,
+ diag::Severity::Error, SourceLocation());
+ }
+
+ if ((NewMethod->hasAttr<NSReturnsRetainedAttr>() !=
+ Overridden->hasAttr<NSReturnsRetainedAttr>())) {
+ Diag(NewMethod->getLocation(),
+ diag::warn_nsreturns_retained_attribute_mismatch) << 1;
+ Diag(Overridden->getLocation(), diag::note_previous_decl) << "method";
+ }
+ if ((NewMethod->hasAttr<NSReturnsNotRetainedAttr>() !=
+ Overridden->hasAttr<NSReturnsNotRetainedAttr>())) {
+ Diag(NewMethod->getLocation(),
+ diag::warn_nsreturns_retained_attribute_mismatch) << 0;
+ Diag(Overridden->getLocation(), diag::note_previous_decl) << "method";
+ }
+
+ ObjCMethodDecl::param_const_iterator oi = Overridden->param_begin(),
+ oe = Overridden->param_end();
+ for (ObjCMethodDecl::param_iterator ni = NewMethod->param_begin(),
+ ne = NewMethod->param_end();
+ ni != ne && oi != oe; ++ni, ++oi) {
+ const ParmVarDecl *oldDecl = (*oi);
+ ParmVarDecl *newDecl = (*ni);
+ if (newDecl->hasAttr<NSConsumedAttr>() !=
+ oldDecl->hasAttr<NSConsumedAttr>()) {
+ Diag(newDecl->getLocation(), diag::warn_nsconsumed_attribute_mismatch);
+ Diag(oldDecl->getLocation(), diag::note_previous_decl) << "parameter";
}
- ObjCMethodDecl::param_const_iterator oi = Overridden->param_begin(),
- oe = Overridden->param_end();
- for (ObjCMethodDecl::param_iterator
- ni = NewMethod->param_begin(), ne = NewMethod->param_end();
- ni != ne && oi != oe; ++ni, ++oi) {
- const ParmVarDecl *oldDecl = (*oi);
- ParmVarDecl *newDecl = (*ni);
- if (newDecl->hasAttr<NSConsumedAttr>() !=
- oldDecl->hasAttr<NSConsumedAttr>()) {
- Diag(newDecl->getLocation(),
- diag::err_nsconsumed_attribute_mismatch);
- Diag(oldDecl->getLocation(), diag::note_previous_decl)
- << "parameter";
- }
+
+ // A parameter of the overriding method should be annotated with noescape
+ // if the corresponding parameter of the overridden method is annotated.
+ if (oldDecl->hasAttr<NoEscapeAttr>() && !newDecl->hasAttr<NoEscapeAttr>()) {
+ Diag(newDecl->getLocation(),
+ diag::warn_overriding_method_missing_noescape);
+ Diag(oldDecl->getLocation(), diag::note_overridden_marked_noescape);
}
}
}
@@ -933,8 +943,9 @@ ActOnStartClassInterface(Scope *S, SourceLocation AtInterfaceLoc,
assert(ClassName && "Missing class identifier");
// Check for another declaration kind with the same name.
- NamedDecl *PrevDecl = LookupSingleName(TUScope, ClassName, ClassLoc,
- LookupOrdinaryName, ForRedeclaration);
+ NamedDecl *PrevDecl =
+ LookupSingleName(TUScope, ClassName, ClassLoc, LookupOrdinaryName,
+ forRedeclarationInCurContext());
if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName;
@@ -1085,16 +1096,18 @@ Decl *Sema::ActOnCompatibilityAlias(SourceLocation AtLoc,
IdentifierInfo *ClassName,
SourceLocation ClassLocation) {
// Look for previous declaration of alias name
- NamedDecl *ADecl = LookupSingleName(TUScope, AliasName, AliasLocation,
- LookupOrdinaryName, ForRedeclaration);
+ NamedDecl *ADecl =
+ LookupSingleName(TUScope, AliasName, AliasLocation, LookupOrdinaryName,
+ forRedeclarationInCurContext());
if (ADecl) {
Diag(AliasLocation, diag::err_conflicting_aliasing_type) << AliasName;
Diag(ADecl->getLocation(), diag::note_previous_declaration);
return nullptr;
}
// Check for class declaration
- NamedDecl *CDeclU = LookupSingleName(TUScope, ClassName, ClassLocation,
- LookupOrdinaryName, ForRedeclaration);
+ NamedDecl *CDeclU =
+ LookupSingleName(TUScope, ClassName, ClassLocation, LookupOrdinaryName,
+ forRedeclarationInCurContext());
if (const TypedefNameDecl *TDecl =
dyn_cast_or_null<TypedefNameDecl>(CDeclU)) {
QualType T = TDecl->getUnderlyingType();
@@ -1102,7 +1115,8 @@ Decl *Sema::ActOnCompatibilityAlias(SourceLocation AtLoc,
if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface()) {
ClassName = IDecl->getIdentifier();
CDeclU = LookupSingleName(TUScope, ClassName, ClassLocation,
- LookupOrdinaryName, ForRedeclaration);
+ LookupOrdinaryName,
+ forRedeclarationInCurContext());
}
}
}
@@ -1164,7 +1178,7 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
// FIXME: Deal with AttrList.
assert(ProtocolName && "Missing protocol identifier");
ObjCProtocolDecl *PrevDecl = LookupProtocol(ProtocolName, ProtocolLoc,
- ForRedeclaration);
+ forRedeclarationInCurContext());
ObjCProtocolDecl *PDecl = nullptr;
if (ObjCProtocolDecl *Def = PrevDecl? PrevDecl->getDefinition() : nullptr) {
// If we already have a definition, complain.
@@ -1720,7 +1734,7 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
for (const IdentifierLocPair &IdentPair : IdentList) {
IdentifierInfo *Ident = IdentPair.first;
ObjCProtocolDecl *PrevDecl = LookupProtocol(Ident, IdentPair.second,
- ForRedeclaration);
+ forRedeclarationInCurContext());
ObjCProtocolDecl *PDecl
= ObjCProtocolDecl::Create(Context, CurContext, Ident,
IdentPair.second, AtProtocolLoc,
@@ -1911,7 +1925,7 @@ Decl *Sema::ActOnStartClassImplementation(
// Check for another declaration kind with the same name.
NamedDecl *PrevDecl
= LookupSingleName(TUScope, ClassName, ClassLoc, LookupOrdinaryName,
- ForRedeclaration);
+ forRedeclarationInCurContext());
if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName;
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
@@ -2987,7 +3001,7 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
// Check for another declaration kind with the same name.
NamedDecl *PrevDecl
= LookupSingleName(TUScope, IdentList[i], IdentLocs[i],
- LookupOrdinaryName, ForRedeclaration);
+ LookupOrdinaryName, forRedeclarationInCurContext());
if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
// GCC apparently allows the following idiom:
//
@@ -3707,6 +3721,26 @@ static void DiagnoseWeakIvars(Sema &S, ObjCImplementationDecl *ID) {
}
}
+/// Diagnose attempts to use flexible array member with retainable object type.
+static void DiagnoseRetainableFlexibleArrayMember(Sema &S,
+ ObjCInterfaceDecl *ID) {
+ if (!S.getLangOpts().ObjCAutoRefCount)
+ return;
+
+ for (auto ivar = ID->all_declared_ivar_begin(); ivar;
+ ivar = ivar->getNextIvar()) {
+ if (ivar->isInvalidDecl())
+ continue;
+ QualType IvarTy = ivar->getType();
+ if (IvarTy->isIncompleteArrayType() &&
+ (IvarTy.getObjCLifetime() != Qualifiers::OCL_ExplicitNone) &&
+ IvarTy->isObjCLifetimeType()) {
+ S.Diag(ivar->getLocation(), diag::err_flexible_array_arc_retainable);
+ ivar->setInvalidDecl();
+ }
+ }
+}
+
Sema::ObjCContainerKind Sema::getObjCContainerKind() const {
switch (CurContext->getDeclKind()) {
case Decl::ObjCInterface:
@@ -3727,6 +3761,96 @@ Sema::ObjCContainerKind Sema::getObjCContainerKind() const {
}
}
+static bool IsVariableSizedType(QualType T) {
+ if (T->isIncompleteArrayType())
+ return true;
+ const auto *RecordTy = T->getAs<RecordType>();
+ return (RecordTy && RecordTy->getDecl()->hasFlexibleArrayMember());
+}
+
+static void DiagnoseVariableSizedIvars(Sema &S, ObjCContainerDecl *OCD) {
+ ObjCInterfaceDecl *IntfDecl = nullptr;
+ ObjCInterfaceDecl::ivar_range Ivars = llvm::make_range(
+ ObjCInterfaceDecl::ivar_iterator(), ObjCInterfaceDecl::ivar_iterator());
+ if ((IntfDecl = dyn_cast<ObjCInterfaceDecl>(OCD))) {
+ Ivars = IntfDecl->ivars();
+ } else if (auto *ImplDecl = dyn_cast<ObjCImplementationDecl>(OCD)) {
+ IntfDecl = ImplDecl->getClassInterface();
+ Ivars = ImplDecl->ivars();
+ } else if (auto *CategoryDecl = dyn_cast<ObjCCategoryDecl>(OCD)) {
+ if (CategoryDecl->IsClassExtension()) {
+ IntfDecl = CategoryDecl->getClassInterface();
+ Ivars = CategoryDecl->ivars();
+ }
+ }
+
+ // Check if variable sized ivar is in interface and visible to subclasses.
+ if (!isa<ObjCInterfaceDecl>(OCD)) {
+ for (auto ivar : Ivars) {
+ if (!ivar->isInvalidDecl() && IsVariableSizedType(ivar->getType())) {
+ S.Diag(ivar->getLocation(), diag::warn_variable_sized_ivar_visibility)
+ << ivar->getDeclName() << ivar->getType();
+ }
+ }
+ }
+
+ // Subsequent checks require interface decl.
+ if (!IntfDecl)
+ return;
+
+ // Check if variable sized ivar is followed by another ivar.
+ for (ObjCIvarDecl *ivar = IntfDecl->all_declared_ivar_begin(); ivar;
+ ivar = ivar->getNextIvar()) {
+ if (ivar->isInvalidDecl() || !ivar->getNextIvar())
+ continue;
+ QualType IvarTy = ivar->getType();
+ bool IsInvalidIvar = false;
+ if (IvarTy->isIncompleteArrayType()) {
+ S.Diag(ivar->getLocation(), diag::err_flexible_array_not_at_end)
+ << ivar->getDeclName() << IvarTy
+ << TTK_Class; // Use "class" for Obj-C.
+ IsInvalidIvar = true;
+ } else if (const RecordType *RecordTy = IvarTy->getAs<RecordType>()) {
+ if (RecordTy->getDecl()->hasFlexibleArrayMember()) {
+ S.Diag(ivar->getLocation(),
+ diag::err_objc_variable_sized_type_not_at_end)
+ << ivar->getDeclName() << IvarTy;
+ IsInvalidIvar = true;
+ }
+ }
+ if (IsInvalidIvar) {
+ S.Diag(ivar->getNextIvar()->getLocation(),
+ diag::note_next_ivar_declaration)
+ << ivar->getNextIvar()->getSynthesize();
+ ivar->setInvalidDecl();
+ }
+ }
+
+ // Check if ObjC container adds ivars after variable sized ivar in superclass.
+ // Perform the check only if OCD is the first container to declare ivars to
+ // avoid multiple warnings for the same ivar.
+ ObjCIvarDecl *FirstIvar =
+ (Ivars.begin() == Ivars.end()) ? nullptr : *Ivars.begin();
+ if (FirstIvar && (FirstIvar == IntfDecl->all_declared_ivar_begin())) {
+ const ObjCInterfaceDecl *SuperClass = IntfDecl->getSuperClass();
+ while (SuperClass && SuperClass->ivar_empty())
+ SuperClass = SuperClass->getSuperClass();
+ if (SuperClass) {
+ auto IvarIter = SuperClass->ivar_begin();
+ std::advance(IvarIter, SuperClass->ivar_size() - 1);
+ const ObjCIvarDecl *LastIvar = *IvarIter;
+ if (IsVariableSizedType(LastIvar->getType())) {
+ S.Diag(FirstIvar->getLocation(),
+ diag::warn_superclass_variable_sized_type_not_at_end)
+ << FirstIvar->getDeclName() << LastIvar->getDeclName()
+ << LastIvar->getType() << SuperClass->getDeclName();
+ S.Diag(LastIvar->getLocation(), diag::note_entity_declared_at)
+ << LastIvar->getDeclName();
+ }
+ }
+ }
+}
+
// Note: For class/category implementations, allMethods is always null.
Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods,
ArrayRef<DeclGroupPtrTy> allTUVars) {
@@ -3858,6 +3982,7 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods,
if (IDecl->hasDesignatedInitializers())
DiagnoseMissingDesignatedInitOverrides(IC, IDecl);
DiagnoseWeakIvars(*this, IC);
+ DiagnoseRetainableFlexibleArrayMember(*this, IDecl);
bool HasRootClassAttr = IDecl->hasAttr<ObjCRootClassAttr>();
if (IDecl->getSuperClass() == nullptr) {
@@ -3927,6 +4052,7 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods,
}
}
}
+ DiagnoseVariableSizedIvars(*this, OCD);
if (isInterfaceDeclKind) {
// Reject invalid vardecls.
for (unsigned i = 0, e = allTUVars.size(); i != e; i++) {
@@ -4209,6 +4335,10 @@ void Sema::CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod,
// Then merge the declarations.
mergeObjCMethodDecls(ObjCMethod, overridden);
+ }
+
+ for (ObjCMethodDecl *overridden : overrides) {
+ CheckObjCMethodOverride(ObjCMethod, overridden);
if (ObjCMethod->isImplicit() && overridden->isImplicit())
continue; // Conflicting properties are detected elsewhere.
@@ -4433,7 +4563,7 @@ Decl *Sema::ActOnMethodDeclaration(
}
LookupResult R(*this, ArgInfo[i].Name, ArgInfo[i].NameLoc,
- LookupOrdinaryName, ForRedeclaration);
+ LookupOrdinaryName, forRedeclarationInCurContext());
LookupName(R, S);
if (R.isSingleResult()) {
NamedDecl *PrevDecl = R.getFoundDecl();
@@ -4670,7 +4800,7 @@ VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType T,
// duration shall not be qualified by an address-space qualifier."
// Since all parameters have automatic store duration, they can not have
// an address space.
- if (T.getAddressSpace() != 0) {
+ if (T.getAddressSpace() != LangAS::Default) {
Diag(IdLoc, diag::err_arg_with_address_space);
Invalid = true;
}
@@ -4716,7 +4846,7 @@ Decl *Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) {
}
if (DS.isInlineSpecified())
Diag(DS.getInlineSpecLoc(), diag::err_inline_non_function)
- << getLangOpts().CPlusPlus1z;
+ << getLangOpts().CPlusPlus17;
if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec())
Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
diag::err_invalid_thread)
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
index deb6cbb53aff5..67d1b02d1fca8 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -145,7 +145,7 @@ bool Sema::CheckSpecifiedExceptionType(QualType &T, SourceRange Range) {
bool Sema::CheckDistantExceptionSpec(QualType T) {
// C++17 removes this rule in favor of putting exception specifications into
// the type system.
- if (getLangOpts().CPlusPlus1z)
+ if (getLangOpts().CPlusPlus17)
return false;
if (const PointerType *PT = T->getAs<PointerType>())
@@ -237,10 +237,10 @@ static bool hasImplicitExceptionSpec(FunctionDecl *Decl) {
}
bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
- // Just completely ignore this under -fno-exceptions prior to C++1z.
- // In C++1z onwards, the exception specification is part of the type and
+ // Just completely ignore this under -fno-exceptions prior to C++17.
+ // In C++17 onwards, the exception specification is part of the type and
// we will diagnose mismatches anyway, so it's better to check for them here.
- if (!getLangOpts().CXXExceptions && !getLangOpts().CPlusPlus1z)
+ if (!getLangOpts().CXXExceptions && !getLangOpts().CPlusPlus17)
return false;
OverloadedOperatorKind OO = New->getDeclName().getCXXOverloadedOperator();
@@ -872,7 +872,7 @@ bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType) {
// This is not an error in C++17 onwards, unless the noexceptness doesn't
// match, but in that case we have a full-on type mismatch, not just a
// type sugar mismatch.
- if (getLangOpts().CPlusPlus1z) {
+ if (getLangOpts().CPlusPlus17) {
DiagID = diag::warn_incompatible_exception_specs;
NestedDiagID = diag::warn_deep_exception_specs_differ;
}
@@ -892,7 +892,7 @@ bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType) {
return CheckExceptionSpecSubset(PDiag(DiagID), PDiag(NestedDiagID), PDiag(),
ToFunc, From->getSourceRange().getBegin(),
FromFunc, SourceLocation()) &&
- !getLangOpts().CPlusPlus1z;
+ !getLangOpts().CPlusPlus17;
}
bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
@@ -953,7 +953,7 @@ static CanThrowResult canCalleeThrow(Sema &S, const Expr *E, const Decl *D) {
QualType T;
// In C++1z, just look at the function type of the callee.
- if (S.getLangOpts().CPlusPlus1z && isa<CallExpr>(E)) {
+ if (S.getLangOpts().CPlusPlus17 && isa<CallExpr>(E)) {
E = cast<CallExpr>(E)->getCallee();
T = E->getType();
if (T->isSpecificPlaceholderType(BuiltinType::BoundMember)) {
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
index d3d7d8b67c70c..929806ac6bfaf 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
@@ -79,7 +79,8 @@ static void DiagnoseUnusedOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc) {
if (const auto *A = D->getAttr<UnusedAttr>()) {
// [[maybe_unused]] should not diagnose uses, but __attribute__((unused))
// should diagnose them.
- if (A->getSemanticSpelling() != UnusedAttr::CXX11_maybe_unused) {
+ if (A->getSemanticSpelling() != UnusedAttr::CXX11_maybe_unused &&
+ A->getSemanticSpelling() != UnusedAttr::C2x_maybe_unused) {
const Decl *DC = cast_or_null<Decl>(S.getCurObjCLexicalContext());
if (DC && !DC->hasAttr<UnusedAttr>())
S.Diag(Loc, diag::warn_used_but_marked_unused) << D->getDeclName();
@@ -425,14 +426,6 @@ ExprResult Sema::DefaultFunctionArrayConversion(Expr *E, bool Diagnose) {
assert(!Ty.isNull() && "DefaultFunctionArrayConversion - missing type");
if (Ty->isFunctionType()) {
- // If we are here, we are not calling a function but taking
- // its address (which is not allowed in OpenCL v1.0 s6.8.a.3).
- if (getLangOpts().OpenCL) {
- if (Diagnose)
- Diag(E->getExprLoc(), diag::err_opencl_taking_function_address);
- return ExprError();
- }
-
if (auto *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()))
if (auto *FD = dyn_cast<FunctionDecl>(DRE->getDecl()))
if (!checkAddressOfFunctionIsAvailable(FD, Diagnose, E->getExprLoc()))
@@ -722,8 +715,10 @@ ExprResult Sema::DefaultArgumentPromotion(Expr *E) {
return ExprError();
E = Res.get();
- // If this is a 'float' or '__fp16' (CVR qualified or typedef) promote to
- // double.
+ // If this is a 'float' or '__fp16' (CVR qualified or typedef)
+ // promote to double.
+ // Note that default argument promotion applies only to float (and
+ // half/fp16); it does not apply to _Float16.
const BuiltinType *BTy = Ty->getAs<BuiltinType>();
if (BTy && (BTy->getKind() == BuiltinType::Half ||
BTy->getKind() == BuiltinType::Float)) {
@@ -995,7 +990,7 @@ static QualType handleComplexFloatConversion(Sema &S, ExprResult &LHS,
return ResultType;
}
-/// \brief Hande arithmetic conversion from integer to float. Helper function
+/// \brief Handle arithmetic conversion from integer to float. Helper function
/// of UsualArithmeticConversions()
static QualType handleIntToFloatConversion(Sema &S, ExprResult &FloatExpr,
ExprResult &IntExpr,
@@ -1502,8 +1497,9 @@ static ExprResult BuildCookedLiteralOperatorCall(Sema &S, Scope *Scope,
LookupResult R(S, OpName, UDSuffixLoc, Sema::LookupOrdinaryName);
if (S.LookupLiteralOperator(Scope, R, llvm::makeArrayRef(ArgTy, Args.size()),
- /*AllowRaw*/false, /*AllowTemplate*/false,
- /*AllowStringTemplate*/false) == Sema::LOLR_Error)
+ /*AllowRaw*/ false, /*AllowTemplate*/ false,
+ /*AllowStringTemplate*/ false,
+ /*DiagnoseMissing*/ true) == Sema::LOLR_Error)
return ExprError();
return S.BuildLiteralOperatorCall(R, OpNameInfo, Args, LitEndLoc);
@@ -1594,8 +1590,9 @@ Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) {
LookupResult R(*this, OpName, UDSuffixLoc, LookupOrdinaryName);
switch (LookupLiteralOperator(UDLScope, R, ArgTy,
- /*AllowRaw*/false, /*AllowTemplate*/false,
- /*AllowStringTemplate*/true)) {
+ /*AllowRaw*/ false, /*AllowTemplate*/ false,
+ /*AllowStringTemplate*/ true,
+ /*DiagnoseMissing*/ true)) {
case LOLR_Cooked: {
llvm::APInt Len(Context.getIntWidth(SizeType), Literal.GetNumStringChars());
@@ -1628,6 +1625,7 @@ Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) {
}
case LOLR_Raw:
case LOLR_Template:
+ case LOLR_ErrorNoDiagnostic:
llvm_unreachable("unexpected literal operator lookup result");
case LOLR_Error:
return ExprError();
@@ -2806,6 +2804,8 @@ ExprResult Sema::BuildDeclarationNameExpr(
{
QualType type = VD->getType();
+ if (type.isNull())
+ return ExprError();
if (auto *FPT = type->getAs<FunctionProtoType>()) {
// C++ [except.spec]p17:
// An exception-specification is considered to be needed when:
@@ -3250,11 +3250,15 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
// literal or a cooked one.
LookupResult R(*this, OpName, UDSuffixLoc, LookupOrdinaryName);
switch (LookupLiteralOperator(UDLScope, R, CookedTy,
- /*AllowRaw*/true, /*AllowTemplate*/true,
- /*AllowStringTemplate*/false)) {
+ /*AllowRaw*/ true, /*AllowTemplate*/ true,
+ /*AllowStringTemplate*/ false,
+ /*DiagnoseMissing*/ !Literal.isImaginary)) {
+ case LOLR_ErrorNoDiagnostic:
+ // Lookup failure for imaginary constants isn't fatal, there's still the
+ // GNU extension producing _Complex types.
+ break;
case LOLR_Error:
return ExprError();
-
case LOLR_Cooked: {
Expr *Lit;
if (Literal.isFloatingLiteral()) {
@@ -3322,6 +3326,8 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
Ty = Context.FloatTy;
else if (Literal.isLong)
Ty = Context.LongDoubleTy;
+ else if (Literal.isFloat16)
+ Ty = Context.Float16Ty;
else if (Literal.isFloat128)
Ty = Context.Float128Ty;
else
@@ -3470,10 +3476,12 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
}
// If this is an imaginary literal, create the ImaginaryLiteral wrapper.
- if (Literal.isImaginary)
+ if (Literal.isImaginary) {
Res = new (Context) ImaginaryLiteral(Res,
Context.getComplexType(Res->getType()));
+ Diag(Tok.getLocation(), diag::ext_imaginary_constant);
+ }
return Res;
}
@@ -4477,6 +4485,22 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD,
*this, ExpressionEvaluationContext::PotentiallyEvaluated, Param);
// Instantiate the expression.
+ //
+ // FIXME: Pass in a correct Pattern argument, otherwise
+ // getTemplateInstantiationArgs uses the lexical context of FD, e.g.
+ //
+ // template<typename T>
+ // struct A {
+ // static int FooImpl();
+ //
+ // template<typename Tp>
+ // // bug: default argument A<T>::FooImpl() is evaluated with 2-level
+ // // template argument list [[T], [Tp]], should be [[Tp]].
+ // friend A<Tp> Foo(int a);
+ // };
+ //
+ // template<typename T>
+ // A<T> Foo(int a = A<T>::FooImpl());
MultiLevelTemplateArgumentList MutiLevelArgList
= getTemplateInstantiationArgs(FD, nullptr, /*RelativeToPrimary=*/true);
@@ -5041,7 +5065,7 @@ static FunctionDecl *rewriteBuiltinFunctionDecl(Sema *Sema, ASTContext &Context,
}
NeedsNewDecl = true;
- unsigned AS = ArgType->getPointeeType().getQualifiers().getAddressSpace();
+ LangAS AS = ArgType->getPointeeType().getAddressSpace();
QualType PointeeType = ParamType->getPointeeType();
PointeeType = Context.getAddrSpaceQualType(PointeeType, AS);
@@ -5104,6 +5128,87 @@ static void checkDirectCallValidity(Sema &S, const Expr *Fn,
}
}
+static bool enclosingClassIsRelatedToClassInWhichMembersWereFound(
+ const UnresolvedMemberExpr *const UME, Sema &S) {
+
+ const auto GetFunctionLevelDCIfCXXClass =
+ [](Sema &S) -> const CXXRecordDecl * {
+ const DeclContext *const DC = S.getFunctionLevelDeclContext();
+ if (!DC || !DC->getParent())
+ return nullptr;
+
+ // If the call to some member function was made from within a member
+ // function body 'M' return return 'M's parent.
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(DC))
+ return MD->getParent()->getCanonicalDecl();
+ // else the call was made from within a default member initializer of a
+ // class, so return the class.
+ if (const auto *RD = dyn_cast<CXXRecordDecl>(DC))
+ return RD->getCanonicalDecl();
+ return nullptr;
+ };
+ // If our DeclContext is neither a member function nor a class (in the
+ // case of a lambda in a default member initializer), we can't have an
+ // enclosing 'this'.
+
+ const CXXRecordDecl *const CurParentClass = GetFunctionLevelDCIfCXXClass(S);
+ if (!CurParentClass)
+ return false;
+
+ // The naming class for implicit member functions call is the class in which
+ // name lookup starts.
+ const CXXRecordDecl *const NamingClass =
+ UME->getNamingClass()->getCanonicalDecl();
+ assert(NamingClass && "Must have naming class even for implicit access");
+
+ // If the unresolved member functions were found in a 'naming class' that is
+ // related (either the same or derived from) to the class that contains the
+ // member function that itself contained the implicit member access.
+
+ return CurParentClass == NamingClass ||
+ CurParentClass->isDerivedFrom(NamingClass);
+}
+
+static void
+tryImplicitlyCaptureThisIfImplicitMemberFunctionAccessWithDependentArgs(
+ Sema &S, const UnresolvedMemberExpr *const UME, SourceLocation CallLoc) {
+
+ if (!UME)
+ return;
+
+ LambdaScopeInfo *const CurLSI = S.getCurLambda();
+ // Only try and implicitly capture 'this' within a C++ Lambda if it hasn't
+ // already been captured, or if this is an implicit member function call (if
+ // it isn't, an attempt to capture 'this' should already have been made).
+ if (!CurLSI || CurLSI->ImpCaptureStyle == CurLSI->ImpCap_None ||
+ !UME->isImplicitAccess() || CurLSI->isCXXThisCaptured())
+ return;
+
+ // Check if the naming class in which the unresolved members were found is
+ // related (same as or is a base of) to the enclosing class.
+
+ if (!enclosingClassIsRelatedToClassInWhichMembersWereFound(UME, S))
+ return;
+
+
+ DeclContext *EnclosingFunctionCtx = S.CurContext->getParent()->getParent();
+ // If the enclosing function is not dependent, then this lambda is
+ // capture ready, so if we can capture this, do so.
+ if (!EnclosingFunctionCtx->isDependentContext()) {
+ // If the current lambda and all enclosing lambdas can capture 'this' -
+ // then go ahead and capture 'this' (since our unresolved overload set
+ // contains at least one non-static member function).
+ if (!S.CheckCXXThisCapture(CallLoc, /*Explcit*/ false, /*Diagnose*/ false))
+ S.CheckCXXThisCapture(CallLoc);
+ } else if (S.CurContext->isDependentContext()) {
+ // ... since this is an implicit member reference, that might potentially
+ // involve a 'this' capture, mark 'this' for potential capture in
+ // enclosing lambdas.
+ if (CurLSI->ImpCaptureStyle != CurLSI->ImpCap_None)
+ CurLSI->addPotentialThisCapture(CallLoc);
+ }
+}
+
/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
/// This provides the location of the left/right parens and a list of comma
/// locations.
@@ -5152,6 +5257,11 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
Context, Fn, cast<CallExpr>(ExecConfig), ArgExprs,
Context.DependentTy, VK_RValue, RParenLoc);
} else {
+
+ tryImplicitlyCaptureThisIfImplicitMemberFunctionAccessWithDependentArgs(
+ *this, dyn_cast<UnresolvedMemberExpr>(Fn->IgnoreParens()),
+ Fn->getLocStart());
+
return new (Context) CallExpr(
Context, Fn, ArgExprs, Context.DependentTy, VK_RValue, RParenLoc);
}
@@ -5651,8 +5761,8 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) {
case Type::STK_ObjCObjectPointer:
switch (DestTy->getScalarTypeKind()) {
case Type::STK_CPointer: {
- unsigned SrcAS = SrcTy->getPointeeType().getAddressSpace();
- unsigned DestAS = DestTy->getPointeeType().getAddressSpace();
+ LangAS SrcAS = SrcTy->getPointeeType().getAddressSpace();
+ LangAS DestAS = DestTy->getPointeeType().getAddressSpace();
if (SrcAS != DestAS)
return CK_AddressSpaceConversion;
return CK_BitCast;
@@ -5924,9 +6034,9 @@ ExprResult Sema::CheckExtVectorCast(SourceRange R, QualType DestTy,
// In OpenCL, casts between vectors of different types are not allowed.
// (See OpenCL 6.2).
if (SrcTy->isVectorType()) {
- if (!areLaxCompatibleVectorTypes(SrcTy, DestTy)
- || (getLangOpts().OpenCL &&
- (DestTy.getCanonicalType() != SrcTy.getCanonicalType()))) {
+ if (!areLaxCompatibleVectorTypes(SrcTy, DestTy) ||
+ (getLangOpts().OpenCL &&
+ !Context.hasSameUnqualifiedType(DestTy, SrcTy))) {
Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors)
<< DestTy << SrcTy << R;
return ExprError();
@@ -6256,9 +6366,9 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS,
Qualifiers lhQual = lhptee.getQualifiers();
Qualifiers rhQual = rhptee.getQualifiers();
- unsigned ResultAddrSpace = 0;
- unsigned LAddrSpace = lhQual.getAddressSpace();
- unsigned RAddrSpace = rhQual.getAddressSpace();
+ LangAS ResultAddrSpace = LangAS::Default;
+ LangAS LAddrSpace = lhQual.getAddressSpace();
+ LangAS RAddrSpace = rhQual.getAddressSpace();
if (S.getLangOpts().OpenCL) {
// OpenCL v1.1 s6.5 - Conversion between pointers to distinct address
// spaces is disallowed.
@@ -7132,6 +7242,16 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
commonExpr = commonRes.get();
}
+ // If the common expression is a class or array prvalue, materialize it
+ // so that we can safely refer to it multiple times.
+ if (commonExpr->isRValue() && (commonExpr->getType()->isRecordType() ||
+ commonExpr->getType()->isArrayType())) {
+ ExprResult MatExpr = TemporaryMaterializationConversion(commonExpr);
+ if (MatExpr.isInvalid())
+ return ExprError();
+ commonExpr = MatExpr.get();
+ }
+
opaqueValue = new (Context) OpaqueValueExpr(commonExpr->getExprLoc(),
commonExpr->getType(),
commonExpr->getValueKind(),
@@ -7391,11 +7511,19 @@ Sema::CheckAssignmentConstraints(SourceLocation Loc,
// usually happen on valid code.
OpaqueValueExpr RHSExpr(Loc, RHSType, VK_RValue);
ExprResult RHSPtr = &RHSExpr;
- CastKind K = CK_Invalid;
+ CastKind K;
return CheckAssignmentConstraints(LHSType, RHSPtr, K, /*ConvertRHS=*/false);
}
+/// This helper function returns true if QT is a vector type that has element
+/// type ElementType.
+static bool isVector(QualType QT, QualType ElementType) {
+ if (const VectorType *VT = QT->getAs<VectorType>())
+ return VT->getElementType() == ElementType;
+ return false;
+}
+
/// CheckAssignmentConstraints (C99 6.5.16) - This routine currently
/// has code to accommodate several GCC extensions when type checking
/// pointers. Here are some objectionable examples that GCC considers warnings:
@@ -7514,6 +7642,12 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
if (unsupportedTypeConversion(*this, LHSType, RHSType))
return Incompatible;
+ // Disallow assigning a _Complex to a real type in C++ mode since it simply
+ // discards the imaginary part.
+ if (getLangOpts().CPlusPlus && RHSType->getAs<ComplexType>() &&
+ !LHSType->getAs<ComplexType>())
+ return Incompatible;
+
// Arithmetic conversions.
if (LHSType->isArithmeticType() && RHSType->isArithmeticType() &&
!(getLangOpts().CPlusPlus && LHSType->isEnumeralType())) {
@@ -7526,8 +7660,8 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
if (const PointerType *LHSPointer = dyn_cast<PointerType>(LHSType)) {
// U* -> T*
if (isa<PointerType>(RHSType)) {
- unsigned AddrSpaceL = LHSPointer->getPointeeType().getAddressSpace();
- unsigned AddrSpaceR = RHSType->getPointeeType().getAddressSpace();
+ LangAS AddrSpaceL = LHSPointer->getPointeeType().getAddressSpace();
+ LangAS AddrSpaceR = RHSType->getPointeeType().getAddressSpace();
Kind = AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion : CK_BitCast;
return checkPointerTypesForAssignment(*this, LHSType, RHSType);
}
@@ -7562,10 +7696,10 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
// U^ -> void*
if (RHSType->getAs<BlockPointerType>()) {
if (LHSPointer->getPointeeType()->isVoidType()) {
- unsigned AddrSpaceL = LHSPointer->getPointeeType().getAddressSpace();
- unsigned AddrSpaceR = RHSType->getAs<BlockPointerType>()
- ->getPointeeType()
- .getAddressSpace();
+ LangAS AddrSpaceL = LHSPointer->getPointeeType().getAddressSpace();
+ LangAS AddrSpaceR = RHSType->getAs<BlockPointerType>()
+ ->getPointeeType()
+ .getAddressSpace();
Kind =
AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion : CK_BitCast;
return Compatible;
@@ -7579,12 +7713,12 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
if (isa<BlockPointerType>(LHSType)) {
// U^ -> T^
if (RHSType->isBlockPointerType()) {
- unsigned AddrSpaceL = LHSType->getAs<BlockPointerType>()
- ->getPointeeType()
- .getAddressSpace();
- unsigned AddrSpaceR = RHSType->getAs<BlockPointerType>()
- ->getPointeeType()
- .getAddressSpace();
+ LangAS AddrSpaceL = LHSType->getAs<BlockPointerType>()
+ ->getPointeeType()
+ .getAddressSpace();
+ LangAS AddrSpaceR = RHSType->getAs<BlockPointerType>()
+ ->getPointeeType()
+ .getAddressSpace();
Kind = AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion : CK_BitCast;
return checkBlockPointerTypesForAssignment(*this, LHSType, RHSType);
}
@@ -7769,7 +7903,7 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType,
}
}
- CastKind Kind = CK_Invalid;
+ CastKind Kind;
if (CheckAssignmentConstraints(it->getType(), RHS, Kind)
== Compatible) {
RHS = ImpCastExprToType(RHS.get(), it->getType(), Kind);
@@ -7885,7 +8019,7 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS,
}
}
- CastKind Kind = CK_Invalid;
+ CastKind Kind;
Sema::AssignConvertType result =
CheckAssignmentConstraints(LHSType, RHS, Kind, ConvertRHS);
@@ -7980,7 +8114,7 @@ static bool tryVectorConvertAndSplat(Sema &S, ExprResult *scalar,
unsigned &DiagID) {
// The conversion to apply to the scalar before splatting it,
// if necessary.
- CastKind scalarCast = CK_Invalid;
+ CastKind scalarCast = CK_NoOp;
if (vectorEltTy->isIntegralType(S.Context)) {
if (S.getLangOpts().OpenCL && (scalarTy->isRealFloatingType() ||
@@ -8011,13 +8145,32 @@ static bool tryVectorConvertAndSplat(Sema &S, ExprResult *scalar,
// Adjust scalar if desired.
if (scalar) {
- if (scalarCast != CK_Invalid)
+ if (scalarCast != CK_NoOp)
*scalar = S.ImpCastExprToType(scalar->get(), vectorEltTy, scalarCast);
*scalar = S.ImpCastExprToType(scalar->get(), vectorTy, CK_VectorSplat);
}
return false;
}
+/// Convert vector E to a vector with the same number of elements but different
+/// element type.
+static ExprResult convertVector(Expr *E, QualType ElementType, Sema &S) {
+ const auto *VecTy = E->getType()->getAs<VectorType>();
+ assert(VecTy && "Expression E must be a vector");
+ QualType NewVecTy = S.Context.getVectorType(ElementType,
+ VecTy->getNumElements(),
+ VecTy->getVectorKind());
+
+ // Look through the implicit cast. Return the subexpression if its type is
+ // NewVecTy.
+ if (auto *ICE = dyn_cast<ImplicitCastExpr>(E))
+ if (ICE->getSubExpr()->getType() == NewVecTy)
+ return ICE->getSubExpr();
+
+ auto Cast = ElementType->isIntegerType() ? CK_IntegralCast : CK_FloatingCast;
+ return S.ImpCastExprToType(E, NewVecTy, Cast);
+}
+
/// Test if a (constant) integer Int can be casted to another integer type
/// IntTy without losing precision.
static bool canConvertIntToOtherIntTy(Sema &S, ExprResult *Int,
@@ -8459,6 +8612,21 @@ static void diagnoseArithmeticOnVoidPointer(Sema &S, SourceLocation Loc,
<< 0 /* one pointer */ << Pointer->getSourceRange();
}
+/// \brief Diagnose invalid arithmetic on a null pointer.
+///
+/// If \p IsGNUIdiom is true, the operation is using the 'p = (i8*)nullptr + n'
+/// idiom, which we recognize as a GNU extension.
+///
+static void diagnoseArithmeticOnNullPointer(Sema &S, SourceLocation Loc,
+ Expr *Pointer, bool IsGNUIdiom) {
+ if (IsGNUIdiom)
+ S.Diag(Loc, diag::warn_gnu_null_ptr_arith)
+ << Pointer->getSourceRange();
+ else
+ S.Diag(Loc, diag::warn_pointer_arith_null_ptr)
+ << S.getLangOpts().CPlusPlus << Pointer->getSourceRange();
+}
+
/// \brief Diagnose invalid arithmetic on two function pointers.
static void diagnoseArithmeticOnTwoFunctionPointers(Sema &S, SourceLocation Loc,
Expr *LHS, Expr *RHS) {
@@ -8753,6 +8921,21 @@ QualType Sema::CheckAdditionOperands(ExprResult &LHS, ExprResult &RHS,
if (!IExp->getType()->isIntegerType())
return InvalidOperands(Loc, LHS, RHS);
+ // Adding to a null pointer results in undefined behavior.
+ if (PExp->IgnoreParenCasts()->isNullPointerConstant(
+ Context, Expr::NPC_ValueDependentIsNotNull)) {
+ // In C++ adding zero to a null pointer is defined.
+ llvm::APSInt KnownVal;
+ if (!getLangOpts().CPlusPlus ||
+ (!IExp->isValueDependent() &&
+ (!IExp->EvaluateAsInt(KnownVal, Context) || KnownVal != 0))) {
+ // Check the conditions to see if this is the 'p = nullptr + n' idiom.
+ bool IsGNUIdiom = BinaryOperator::isNullPointerArithmeticExtension(
+ Context, BO_Add, PExp, IExp);
+ diagnoseArithmeticOnNullPointer(*this, Loc, PExp, IsGNUIdiom);
+ }
+ }
+
if (!checkArithmeticOpPointerOperand(*this, Loc, PExp))
return QualType();
@@ -8814,6 +8997,20 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
// The result type of a pointer-int computation is the pointer type.
if (RHS.get()->getType()->isIntegerType()) {
+ // Subtracting from a null pointer should produce a warning.
+ // The last argument to the diagnose call says this doesn't match the
+ // GNU int-to-pointer idiom.
+ if (LHS.get()->IgnoreParenCasts()->isNullPointerConstant(Context,
+ Expr::NPC_ValueDependentIsNotNull)) {
+ // In C++ adding zero to a null pointer is defined.
+ llvm::APSInt KnownVal;
+ if (!getLangOpts().CPlusPlus ||
+ (!RHS.get()->isValueDependent() &&
+ (!RHS.get()->EvaluateAsInt(KnownVal, Context) || KnownVal != 0))) {
+ diagnoseArithmeticOnNullPointer(*this, Loc, LHS.get(), false);
+ }
+ }
+
if (!checkArithmeticOpPointerOperand(*this, Loc, LHS.get()))
return QualType();
@@ -8849,6 +9046,8 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
LHS.get(), RHS.get()))
return QualType();
+ // FIXME: Add warnings for nullptr - ptr.
+
// The pointee type may have zero size. As an extension, a structure or
// union may have zero size or an array may have zero length. In this
// case subtraction does not make sense.
@@ -9124,9 +9323,11 @@ static void checkEnumComparison(Sema &S, SourceLocation Loc, Expr *LHS,
return;
// Ignore anonymous enums.
- if (!LHSEnumType->getDecl()->getIdentifier())
+ if (!LHSEnumType->getDecl()->getIdentifier() &&
+ !LHSEnumType->getDecl()->getTypedefNameForAnonDecl())
return;
- if (!RHSEnumType->getDecl()->getIdentifier())
+ if (!RHSEnumType->getDecl()->getIdentifier() &&
+ !RHSEnumType->getDecl()->getTypedefNameForAnonDecl())
return;
if (S.Context.hasSameUnqualifiedType(LHSStrippedType, RHSStrippedType))
@@ -9614,8 +9815,8 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
}
}
- unsigned AddrSpaceL = LCanPointeeTy.getAddressSpace();
- unsigned AddrSpaceR = RCanPointeeTy.getAddressSpace();
+ LangAS AddrSpaceL = LCanPointeeTy.getAddressSpace();
+ LangAS AddrSpaceR = RCanPointeeTy.getAddressSpace();
CastKind Kind = AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion
: CK_BitCast;
if (LHSIsNull && !RHSIsNull)
@@ -10145,22 +10346,23 @@ static bool IsTypeModifiable(QualType Ty, bool IsDereference) {
return !Ty.isConstQualified();
}
+// Update err_typecheck_assign_const and note_typecheck_assign_const
+// when this enum is changed.
+enum {
+ ConstFunction,
+ ConstVariable,
+ ConstMember,
+ ConstMethod,
+ NestedConstMember,
+ ConstUnknown, // Keep as last element
+};
+
/// Emit the "read-only variable not assignable" error and print notes to give
/// more information about why the variable is not assignable, such as pointing
/// to the declaration of a const variable, showing that a method is const, or
/// that the function is returning a const reference.
static void DiagnoseConstAssignment(Sema &S, const Expr *E,
SourceLocation Loc) {
- // Update err_typecheck_assign_const and note_typecheck_assign_const
- // when this enum is changed.
- enum {
- ConstFunction,
- ConstVariable,
- ConstMember,
- ConstMethod,
- ConstUnknown, // Keep as last element
- };
-
SourceRange ExprRange = E->getSourceRange();
// Only emit one error on the first const found. All other consts will emit
@@ -10270,6 +10472,66 @@ static void DiagnoseConstAssignment(Sema &S, const Expr *E,
S.Diag(Loc, diag::err_typecheck_assign_const) << ExprRange << ConstUnknown;
}
+enum OriginalExprKind {
+ OEK_Variable,
+ OEK_Member,
+ OEK_LValue
+};
+
+static void DiagnoseRecursiveConstFields(Sema &S, const ValueDecl *VD,
+ const RecordType *Ty,
+ SourceLocation Loc, SourceRange Range,
+ OriginalExprKind OEK,
+ bool &DiagnosticEmitted,
+ bool IsNested = false) {
+ // We walk the record hierarchy breadth-first to ensure that we print
+ // diagnostics in field nesting order.
+ // First, check every field for constness.
+ for (const FieldDecl *Field : Ty->getDecl()->fields()) {
+ if (Field->getType().isConstQualified()) {
+ if (!DiagnosticEmitted) {
+ S.Diag(Loc, diag::err_typecheck_assign_const)
+ << Range << NestedConstMember << OEK << VD
+ << IsNested << Field;
+ DiagnosticEmitted = true;
+ }
+ S.Diag(Field->getLocation(), diag::note_typecheck_assign_const)
+ << NestedConstMember << IsNested << Field
+ << Field->getType() << Field->getSourceRange();
+ }
+ }
+ // Then, recurse.
+ for (const FieldDecl *Field : Ty->getDecl()->fields()) {
+ QualType FTy = Field->getType();
+ if (const RecordType *FieldRecTy = FTy->getAs<RecordType>())
+ DiagnoseRecursiveConstFields(S, VD, FieldRecTy, Loc, Range,
+ OEK, DiagnosticEmitted, true);
+ }
+}
+
+/// Emit an error for the case where a record we are trying to assign to has a
+/// const-qualified field somewhere in its hierarchy.
+static void DiagnoseRecursiveConstFields(Sema &S, const Expr *E,
+ SourceLocation Loc) {
+ QualType Ty = E->getType();
+ assert(Ty->isRecordType() && "lvalue was not record?");
+ SourceRange Range = E->getSourceRange();
+ const RecordType *RTy = Ty.getCanonicalType()->getAs<RecordType>();
+ bool DiagEmitted = false;
+
+ if (const MemberExpr *ME = dyn_cast<MemberExpr>(E))
+ DiagnoseRecursiveConstFields(S, ME->getMemberDecl(), RTy, Loc,
+ Range, OEK_Member, DiagEmitted);
+ else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
+ DiagnoseRecursiveConstFields(S, DRE->getDecl(), RTy, Loc,
+ Range, OEK_Variable, DiagEmitted);
+ else
+ DiagnoseRecursiveConstFields(S, nullptr, RTy, Loc,
+ Range, OEK_LValue, DiagEmitted);
+ if (!DiagEmitted)
+ DiagnoseConstAssignment(S, E, Loc);
+}
+
/// CheckForModifiableLvalue - Verify that E is a modifiable lvalue. If not,
/// emit an error and return true. If so, return false.
static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
@@ -10345,6 +10607,9 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
case Expr::MLV_ConstAddrSpace:
DiagnoseConstAssignment(S, E, Loc);
return true;
+ case Expr::MLV_ConstQualifiedField:
+ DiagnoseRecursiveConstFields(S, E, Loc);
+ return true;
case Expr::MLV_ArrayType:
case Expr::MLV_ArrayTemporary:
DiagID = diag::err_typecheck_array_not_modifiable_lvalue;
@@ -10654,7 +10919,7 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
return QualType();
}
// Increment of bool sets it to true, but is deprecated.
- S.Diag(OpLoc, S.getLangOpts().CPlusPlus1z ? diag::ext_increment_bool
+ S.Diag(OpLoc, S.getLangOpts().CPlusPlus17 ? diag::ext_increment_bool
: diag::warn_increment_bool)
<< Op->getSourceRange();
} else if (S.getLangOpts().CPlusPlus && ResType->isEnumeralType()) {
@@ -10838,10 +11103,17 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
// Make sure to ignore parentheses in subsequent checks
Expr *op = OrigOp.get()->IgnoreParens();
- // OpenCL v1.0 s6.8.a.3: Pointers to functions are not allowed.
- if (LangOpts.OpenCL && op->getType()->isFunctionType()) {
- Diag(op->getExprLoc(), diag::err_opencl_taking_function_address);
- return QualType();
+ // In OpenCL captures for blocks called as lambda functions
+ // are located in the private address space. Blocks used in
+ // enqueue_kernel can be located in a different address space
+ // depending on a vendor implementation. Thus preventing
+ // taking an address of the capture to avoid invalid AS casts.
+ if (LangOpts.OpenCL) {
+ auto* VarRef = dyn_cast<DeclRefExpr>(op);
+ if (VarRef && VarRef->refersToEnclosingVariableOrCapture()) {
+ Diag(op->getExprLoc(), diag::err_opencl_taking_address_capture);
+ return QualType();
+ }
}
if (getLangOpts().C99) {
@@ -11103,6 +11375,7 @@ BinaryOperatorKind Sema::ConvertTokenKindToBinaryOpcode(tok::TokenKind Kind) {
case tok::greater: Opc = BO_GT; break;
case tok::exclaimequal: Opc = BO_NE; break;
case tok::equalequal: Opc = BO_EQ; break;
+ case tok::spaceship: Opc = BO_Cmp; break;
case tok::amp: Opc = BO_And; break;
case tok::caret: Opc = BO_Xor; break;
case tok::pipe: Opc = BO_Or; break;
@@ -11233,6 +11506,70 @@ static NamedDecl *getDeclFromExpr(Expr *E) {
return nullptr;
}
+// This helper function promotes a binary operator's operands (which are of a
+// half vector type) to a vector of floats and then truncates the result to
+// a vector of either half or short.
+static ExprResult convertHalfVecBinOp(Sema &S, ExprResult LHS, ExprResult RHS,
+ BinaryOperatorKind Opc, QualType ResultTy,
+ ExprValueKind VK, ExprObjectKind OK,
+ bool IsCompAssign, SourceLocation OpLoc,
+ FPOptions FPFeatures) {
+ auto &Context = S.getASTContext();
+ assert((isVector(ResultTy, Context.HalfTy) ||
+ isVector(ResultTy, Context.ShortTy)) &&
+ "Result must be a vector of half or short");
+ assert(isVector(LHS.get()->getType(), Context.HalfTy) &&
+ isVector(RHS.get()->getType(), Context.HalfTy) &&
+ "both operands expected to be a half vector");
+
+ RHS = convertVector(RHS.get(), Context.FloatTy, S);
+ QualType BinOpResTy = RHS.get()->getType();
+
+ // If Opc is a comparison, ResultType is a vector of shorts. In that case,
+ // change BinOpResTy to a vector of ints.
+ if (isVector(ResultTy, Context.ShortTy))
+ BinOpResTy = S.GetSignedVectorType(BinOpResTy);
+
+ if (IsCompAssign)
+ return new (Context) CompoundAssignOperator(
+ LHS.get(), RHS.get(), Opc, ResultTy, VK, OK, BinOpResTy, BinOpResTy,
+ OpLoc, FPFeatures);
+
+ LHS = convertVector(LHS.get(), Context.FloatTy, S);
+ auto *BO = new (Context) BinaryOperator(LHS.get(), RHS.get(), Opc, BinOpResTy,
+ VK, OK, OpLoc, FPFeatures);
+ return convertVector(BO, ResultTy->getAs<VectorType>()->getElementType(), S);
+}
+
+static std::pair<ExprResult, ExprResult>
+CorrectDelayedTyposInBinOp(Sema &S, BinaryOperatorKind Opc, Expr *LHSExpr,
+ Expr *RHSExpr) {
+ ExprResult LHS = LHSExpr, RHS = RHSExpr;
+ if (!S.getLangOpts().CPlusPlus) {
+ // C cannot handle TypoExpr nodes on either side of a binop because it
+ // doesn't handle dependent types properly, so make sure any TypoExprs have
+ // been dealt with before checking the operands.
+ LHS = S.CorrectDelayedTyposInExpr(LHS);
+ RHS = S.CorrectDelayedTyposInExpr(RHS, [Opc, LHS](Expr *E) {
+ if (Opc != BO_Assign)
+ return ExprResult(E);
+ // Avoid correcting the RHS to the same Expr as the LHS.
+ Decl *D = getDeclFromExpr(E);
+ return (D && D == getDeclFromExpr(LHS.get())) ? ExprError() : E;
+ });
+ }
+ return std::make_pair(LHS, RHS);
+}
+
+/// Returns true if conversion between vectors of halfs and vectors of floats
+/// is needed.
+static bool needsConversionOfHalfVec(bool OpRequiresConversion, ASTContext &Ctx,
+ QualType SrcType) {
+ return OpRequiresConversion && !Ctx.getLangOpts().NativeHalfType &&
+ !Ctx.getTargetInfo().useFP16ConversionIntrinsics() &&
+ isVector(SrcType, Ctx.HalfTy);
+}
+
/// CreateBuiltinBinOp - Creates a new built-in binary operation with
/// operator @p Opc at location @c TokLoc. This routine only supports
/// built-in operations; ActOnBinOp handles overloaded operators.
@@ -11264,22 +11601,11 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
QualType CompResultTy; // Type of computation result
ExprValueKind VK = VK_RValue;
ExprObjectKind OK = OK_Ordinary;
+ bool ConvertHalfVec = false;
- if (!getLangOpts().CPlusPlus) {
- // C cannot handle TypoExpr nodes on either side of a binop because it
- // doesn't handle dependent types properly, so make sure any TypoExprs have
- // been dealt with before checking the operands.
- LHS = CorrectDelayedTyposInExpr(LHSExpr);
- RHS = CorrectDelayedTyposInExpr(RHSExpr, [Opc, LHS](Expr *E) {
- if (Opc != BO_Assign)
- return ExprResult(E);
- // Avoid correcting the RHS to the same Expr as the LHS.
- Decl *D = getDeclFromExpr(E);
- return (D && D == getDeclFromExpr(LHS.get())) ? ExprError() : E;
- });
- if (!LHS.isUsable() || !RHS.isUsable())
- return ExprError();
- }
+ std::tie(LHS, RHS) = CorrectDelayedTyposInBinOp(*this, Opc, LHSExpr, RHSExpr);
+ if (!LHS.isUsable() || !RHS.isUsable())
+ return ExprError();
if (getLangOpts().OpenCL) {
QualType LHSTy = LHSExpr->getType();
@@ -11327,6 +11653,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
break;
case BO_Mul:
case BO_Div:
+ ConvertHalfVec = true;
ResultTy = CheckMultiplyDivideOperands(LHS, RHS, OpLoc, false,
Opc == BO_Div);
break;
@@ -11334,9 +11661,11 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
ResultTy = CheckRemainderOperands(LHS, RHS, OpLoc);
break;
case BO_Add:
+ ConvertHalfVec = true;
ResultTy = CheckAdditionOperands(LHS, RHS, OpLoc, Opc);
break;
case BO_Sub:
+ ConvertHalfVec = true;
ResultTy = CheckSubtractionOperands(LHS, RHS, OpLoc);
break;
case BO_Shl:
@@ -11347,12 +11676,21 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
case BO_LT:
case BO_GE:
case BO_GT:
+ ConvertHalfVec = true;
ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc, true);
break;
case BO_EQ:
case BO_NE:
+ ConvertHalfVec = true;
ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc, false);
break;
+ case BO_Cmp:
+ // FIXME: Implement proper semantic checking of '<=>'.
+ ConvertHalfVec = true;
+ ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc, true);
+ if (!ResultTy.isNull())
+ ResultTy = Context.VoidTy;
+ break;
case BO_And:
checkObjCPointerIntrospection(*this, LHS, RHS, OpLoc);
LLVM_FALLTHROUGH;
@@ -11362,10 +11700,12 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
break;
case BO_LAnd:
case BO_LOr:
+ ConvertHalfVec = true;
ResultTy = CheckLogicalOperands(LHS, RHS, OpLoc, Opc);
break;
case BO_MulAssign:
case BO_DivAssign:
+ ConvertHalfVec = true;
CompResultTy = CheckMultiplyDivideOperands(LHS, RHS, OpLoc, true,
Opc == BO_DivAssign);
CompLHSTy = CompResultTy;
@@ -11379,11 +11719,13 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy);
break;
case BO_AddAssign:
+ ConvertHalfVec = true;
CompResultTy = CheckAdditionOperands(LHS, RHS, OpLoc, Opc, &CompLHSTy);
if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid())
ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy);
break;
case BO_SubAssign:
+ ConvertHalfVec = true;
CompResultTy = CheckSubtractionOperands(LHS, RHS, OpLoc, &CompLHSTy);
if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid())
ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy);
@@ -11416,6 +11758,16 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
if (ResultTy.isNull() || LHS.isInvalid() || RHS.isInvalid())
return ExprError();
+ // Some of the binary operations require promoting operands of half vector to
+ // float vectors and truncating the result back to half vector. For now, we do
+ // this only when HalfArgsAndReturn is set (that is, when the target is arm or
+ // arm64).
+ assert(isVector(RHS.get()->getType(), Context.HalfTy) ==
+ isVector(LHS.get()->getType(), Context.HalfTy) &&
+ "both sides are half vectors or neither sides are");
+ ConvertHalfVec = needsConversionOfHalfVec(ConvertHalfVec, Context,
+ LHS.get()->getType());
+
// Check for array bounds violations for both sides of the BinaryOperator
CheckArrayAccess(LHS.get());
CheckArrayAccess(RHS.get());
@@ -11438,14 +11790,26 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
dyn_cast<ObjCIvarRefExpr>(LHS.get()->IgnoreParenCasts()))
DiagnoseDirectIsaAccess(*this, OIRE, OpLoc, RHS.get());
- if (CompResultTy.isNull())
+ // Opc is not a compound assignment if CompResultTy is null.
+ if (CompResultTy.isNull()) {
+ if (ConvertHalfVec)
+ return convertHalfVecBinOp(*this, LHS, RHS, Opc, ResultTy, VK, OK, false,
+ OpLoc, FPFeatures);
return new (Context) BinaryOperator(LHS.get(), RHS.get(), Opc, ResultTy, VK,
OK, OpLoc, FPFeatures);
+ }
+
+ // Handle compound assignments.
if (getLangOpts().CPlusPlus && LHS.get()->getObjectKind() !=
OK_ObjCProperty) {
VK = VK_LValue;
OK = LHS.get()->getObjectKind();
}
+
+ if (ConvertHalfVec)
+ return convertHalfVecBinOp(*this, LHS, RHS, Opc, ResultTy, VK, OK, true,
+ OpLoc, FPFeatures);
+
return new (Context) CompoundAssignOperator(
LHS.get(), RHS.get(), Opc, ResultTy, VK, OK, CompLHSTy, CompResultTy,
OpLoc, FPFeatures);
@@ -11693,6 +12057,13 @@ static ExprResult BuildOverloadedBinOp(Sema &S, Scope *Sc, SourceLocation OpLoc,
ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
BinaryOperatorKind Opc,
Expr *LHSExpr, Expr *RHSExpr) {
+ ExprResult LHS, RHS;
+ std::tie(LHS, RHS) = CorrectDelayedTyposInBinOp(*this, Opc, LHSExpr, RHSExpr);
+ if (!LHS.isUsable() || !RHS.isUsable())
+ return ExprError();
+ LHSExpr = LHS.get();
+ RHSExpr = RHS.get();
+
// We want to end up calling one of checkPseudoObjectAssignment
// (if the LHS is a pseudo-object), BuildOverloadedBinOp (if
// both expressions are overloadable or either is type-dependent),
@@ -11796,6 +12167,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
ExprValueKind VK = VK_RValue;
ExprObjectKind OK = OK_Ordinary;
QualType resultType;
+ bool ConvertHalfVec = false;
if (getLangOpts().OpenCL) {
QualType Ty = InputExpr->getType();
// The only legal unary operation for atomics is '&'.
@@ -11835,6 +12207,16 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
case UO_Minus:
Input = UsualUnaryConversions(Input.get());
if (Input.isInvalid()) return ExprError();
+ // Unary plus and minus require promoting an operand of half vector to a
+ // float vector and truncating the result back to a half vector. For now, we
+ // do this only when HalfArgsAndReturns is set (that is, when the target is
+ // arm or arm64).
+ ConvertHalfVec =
+ needsConversionOfHalfVec(true, Context, Input.get()->getType());
+
+ // If the operand is a half vector, promote it to a float vector.
+ if (ConvertHalfVec)
+ Input = convertVector(Input.get(), Context.FloatTy, *this);
resultType = Input.get()->getType();
if (resultType->isDependentType())
break;
@@ -11972,8 +12354,12 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
if (Opc != UO_AddrOf && Opc != UO_Deref)
CheckArrayAccess(Input.get());
- return new (Context)
+ auto *UO = new (Context)
UnaryOperator(Input.get(), Opc, resultType, VK, OK, OpLoc);
+ // Convert the result back to a half vector.
+ if (ConvertHalfVec)
+ return convertVector(UO, Context.HalfTy, *this);
+ return UO;
}
/// \brief Determine whether the given expression is a qualified member
@@ -12211,15 +12597,7 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
&& RequireCompleteType(BuiltinLoc, ArgTy,
diag::err_offsetof_incomplete_type, TypeRange))
return ExprError();
-
- // offsetof with non-identifier designators (e.g. "offsetof(x, a.b[c])") are a
- // GCC extension, diagnose them.
- // FIXME: This diagnostic isn't actually visible because the location is in
- // a system header!
- if (Components.size() != 1)
- Diag(BuiltinLoc, diag::ext_offsetof_extended_field_designator)
- << SourceRange(Components[1].LocStart, Components.back().LocEnd);
-
+
bool DidWarnAboutNonPOD = false;
QualType CurrentType = ArgTy;
SmallVector<OffsetOfNode, 4> Comps;
@@ -12482,8 +12860,8 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
// Look for an explicit signature in that function type.
FunctionProtoTypeLoc ExplicitSignature;
- TypeLoc tmp = Sig->getTypeLoc().IgnoreParens();
- if ((ExplicitSignature = tmp.getAs<FunctionProtoTypeLoc>())) {
+ if ((ExplicitSignature =
+ Sig->getTypeLoc().getAsAdjusted<FunctionProtoTypeLoc>())) {
// Check whether that explicit signature was synthesized by
// GetTypeForDeclarator. If so, don't save that as part of the
@@ -13366,7 +13744,7 @@ void Sema::PopExpressionEvaluationContext() {
// are part of function-signatures. Be mindful that P0315 (Lambdas in
// unevaluated contexts) might lift some of these restrictions in a
// future version.
- if (!Rec.isConstantEvaluated() || !getLangOpts().CPlusPlus1z)
+ if (!Rec.isConstantEvaluated() || !getLangOpts().CPlusPlus17)
for (const auto *L : Rec.Lambdas)
Diag(L->getLocStart(), D);
} else {
@@ -13591,29 +13969,21 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
// Implicit instantiation of function templates and member functions of
// class templates.
if (Func->isImplicitlyInstantiable()) {
- bool AlreadyInstantiated = false;
- SourceLocation PointOfInstantiation = Loc;
- if (FunctionTemplateSpecializationInfo *SpecInfo
- = Func->getTemplateSpecializationInfo()) {
- if (SpecInfo->getPointOfInstantiation().isInvalid())
- SpecInfo->setPointOfInstantiation(Loc);
- else if (SpecInfo->getTemplateSpecializationKind()
- == TSK_ImplicitInstantiation) {
- AlreadyInstantiated = true;
- PointOfInstantiation = SpecInfo->getPointOfInstantiation();
- }
- } else if (MemberSpecializationInfo *MSInfo
- = Func->getMemberSpecializationInfo()) {
- if (MSInfo->getPointOfInstantiation().isInvalid())
- MSInfo->setPointOfInstantiation(Loc);
- else if (MSInfo->getTemplateSpecializationKind()
- == TSK_ImplicitInstantiation) {
- AlreadyInstantiated = true;
- PointOfInstantiation = MSInfo->getPointOfInstantiation();
- }
+ TemplateSpecializationKind TSK = Func->getTemplateSpecializationKind();
+ SourceLocation PointOfInstantiation = Func->getPointOfInstantiation();
+ bool FirstInstantiation = PointOfInstantiation.isInvalid();
+ if (FirstInstantiation) {
+ PointOfInstantiation = Loc;
+ Func->setTemplateSpecializationKind(TSK, PointOfInstantiation);
+ } else if (TSK != TSK_ImplicitInstantiation) {
+ // Use the point of use as the point of instantiation, instead of the
+ // point of explicit instantiation (which we track as the actual point of
+ // instantiation). This gives better backtraces in diagnostics.
+ PointOfInstantiation = Loc;
}
- if (!AlreadyInstantiated || Func->isConstexpr()) {
+ if (FirstInstantiation || TSK != TSK_ImplicitInstantiation ||
+ Func->isConstexpr()) {
if (isa<CXXRecordDecl>(Func->getDeclContext()) &&
cast<CXXRecordDecl>(Func->getDeclContext())->isLocalClass() &&
CodeSynthesisContexts.size())
@@ -13650,6 +14020,8 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
!LangOpts.GNUInline &&
!Func->getMostRecentDecl()->hasAttr<GNUInlineAttr>())
UndefinedButUsed.insert(std::make_pair(Func->getCanonicalDecl(), Loc));
+ else if (isExternalWithNoLinkageType(Func))
+ UndefinedButUsed.insert(std::make_pair(Func->getCanonicalDecl(), Loc));
}
Func->markUsed(Context);
@@ -13973,8 +14345,13 @@ static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI,
bool ByRef = true;
// Using an LValue reference type is consistent with Lambdas (see below).
if (S.getLangOpts().OpenMP && RSI->CapRegionKind == CR_OpenMP) {
- if (S.IsOpenMPCapturedDecl(Var))
+ if (S.IsOpenMPCapturedDecl(Var)) {
+ bool HasConst = DeclRefType.isConstQualified();
DeclRefType = DeclRefType.getUnqualifiedType();
+ // Don't lose diagnostics about assignments to const.
+ if (HasConst)
+ DeclRefType.addConst();
+ }
ByRef = S.IsOpenMPCapturedByRef(Var, RSI->OpenMPLevel);
}
@@ -13997,6 +14374,8 @@ static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI,
Field->setImplicit(true);
Field->setAccess(AS_private);
RD->addDecl(Field);
+ if (S.getLangOpts().OpenMP && RSI->CapRegionKind == CR_OpenMP)
+ S.setOpenMPCaptureKind(Field, Var, RSI->OpenMPLevel);
CopyExpr = new (S.Context) DeclRefExpr(Var, RefersToCapturedVariable,
DeclRefType, VK_LValue, Loc);
@@ -14167,6 +14546,7 @@ bool Sema::tryCaptureVariable(
bool IsGlobal = !Var->hasLocalStorage();
if (IsGlobal && !(LangOpts.OpenMP && IsOpenMPCapturedDecl(Var)))
return true;
+ Var = Var->getCanonicalDecl();
// Walk up the stack to determine whether we can capture the variable,
// performing the "simple" checks that don't depend on type. We stop when
@@ -14248,14 +14628,16 @@ bool Sema::tryCaptureVariable(
// just break here. Similarly, global variables that are captured in a
// target region should not be captured outside the scope of the region.
if (RSI->CapRegionKind == CR_OpenMP) {
- auto IsTargetCap = isOpenMPTargetCapturedDecl(Var, RSI->OpenMPLevel);
+ bool IsOpenMPPrivateDecl = isOpenMPPrivateDecl(Var, RSI->OpenMPLevel);
+ auto IsTargetCap = !IsOpenMPPrivateDecl &&
+ isOpenMPTargetCapturedDecl(Var, RSI->OpenMPLevel);
// When we detect target captures we are looking from inside the
// target region, therefore we need to propagate the capture from the
// enclosing region. Therefore, the capture is not initially nested.
if (IsTargetCap)
- FunctionScopesIndex--;
+ adjustOpenMPTargetScopeIndex(FunctionScopesIndex, RSI->OpenMPLevel);
- if (IsTargetCap || isOpenMPPrivateDecl(Var, RSI->OpenMPLevel)) {
+ if (IsTargetCap || IsOpenMPPrivateDecl) {
Nested = !IsTargetCap;
DeclRefType = DeclRefType.getUnqualifiedType();
CaptureType = Context.getLValueReferenceType(DeclRefType);
@@ -14451,9 +14833,10 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
TemplateSpecializationKind TSK = Var->getTemplateSpecializationKind();
bool OdrUseContext = isOdrUseContext(SemaRef);
+ bool UsableInConstantExpr =
+ Var->isUsableInConstantExpressions(SemaRef.Context);
bool NeedDefinition =
- OdrUseContext || (isEvaluatableContext(SemaRef) &&
- Var->isUsableInConstantExpressions(SemaRef.Context));
+ OdrUseContext || (isEvaluatableContext(SemaRef) && UsableInConstantExpr);
VarTemplateSpecializationDecl *VarSpec =
dyn_cast<VarTemplateSpecializationDecl>(Var);
@@ -14472,24 +14855,21 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
// instantiations of variable templates, except for those that could be used
// in a constant expression.
if (NeedDefinition && isTemplateInstantiation(TSK)) {
- bool TryInstantiating = TSK == TSK_ImplicitInstantiation;
-
- if (TryInstantiating && !isa<VarTemplateSpecializationDecl>(Var)) {
- if (Var->getPointOfInstantiation().isInvalid()) {
- // This is a modification of an existing AST node. Notify listeners.
- if (ASTMutationListener *L = SemaRef.getASTMutationListener())
- L->StaticDataMemberInstantiated(Var);
- } else if (!Var->isUsableInConstantExpressions(SemaRef.Context))
- // Don't bother trying to instantiate it again, unless we might need
- // its initializer before we get to the end of the TU.
- TryInstantiating = false;
- }
-
- if (Var->getPointOfInstantiation().isInvalid())
- Var->setTemplateSpecializationKind(TSK, Loc);
+ // Per C++17 [temp.explicit]p10, we may instantiate despite an explicit
+ // instantiation declaration if a variable is usable in a constant
+ // expression (among other cases).
+ bool TryInstantiating =
+ TSK == TSK_ImplicitInstantiation ||
+ (TSK == TSK_ExplicitInstantiationDeclaration && UsableInConstantExpr);
if (TryInstantiating) {
SourceLocation PointOfInstantiation = Var->getPointOfInstantiation();
+ bool FirstInstantiation = PointOfInstantiation.isInvalid();
+ if (FirstInstantiation) {
+ PointOfInstantiation = Loc;
+ Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
+ }
+
bool InstantiationDependent = false;
bool IsNonDependent =
VarSpec ? !TemplateSpecializationType::anyDependentTemplateArguments(
@@ -14498,11 +14878,17 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
// Do not instantiate specializations that are still type-dependent.
if (IsNonDependent) {
- if (Var->isUsableInConstantExpressions(SemaRef.Context)) {
- // Do not defer instantiations of variables which could be used in a
+ if (UsableInConstantExpr) {
+ // Do not defer instantiations of variables that could be used in a
// constant expression.
SemaRef.InstantiateVariableDefinition(PointOfInstantiation, Var);
- } else {
+ } else if (FirstInstantiation ||
+ isa<VarTemplateSpecializationDecl>(Var)) {
+ // FIXME: For a specialization of a variable template, we don't
+ // distinguish between "declaration and type implicitly instantiated"
+ // and "implicit instantiation of definition requested", so we have
+ // no direct way to avoid enqueueing the pending instantiation
+ // multiple times.
SemaRef.PendingInstantiations
.push_back(std::make_pair(Var, PointOfInstantiation));
}
@@ -14522,7 +14908,8 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
IsVariableAConstantExpression(Var, SemaRef.Context)) {
// A reference initialized by a constant expression can never be
// odr-used, so simply ignore it.
- if (!Var->getType()->isReferenceType())
+ if (!Var->getType()->isReferenceType() ||
+ (SemaRef.LangOpts.OpenMP && SemaRef.IsOpenMPCapturedDecl(Var)))
SemaRef.MaybeODRUseExprs.insert(E);
} else if (OdrUseContext) {
MarkVarDeclODRUsed(Var, Loc, SemaRef,
@@ -14595,7 +14982,7 @@ static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc,
ME->getBase(), SemaRef.getLangOpts().AppleKext);
if (DM)
SemaRef.MarkAnyDeclReferenced(Loc, DM, MightBeOdrUse);
-}
+}
/// \brief Perform reference-marking and odr-use handling for a DeclRefExpr.
void Sema::MarkDeclRefReferenced(DeclRefExpr *E, const Expr *Base) {
@@ -14810,10 +15197,24 @@ bool Sema::DiagRuntimeBehavior(SourceLocation Loc, const Stmt *Statement,
if (Statement && getCurFunctionOrMethodDecl()) {
FunctionScopes.back()->PossiblyUnreachableDiags.
push_back(sema::PossiblyUnreachableDiag(PD, Loc, Statement));
+ return true;
}
- else
- Diag(Loc, PD);
-
+
+ // The initializer of a constexpr variable or of the first declaration of a
+ // static data member is not syntactically a constant evaluated constant,
+ // but nonetheless is always required to be a constant expression, so we
+ // can skip diagnosing.
+ // FIXME: Using the mangling context here is a hack.
+ if (auto *VD = dyn_cast_or_null<VarDecl>(
+ ExprEvalContexts.back().ManglingContextDecl)) {
+ if (VD->isConstexpr() ||
+ (VD->isStaticDataMember() && VD->isFirstDecl() && !VD->isInline()))
+ break;
+ // FIXME: For any other kind of variable, we should build a CFG for its
+ // initializer and check whether the context in question is reachable.
+ }
+
+ Diag(Loc, PD);
return true;
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
index a9cf3ec7990b2..9c842ded1e101 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
@@ -24,6 +24,7 @@
#include "clang/AST/ExprObjC.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/TypeLoc.h"
+#include "clang/Basic/AlignedAllocation.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
@@ -1377,9 +1378,6 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
/// \brief Determine whether the given function is a non-placement
/// deallocation function.
static bool isNonPlacementDeallocationFunction(Sema &S, FunctionDecl *FD) {
- if (FD->isInvalidDecl())
- return false;
-
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FD))
return Method->isUsualDeallocationFunction();
@@ -1409,14 +1407,20 @@ namespace {
UsualDeallocFnInfo() : Found(), FD(nullptr) {}
UsualDeallocFnInfo(Sema &S, DeclAccessPair Found)
: Found(Found), FD(dyn_cast<FunctionDecl>(Found->getUnderlyingDecl())),
- HasSizeT(false), HasAlignValT(false), CUDAPref(Sema::CFP_Native) {
+ Destroying(false), HasSizeT(false), HasAlignValT(false),
+ CUDAPref(Sema::CFP_Native) {
// A function template declaration is never a usual deallocation function.
if (!FD)
return;
- if (FD->getNumParams() == 3)
+ unsigned NumBaseParams = 1;
+ if (FD->isDestroyingOperatorDelete()) {
+ Destroying = true;
+ ++NumBaseParams;
+ }
+ if (FD->getNumParams() == NumBaseParams + 2)
HasAlignValT = HasSizeT = true;
- else if (FD->getNumParams() == 2) {
- HasSizeT = FD->getParamDecl(1)->getType()->isIntegerType();
+ else if (FD->getNumParams() == NumBaseParams + 1) {
+ HasSizeT = FD->getParamDecl(NumBaseParams)->getType()->isIntegerType();
HasAlignValT = !HasSizeT;
}
@@ -1430,6 +1434,12 @@ namespace {
bool isBetterThan(const UsualDeallocFnInfo &Other, bool WantSize,
bool WantAlign) const {
+ // C++ P0722:
+ // A destroying operator delete is preferred over a non-destroying
+ // operator delete.
+ if (Destroying != Other.Destroying)
+ return Destroying;
+
// C++17 [expr.delete]p10:
// If the type has new-extended alignment, a function with a parameter
// of type std::align_val_t is preferred; otherwise a function without
@@ -1446,7 +1456,7 @@ namespace {
DeclAccessPair Found;
FunctionDecl *FD;
- bool HasSizeT, HasAlignValT;
+ bool Destroying, HasSizeT, HasAlignValT;
Sema::CUDAFunctionPreference CUDAPref;
};
}
@@ -1660,9 +1670,13 @@ static void diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD,
bool IsAligned = false;
if (FD.isReplaceableGlobalAllocationFunction(&IsAligned) && IsAligned) {
+ const llvm::Triple &T = S.getASTContext().getTargetInfo().getTriple();
+ StringRef OSName = AvailabilityAttr::getPlatformNameSourceSpelling(
+ S.getASTContext().getTargetInfo().getPlatformName());
+
S.Diag(Loc, diag::warn_aligned_allocation_unavailable)
- << IsDelete << FD.getType().getAsString()
- << S.getASTContext().getTargetInfo().getTriple().str();
+ << IsDelete << FD.getType().getAsString() << OSName
+ << alignedAllocMinVersion(T.getOS()).getAsString();
S.Diag(Loc, diag::note_silence_unligned_allocation_unavailable);
}
}
@@ -1734,20 +1748,27 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
if (AllocType.isNull())
return ExprError();
} else if (Deduced) {
+ bool Braced = (initStyle == CXXNewExpr::ListInit);
+ if (NumInits == 1) {
+ if (auto p = dyn_cast_or_null<InitListExpr>(Inits[0])) {
+ Inits = p->getInits();
+ NumInits = p->getNumInits();
+ Braced = true;
+ }
+ }
+
if (initStyle == CXXNewExpr::NoInit || NumInits == 0)
return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ctor_arg)
<< AllocType << TypeRange);
- if (initStyle == CXXNewExpr::ListInit ||
- (NumInits == 1 && isa<InitListExpr>(Inits[0])))
- return ExprError(Diag(Inits[0]->getLocStart(),
- diag::err_auto_new_list_init)
- << AllocType << TypeRange);
if (NumInits > 1) {
Expr *FirstBad = Inits[1];
return ExprError(Diag(FirstBad->getLocStart(),
diag::err_auto_new_ctor_multiple_expressions)
<< AllocType << TypeRange);
}
+ if (Braced && !getLangOpts().CPlusPlus17)
+ Diag(Initializer->getLocStart(), diag::ext_auto_new_list_init)
+ << AllocType << TypeRange;
Expr *Deduce = Inits[0];
QualType DeducedType;
if (DeduceAutoType(AllocTypeInfo, Deduce, DeducedType) == DAR_Failed)
@@ -2099,7 +2120,7 @@ bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc,
else if (AllocType->isVariablyModifiedType())
return Diag(Loc, diag::err_variably_modified_new_type)
<< AllocType;
- else if (AllocType.getAddressSpace())
+ else if (AllocType.getAddressSpace() != LangAS::Default)
return Diag(Loc, diag::err_address_space_qualified_new)
<< AllocType.getUnqualifiedType()
<< AllocType.getQualifiers().getAddressSpaceAttributePrintValue();
@@ -3171,7 +3192,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
QualType Pointee = Type->getAs<PointerType>()->getPointeeType();
QualType PointeeElem = Context.getBaseElementType(Pointee);
- if (Pointee.getAddressSpace())
+ if (Pointee.getAddressSpace() != LangAS::Default)
return Diag(Ex.get()->getLocStart(),
diag::err_address_space_qualified_delete)
<< Pointee.getUnqualifiedType()
@@ -3259,16 +3280,39 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
MarkFunctionReferenced(StartLoc, OperatorDelete);
- // Check access and ambiguity of operator delete and destructor.
+ // Check access and ambiguity of destructor if we're going to call it.
+ // Note that this is required even for a virtual delete.
+ bool IsVirtualDelete = false;
if (PointeeRD) {
if (CXXDestructorDecl *Dtor = LookupDestructor(PointeeRD)) {
- CheckDestructorAccess(Ex.get()->getExprLoc(), Dtor,
- PDiag(diag::err_access_dtor) << PointeeElem);
+ CheckDestructorAccess(Ex.get()->getExprLoc(), Dtor,
+ PDiag(diag::err_access_dtor) << PointeeElem);
+ IsVirtualDelete = Dtor->isVirtual();
}
}
diagnoseUnavailableAlignedAllocation(*OperatorDelete, StartLoc, true,
*this);
+
+ // Convert the operand to the type of the first parameter of operator
+ // delete. This is only necessary if we selected a destroying operator
+ // delete that we are going to call (non-virtually); converting to void*
+ // is trivial and left to AST consumers to handle.
+ QualType ParamType = OperatorDelete->getParamDecl(0)->getType();
+ if (!IsVirtualDelete && !ParamType->getPointeeType()->isVoidType()) {
+ Qualifiers Qs = Pointee.getQualifiers();
+ if (Qs.hasCVRQualifiers()) {
+ // Qualifiers are irrelevant to this conversion; we're only looking
+ // for access and ambiguity.
+ Qs.removeCVRQualifiers();
+ QualType Unqual = Context.getPointerType(
+ Context.getQualifiedType(Pointee.getUnqualifiedType(), Qs));
+ Ex = ImpCastExprToType(Ex.get(), Unqual, CK_NoOp);
+ }
+ Ex = PerformImplicitConversion(Ex.get(), ParamType, AA_Passing);
+ if (Ex.isInvalid())
+ return ExprError();
+ }
}
CXXDeleteExpr *Result = new (Context) CXXDeleteExpr(
@@ -3282,7 +3326,7 @@ void Sema::CheckVirtualDtorCall(CXXDestructorDecl *dtor, SourceLocation Loc,
bool IsDelete, bool CallCanBeVirtual,
bool WarnOnNonAbstractTypes,
SourceLocation DtorLoc) {
- if (!dtor || dtor->isVirtual() || !CallCanBeVirtual)
+ if (!dtor || dtor->isVirtual() || !CallCanBeVirtual || isUnevaluatedContext())
return;
// C++ [expr.delete]p3:
@@ -3297,6 +3341,12 @@ void Sema::CheckVirtualDtorCall(CXXDestructorDecl *dtor, SourceLocation Loc,
if (!PointeeRD->isPolymorphic() || PointeeRD->hasAttr<FinalAttr>())
return;
+ // If the superclass is in a system header, there's nothing that can be done.
+ // The `delete` (where we emit the warning) can be in a system header,
+ // what matters for this warning is where the deleted type is defined.
+ if (getSourceManager().isInSystemHeader(PointeeRD->getLocation()))
+ return;
+
QualType ClassType = dtor->getThisType(Context)->getPointeeType();
if (PointeeRD->isAbstract()) {
// If the class is abstract, we warn by default, because we're
@@ -3797,7 +3847,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
<< From->getSourceRange();
}
- CastKind Kind = CK_Invalid;
+ CastKind Kind;
CXXCastPath BasePath;
if (CheckPointerConversion(From, ToType, Kind, BasePath, CStyle))
return ExprError();
@@ -3817,7 +3867,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
}
case ICK_Pointer_Member: {
- CastKind Kind = CK_Invalid;
+ CastKind Kind;
CXXCastPath BasePath;
if (CheckMemberPointerConversion(From, ToType, Kind, BasePath, CStyle))
return ExprError();
@@ -4141,6 +4191,7 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT,
case UTT_IsDestructible:
case UTT_IsNothrowDestructible:
case UTT_IsTriviallyDestructible:
+ case UTT_HasUniqueObjectRepresentations:
if (ArgTy->isIncompleteArrayType() || ArgTy->isVoidType())
return true;
@@ -4580,6 +4631,8 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
// Returns True if and only if T is a complete type at the point of the
// function call.
return !T->isIncompleteType();
+ case UTT_HasUniqueObjectRepresentations:
+ return C.hasUniqueObjectRepresentations(T);
}
}
@@ -4790,9 +4843,13 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT,
}
case BTT_IsSame:
return Self.Context.hasSameType(LhsT, RhsT);
- case BTT_TypeCompatible:
- return Self.Context.typesAreCompatible(LhsT.getUnqualifiedType(),
- RhsT.getUnqualifiedType());
+ case BTT_TypeCompatible: {
+ // GCC ignores cv-qualifiers on arrays for this builtin.
+ Qualifiers LhsQuals, RhsQuals;
+ QualType Lhs = Self.getASTContext().getUnqualifiedArrayType(LhsT, LhsQuals);
+ QualType Rhs = Self.getASTContext().getUnqualifiedArrayType(RhsT, RhsQuals);
+ return Self.Context.typesAreCompatible(Lhs, Rhs);
+ }
case BTT_IsConvertible:
case BTT_IsConvertibleTo: {
// C++0x [meta.rel]p4:
@@ -5173,9 +5230,16 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS,
break;
case RQ_LValue:
- if (!isIndirect && !LHS.get()->Classify(Context).isLValue())
- Diag(Loc, diag::err_pointer_to_member_oper_value_classify)
- << RHSType << 1 << LHS.get()->getSourceRange();
+ if (!isIndirect && !LHS.get()->Classify(Context).isLValue()) {
+ // C++2a allows functions with ref-qualifier & if they are also 'const'.
+ if (Proto->isConst())
+ Diag(Loc, getLangOpts().CPlusPlus2a
+ ? diag::warn_cxx17_compat_pointer_to_const_ref_member_on_rvalue
+ : diag::ext_pointer_to_const_ref_member_on_rvalue);
+ else
+ Diag(Loc, diag::err_pointer_to_member_oper_value_classify)
+ << RHSType << 1 << LHS.get()->getSourceRange();
+ }
break;
case RQ_RValue:
@@ -5702,7 +5766,7 @@ mergeExceptionSpecs(Sema &S, FunctionProtoType::ExceptionSpecInfo ESI1,
// happen in C++17, because it would mean we were computing the composite
// pointer type of dependent types, which should never happen.
if (EST1 == EST_ComputedNoexcept || EST2 == EST_ComputedNoexcept) {
- assert(!S.getLangOpts().CPlusPlus1z &&
+ assert(!S.getLangOpts().CPlusPlus17 &&
"computing composite pointer type of dependent types");
return FunctionProtoType::ExceptionSpecInfo();
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp
index c3d0e2db76b67..03ddcc0a3eca9 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp
@@ -384,7 +384,9 @@ CheckExtVectorComponent(Sema &S, QualType baseType, ExprValueKind &VK,
}
}
- if (!HalvingSwizzle) {
+ // OpenCL mode requires swizzle length to be in accordance with accepted
+ // sizes. Clang however supports arbitrary lengths for other languages.
+ if (S.getLangOpts().OpenCL && !HalvingSwizzle) {
unsigned SwizzleLength = CompName->getLength();
if (HexSwizzle)
@@ -693,8 +695,7 @@ static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
Sema::RedeclarationKind Redecl;
};
QueryState Q = {R.getSema(), R.getLookupNameInfo(), R.getLookupKind(),
- R.isForRedeclaration() ? Sema::ForRedeclaration
- : Sema::NotForRedeclaration};
+ R.redeclarationKind()};
TE = SemaRef.CorrectTypoDelayed(
R.getLookupNameInfo(), R.getLookupKind(), nullptr, &SS,
llvm::make_unique<RecordMemberExprValidatorCCC>(RTy),
@@ -1001,53 +1002,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
BaseExpr = Converted.get();
}
- LambdaScopeInfo *const CurLSI = getCurLambda();
- // If this is an implicit member reference and the overloaded
- // name refers to both static and non-static member functions
- // (i.e. BaseExpr is null) and if we are currently processing a lambda,
- // check if we should/can capture 'this'...
- // Keep this example in mind:
- // struct X {
- // void f(int) { }
- // static void f(double) { }
- //
- // int g() {
- // auto L = [=](auto a) {
- // return [](int i) {
- // return [=](auto b) {
- // f(b);
- // //f(decltype(a){});
- // };
- // };
- // };
- // auto M = L(0.0);
- // auto N = M(3);
- // N(5.32); // OK, must not error.
- // return 0;
- // }
- // };
- //
- if (!BaseExpr && CurLSI) {
- SourceLocation Loc = R.getNameLoc();
- if (SS.getRange().isValid())
- Loc = SS.getRange().getBegin();
- DeclContext *EnclosingFunctionCtx = CurContext->getParent()->getParent();
- // If the enclosing function is not dependent, then this lambda is
- // capture ready, so if we can capture this, do so.
- if (!EnclosingFunctionCtx->isDependentContext()) {
- // If the current lambda and all enclosing lambdas can capture 'this' -
- // then go ahead and capture 'this' (since our unresolved overload set
- // contains both static and non-static member functions).
- if (!CheckCXXThisCapture(Loc, /*Explcit*/false, /*Diagnose*/false))
- CheckCXXThisCapture(Loc);
- } else if (CurContext->isDependentContext()) {
- // ... since this is an implicit member reference, that might potentially
- // involve a 'this' capture, mark 'this' for potential capture in
- // enclosing lambdas.
- if (CurLSI->ImpCaptureStyle != CurLSI->ImpCap_None)
- CurLSI->addPotentialThisCapture(Loc);
- }
- }
+
const DeclarationNameInfo &MemberNameInfo = R.getLookupNameInfo();
DeclarationName MemberName = MemberNameInfo.getName();
SourceLocation MemberLoc = MemberNameInfo.getLoc();
@@ -1836,7 +1791,9 @@ Sema::BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow,
MemberType = Context.getQualifiedType(MemberType, Combined);
}
- UnusedPrivateFields.remove(Field);
+ auto *CurMethod = dyn_cast<CXXMethodDecl>(CurContext);
+ if (!(CurMethod && CurMethod->isDefaulted()))
+ UnusedPrivateFields.remove(Field);
ExprResult Base = PerformObjectMemberConversion(BaseExpr, SS.getScopeRep(),
FoundDecl, Field);
@@ -1848,8 +1805,10 @@ Sema::BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow,
if (getLangOpts().OpenMP && IsArrow &&
!CurContext->isDependentContext() &&
isa<CXXThisExpr>(Base.get()->IgnoreParenImpCasts())) {
- if (auto *PrivateCopy = IsOpenMPCapturedDecl(Field))
- return getOpenMPCapturedExpr(PrivateCopy, VK, OK, OpLoc);
+ if (auto *PrivateCopy = IsOpenMPCapturedDecl(Field)) {
+ return getOpenMPCapturedExpr(PrivateCopy, VK, OK,
+ MemberNameInfo.getLoc());
+ }
}
return BuildMemberExpr(*this, Context, Base.get(), IsArrow, OpLoc, SS,
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp
index 28581bad1a7a4..6ed5047c35daa 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp
@@ -564,6 +564,13 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
BoxingMethod = StringWithUTF8StringMethod;
BoxedType = NSStringPointer;
+ // Transfer the nullability from method's return type.
+ Optional<NullabilityKind> Nullability =
+ BoxingMethod->getReturnType()->getNullability(Context);
+ if (Nullability)
+ BoxedType = Context.getAttributedType(
+ AttributedType::getNullabilityAttrKind(*Nullability), BoxedType,
+ BoxedType);
}
} else if (ValueType->isBuiltinType()) {
// The other types we support are numeric, char and BOOL/bool. We could also
@@ -2705,6 +2712,9 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
}
}
+ if (ReceiverType->isObjCIdType() && !isImplicit)
+ Diag(Receiver->getExprLoc(), diag::warn_messaging_unqualified_id);
+
// There's a somewhat weird interaction here where we assume that we
// won't actually have a method unless we also don't need to do some
// of the more detailed type-checking on the receiver.
@@ -4314,14 +4324,37 @@ bool Sema::CheckObjCARCUnavailableWeakConversion(QualType castType,
/// Look for an ObjCReclaimReturnedObject cast and destroy it.
static Expr *maybeUndoReclaimObject(Expr *e) {
- // For now, we just undo operands that are *immediately* reclaim
- // expressions, which prevents the vast majority of potential
- // problems here. To catch them all, we'd need to rebuild arbitrary
- // value-propagating subexpressions --- we can't reliably rebuild
- // in-place because of expression sharing.
- if (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e))
- if (ice->getCastKind() == CK_ARCReclaimReturnedObject)
- return ice->getSubExpr();
+ Expr *curExpr = e, *prevExpr = nullptr;
+
+ // Walk down the expression until we hit an implicit cast of kind
+ // ARCReclaimReturnedObject or an Expr that is neither a Paren nor a Cast.
+ while (true) {
+ if (auto *pe = dyn_cast<ParenExpr>(curExpr)) {
+ prevExpr = curExpr;
+ curExpr = pe->getSubExpr();
+ continue;
+ }
+
+ if (auto *ce = dyn_cast<CastExpr>(curExpr)) {
+ if (auto *ice = dyn_cast<ImplicitCastExpr>(ce))
+ if (ice->getCastKind() == CK_ARCReclaimReturnedObject) {
+ if (!prevExpr)
+ return ice->getSubExpr();
+ if (auto *pe = dyn_cast<ParenExpr>(prevExpr))
+ pe->setSubExpr(ice->getSubExpr());
+ else
+ cast<CastExpr>(prevExpr)->setSubExpr(ice->getSubExpr());
+ return e;
+ }
+
+ prevExpr = curExpr;
+ curExpr = ce->getSubExpr();
+ continue;
+ }
+
+ // Break out of the loop if curExpr is neither a Paren nor a Cast.
+ break;
+ }
return e;
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
index 32024cb335dc3..e4789cdf53bfb 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
@@ -826,6 +826,34 @@ int InitListChecker::numStructUnionElements(QualType DeclType) {
return InitializableMembers - structDecl->hasFlexibleArrayMember();
}
+/// Determine whether Entity is an entity for which it is idiomatic to elide
+/// the braces in aggregate initialization.
+static bool isIdiomaticBraceElisionEntity(const InitializedEntity &Entity) {
+ // Recursive initialization of the one and only field within an aggregate
+ // class is considered idiomatic. This case arises in particular for
+ // initialization of std::array, where the C++ standard suggests the idiom of
+ //
+ // std::array<T, N> arr = {1, 2, 3};
+ //
+ // (where std::array is an aggregate struct containing a single array field.
+
+ // FIXME: Should aggregate initialization of a struct with a single
+ // base class and no members also suppress the warning?
+ if (Entity.getKind() != InitializedEntity::EK_Member || !Entity.getParent())
+ return false;
+
+ auto *ParentRD =
+ Entity.getParent()->getType()->castAs<RecordType>()->getDecl();
+ if (CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(ParentRD))
+ if (CXXRD->getNumBases())
+ return false;
+
+ auto FieldIt = ParentRD->field_begin();
+ assert(FieldIt != ParentRD->field_end() &&
+ "no fields but have initializer for member?");
+ return ++FieldIt == ParentRD->field_end();
+}
+
/// Check whether the range of the initializer \p ParentIList from element
/// \p Index onwards can be used to initialize an object of type \p T. Update
/// \p Index to indicate how many elements of the list were consumed.
@@ -886,7 +914,9 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
}
// Complain about missing braces.
- if (T->isArrayType() || T->isRecordType()) {
+ if ((T->isArrayType() || T->isRecordType()) &&
+ !ParentIList->isIdiomaticZeroInitializer(SemaRef.getLangOpts()) &&
+ !isIdiomaticBraceElisionEntity(Entity)) {
SemaRef.Diag(StructuredSubobjectInitList->getLocStart(),
diag::warn_missing_braces)
<< StructuredSubobjectInitList->getSourceRange()
@@ -1833,7 +1863,9 @@ void InitListChecker::CheckStructUnionTypes(
// worthwhile to skip over the rest of the initializer, though.
RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl();
RecordDecl::field_iterator FieldEnd = RD->field_end();
- bool CheckForMissingFields = true;
+ bool CheckForMissingFields =
+ !IList->isIdiomaticZeroInitializer(SemaRef.getLangOpts());
+
while (Index < IList->getNumInits()) {
Expr *Init = IList->getInit(Index);
@@ -3531,12 +3563,13 @@ static OverloadingResult
ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
MultiExprArg Args,
OverloadCandidateSet &CandidateSet,
+ QualType DestType,
DeclContext::lookup_result Ctors,
OverloadCandidateSet::iterator &Best,
bool CopyInitializing, bool AllowExplicit,
bool OnlyListConstructors, bool IsListInit,
bool SecondStepOfCopyInit = false) {
- CandidateSet.clear();
+ CandidateSet.clear(OverloadCandidateSet::CSK_InitByConstructor);
for (NamedDecl *D : Ctors) {
auto Info = getConstructorInfo(D);
@@ -3587,6 +3620,50 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
}
}
+ // FIXME: Work around a bug in C++17 guaranteed copy elision.
+ //
+ // When initializing an object of class type T by constructor
+ // ([over.match.ctor]) or by list-initialization ([over.match.list])
+ // from a single expression of class type U, conversion functions of
+ // U that convert to the non-reference type cv T are candidates.
+ // Explicit conversion functions are only candidates during
+ // direct-initialization.
+ //
+ // Note: SecondStepOfCopyInit is only ever true in this case when
+ // evaluating whether to produce a C++98 compatibility warning.
+ if (S.getLangOpts().CPlusPlus17 && Args.size() == 1 &&
+ !SecondStepOfCopyInit) {
+ Expr *Initializer = Args[0];
+ auto *SourceRD = Initializer->getType()->getAsCXXRecordDecl();
+ if (SourceRD && S.isCompleteType(DeclLoc, Initializer->getType())) {
+ const auto &Conversions = SourceRD->getVisibleConversionFunctions();
+ for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) {
+ NamedDecl *D = *I;
+ CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
+ D = D->getUnderlyingDecl();
+
+ FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(D);
+ CXXConversionDecl *Conv;
+ if (ConvTemplate)
+ Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
+ else
+ Conv = cast<CXXConversionDecl>(D);
+
+ if ((AllowExplicit && !CopyInitializing) || !Conv->isExplicit()) {
+ if (ConvTemplate)
+ S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(),
+ ActingDC, Initializer, DestType,
+ CandidateSet, AllowExplicit,
+ /*AllowResultConversion*/false);
+ else
+ S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Initializer,
+ DestType, CandidateSet, AllowExplicit,
+ /*AllowResultConversion*/false);
+ }
+ }
+ }
+ }
+
// Perform overload resolution and return the result.
return CandidateSet.BestViableFunction(S, DeclLoc, Best);
}
@@ -3624,7 +3701,7 @@ static void TryConstructorInitialization(Sema &S,
return;
}
- // C++1z [dcl.init]p17:
+ // C++17 [dcl.init]p17:
// - If the initializer expression is a prvalue and the cv-unqualified
// version of the source type is the same class as the class of the
// destination, the initializer expression is used to initialize the
@@ -3633,7 +3710,7 @@ static void TryConstructorInitialization(Sema &S,
// class or delegating to another constructor from a mem-initializer.
// ObjC++: Lambda captured by the block in the lambda to block conversion
// should avoid copy elision.
- if (S.getLangOpts().CPlusPlus1z &&
+ if (S.getLangOpts().CPlusPlus17 &&
Entity.getKind() != InitializedEntity::EK_Base &&
Entity.getKind() != InitializedEntity::EK_Delegating &&
Entity.getKind() !=
@@ -3686,7 +3763,7 @@ static void TryConstructorInitialization(Sema &S,
// the first phase is omitted.
if (!(UnwrappedArgs.empty() && DestRecordDecl->hasDefaultConstructor()))
Result = ResolveConstructorOverload(S, Kind.getLocation(), Args,
- CandidateSet, Ctors, Best,
+ CandidateSet, DestType, Ctors, Best,
CopyInitialization, AllowExplicit,
/*OnlyListConstructor=*/true,
IsListInit);
@@ -3700,7 +3777,7 @@ static void TryConstructorInitialization(Sema &S,
if (Result == OR_No_Viable_Function) {
AsInitializerList = false;
Result = ResolveConstructorOverload(S, Kind.getLocation(), UnwrappedArgs,
- CandidateSet, Ctors, Best,
+ CandidateSet, DestType, Ctors, Best,
CopyInitialization, AllowExplicit,
/*OnlyListConstructors=*/false,
IsListInit);
@@ -3713,6 +3790,24 @@ static void TryConstructorInitialization(Sema &S,
return;
}
+ bool HadMultipleCandidates = (CandidateSet.size() > 1);
+
+ // In C++17, ResolveConstructorOverload can select a conversion function
+ // instead of a constructor.
+ if (auto *CD = dyn_cast<CXXConversionDecl>(Best->Function)) {
+ // Add the user-defined conversion step that calls the conversion function.
+ QualType ConvType = CD->getConversionType();
+ assert(S.Context.hasSameUnqualifiedType(ConvType, DestType) &&
+ "should not have selected this conversion function");
+ Sequence.AddUserConversionStep(CD, Best->FoundDecl, ConvType,
+ HadMultipleCandidates);
+ if (!S.Context.hasSameType(ConvType, DestType))
+ Sequence.AddQualificationConversionStep(DestType, VK_RValue);
+ if (IsListInit)
+ Sequence.RewrapReferenceInitList(Entity.getType(), ILE);
+ return;
+ }
+
// C++11 [dcl.init]p6:
// If a program calls for the default initialization of an object
// of a const-qualified type T, T shall be a class type with a
@@ -3741,7 +3836,6 @@ static void TryConstructorInitialization(Sema &S,
// Add the constructor initialization step. Any cv-qualification conversion is
// subsumed by the initialization.
- bool HadMultipleCandidates = (CandidateSet.size() > 1);
Sequence.AddConstructorInitializationStep(
Best->FoundDecl, CtorDecl, DestArrayType, HadMultipleCandidates,
IsListInit | IsInitListCopy, AsInitializerList);
@@ -3984,7 +4078,7 @@ static void TryListInitialization(Sema &S,
// value T(v); if a narrowing conversion is required to convert v to
// the underlying type of T, the program is ill-formed.
auto *ET = DestType->getAs<EnumType>();
- if (S.getLangOpts().CPlusPlus1z &&
+ if (S.getLangOpts().CPlusPlus17 &&
Kind.getKind() == InitializationKind::IK_DirectList &&
ET && ET->getDecl()->isFixed() &&
!S.Context.hasSameUnqualifiedType(E->getType(), DestType) &&
@@ -4087,7 +4181,7 @@ static OverloadingResult TryRefInitWithConversionFunction(
// Build the candidate set directly in the initialization sequence
// structure, so that it will persist if we fail.
OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
- CandidateSet.clear();
+ CandidateSet.clear(OverloadCandidateSet::CSK_InitByUserDefinedConversion);
// Determine whether we are allowed to call explicit constructors or
// explicit conversion operators.
@@ -4173,7 +4267,7 @@ static OverloadingResult TryRefInitWithConversionFunction(
// Perform overload resolution. If it fails, return the failed result.
OverloadCandidateSet::iterator Best;
if (OverloadingResult Result
- = CandidateSet.BestViableFunction(S, DeclLoc, Best, true))
+ = CandidateSet.BestViableFunction(S, DeclLoc, Best))
return Result;
FunctionDecl *Function = Best->Function;
@@ -4417,7 +4511,7 @@ static void TryReferenceInitializationCore(Sema &S,
RefRelationship == Sema::Ref_Related)) &&
((InitCategory.isXValue() && !isNonReferenceableGLValue(Initializer)) ||
(InitCategory.isPRValue() &&
- (S.getLangOpts().CPlusPlus1z || T2->isRecordType() ||
+ (S.getLangOpts().CPlusPlus17 || T2->isRecordType() ||
T2->isArrayType())))) {
ExprValueKind ValueKind = InitCategory.isXValue() ? VK_XValue : VK_RValue;
if (InitCategory.isPRValue() && T2->isRecordType()) {
@@ -4687,7 +4781,7 @@ static void TryUserDefinedConversion(Sema &S,
// Build the candidate set directly in the initialization sequence
// structure, so that it will persist if we fail.
OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
- CandidateSet.clear();
+ CandidateSet.clear(OverloadCandidateSet::CSK_InitByUserDefinedConversion);
// Determine whether we are allowed to call explicit constructors or
// explicit conversion operators.
@@ -4766,7 +4860,7 @@ static void TryUserDefinedConversion(Sema &S,
// Perform overload resolution. If it fails, return the failed result.
OverloadCandidateSet::iterator Best;
if (OverloadingResult Result
- = CandidateSet.BestViableFunction(S, DeclLoc, Best, true)) {
+ = CandidateSet.BestViableFunction(S, DeclLoc, Best)) {
Sequence.SetOverloadFailure(
InitializationSequence::FK_UserConversionOverloadFailed,
Result);
@@ -4793,7 +4887,7 @@ static void TryUserDefinedConversion(Sema &S,
// copy-initialization.
// Note that this just performs a simple object copy from the temporary.
//
- // C++1z:
+ // C++17:
// - if the function is a constructor, the call is a prvalue of the
// cv-unqualified version of the destination type whose return object
// is initialized by the constructor. The call is used to
@@ -4802,7 +4896,7 @@ static void TryUserDefinedConversion(Sema &S,
// Therefore we need to do nothing further.
//
// FIXME: Mark this copy as extraneous.
- if (!S.getLangOpts().CPlusPlus1z)
+ if (!S.getLangOpts().CPlusPlus17)
Sequence.AddFinalCopy(DestType);
else if (DestType.hasQualifiers())
Sequence.AddQualificationConversionStep(DestType, VK_RValue);
@@ -4818,13 +4912,13 @@ static void TryUserDefinedConversion(Sema &S,
// The call is used to direct-initialize [...] the object that is the
// destination of the copy-initialization.
//
- // In C++1z, this does not call a constructor if we enter /17.6.1:
+ // In C++17, this does not call a constructor if we enter /17.6.1:
// - If the initializer expression is a prvalue and the cv-unqualified
// version of the source type is the same as the class of the
// destination [... do not make an extra copy]
//
// FIXME: Mark this copy as extraneous.
- if (!S.getLangOpts().CPlusPlus1z ||
+ if (!S.getLangOpts().CPlusPlus17 ||
Function->getReturnType()->isReferenceType() ||
!S.Context.hasSameUnqualifiedType(ConvType, DestType))
Sequence.AddFinalCopy(DestType);
@@ -5657,7 +5751,7 @@ static ExprResult CopyObject(Sema &S,
OverloadCandidateSet::iterator Best;
switch (ResolveConstructorOverload(
- S, Loc, CurInitExpr, CandidateSet, Ctors, Best,
+ S, Loc, CurInitExpr, CandidateSet, T, Ctors, Best,
/*CopyInitializing=*/false, /*AllowExplicit=*/true,
/*OnlyListConstructors=*/false, /*IsListInit=*/false,
/*SecondStepOfCopyInit=*/true)) {
@@ -5797,7 +5891,7 @@ static void CheckCXX98CompatAccessibleCopy(Sema &S,
// Perform overload resolution.
OverloadCandidateSet::iterator Best;
OverloadingResult OR = ResolveConstructorOverload(
- S, Loc, CurInitExpr, CandidateSet, Ctors, Best,
+ S, Loc, CurInitExpr, CandidateSet, CurInitExpr->getType(), Ctors, Best,
/*CopyInitializing=*/false, /*AllowExplicit=*/true,
/*OnlyListConstructors=*/false, /*IsListInit=*/false,
/*SecondStepOfCopyInit=*/true);
@@ -6328,6 +6422,10 @@ static void CheckMoveOnConstruction(Sema &S, const Expr *InitExpr,
if (!VD || !VD->hasLocalStorage())
return;
+ // __block variables are not moved implicitly.
+ if (VD->hasAttr<BlocksAttr>())
+ return;
+
QualType SourceType = VD->getType();
if (!SourceType->isRecordType())
return;
@@ -7535,8 +7633,7 @@ bool InitializationSequence::Diagnose(Sema &S,
<< Args[0]->getSourceRange();
OverloadCandidateSet::iterator Best;
OverloadingResult Ovl
- = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best,
- true);
+ = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best);
if (Ovl == OR_Deleted) {
S.NoteDeletedFunction(Best->Function);
} else {
@@ -8339,6 +8436,16 @@ Sema::PerformCopyInitialization(const InitializedEntity &Entity,
return Result;
}
+/// Determine whether RD is, or is derived from, a specialization of CTD.
+static bool isOrIsDerivedFromSpecializationOf(CXXRecordDecl *RD,
+ ClassTemplateDecl *CTD) {
+ auto NotSpecialization = [&] (const CXXRecordDecl *Candidate) {
+ auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(Candidate);
+ return !CTSD || !declaresSameEntity(CTSD->getSpecializedTemplate(), CTD);
+ };
+ return !(NotSpecialization(RD) && RD->forallBases(NotSpecialization));
+}
+
QualType Sema::DeduceTemplateSpecializationFromInitializer(
TypeSourceInfo *TSInfo, const InitializedEntity &Entity,
const InitializationKind &Kind, MultiExprArg Inits) {
@@ -8405,7 +8512,7 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
OverloadCandidateSet::iterator Best;
auto tryToResolveOverload =
[&](bool OnlyListConstructors) -> OverloadingResult {
- Candidates.clear();
+ Candidates.clear(OverloadCandidateSet::CSK_Normal);
for (auto I = Guides.begin(), E = Guides.end(); I != E; ++I) {
NamedDecl *D = (*I)->getUnderlyingDecl();
if (D->isInvalidDecl())
@@ -8483,6 +8590,17 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
break;
}
}
+ } else if (ListInit->getNumInits() == 1) {
+ // C++ [over.match.class.deduct]:
+ // As an exception, the first phase in [over.match.list] (considering
+ // initializer-list constructors) is omitted if the initializer list
+ // consists of a single expression of type cv U, where U is a
+ // specialization of C or a class derived from a specialization of C.
+ Expr *E = ListInit->getInit(0);
+ auto *RD = E->getType()->getAsCXXRecordDecl();
+ if (!isa<InitListExpr>(E) && RD &&
+ isOrIsDerivedFromSpecializationOf(RD, Template))
+ TryListConstructors = false;
}
if (TryListConstructors)
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp
index b0b7e64711f64..cbfc330ca60b2 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp
@@ -288,7 +288,9 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC,
Normal,
DefaultArgument,
DataMember,
- StaticDataMember
+ StaticDataMember,
+ InlineVariable,
+ VariableTemplate
} Kind = Normal;
// Default arguments of member function parameters that appear in a class
@@ -303,6 +305,14 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC,
} else if (VarDecl *Var = dyn_cast<VarDecl>(ManglingContextDecl)) {
if (Var->getDeclContext()->isRecord())
Kind = StaticDataMember;
+ else if (Var->getMostRecentDecl()->isInline())
+ Kind = InlineVariable;
+ else if (Var->getDescribedVarTemplate())
+ Kind = VariableTemplate;
+ else if (auto *VTS = dyn_cast<VarTemplateSpecializationDecl>(Var)) {
+ if (!VTS->isExplicitSpecialization())
+ Kind = VariableTemplate;
+ }
} else if (isa<FieldDecl>(ManglingContextDecl)) {
Kind = DataMember;
}
@@ -343,6 +353,10 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC,
// -- the in-class initializers of class members
case DefaultArgument:
// -- default arguments appearing in class definitions
+ case InlineVariable:
+ // -- the initializers of inline variables
+ case VariableTemplate:
+ // -- the initializers of templated variables
return &ExprEvalContexts.back().getMangleNumberingContext(Context);
}
@@ -933,8 +947,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
PrevCaptureLoc = C->Loc, ++C) {
if (C->Kind == LCK_This || C->Kind == LCK_StarThis) {
if (C->Kind == LCK_StarThis)
- Diag(C->Loc, !getLangOpts().CPlusPlus1z
- ? diag::ext_star_this_lambda_capture_cxx1z
+ Diag(C->Loc, !getLangOpts().CPlusPlus17
+ ? diag::ext_star_this_lambda_capture_cxx17
: diag::warn_cxx14_compat_star_this_lambda_capture);
// C++11 [expr.prim.lambda]p8:
@@ -948,17 +962,15 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
continue;
}
- // C++1z [expr.prim.lambda]p8:
- // If a lambda-capture includes a capture-default that is =, each
- // simple-capture of that lambda-capture shall be of the form "&
- // identifier" or "* this". [ Note: The form [&,this] is redundant but
- // accepted for compatibility with ISO C++14. --end note ]
- if (Intro.Default == LCD_ByCopy && C->Kind != LCK_StarThis) {
- Diag(C->Loc, diag::err_this_capture_with_copy_default)
- << FixItHint::CreateRemoval(
- SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc));
- continue;
- }
+ // C++2a [expr.prim.lambda]p8:
+ // If a lambda-capture includes a capture-default that is =,
+ // each simple-capture of that lambda-capture shall be of the form
+ // "&identifier", "this", or "* this". [ Note: The form [&,this] is
+ // redundant but accepted for compatibility with ISO C++14. --end note ]
+ if (Intro.Default == LCD_ByCopy && C->Kind != LCK_StarThis)
+ Diag(C->Loc, !getLangOpts().CPlusPlus2a
+ ? diag::ext_equals_this_lambda_capture_cxx2a
+ : diag::warn_cxx17_compat_equals_this_lambda_capture);
// C++11 [expr.prim.lambda]p12:
// If this is captured by a local lambda expression, its nearest
@@ -1276,7 +1288,7 @@ static void addFunctionPointerConversion(Sema &S,
ConvTy,
ConvTSI,
/*isInline=*/true, /*isExplicit=*/false,
- /*isConstexpr=*/S.getLangOpts().CPlusPlus1z,
+ /*isConstexpr=*/S.getLangOpts().CPlusPlus17,
CallOperator->getBody()->getLocEnd());
Conversion->setAccess(AS_public);
Conversion->setImplicit(true);
@@ -1599,7 +1611,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
// If the lambda expression's call operator is not explicitly marked constexpr
// and we are not in a dependent context, analyze the call operator to infer
// its constexpr-ness, suppressing diagnostics while doing so.
- if (getLangOpts().CPlusPlus1z && !CallOperator->isInvalidDecl() &&
+ if (getLangOpts().CPlusPlus17 && !CallOperator->isInvalidDecl() &&
!CallOperator->isConstexpr() &&
!isa<CoroutineBodyStmt>(CallOperator->getBody()) &&
!Class->getDeclContext()->isDependentContext()) {
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
index 85596ed52e9d6..d3f91a4e273d2 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
@@ -88,13 +88,15 @@ namespace {
/// A collection of using directives, as used by C++ unqualified
/// lookup.
class UnqualUsingDirectiveSet {
+ Sema &SemaRef;
+
typedef SmallVector<UnqualUsingEntry, 8> ListTy;
ListTy list;
llvm::SmallPtrSet<DeclContext*, 8> visited;
public:
- UnqualUsingDirectiveSet() {}
+ UnqualUsingDirectiveSet(Sema &SemaRef) : SemaRef(SemaRef) {}
void visitScopeChain(Scope *S, Scope *InnermostFileScope) {
// C++ [namespace.udir]p1:
@@ -113,7 +115,8 @@ namespace {
visit(Ctx, Ctx);
} else if (!Ctx || Ctx->isFunctionOrMethod()) {
for (auto *I : S->using_directives())
- visit(I, InnermostFileDC);
+ if (SemaRef.isVisible(I))
+ visit(I, InnermostFileDC);
}
}
}
@@ -152,7 +155,7 @@ namespace {
while (true) {
for (auto UD : DC->using_directives()) {
DeclContext *NS = UD->getNominatedNamespace();
- if (visited.insert(NS).second) {
+ if (SemaRef.isVisible(UD) && visited.insert(NS).second) {
addUsingDirective(UD, EffectiveDC);
queue.push_back(NS);
}
@@ -1031,7 +1034,8 @@ struct FindLocalExternScope {
FindLocalExternScope(LookupResult &R)
: R(R), OldFindLocalExtern(R.getIdentifierNamespace() &
Decl::IDNS_LocalExtern) {
- R.setFindLocalExtern(R.getIdentifierNamespace() & Decl::IDNS_Ordinary);
+ R.setFindLocalExtern(R.getIdentifierNamespace() &
+ (Decl::IDNS_Ordinary | Decl::IDNS_NonMemberOperator));
}
void restore() {
R.setFindLocalExtern(OldFindLocalExtern);
@@ -1084,7 +1088,7 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
// }
// }
//
- UnqualUsingDirectiveSet UDirs;
+ UnqualUsingDirectiveSet UDirs(*this);
bool VisitedUsingDirectives = false;
bool LeftStartingScope = false;
DeclContext *OutsideOfTemplateParamDC = nullptr;
@@ -1370,7 +1374,7 @@ static Module *getDefiningModule(Sema &S, Decl *Entity) {
// Walk up to the containing context. That might also have been instantiated
// from a template.
- DeclContext *Context = Entity->getDeclContext();
+ DeclContext *Context = Entity->getLexicalDeclContext();
if (Context->isFileContext())
return S.getOwningModule(Entity);
return getDefiningModule(S, cast<Decl>(Context));
@@ -1608,11 +1612,39 @@ bool Sema::isVisibleSlow(const NamedDecl *D) {
}
bool Sema::shouldLinkPossiblyHiddenDecl(LookupResult &R, const NamedDecl *New) {
+ // FIXME: If there are both visible and hidden declarations, we need to take
+ // into account whether redeclaration is possible. Example:
+ //
+ // Non-imported module:
+ // int f(T); // #1
+ // Some TU:
+ // static int f(U); // #2, not a redeclaration of #1
+ // int f(T); // #3, finds both, should link with #1 if T != U, but
+ // // with #2 if T == U; neither should be ambiguous.
for (auto *D : R) {
if (isVisible(D))
return true;
+ assert(D->isExternallyDeclarable() &&
+ "should not have hidden, non-externally-declarable result here");
}
- return New->isExternallyVisible();
+
+ // This function is called once "New" is essentially complete, but before a
+ // previous declaration is attached. We can't query the linkage of "New" in
+ // general, because attaching the previous declaration can change the
+ // linkage of New to match the previous declaration.
+ //
+ // However, because we've just determined that there is no *visible* prior
+ // declaration, we can compute the linkage here. There are two possibilities:
+ //
+ // * This is not a redeclaration; it's safe to compute the linkage now.
+ //
+ // * This is a redeclaration of a prior declaration that is externally
+ // redeclarable. In that case, the linkage of the declaration is not
+ // changed by attaching the prior declaration, because both are externally
+ // declarable (and thus ExternalLinkage or VisibleNoLinkage).
+ //
+ // FIXME: This is subtle and fragile.
+ return New->isExternallyDeclarable();
}
/// \brief Retrieve the visible declaration corresponding to D, if any.
@@ -1839,22 +1871,19 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R,
DeclContext *StartDC) {
assert(StartDC->isFileContext() && "start context is not a file context");
- DeclContext::udir_range UsingDirectives = StartDC->using_directives();
- if (UsingDirectives.begin() == UsingDirectives.end()) return false;
+ // We have not yet looked into these namespaces, much less added
+ // their "using-children" to the queue.
+ SmallVector<NamespaceDecl*, 8> Queue;
// We have at least added all these contexts to the queue.
llvm::SmallPtrSet<DeclContext*, 8> Visited;
Visited.insert(StartDC);
- // We have not yet looked into these namespaces, much less added
- // their "using-children" to the queue.
- SmallVector<NamespaceDecl*, 8> Queue;
-
// We have already looked into the initial namespace; seed the queue
// with its using-children.
- for (auto *I : UsingDirectives) {
+ for (auto *I : StartDC->using_directives()) {
NamespaceDecl *ND = I->getNominatedNamespace()->getOriginalNamespace();
- if (Visited.insert(ND).second)
+ if (S.isVisible(I) && Visited.insert(ND).second)
Queue.push_back(ND);
}
@@ -1902,7 +1931,7 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R,
for (auto I : ND->using_directives()) {
NamespaceDecl *Nom = I->getNominatedNamespace();
- if (Visited.insert(Nom).second)
+ if (S.isVisible(I) && Visited.insert(Nom).second)
Queue.push_back(Nom);
}
}
@@ -3121,7 +3150,7 @@ Sema::LiteralOperatorLookupResult
Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
ArrayRef<QualType> ArgTys,
bool AllowRaw, bool AllowTemplate,
- bool AllowStringTemplate) {
+ bool AllowStringTemplate, bool DiagnoseMissing) {
LookupName(R, S);
assert(R.getResultKind() != LookupResult::Ambiguous &&
"literal operator lookup can't be ambiguous");
@@ -3222,11 +3251,15 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
return LOLR_StringTemplate;
// Didn't find anything we could use.
- Diag(R.getNameLoc(), diag::err_ovl_no_viable_literal_operator)
- << R.getLookupName() << (int)ArgTys.size() << ArgTys[0]
- << (ArgTys.size() == 2 ? ArgTys[1] : QualType()) << AllowRaw
- << (AllowTemplate || AllowStringTemplate);
- return LOLR_Error;
+ if (DiagnoseMissing) {
+ Diag(R.getNameLoc(), diag::err_ovl_no_viable_literal_operator)
+ << R.getLookupName() << (int)ArgTys.size() << ArgTys[0]
+ << (ArgTys.size() == 2 ? ArgTys[1] : QualType()) << AllowRaw
+ << (AllowTemplate || AllowStringTemplate);
+ return LOLR_Error;
+ }
+
+ return LOLR_ErrorNoDiagnostic;
}
void ADLResult::insert(NamedDecl *New) {
@@ -3316,16 +3349,24 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
continue;
}
- if (isa<UsingShadowDecl>(D))
- D = cast<UsingShadowDecl>(D)->getTargetDecl();
+ auto *Underlying = D;
+ if (auto *USD = dyn_cast<UsingShadowDecl>(D))
+ Underlying = USD->getTargetDecl();
- if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D))
+ if (!isa<FunctionDecl>(Underlying) &&
+ !isa<FunctionTemplateDecl>(Underlying))
continue;
- if (!isVisible(D) && !(D = findAcceptableDecl(*this, D)))
- continue;
+ if (!isVisible(D)) {
+ D = findAcceptableDecl(*this, D);
+ if (!D)
+ continue;
+ if (auto *USD = dyn_cast<UsingShadowDecl>(D))
+ Underlying = USD->getTargetDecl();
+ }
- Result.insert(D);
+ // FIXME: Preserve D as the FoundDecl.
+ Result.insert(Underlying);
}
}
}
@@ -3507,6 +3548,8 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
if (QualifiedNameLookup) {
ShadowContextRAII Shadow(Visited);
for (auto I : Ctx->using_directives()) {
+ if (!Result.getSema().isVisible(I))
+ continue;
LookupVisibleDecls(I->getNominatedNamespace(), Result,
QualifiedNameLookup, InBaseClass, Consumer, Visited,
IncludeDependentBases);
@@ -3634,8 +3677,10 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result,
!Visited.alreadyVisitedContext(S->getEntity())) ||
(S->getEntity())->isFunctionOrMethod()) {
FindLocalExternScope FindLocals(Result);
- // Walk through the declarations in this Scope.
- for (auto *D : S->decls()) {
+ // Walk through the declarations in this Scope. The consumer might add new
+ // decls to the scope as part of deserialization, so make a copy first.
+ SmallVector<Decl *, 8> ScopeDecls(S->decls().begin(), S->decls().end());
+ for (Decl *D : ScopeDecls) {
if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
if ((ND = Result.getAcceptableDecl(ND))) {
Consumer.FoundDecl(ND, Visited.checkHidden(ND), nullptr, false);
@@ -3713,7 +3758,7 @@ void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind,
// Determine the set of using directives available during
// unqualified name lookup.
Scope *Initial = S;
- UnqualUsingDirectiveSet UDirs;
+ UnqualUsingDirectiveSet UDirs(*this);
if (getLangOpts().CPlusPlus) {
// Find the first namespace or translation-unit scope.
while (S && !isNamespaceOrTranslationUnitScope(S))
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
index bfb0071a54f9f..ea5b1da46f32f 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
@@ -1290,6 +1290,14 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
// An abstract type is as bad as an incomplete type.
CompleteTypeErr = true;
}
+ if (!CompleteTypeErr) {
+ const RecordType *RecordTy = PropertyIvarType->getAs<RecordType>();
+ if (RecordTy && RecordTy->getDecl()->hasFlexibleArrayMember()) {
+ Diag(PropertyIvarLoc, diag::err_synthesize_variable_sized_ivar)
+ << PropertyIvarType;
+ CompleteTypeErr = true; // suppress later diagnostics about the ivar
+ }
+ }
if (CompleteTypeErr)
Ivar->setInvalidDecl();
ClassImpDecl->addDecl(Ivar);
@@ -1599,7 +1607,11 @@ Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
// meaningless for readonly properties, so don't diagnose if the
// atomic property is 'readonly'.
checkAtomicPropertyMismatch(*this, SuperProperty, Property, false);
- if (Property->getSetterName() != SuperProperty->getSetterName()) {
+ // Readonly properties from protocols can be implemented as "readwrite"
+ // with a custom setter name.
+ if (Property->getSetterName() != SuperProperty->getSetterName() &&
+ !(SuperProperty->isReadOnly() &&
+ isa<ObjCProtocolDecl>(SuperProperty->getDeclContext()))) {
Diag(Property->getLocation(), diag::warn_property_attribute)
<< Property->getDeclName() << "setter" << inheritedName;
Diag(SuperProperty->getLocation(), diag::note_property_declare);
@@ -1895,7 +1907,7 @@ void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl *IMPDecl,
/* property = */ Prop->getIdentifier(),
/* ivar = */ Prop->getDefaultSynthIvarName(Context),
Prop->getLocation(), Prop->getQueryKind()));
- if (PIDecl) {
+ if (PIDecl && !Prop->isUnavailable()) {
Diag(Prop->getLocation(), diag::warn_missing_explicit_synthesis);
Diag(IMPDecl->getLocation(), diag::note_while_in_implementation);
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp
index 1ae6f9d6c19c3..b34bb3388d717 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp
@@ -22,27 +22,36 @@
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtOpenMP.h"
#include "clang/AST/StmtVisitor.h"
-#include "clang/AST/TypeOrdering.h"
#include "clang/Basic/OpenMPKinds.h"
-#include "clang/Basic/TargetInfo.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
+#include "llvm/ADT/PointerEmbeddedInt.h"
using namespace clang;
//===----------------------------------------------------------------------===//
// Stack of data-sharing attributes for variables
//===----------------------------------------------------------------------===//
+static Expr *CheckMapClauseExpressionBase(
+ Sema &SemaRef, Expr *E,
+ OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
+ OpenMPClauseKind CKind, bool NoDiagnose);
+
namespace {
/// \brief Default data sharing attributes, which can be applied to directive.
enum DefaultDataSharingAttributes {
DSA_unspecified = 0, /// \brief Data sharing attribute not specified.
DSA_none = 1 << 0, /// \brief Default data sharing attribute 'none'.
- DSA_shared = 1 << 1 /// \brief Default data sharing attribute 'shared'.
+ DSA_shared = 1 << 1, /// \brief Default data sharing attribute 'shared'.
+};
+
+/// Attributes of the defaultmap clause.
+enum DefaultMapAttributes {
+ DMA_unspecified, /// Default mapping is not specified.
+ DMA_tofrom_scalar, /// Default mapping is 'tofrom:scalar'.
};
/// \brief Stack for tracking declarations used in OpenMP directives and
@@ -55,7 +64,11 @@ public:
Expr *RefExpr = nullptr;
DeclRefExpr *PrivateCopy = nullptr;
SourceLocation ImplicitDSALoc;
- DSAVarData() {}
+ DSAVarData() = default;
+ DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, Expr *RefExpr,
+ DeclRefExpr *PrivateCopy, SourceLocation ImplicitDSALoc)
+ : DKind(DKind), CKind(CKind), RefExpr(RefExpr),
+ PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc) {}
};
typedef llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>
OperatorOffsetTy;
@@ -84,14 +97,32 @@ private:
CriticalsWithHintsTy;
typedef llvm::DenseMap<OMPDependClause *, OperatorOffsetTy>
DoacrossDependMapTy;
+ struct ReductionData {
+ typedef llvm::PointerEmbeddedInt<BinaryOperatorKind, 16> BOKPtrType;
+ SourceRange ReductionRange;
+ llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
+ ReductionData() = default;
+ void set(BinaryOperatorKind BO, SourceRange RR) {
+ ReductionRange = RR;
+ ReductionOp = BO;
+ }
+ void set(const Expr *RefExpr, SourceRange RR) {
+ ReductionRange = RR;
+ ReductionOp = RefExpr;
+ }
+ };
+ typedef llvm::DenseMap<ValueDecl *, ReductionData> DeclReductionMapTy;
struct SharingMapTy final {
DeclSAMapTy SharingMap;
+ DeclReductionMapTy ReductionMap;
AlignedMapTy AlignedMap;
MappedExprComponentsTy MappedExprComponents;
LoopControlVariablesMapTy LCVMap;
DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
SourceLocation DefaultAttrLoc;
+ DefaultMapAttributes DefaultMapAttr = DMA_unspecified;
+ SourceLocation DefaultMapAttrLoc;
OpenMPDirectiveKind Directive = OMPD_unknown;
DeclarationNameInfo DirectiveName;
Scope *CurScope = nullptr;
@@ -108,11 +139,13 @@ private:
bool CancelRegion = false;
unsigned AssociatedLoops = 1;
SourceLocation InnerTeamsRegionLoc;
+ /// Reference to the taskgroup task_reduction reference expression.
+ Expr *TaskgroupReductionRef = nullptr;
SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
Scope *CurScope, SourceLocation Loc)
: Directive(DKind), DirectiveName(Name), CurScope(CurScope),
ConstructLoc(Loc) {}
- SharingMapTy() {}
+ SharingMapTy() = default;
};
typedef SmallVector<SharingMapTy, 4> StackTy;
@@ -145,6 +178,10 @@ public:
explicit DSAStackTy(Sema &S) : SemaRef(S) {}
bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
+ OpenMPClauseKind getClauseParsingMode() const {
+ assert(isClauseParsingMode() && "Must be in clause parsing mode.");
+ return ClauseKindMode;
+ }
void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
bool isForceVarCapturing() const { return ForceCapturing; }
@@ -221,6 +258,39 @@ public:
void addDSA(ValueDecl *D, Expr *E, OpenMPClauseKind A,
DeclRefExpr *PrivateCopy = nullptr);
+ /// Adds additional information for the reduction items with the reduction id
+ /// represented as an operator.
+ void addTaskgroupReductionData(ValueDecl *D, SourceRange SR,
+ BinaryOperatorKind BOK);
+ /// Adds additional information for the reduction items with the reduction id
+ /// represented as reduction identifier.
+ void addTaskgroupReductionData(ValueDecl *D, SourceRange SR,
+ const Expr *ReductionRef);
+ /// Returns the location and reduction operation from the innermost parent
+ /// region for the given \p D.
+ DSAVarData getTopMostTaskgroupReductionData(ValueDecl *D, SourceRange &SR,
+ BinaryOperatorKind &BOK,
+ Expr *&TaskgroupDescriptor);
+ /// Returns the location and reduction operation from the innermost parent
+ /// region for the given \p D.
+ DSAVarData getTopMostTaskgroupReductionData(ValueDecl *D, SourceRange &SR,
+ const Expr *&ReductionRef,
+ Expr *&TaskgroupDescriptor);
+ /// Return reduction reference expression for the current taskgroup.
+ Expr *getTaskgroupReductionRef() const {
+ assert(Stack.back().first.back().Directive == OMPD_taskgroup &&
+ "taskgroup reference expression requested for non taskgroup "
+ "directive.");
+ return Stack.back().first.back().TaskgroupReductionRef;
+ }
+ /// Checks if the given \p VD declaration is actually a taskgroup reduction
+ /// descriptor variable at the \p Level of OpenMP regions.
+ bool isTaskgroupReductionRef(ValueDecl *VD, unsigned Level) const {
+ return Stack.back().first[Level].TaskgroupReductionRef &&
+ cast<DeclRefExpr>(Stack.back().first[Level].TaskgroupReductionRef)
+ ->getDecl() == VD;
+ }
+
/// \brief Returns data sharing attributes from top of the stack for the
/// specified declaration.
DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
@@ -264,6 +334,11 @@ public:
OpenMPDirectiveKind getCurrentDirective() const {
return isStackEmpty() ? OMPD_unknown : Stack.back().first.back().Directive;
}
+ /// \brief Returns directive kind at specified level.
+ OpenMPDirectiveKind getDirective(unsigned Level) const {
+ assert(!isStackEmpty() && "No directive at specified level.");
+ return Stack.back().first[Level].Directive;
+ }
/// \brief Returns parent directive.
OpenMPDirectiveKind getParentDirective() const {
if (isStackEmpty() || Stack.back().first.size() == 1)
@@ -283,6 +358,12 @@ public:
Stack.back().first.back().DefaultAttr = DSA_shared;
Stack.back().first.back().DefaultAttrLoc = Loc;
}
+ /// Set default data mapping attribute to 'tofrom:scalar'.
+ void setDefaultDMAToFromScalar(SourceLocation Loc) {
+ assert(!isStackEmpty());
+ Stack.back().first.back().DefaultMapAttr = DMA_tofrom_scalar;
+ Stack.back().first.back().DefaultMapAttrLoc = Loc;
+ }
DefaultDataSharingAttributes getDefaultDSA() const {
return isStackEmpty() ? DSA_unspecified
@@ -292,6 +373,17 @@ public:
return isStackEmpty() ? SourceLocation()
: Stack.back().first.back().DefaultAttrLoc;
}
+ DefaultMapAttributes getDefaultDMA() const {
+ return isStackEmpty() ? DMA_unspecified
+ : Stack.back().first.back().DefaultMapAttr;
+ }
+ DefaultMapAttributes getDefaultDMAAtLevel(unsigned Level) const {
+ return Stack.back().first[Level].DefaultMapAttr;
+ }
+ SourceLocation getDefaultDMALocation() const {
+ return isStackEmpty() ? SourceLocation()
+ : Stack.back().first.back().DefaultMapAttrLoc;
+ }
/// \brief Checks if the specified variable is a threadprivate.
bool isThreadPrivate(VarDecl *D) {
@@ -479,7 +571,25 @@ bool isParallelOrTaskRegion(OpenMPDirectiveKind DKind) {
}
} // namespace
+static Expr *getExprAsWritten(Expr *E) {
+ if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(E))
+ E = ExprTemp->getSubExpr();
+
+ if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
+ E = MTE->GetTemporaryExpr();
+
+ while (auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
+ E = Binder->getSubExpr();
+
+ if (auto *ICE = dyn_cast<ImplicitCastExpr>(E))
+ E = ICE->getSubExprAsWritten();
+ return E->IgnoreParens();
+}
+
static ValueDecl *getCanonicalDecl(ValueDecl *D) {
+ if (auto *CED = dyn_cast<OMPCapturedExprDecl>(D))
+ if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
+ D = ME->getMemberDecl();
auto *VD = dyn_cast<VarDecl>(D);
auto *FD = dyn_cast<FieldDecl>(D);
if (VD != nullptr) {
@@ -522,7 +632,6 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator &Iter,
return DVar;
}
- DVar.DKind = Iter->Directive;
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
// in a Construct, C/C++, predetermined, p.1]
// Variables with automatic storage duration that are declared in a scope
@@ -533,6 +642,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator &Iter,
return DVar;
}
+ DVar.DKind = Iter->Directive;
// Explicitly specified attributes and local variables with predetermined
// attributes.
if (Iter->SharingMap.count(D)) {
@@ -691,24 +801,6 @@ void DSAStackTy::addDSA(ValueDecl *D, Expr *E, OpenMPClauseKind A,
}
}
-bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) {
- D = D->getCanonicalDecl();
- if (!isStackEmpty() && Stack.back().first.size() > 1) {
- reverse_iterator I = Iter, E = Stack.back().first.rend();
- Scope *TopScope = nullptr;
- while (I != E && !isParallelOrTaskRegion(I->Directive))
- ++I;
- if (I == E)
- return false;
- TopScope = I->CurScope ? I->CurScope->getParent() : nullptr;
- Scope *CurScope = getCurScope();
- while (CurScope != TopScope && !CurScope->isDeclScope(D))
- CurScope = CurScope->getParent();
- return CurScope != TopScope;
- }
- return false;
-}
-
/// \brief Build a variable declaration for OpenMP loop iteration variable.
static VarDecl *buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type,
StringRef Name, const AttrVec *Attrs = nullptr) {
@@ -736,6 +828,130 @@ static DeclRefExpr *buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty,
VK_LValue);
}
+void DSAStackTy::addTaskgroupReductionData(ValueDecl *D, SourceRange SR,
+ BinaryOperatorKind BOK) {
+ D = getCanonicalDecl(D);
+ assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
+ assert(
+ Stack.back().first.back().SharingMap[D].Attributes == OMPC_reduction &&
+ "Additional reduction info may be specified only for reduction items.");
+ auto &ReductionData = Stack.back().first.back().ReductionMap[D];
+ assert(ReductionData.ReductionRange.isInvalid() &&
+ Stack.back().first.back().Directive == OMPD_taskgroup &&
+ "Additional reduction info may be specified only once for reduction "
+ "items.");
+ ReductionData.set(BOK, SR);
+ Expr *&TaskgroupReductionRef =
+ Stack.back().first.back().TaskgroupReductionRef;
+ if (!TaskgroupReductionRef) {
+ auto *VD = buildVarDecl(SemaRef, SR.getBegin(),
+ SemaRef.Context.VoidPtrTy, ".task_red.");
+ TaskgroupReductionRef =
+ buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
+ }
+}
+
+void DSAStackTy::addTaskgroupReductionData(ValueDecl *D, SourceRange SR,
+ const Expr *ReductionRef) {
+ D = getCanonicalDecl(D);
+ assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
+ assert(
+ Stack.back().first.back().SharingMap[D].Attributes == OMPC_reduction &&
+ "Additional reduction info may be specified only for reduction items.");
+ auto &ReductionData = Stack.back().first.back().ReductionMap[D];
+ assert(ReductionData.ReductionRange.isInvalid() &&
+ Stack.back().first.back().Directive == OMPD_taskgroup &&
+ "Additional reduction info may be specified only once for reduction "
+ "items.");
+ ReductionData.set(ReductionRef, SR);
+ Expr *&TaskgroupReductionRef =
+ Stack.back().first.back().TaskgroupReductionRef;
+ if (!TaskgroupReductionRef) {
+ auto *VD = buildVarDecl(SemaRef, SR.getBegin(), SemaRef.Context.VoidPtrTy,
+ ".task_red.");
+ TaskgroupReductionRef =
+ buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
+ }
+}
+
+DSAStackTy::DSAVarData
+DSAStackTy::getTopMostTaskgroupReductionData(ValueDecl *D, SourceRange &SR,
+ BinaryOperatorKind &BOK,
+ Expr *&TaskgroupDescriptor) {
+ D = getCanonicalDecl(D);
+ assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
+ if (Stack.back().first.empty())
+ return DSAVarData();
+ for (auto I = std::next(Stack.back().first.rbegin(), 1),
+ E = Stack.back().first.rend();
+ I != E; std::advance(I, 1)) {
+ auto &Data = I->SharingMap[D];
+ if (Data.Attributes != OMPC_reduction || I->Directive != OMPD_taskgroup)
+ continue;
+ auto &ReductionData = I->ReductionMap[D];
+ if (!ReductionData.ReductionOp ||
+ ReductionData.ReductionOp.is<const Expr *>())
+ return DSAVarData();
+ SR = ReductionData.ReductionRange;
+ BOK = ReductionData.ReductionOp.get<ReductionData::BOKPtrType>();
+ assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
+ "expression for the descriptor is not "
+ "set.");
+ TaskgroupDescriptor = I->TaskgroupReductionRef;
+ return DSAVarData(OMPD_taskgroup, OMPC_reduction, Data.RefExpr.getPointer(),
+ Data.PrivateCopy, I->DefaultAttrLoc);
+ }
+ return DSAVarData();
+}
+
+DSAStackTy::DSAVarData
+DSAStackTy::getTopMostTaskgroupReductionData(ValueDecl *D, SourceRange &SR,
+ const Expr *&ReductionRef,
+ Expr *&TaskgroupDescriptor) {
+ D = getCanonicalDecl(D);
+ assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
+ if (Stack.back().first.empty())
+ return DSAVarData();
+ for (auto I = std::next(Stack.back().first.rbegin(), 1),
+ E = Stack.back().first.rend();
+ I != E; std::advance(I, 1)) {
+ auto &Data = I->SharingMap[D];
+ if (Data.Attributes != OMPC_reduction || I->Directive != OMPD_taskgroup)
+ continue;
+ auto &ReductionData = I->ReductionMap[D];
+ if (!ReductionData.ReductionOp ||
+ !ReductionData.ReductionOp.is<const Expr *>())
+ return DSAVarData();
+ SR = ReductionData.ReductionRange;
+ ReductionRef = ReductionData.ReductionOp.get<const Expr *>();
+ assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
+ "expression for the descriptor is not "
+ "set.");
+ TaskgroupDescriptor = I->TaskgroupReductionRef;
+ return DSAVarData(OMPD_taskgroup, OMPC_reduction, Data.RefExpr.getPointer(),
+ Data.PrivateCopy, I->DefaultAttrLoc);
+ }
+ return DSAVarData();
+}
+
+bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) {
+ D = D->getCanonicalDecl();
+ if (!isStackEmpty() && Stack.back().first.size() > 1) {
+ reverse_iterator I = Iter, E = Stack.back().first.rend();
+ Scope *TopScope = nullptr;
+ while (I != E && !isParallelOrTaskRegion(I->Directive))
+ ++I;
+ if (I == E)
+ return false;
+ TopScope = I->CurScope ? I->CurScope->getParent() : nullptr;
+ Scope *CurScope = getCurScope();
+ while (CurScope != TopScope && !CurScope->isDeclScope(D))
+ CurScope = CurScope->getParent();
+ return CurScope != TopScope;
+ }
+ return false;
+}
+
DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, bool FromParent) {
D = getCanonicalDecl(D);
DSAVarData DVar;
@@ -759,6 +975,12 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, bool FromParent) {
DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
DVar.CKind = OMPC_threadprivate;
return DVar;
+ } else if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
+ DVar.RefExpr = buildDeclRefExpr(
+ SemaRef, VD, D->getType().getNonReferenceType(),
+ VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
+ DVar.CKind = OMPC_threadprivate;
+ addDSA(D, DVar.RefExpr, OMPC_threadprivate);
}
if (isStackEmpty())
@@ -811,16 +1033,16 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, bool FromParent) {
// Explicitly specified attributes and local variables with predetermined
// attributes.
- auto StartI = std::next(Stack.back().first.rbegin());
+ auto I = Stack.back().first.rbegin();
auto EndI = Stack.back().first.rend();
- if (FromParent && StartI != EndI)
- StartI = std::next(StartI);
- auto I = std::prev(StartI);
+ if (FromParent && I != EndI)
+ std::advance(I, 1);
if (I->SharingMap.count(D)) {
DVar.RefExpr = I->SharingMap[D].RefExpr.getPointer();
DVar.PrivateCopy = I->SharingMap[D].PrivateCopy;
DVar.CKind = I->SharingMap[D].Attributes;
DVar.ImplicitDSALoc = I->DefaultAttrLoc;
+ DVar.DKind = I->Directive;
}
return DVar;
@@ -836,7 +1058,7 @@ DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
auto StartI = Stack.back().first.rbegin();
auto EndI = Stack.back().first.rend();
if (FromParent && StartI != EndI)
- StartI = std::next(StartI);
+ std::advance(StartI, 1);
return getDSA(StartI, D);
}
@@ -848,16 +1070,16 @@ DSAStackTy::hasDSA(ValueDecl *D,
if (isStackEmpty())
return {};
D = getCanonicalDecl(D);
- auto I = (FromParent && Stack.back().first.size() > 1)
- ? std::next(Stack.back().first.rbegin())
- : Stack.back().first.rbegin();
+ auto I = Stack.back().first.rbegin();
auto EndI = Stack.back().first.rend();
- while (std::distance(I, EndI) > 1) {
+ if (FromParent && I != EndI)
std::advance(I, 1);
+ for (; I != EndI; std::advance(I, 1)) {
if (!DPred(I->Directive) && !isParallelOrTaskRegion(I->Directive))
continue;
- DSAVarData DVar = getDSA(I, D);
- if (CPred(DVar.CKind))
+ auto NewI = I;
+ DSAVarData DVar = getDSA(NewI, D);
+ if (I == NewI && CPred(DVar.CKind))
return DVar;
}
return {};
@@ -870,21 +1092,20 @@ DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
if (isStackEmpty())
return {};
D = getCanonicalDecl(D);
- auto StartI = std::next(Stack.back().first.rbegin());
+ auto StartI = Stack.back().first.rbegin();
auto EndI = Stack.back().first.rend();
if (FromParent && StartI != EndI)
- StartI = std::next(StartI);
+ std::advance(StartI, 1);
if (StartI == EndI || !DPred(StartI->Directive))
return {};
- DSAVarData DVar = getDSA(StartI, D);
- return CPred(DVar.CKind) ? DVar : DSAVarData();
+ auto NewI = StartI;
+ DSAVarData DVar = getDSA(NewI, D);
+ return (NewI == StartI && CPred(DVar.CKind)) ? DVar : DSAVarData();
}
bool DSAStackTy::hasExplicitDSA(
ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> &CPred,
unsigned Level, bool NotLastprivate) {
- if (CPred(ClauseKindMode))
- return true;
if (isStackEmpty())
return false;
D = getCanonicalDecl(D);
@@ -952,6 +1173,7 @@ bool Sema::IsOpenMPCapturedByRef(ValueDecl *D, unsigned Level) {
bool IsByRef = true;
// Find the directive that is associated with the provided scope.
+ D = cast<ValueDecl>(D->getCanonicalDecl());
auto Ty = D->getType();
if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level)) {
@@ -1057,8 +1279,13 @@ bool Sema::IsOpenMPCapturedByRef(ValueDecl *D, unsigned Level) {
// reference except if it is a pointer that is dereferenced somehow.
IsByRef = !(Ty->isPointerType() && IsVariableAssociatedWithSection);
} else {
- // By default, all the data that has a scalar type is mapped by copy.
- IsByRef = !Ty->isScalarType();
+ // By default, all the data that has a scalar type is mapped by copy
+ // (except for reduction variables).
+ IsByRef =
+ !Ty->isScalarType() ||
+ DSAStack->getDefaultDMAAtLevel(Level) == DMA_tofrom_scalar ||
+ DSAStack->hasExplicitDSA(
+ D, [](OpenMPClauseKind K) { return K == OMPC_reduction; }, Level);
}
}
@@ -1087,6 +1314,17 @@ unsigned Sema::getOpenMPNestingLevel() const {
return DSAStack->getNestingLevel();
}
+bool Sema::isInOpenMPTargetExecutionDirective() const {
+ return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
+ !DSAStack->isClauseParsingMode()) ||
+ DSAStack->hasDirective(
+ [](OpenMPDirectiveKind K, const DeclarationNameInfo &,
+ SourceLocation) -> bool {
+ return isOpenMPTargetExecutionDirective(K);
+ },
+ false);
+}
+
VarDecl *Sema::IsOpenMPCapturedDecl(ValueDecl *D) {
assert(LangOpts.OpenMP && "OpenMP is not allowed");
D = getCanonicalDecl(D);
@@ -1099,18 +1337,8 @@ VarDecl *Sema::IsOpenMPCapturedDecl(ValueDecl *D) {
// inserted here once support for 'declare target' is added.
//
auto *VD = dyn_cast<VarDecl>(D);
- if (VD && !VD->hasLocalStorage()) {
- if (DSAStack->getCurrentDirective() == OMPD_target &&
- !DSAStack->isClauseParsingMode())
- return VD;
- if (DSAStack->hasDirective(
- [](OpenMPDirectiveKind K, const DeclarationNameInfo &,
- SourceLocation) -> bool {
- return isOpenMPTargetExecutionDirective(K);
- },
- false))
- return VD;
- }
+ if (VD && !VD->hasLocalStorage() && isInOpenMPTargetExecutionDirective())
+ return VD;
if (DSAStack->getCurrentDirective() != OMPD_unknown &&
(!DSAStack->isClauseParsingMode() ||
@@ -1133,10 +1361,59 @@ VarDecl *Sema::IsOpenMPCapturedDecl(ValueDecl *D) {
return nullptr;
}
+void Sema::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
+ unsigned Level) const {
+ SmallVector<OpenMPDirectiveKind, 4> Regions;
+ getOpenMPCaptureRegions(Regions, DSAStack->getDirective(Level));
+ FunctionScopesIndex -= Regions.size();
+}
+
bool Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level) {
assert(LangOpts.OpenMP && "OpenMP is not allowed");
return DSAStack->hasExplicitDSA(
- D, [](OpenMPClauseKind K) -> bool { return K == OMPC_private; }, Level);
+ D, [](OpenMPClauseKind K) -> bool { return K == OMPC_private; },
+ Level) ||
+ (DSAStack->isClauseParsingMode() &&
+ DSAStack->getClauseParsingMode() == OMPC_private) ||
+ // Consider taskgroup reduction descriptor variable a private to avoid
+ // possible capture in the region.
+ (DSAStack->hasExplicitDirective(
+ [](OpenMPDirectiveKind K) { return K == OMPD_taskgroup; },
+ Level) &&
+ DSAStack->isTaskgroupReductionRef(D, Level));
+}
+
+void Sema::setOpenMPCaptureKind(FieldDecl *FD, ValueDecl *D, unsigned Level) {
+ assert(LangOpts.OpenMP && "OpenMP is not allowed");
+ D = getCanonicalDecl(D);
+ OpenMPClauseKind OMPC = OMPC_unknown;
+ for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
+ const unsigned NewLevel = I - 1;
+ if (DSAStack->hasExplicitDSA(D,
+ [&OMPC](const OpenMPClauseKind K) {
+ if (isOpenMPPrivate(K)) {
+ OMPC = K;
+ return true;
+ }
+ return false;
+ },
+ NewLevel))
+ break;
+ if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
+ D, NewLevel,
+ [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
+ OpenMPClauseKind) { return true; })) {
+ OMPC = OMPC_map;
+ break;
+ }
+ if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
+ NewLevel)) {
+ OMPC = OMPC_firstprivate;
+ break;
+ }
+ }
+ if (OMPC != OMPC_unknown)
+ FD->addAttr(OMPCaptureKindAttr::CreateImplicit(Context, OMPC));
}
bool Sema::isOpenMPTargetCapturedDecl(ValueDecl *D, unsigned Level) {
@@ -1249,7 +1526,7 @@ public:
explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
bool ValidateCandidate(const TypoCorrection &Candidate) override {
NamedDecl *ND = Candidate.getCorrectionDecl();
- if (isa<VarDecl>(ND) || isa<FunctionDecl>(ND)) {
+ if (ND && (isa<VarDecl>(ND) || isa<FunctionDecl>(ND))) {
return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
SemaRef.getCurScope());
}
@@ -1568,7 +1845,9 @@ class DSAAttrChecker : public StmtVisitor<DSAAttrChecker, void> {
bool ErrorFound;
CapturedStmt *CS;
llvm::SmallVector<Expr *, 8> ImplicitFirstprivate;
+ llvm::SmallVector<Expr *, 8> ImplicitMap;
llvm::DenseMap<ValueDecl *, Expr *> VarsWithInheritedDSA;
+ llvm::DenseSet<ValueDecl *> ImplicitDeclarations;
public:
void VisitDeclRefExpr(DeclRefExpr *E) {
@@ -1576,13 +1855,18 @@ public:
E->containsUnexpandedParameterPack() || E->isInstantiationDependent())
return;
if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
+ VD = VD->getCanonicalDecl();
// Skip internally declared variables.
- if (VD->isLocalVarDecl() && !CS->capturesVariable(VD))
+ if (VD->hasLocalStorage() && !CS->capturesVariable(VD))
return;
auto DVar = Stack->getTopDSA(VD, false);
// Check if the variable has explicit DSA set and stop analysis if it so.
- if (DVar.RefExpr)
+ if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
+ return;
+
+ // Skip internally declared static variables.
+ if (VD->hasGlobalStorage() && !CS->capturesVariable(VD))
return;
auto ELoc = E->getExprLoc();
@@ -1598,6 +1882,46 @@ public:
return;
}
+ if (isOpenMPTargetExecutionDirective(DKind) &&
+ !Stack->isLoopControlVariable(VD).first) {
+ if (!Stack->checkMappableExprComponentListsForDecl(
+ VD, /*CurrentRegionOnly=*/true,
+ [](OMPClauseMappableExprCommon::MappableExprComponentListRef
+ StackComponents,
+ OpenMPClauseKind) {
+ // Variable is used if it has been marked as an array, array
+ // section or the variable iself.
+ return StackComponents.size() == 1 ||
+ std::all_of(
+ std::next(StackComponents.rbegin()),
+ StackComponents.rend(),
+ [](const OMPClauseMappableExprCommon::
+ MappableComponent &MC) {
+ return MC.getAssociatedDeclaration() ==
+ nullptr &&
+ (isa<OMPArraySectionExpr>(
+ MC.getAssociatedExpression()) ||
+ isa<ArraySubscriptExpr>(
+ MC.getAssociatedExpression()));
+ });
+ })) {
+ bool IsFirstprivate = false;
+ // By default lambdas are captured as firstprivates.
+ if (const auto *RD =
+ VD->getType().getNonReferenceType()->getAsCXXRecordDecl())
+ IsFirstprivate = RD->isLambda();
+ IsFirstprivate =
+ IsFirstprivate ||
+ (VD->getType().getNonReferenceType()->isScalarType() &&
+ Stack->getDefaultDMA() != DMA_tofrom_scalar);
+ if (IsFirstprivate)
+ ImplicitFirstprivate.emplace_back(E);
+ else
+ ImplicitMap.emplace_back(E);
+ return;
+ }
+ }
+
// OpenMP [2.9.3.6, Restrictions, p.2]
// A list item that appears in a reduction clause of the innermost
// enclosing worksharing or parallel construct may not be accessed in an
@@ -1608,7 +1932,7 @@ public:
return isOpenMPParallelDirective(K) ||
isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K);
},
- false);
+ /*FromParent=*/true);
if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
ErrorFound = true;
SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
@@ -1627,40 +1951,103 @@ public:
if (E->isTypeDependent() || E->isValueDependent() ||
E->containsUnexpandedParameterPack() || E->isInstantiationDependent())
return;
+ auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
+ OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
- if (auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl())) {
- auto DVar = Stack->getTopDSA(FD, false);
- // Check if the variable has explicit DSA set and stop analysis if it
- // so.
- if (DVar.RefExpr)
- return;
+ if (!FD)
+ return;
+ auto DVar = Stack->getTopDSA(FD, false);
+ // Check if the variable has explicit DSA set and stop analysis if it
+ // so.
+ if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
+ return;
- auto ELoc = E->getExprLoc();
- auto DKind = Stack->getCurrentDirective();
- // OpenMP [2.9.3.6, Restrictions, p.2]
- // A list item that appears in a reduction clause of the innermost
- // enclosing worksharing or parallel construct may not be accessed in
- // an explicit task.
- DVar = Stack->hasInnermostDSA(
- FD, [](OpenMPClauseKind C) -> bool { return C == OMPC_reduction; },
- [](OpenMPDirectiveKind K) -> bool {
- return isOpenMPParallelDirective(K) ||
- isOpenMPWorksharingDirective(K) ||
- isOpenMPTeamsDirective(K);
- },
- false);
- if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
- ErrorFound = true;
- SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
- ReportOriginalDSA(SemaRef, Stack, FD, DVar);
+ if (isOpenMPTargetExecutionDirective(DKind) &&
+ !Stack->isLoopControlVariable(FD).first &&
+ !Stack->checkMappableExprComponentListsForDecl(
+ FD, /*CurrentRegionOnly=*/true,
+ [](OMPClauseMappableExprCommon::MappableExprComponentListRef
+ StackComponents,
+ OpenMPClauseKind) {
+ return isa<CXXThisExpr>(
+ cast<MemberExpr>(
+ StackComponents.back().getAssociatedExpression())
+ ->getBase()
+ ->IgnoreParens());
+ })) {
+ // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
+ // A bit-field cannot appear in a map clause.
+ //
+ if (FD->isBitField())
return;
- }
+ ImplicitMap.emplace_back(E);
+ return;
+ }
+
+ auto ELoc = E->getExprLoc();
+ // OpenMP [2.9.3.6, Restrictions, p.2]
+ // A list item that appears in a reduction clause of the innermost
+ // enclosing worksharing or parallel construct may not be accessed in
+ // an explicit task.
+ DVar = Stack->hasInnermostDSA(
+ FD, [](OpenMPClauseKind C) -> bool { return C == OMPC_reduction; },
+ [](OpenMPDirectiveKind K) -> bool {
+ return isOpenMPParallelDirective(K) ||
+ isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K);
+ },
+ /*FromParent=*/true);
+ if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
+ ErrorFound = true;
+ SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
+ ReportOriginalDSA(SemaRef, Stack, FD, DVar);
+ return;
+ }
+
+ // Define implicit data-sharing attributes for task.
+ DVar = Stack->getImplicitDSA(FD, false);
+ if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
+ !Stack->isLoopControlVariable(FD).first)
+ ImplicitFirstprivate.push_back(E);
+ return;
+ }
+ if (isOpenMPTargetExecutionDirective(DKind)) {
+ OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
+ if (!CheckMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
+ /*NoDiagnose=*/true))
+ return;
+ auto *VD = cast<ValueDecl>(
+ CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
+ if (!Stack->checkMappableExprComponentListsForDecl(
+ VD, /*CurrentRegionOnly=*/true,
+ [&CurComponents](
+ OMPClauseMappableExprCommon::MappableExprComponentListRef
+ StackComponents,
+ OpenMPClauseKind) {
+ auto CCI = CurComponents.rbegin();
+ auto CCE = CurComponents.rend();
+ for (const auto &SC : llvm::reverse(StackComponents)) {
+ // Do both expressions have the same kind?
+ if (CCI->getAssociatedExpression()->getStmtClass() !=
+ SC.getAssociatedExpression()->getStmtClass())
+ if (!(isa<OMPArraySectionExpr>(
+ SC.getAssociatedExpression()) &&
+ isa<ArraySubscriptExpr>(
+ CCI->getAssociatedExpression())))
+ return false;
- // Define implicit data-sharing attributes for task.
- DVar = Stack->getImplicitDSA(FD, false);
- if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
- !Stack->isLoopControlVariable(FD).first)
- ImplicitFirstprivate.push_back(E);
+ Decl *CCD = CCI->getAssociatedDeclaration();
+ Decl *SCD = SC.getAssociatedDeclaration();
+ CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
+ SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
+ if (SCD != CCD)
+ return false;
+ std::advance(CCI, 1);
+ if (CCI == CCE)
+ break;
+ }
+ return true;
+ })) {
+ Visit(E->getBase());
}
} else
Visit(E->getBase());
@@ -1668,12 +2055,16 @@ public:
void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
for (auto *C : S->clauses()) {
// Skip analysis of arguments of implicitly defined firstprivate clause
- // for task directives.
- if (C && (!isa<OMPFirstprivateClause>(C) || C->getLocStart().isValid()))
+ // for task|target directives.
+ // Skip analysis of arguments of implicitly defined map clause for target
+ // directives.
+ if (C && !((isa<OMPFirstprivateClause>(C) || isa<OMPMapClause>(C)) &&
+ C->isImplicit())) {
for (auto *CC : C->children()) {
if (CC)
Visit(CC);
}
+ }
}
}
void VisitStmt(Stmt *S) {
@@ -1684,7 +2075,10 @@ public:
}
bool isErrorFound() { return ErrorFound; }
- ArrayRef<Expr *> getImplicitFirstprivate() { return ImplicitFirstprivate; }
+ ArrayRef<Expr *> getImplicitFirstprivate() const {
+ return ImplicitFirstprivate;
+ }
+ ArrayRef<Expr *> getImplicitMap() const { return ImplicitMap; }
llvm::DenseMap<ValueDecl *, Expr *> &getVarsWithInheritedDSA() {
return VarsWithInheritedDSA;
}
@@ -1700,7 +2094,9 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
case OMPD_parallel_for:
case OMPD_parallel_for_simd:
case OMPD_parallel_sections:
- case OMPD_teams: {
+ case OMPD_teams:
+ case OMPD_teams_distribute:
+ case OMPD_teams_distribute_simd: {
QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
QualType KmpInt32PtrTy =
Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
@@ -1714,7 +2110,11 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
break;
}
case OMPD_target_teams:
- case OMPD_target_parallel: {
+ case OMPD_target_parallel:
+ case OMPD_target_parallel_for:
+ case OMPD_target_parallel_for_simd:
+ case OMPD_target_teams_distribute:
+ case OMPD_target_teams_distribute_simd: {
Sema::CapturedParamNameType ParamsTarget[] = {
std::make_pair(StringRef(), QualType()) // __context with shared vars
};
@@ -1745,12 +2145,11 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
case OMPD_critical:
case OMPD_taskgroup:
case OMPD_distribute:
+ case OMPD_distribute_simd:
case OMPD_ordered:
case OMPD_atomic:
case OMPD_target_data:
case OMPD_target:
- case OMPD_target_parallel_for:
- case OMPD_target_parallel_for_simd:
case OMPD_target_simd: {
Sema::CapturedParamNameType Params[] = {
std::make_pair(StringRef(), QualType()) // __context with shared vars
@@ -1821,16 +2220,9 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
break;
}
case OMPD_distribute_parallel_for_simd:
- case OMPD_distribute_simd:
case OMPD_distribute_parallel_for:
- case OMPD_teams_distribute:
- case OMPD_teams_distribute_simd:
- case OMPD_teams_distribute_parallel_for_simd:
- case OMPD_teams_distribute_parallel_for:
- case OMPD_target_teams_distribute:
case OMPD_target_teams_distribute_parallel_for:
- case OMPD_target_teams_distribute_parallel_for_simd:
- case OMPD_target_teams_distribute_simd: {
+ case OMPD_target_teams_distribute_parallel_for_simd: {
QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
QualType KmpInt32PtrTy =
Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
@@ -1845,6 +2237,60 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
Params);
break;
}
+ case OMPD_teams_distribute_parallel_for:
+ case OMPD_teams_distribute_parallel_for_simd: {
+ QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
+ QualType KmpInt32PtrTy =
+ Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
+
+ Sema::CapturedParamNameType ParamsTeams[] = {
+ std::make_pair(".global_tid.", KmpInt32PtrTy),
+ std::make_pair(".bound_tid.", KmpInt32PtrTy),
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ // Start a captured region for 'target' with no implicit parameters.
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ ParamsTeams);
+
+ Sema::CapturedParamNameType ParamsParallel[] = {
+ std::make_pair(".global_tid.", KmpInt32PtrTy),
+ std::make_pair(".bound_tid.", KmpInt32PtrTy),
+ std::make_pair(".previous.lb.", Context.getSizeType()),
+ std::make_pair(".previous.ub.", Context.getSizeType()),
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ // Start a captured region for 'teams' or 'parallel'. Both regions have
+ // the same implicit parameters.
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ ParamsParallel);
+ break;
+ }
+ case OMPD_target_update:
+ case OMPD_target_enter_data:
+ case OMPD_target_exit_data: {
+ QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
+ QualType Args[] = {Context.VoidPtrTy.withConst().withRestrict()};
+ FunctionProtoType::ExtProtoInfo EPI;
+ EPI.Variadic = true;
+ QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(".global_tid.", KmpInt32Ty),
+ std::make_pair(".part_id.", Context.getPointerType(KmpInt32Ty)),
+ std::make_pair(".privates.", Context.VoidPtrTy.withConst()),
+ std::make_pair(".copy_fn.",
+ Context.getPointerType(CopyFnType).withConst()),
+ std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ // Mark this captured region as inlined, because we don't use outlined
+ // function directly.
+ getCurCapturedRegion()->TheCapturedDecl->addAttr(
+ AlwaysInlineAttr::CreateImplicit(
+ Context, AlwaysInlineAttr::Keyword_forceinline, SourceRange()));
+ break;
+ }
case OMPD_threadprivate:
case OMPD_taskyield:
case OMPD_barrier:
@@ -1852,13 +2298,10 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
case OMPD_cancellation_point:
case OMPD_cancel:
case OMPD_flush:
- case OMPD_target_enter_data:
- case OMPD_target_exit_data:
case OMPD_declare_reduction:
case OMPD_declare_simd:
case OMPD_declare_target:
case OMPD_end_declare_target:
- case OMPD_target_update:
llvm_unreachable("OpenMP Directive is not allowed");
case OMPD_unknown:
llvm_unreachable("Unknown OpenMP directive");
@@ -1969,12 +2412,23 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
return StmtError();
}
+ SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
+ getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
OMPOrderedClause *OC = nullptr;
OMPScheduleClause *SC = nullptr;
SmallVector<OMPLinearClause *, 4> LCs;
SmallVector<OMPClauseWithPreInit *, 8> PICs;
// This is required for proper codegen.
for (auto *Clause : Clauses) {
+ if (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
+ Clause->getClauseKind() == OMPC_in_reduction) {
+ // Capture taskgroup task_reduction descriptors inside the tasking regions
+ // with the corresponding in_reduction items.
+ auto *IRC = cast<OMPInReductionClause>(Clause);
+ for (auto *E : IRC->taskgroup_descriptors())
+ if (E)
+ MarkDeclarationsReferencedInExpr(E);
+ }
if (isOpenMPPrivate(Clause->getClauseKind()) ||
Clause->getClauseKind() == OMPC_copyprivate ||
(getLangOpts().OpenMPUseTLS &&
@@ -1988,7 +2442,8 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
}
}
DSAStack->setForceVarCapturing(/*V=*/false);
- } else if (isParallelOrTaskRegion(DSAStack->getCurrentDirective())) {
+ } else if (CaptureRegions.size() > 1 ||
+ CaptureRegions.back() != OMPD_unknown) {
if (auto *C = OMPClauseWithPreInit::get(Clause))
PICs.push_back(C);
if (auto *C = OMPClauseWithPostUpdate::get(Clause)) {
@@ -2036,13 +2491,11 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
return StmtError();
}
StmtResult SR = S;
- SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
- getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
- for (auto ThisCaptureRegion : llvm::reverse(CaptureRegions)) {
+ for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) {
// Mark all variables in private list clauses as used in inner region.
// Required for proper codegen of combined directives.
// TODO: add processing for other clauses.
- if (isParallelOrTaskRegion(DSAStack->getCurrentDirective())) {
+ if (ThisCaptureRegion != OMPD_unknown) {
for (auto *C : PICs) {
OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
// Find the particular capture region for the clause if the
@@ -2157,7 +2610,10 @@ static bool checkNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
ParentRegion == OMPD_target_parallel)) ||
(CancelRegion == OMPD_for &&
(ParentRegion == OMPD_for || ParentRegion == OMPD_parallel_for ||
- ParentRegion == OMPD_target_parallel_for)) ||
+ ParentRegion == OMPD_target_parallel_for ||
+ ParentRegion == OMPD_distribute_parallel_for ||
+ ParentRegion == OMPD_teams_distribute_parallel_for ||
+ ParentRegion == OMPD_target_teams_distribute_parallel_for)) ||
(CancelRegion == OMPD_taskgroup && ParentRegion == OMPD_task) ||
(CancelRegion == OMPD_sections &&
(ParentRegion == OMPD_section || ParentRegion == OMPD_sections ||
@@ -2236,7 +2692,6 @@ static bool checkNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
NestingProhibited = ParentRegion != OMPD_target;
OrphanSeen = ParentRegion == OMPD_unknown;
Recommend = ShouldBeInTargetRegion;
- Stack->setParentTeamsRegionLoc(Stack->getConstructLoc());
}
if (!NestingProhibited &&
!isOpenMPTargetExecutionDirective(CurrentRegion) &&
@@ -2390,7 +2845,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
llvm::DenseMap<ValueDecl *, Expr *> VarsWithInheritedDSA;
bool ErrorFound = false;
ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
- if (AStmt) {
+ if (AStmt && !CurContext->isDependentContext()) {
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
// Check default data sharing attributes for referenced variables.
@@ -2405,13 +2860,37 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
// Generate list of implicitly defined firstprivate variables.
VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
- if (!DSAChecker.getImplicitFirstprivate().empty()) {
+ SmallVector<Expr *, 4> ImplicitFirstprivates(
+ DSAChecker.getImplicitFirstprivate().begin(),
+ DSAChecker.getImplicitFirstprivate().end());
+ SmallVector<Expr *, 4> ImplicitMaps(DSAChecker.getImplicitMap().begin(),
+ DSAChecker.getImplicitMap().end());
+ // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
+ for (auto *C : Clauses) {
+ if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) {
+ for (auto *E : IRC->taskgroup_descriptors())
+ if (E)
+ ImplicitFirstprivates.emplace_back(E);
+ }
+ }
+ if (!ImplicitFirstprivates.empty()) {
if (OMPClause *Implicit = ActOnOpenMPFirstprivateClause(
- DSAChecker.getImplicitFirstprivate(), SourceLocation(),
- SourceLocation(), SourceLocation())) {
+ ImplicitFirstprivates, SourceLocation(), SourceLocation(),
+ SourceLocation())) {
ClausesWithImplicit.push_back(Implicit);
ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
- DSAChecker.getImplicitFirstprivate().size();
+ ImplicitFirstprivates.size();
+ } else
+ ErrorFound = true;
+ }
+ if (!ImplicitMaps.empty()) {
+ if (OMPClause *Implicit = ActOnOpenMPMapClause(
+ OMPC_MAP_unknown, OMPC_MAP_tofrom, /*IsMapTypeImplicit=*/true,
+ SourceLocation(), SourceLocation(), ImplicitMaps,
+ SourceLocation(), SourceLocation(), SourceLocation())) {
+ ClausesWithImplicit.emplace_back(Implicit);
+ ErrorFound |=
+ cast<OMPMapClause>(Implicit)->varlist_size() != ImplicitMaps.size();
} else
ErrorFound = true;
}
@@ -2558,12 +3037,12 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
break;
case OMPD_target_enter_data:
Res = ActOnOpenMPTargetEnterDataDirective(ClausesWithImplicit, StartLoc,
- EndLoc);
+ EndLoc, AStmt);
AllowedNameModifiers.push_back(OMPD_target_enter_data);
break;
case OMPD_target_exit_data:
Res = ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit, StartLoc,
- EndLoc);
+ EndLoc, AStmt);
AllowedNameModifiers.push_back(OMPD_target_exit_data);
break;
case OMPD_taskloop:
@@ -2581,9 +3060,8 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
EndLoc, VarsWithInheritedDSA);
break;
case OMPD_target_update:
- assert(!AStmt && "Statement is not allowed for target update");
- Res =
- ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit, StartLoc, EndLoc);
+ Res = ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit, StartLoc,
+ EndLoc, AStmt);
AllowedNameModifiers.push_back(OMPD_target_update);
break;
case OMPD_distribute_parallel_for:
@@ -3053,21 +3531,6 @@ bool OpenMPIterationSpaceChecker::Dependent() const {
(Step && Step->isValueDependent());
}
-static Expr *getExprAsWritten(Expr *E) {
- if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(E))
- E = ExprTemp->getSubExpr();
-
- if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
- E = MTE->GetTemporaryExpr();
-
- while (auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
- E = Binder->getSubExpr();
-
- if (auto *ICE = dyn_cast<ImplicitCastExpr>(E))
- E = ICE->getSubExprAsWritten();
- return E->IgnoreParens();
-}
-
bool OpenMPIterationSpaceChecker::SetLCDeclAndLB(ValueDecl *NewLCDecl,
Expr *NewLCRefExpr,
Expr *NewLB) {
@@ -3249,12 +3712,8 @@ static const ValueDecl *GetInitLCDecl(Expr *E) {
CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
E = CE->getArg(0)->IgnoreParenImpCasts();
if (auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
- if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
- if (auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
- if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
- return getCanonicalDecl(ME->getMemberDecl());
+ if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
return getCanonicalDecl(VD);
- }
}
if (auto *ME = dyn_cast_or_null<MemberExpr>(E))
if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
@@ -3939,7 +4398,7 @@ static bool FitsInto(unsigned Bits, bool Signed, Expr *E, Sema &SemaRef) {
/// Build preinits statement for the given declarations.
static Stmt *buildPreInits(ASTContext &Context,
- SmallVectorImpl<Decl *> &PreInits) {
+ MutableArrayRef<Decl *> PreInits) {
if (!PreInits.empty()) {
return new (Context) DeclStmt(
DeclGroupRef::Create(Context, PreInits.begin(), PreInits.size()),
@@ -3949,8 +4408,9 @@ static Stmt *buildPreInits(ASTContext &Context,
}
/// Build preinits statement for the given declarations.
-static Stmt *buildPreInits(ASTContext &Context,
- llvm::MapVector<Expr *, DeclRefExpr *> &Captures) {
+static Stmt *
+buildPreInits(ASTContext &Context,
+ const llvm::MapVector<Expr *, DeclRefExpr *> &Captures) {
if (!Captures.empty()) {
SmallVector<Decl *, 16> PreInits;
for (auto &Pair : Captures)
@@ -5080,7 +5540,8 @@ StmtResult Sema::ActOnOpenMPTaskgroupDirective(ArrayRef<OMPClause *> Clauses,
getCurFunction()->setHasBranchProtectedScope();
return OMPTaskgroupDirective::Create(Context, StartLoc, EndLoc, Clauses,
- AStmt);
+ AStmt,
+ DSAStack->getTaskgroupReductionRef());
}
StmtResult Sema::ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
@@ -5924,13 +6385,23 @@ StmtResult Sema::ActOnOpenMPTargetParallelForDirective(
// The point of exit cannot be a branch out of the structured block.
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
+ for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_for);
+ ThisCaptureLevel > 1; --ThisCaptureLevel) {
+ CS = cast<CapturedStmt>(CS->getCapturedStmt());
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+ }
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
CheckOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
- getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
+ getOrderedNumberExpr(Clauses), CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
return StmtError();
@@ -5995,7 +6466,28 @@ StmtResult Sema::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses,
StmtResult
Sema::ActOnOpenMPTargetEnterDataDirective(ArrayRef<OMPClause *> Clauses,
SourceLocation StartLoc,
- SourceLocation EndLoc) {
+ SourceLocation EndLoc, Stmt *AStmt) {
+ if (!AStmt)
+ return StmtError();
+
+ CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+ for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_enter_data);
+ ThisCaptureLevel > 1; --ThisCaptureLevel) {
+ CS = cast<CapturedStmt>(CS->getCapturedStmt());
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+ }
+
// OpenMP [2.10.2, Restrictions, p. 99]
// At least one map clause must appear on the directive.
if (!hasClauses(Clauses, OMPC_map)) {
@@ -6004,14 +6496,35 @@ Sema::ActOnOpenMPTargetEnterDataDirective(ArrayRef<OMPClause *> Clauses,
return StmtError();
}
- return OMPTargetEnterDataDirective::Create(Context, StartLoc, EndLoc,
- Clauses);
+ return OMPTargetEnterDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
+ AStmt);
}
StmtResult
Sema::ActOnOpenMPTargetExitDataDirective(ArrayRef<OMPClause *> Clauses,
SourceLocation StartLoc,
- SourceLocation EndLoc) {
+ SourceLocation EndLoc, Stmt *AStmt) {
+ if (!AStmt)
+ return StmtError();
+
+ CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+ for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_exit_data);
+ ThisCaptureLevel > 1; --ThisCaptureLevel) {
+ CS = cast<CapturedStmt>(CS->getCapturedStmt());
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+ }
+
// OpenMP [2.10.3, Restrictions, p. 102]
// At least one map clause must appear on the directive.
if (!hasClauses(Clauses, OMPC_map)) {
@@ -6020,17 +6533,41 @@ Sema::ActOnOpenMPTargetExitDataDirective(ArrayRef<OMPClause *> Clauses,
return StmtError();
}
- return OMPTargetExitDataDirective::Create(Context, StartLoc, EndLoc, Clauses);
+ return OMPTargetExitDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
+ AStmt);
}
StmtResult Sema::ActOnOpenMPTargetUpdateDirective(ArrayRef<OMPClause *> Clauses,
SourceLocation StartLoc,
- SourceLocation EndLoc) {
+ SourceLocation EndLoc,
+ Stmt *AStmt) {
+ if (!AStmt)
+ return StmtError();
+
+ CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+ for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_update);
+ ThisCaptureLevel > 1; --ThisCaptureLevel) {
+ CS = cast<CapturedStmt>(CS->getCapturedStmt());
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+ }
+
if (!hasClauses(Clauses, OMPC_to, OMPC_from)) {
Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
return StmtError();
}
- return OMPTargetUpdateDirective::Create(Context, StartLoc, EndLoc, Clauses);
+ return OMPTargetUpdateDirective::Create(Context, StartLoc, EndLoc, Clauses,
+ AStmt);
}
StmtResult Sema::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
@@ -6049,6 +6586,8 @@ StmtResult Sema::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
getCurFunction()->setHasBranchProtectedScope();
+ DSAStack->setParentTeamsRegionLoc(StartLoc);
+
return OMPTeamsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
}
@@ -6215,6 +6754,8 @@ StmtResult Sema::ActOnOpenMPTaskLoopSimdDirective(
// clause must not be specified.
if (checkReductionClauseWithNogroup(*this, Clauses))
return StmtError();
+ if (checkSimdlenSafelenSpecified(*this, Clauses))
+ return StmtError();
getCurFunction()->setHasBranchProtectedScope();
return OMPTaskLoopSimdDirective::Create(Context, StartLoc, EndLoc,
@@ -6261,13 +6802,24 @@ StmtResult Sema::ActOnOpenMPDistributeParallelForDirective(
// The point of exit cannot be a branch out of the structured block.
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
+ for (int ThisCaptureLevel =
+ getOpenMPCaptureLevels(OMPD_distribute_parallel_for);
+ ThisCaptureLevel > 1; --ThisCaptureLevel) {
+ CS = cast<CapturedStmt>(CS->getCapturedStmt());
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+ }
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount = CheckOpenMPLoop(
OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses),
- nullptr /*ordered not a clause on distribute*/, AStmt, *this, *DSAStack,
+ nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
return StmtError();
@@ -6277,7 +6829,8 @@ StmtResult Sema::ActOnOpenMPDistributeParallelForDirective(
getCurFunction()->setHasBranchProtectedScope();
return OMPDistributeParallelForDirective::Create(
- Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
+ Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
+ DSAStack->isCancelRegion());
}
StmtResult Sema::ActOnOpenMPDistributeParallelForSimdDirective(
@@ -6294,13 +6847,24 @@ StmtResult Sema::ActOnOpenMPDistributeParallelForSimdDirective(
// The point of exit cannot be a branch out of the structured block.
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
+ for (int ThisCaptureLevel =
+ getOpenMPCaptureLevels(OMPD_distribute_parallel_for_simd);
+ ThisCaptureLevel > 1; --ThisCaptureLevel) {
+ CS = cast<CapturedStmt>(CS->getCapturedStmt());
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+ }
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount = CheckOpenMPLoop(
OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
- nullptr /*ordered not a clause on distribute*/, AStmt, *this, *DSAStack,
+ nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
return StmtError();
@@ -6308,6 +6872,17 @@ StmtResult Sema::ActOnOpenMPDistributeParallelForSimdDirective(
assert((CurContext->isDependentContext() || B.builtAll()) &&
"omp for loop exprs were not built");
+ if (!CurContext->isDependentContext()) {
+ // Finalize the clauses that need pre-built expressions for CodeGen.
+ for (auto C : Clauses) {
+ if (auto *LC = dyn_cast<OMPLinearClause>(C))
+ if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
+ B.NumIterations, *this, CurScope,
+ DSAStack))
+ return StmtError();
+ }
+ }
+
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
@@ -6330,20 +6905,41 @@ StmtResult Sema::ActOnOpenMPDistributeSimdDirective(
// The point of exit cannot be a branch out of the structured block.
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
+ for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_distribute_simd);
+ ThisCaptureLevel > 1; --ThisCaptureLevel) {
+ CS = cast<CapturedStmt>(CS->getCapturedStmt());
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+ }
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
CheckOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
- nullptr /*ordered not a clause on distribute*/, AStmt,
- *this, *DSAStack, VarsWithImplicitDSA, B);
+ nullptr /*ordered not a clause on distribute*/, CS, *this,
+ *DSAStack, VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
return StmtError();
assert((CurContext->isDependentContext() || B.builtAll()) &&
"omp for loop exprs were not built");
+ if (!CurContext->isDependentContext()) {
+ // Finalize the clauses that need pre-built expressions for CodeGen.
+ for (auto C : Clauses) {
+ if (auto *LC = dyn_cast<OMPLinearClause>(C))
+ if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
+ B.NumIterations, *this, CurScope,
+ DSAStack))
+ return StmtError();
+ }
+ }
+
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
@@ -6366,13 +6962,23 @@ StmtResult Sema::ActOnOpenMPTargetParallelForSimdDirective(
// The point of exit cannot be a branch out of the structured block.
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
+ for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_for);
+ ThisCaptureLevel > 1; --ThisCaptureLevel) {
+ CS = cast<CapturedStmt>(CS->getCapturedStmt());
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+ }
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount = CheckOpenMPLoop(
OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
- getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
+ getOrderedNumberExpr(Clauses), CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
return StmtError();
@@ -6412,13 +7018,23 @@ StmtResult Sema::ActOnOpenMPTargetSimdDirective(
// The point of exit cannot be a branch out of the structured block.
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
+ for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_simd);
+ ThisCaptureLevel > 1; --ThisCaptureLevel) {
+ CS = cast<CapturedStmt>(CS->getCapturedStmt());
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+ }
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will define the
// nested loops number.
unsigned NestedLoopCount =
CheckOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
- getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
+ getOrderedNumberExpr(Clauses), CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
return StmtError();
@@ -6459,14 +7075,24 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeDirective(
// The point of exit cannot be a branch out of the structured block.
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
+ for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_teams_distribute);
+ ThisCaptureLevel > 1; --ThisCaptureLevel) {
+ CS = cast<CapturedStmt>(CS->getCapturedStmt());
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+ }
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
CheckOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
- nullptr /*ordered not a clause on distribute*/, AStmt,
- *this, *DSAStack, VarsWithImplicitDSA, B);
+ nullptr /*ordered not a clause on distribute*/, CS, *this,
+ *DSAStack, VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
return StmtError();
@@ -6474,6 +7100,9 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeDirective(
"omp teams distribute loop exprs were not built");
getCurFunction()->setHasBranchProtectedScope();
+
+ DSAStack->setParentTeamsRegionLoc(StartLoc);
+
return OMPTeamsDistributeDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
}
@@ -6492,13 +7121,25 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeSimdDirective(
// The point of exit cannot be a branch out of the structured block.
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
+ for (int ThisCaptureLevel =
+ getOpenMPCaptureLevels(OMPD_teams_distribute_simd);
+ ThisCaptureLevel > 1; --ThisCaptureLevel) {
+ CS = cast<CapturedStmt>(CS->getCapturedStmt());
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+ }
+
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount = CheckOpenMPLoop(
OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
- nullptr /*ordered not a clause on distribute*/, AStmt, *this, *DSAStack,
+ nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
@@ -6522,6 +7163,9 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeSimdDirective(
return StmtError();
getCurFunction()->setHasBranchProtectedScope();
+
+ DSAStack->setParentTeamsRegionLoc(StartLoc);
+
return OMPTeamsDistributeSimdDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
}
@@ -6541,12 +7185,24 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
+ for (int ThisCaptureLevel =
+ getOpenMPCaptureLevels(OMPD_teams_distribute_parallel_for_simd);
+ ThisCaptureLevel > 1; --ThisCaptureLevel) {
+ CS = cast<CapturedStmt>(CS->getCapturedStmt());
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+ }
+
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
auto NestedLoopCount = CheckOpenMPLoop(
OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
- nullptr /*ordered not a clause on distribute*/, AStmt, *this, *DSAStack,
+ nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
@@ -6570,6 +7226,9 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
return StmtError();
getCurFunction()->setHasBranchProtectedScope();
+
+ DSAStack->setParentTeamsRegionLoc(StartLoc);
+
return OMPTeamsDistributeParallelForSimdDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
}
@@ -6589,12 +7248,24 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForDirective(
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
+ for (int ThisCaptureLevel =
+ getOpenMPCaptureLevels(OMPD_teams_distribute_parallel_for);
+ ThisCaptureLevel > 1; --ThisCaptureLevel) {
+ CS = cast<CapturedStmt>(CS->getCapturedStmt());
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+ }
+
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount = CheckOpenMPLoop(
OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
- nullptr /*ordered not a clause on distribute*/, AStmt, *this, *DSAStack,
+ nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
@@ -6603,20 +7274,13 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForDirective(
assert((CurContext->isDependentContext() || B.builtAll()) &&
"omp for loop exprs were not built");
- if (!CurContext->isDependentContext()) {
- // Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
- if (auto *LC = dyn_cast<OMPLinearClause>(C))
- if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
- B.NumIterations, *this, CurScope,
- DSAStack))
- return StmtError();
- }
- }
-
getCurFunction()->setHasBranchProtectedScope();
+
+ DSAStack->setParentTeamsRegionLoc(StartLoc);
+
return OMPTeamsDistributeParallelForDirective::Create(
- Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
+ Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
+ DSAStack->isCancelRegion());
}
StmtResult Sema::ActOnOpenMPTargetTeamsDirective(ArrayRef<OMPClause *> Clauses,
@@ -6634,6 +7298,16 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDirective(ArrayRef<OMPClause *> Clauses,
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
+ for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_teams);
+ ThisCaptureLevel > 1; --ThisCaptureLevel) {
+ CS = cast<CapturedStmt>(CS->getCapturedStmt());
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+ }
getCurFunction()->setHasBranchProtectedScope();
return OMPTargetTeamsDirective::Create(Context, StartLoc, EndLoc, Clauses,
@@ -6654,14 +7328,24 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDistributeDirective(
// The point of exit cannot be a branch out of the structured block.
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
+ for (int ThisCaptureLevel =
+ getOpenMPCaptureLevels(OMPD_target_teams_distribute);
+ ThisCaptureLevel > 1; --ThisCaptureLevel) {
+ CS = cast<CapturedStmt>(CS->getCapturedStmt());
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+ }
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
auto NestedLoopCount = CheckOpenMPLoop(
- OMPD_target_teams_distribute,
- getCollapseNumberExpr(Clauses),
- nullptr /*ordered not a clause on distribute*/, AStmt, *this, *DSAStack,
+ OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
+ nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
return StmtError();
@@ -6703,20 +7387,10 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForDirective(
assert((CurContext->isDependentContext() || B.builtAll()) &&
"omp target teams distribute parallel for loop exprs were not built");
- if (!CurContext->isDependentContext()) {
- // Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
- if (auto *LC = dyn_cast<OMPLinearClause>(C))
- if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
- B.NumIterations, *this, CurScope,
- DSAStack))
- return StmtError();
- }
- }
-
getCurFunction()->setHasBranchProtectedScope();
return OMPTargetTeamsDistributeParallelForDirective::Create(
- Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
+ Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
+ DSAStack->isCancelRegion());
}
StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
@@ -6760,6 +7434,9 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
}
}
+ if (checkSimdlenSafelenSpecified(*this, Clauses))
+ return StmtError();
+
getCurFunction()->setHasBranchProtectedScope();
return OMPTargetTeamsDistributeParallelForSimdDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
@@ -6779,13 +7456,24 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDistributeSimdDirective(
// The point of exit cannot be a branch out of the structured block.
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
+ for (int ThisCaptureLevel =
+ getOpenMPCaptureLevels(OMPD_target_teams_distribute_simd);
+ ThisCaptureLevel > 1; --ThisCaptureLevel) {
+ CS = cast<CapturedStmt>(CS->getCapturedStmt());
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+ }
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
auto NestedLoopCount = CheckOpenMPLoop(
OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
- nullptr /*ordered not a clause on distribute*/, AStmt, *this, *DSAStack,
+ nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
return StmtError();
@@ -6793,6 +7481,20 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDistributeSimdDirective(
assert((CurContext->isDependentContext() || B.builtAll()) &&
"omp target teams distribute simd loop exprs were not built");
+ if (!CurContext->isDependentContext()) {
+ // Finalize the clauses that need pre-built expressions for CodeGen.
+ for (auto C : Clauses) {
+ if (auto *LC = dyn_cast<OMPLinearClause>(C))
+ if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
+ B.NumIterations, *this, CurScope,
+ DSAStack))
+ return StmtError();
+ }
+ }
+
+ if (checkSimdlenSafelenSpecified(*this, Clauses))
+ return StmtError();
+
getCurFunction()->setHasBranchProtectedScope();
return OMPTargetTeamsDistributeSimdDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
@@ -6853,6 +7555,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
case OMPC_shared:
case OMPC_reduction:
case OMPC_task_reduction:
+ case OMPC_in_reduction:
case OMPC_linear:
case OMPC_aligned:
case OMPC_copyin:
@@ -6894,16 +7597,23 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
OpenMPDirectiveKind NameModifier = OMPD_unknown) {
OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
-
switch (CKind) {
case OMPC_if:
switch (DKind) {
case OMPD_target_parallel:
+ case OMPD_target_parallel_for:
+ case OMPD_target_parallel_for_simd:
+ case OMPD_target_teams_distribute_parallel_for:
+ case OMPD_target_teams_distribute_parallel_for_simd:
// If this clause applies to the nested 'parallel' region, capture within
// the 'target' region, otherwise do not capture.
if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel)
CaptureRegion = OMPD_target;
break;
+ case OMPD_teams_distribute_parallel_for:
+ case OMPD_teams_distribute_parallel_for_simd:
+ CaptureRegion = OMPD_teams;
+ break;
case OMPD_cancel:
case OMPD_parallel:
case OMPD_parallel_sections:
@@ -6911,15 +7621,9 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_parallel_for_simd:
case OMPD_target:
case OMPD_target_simd:
- case OMPD_target_parallel_for:
- case OMPD_target_parallel_for_simd:
case OMPD_target_teams:
case OMPD_target_teams_distribute:
case OMPD_target_teams_distribute_simd:
- case OMPD_target_teams_distribute_parallel_for:
- case OMPD_target_teams_distribute_parallel_for_simd:
- case OMPD_teams_distribute_parallel_for:
- case OMPD_teams_distribute_parallel_for_simd:
case OMPD_distribute_parallel_for:
case OMPD_distribute_parallel_for_simd:
case OMPD_task:
@@ -6965,24 +7669,84 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPC_num_threads:
switch (DKind) {
case OMPD_target_parallel:
+ case OMPD_target_parallel_for:
+ case OMPD_target_parallel_for_simd:
+ case OMPD_target_teams_distribute_parallel_for:
+ case OMPD_target_teams_distribute_parallel_for_simd:
CaptureRegion = OMPD_target;
break;
- case OMPD_cancel:
+ case OMPD_teams_distribute_parallel_for:
+ case OMPD_teams_distribute_parallel_for_simd:
+ CaptureRegion = OMPD_teams;
+ break;
case OMPD_parallel:
case OMPD_parallel_sections:
case OMPD_parallel_for:
case OMPD_parallel_for_simd:
+ case OMPD_distribute_parallel_for:
+ case OMPD_distribute_parallel_for_simd:
+ // Do not capture num_threads-clause expressions.
+ break;
+ case OMPD_target_data:
+ case OMPD_target_enter_data:
+ case OMPD_target_exit_data:
+ case OMPD_target_update:
case OMPD_target:
case OMPD_target_simd:
- case OMPD_target_parallel_for:
- case OMPD_target_parallel_for_simd:
+ case OMPD_target_teams:
+ case OMPD_target_teams_distribute:
+ case OMPD_target_teams_distribute_simd:
+ case OMPD_cancel:
+ case OMPD_task:
+ case OMPD_taskloop:
+ case OMPD_taskloop_simd:
+ case OMPD_threadprivate:
+ case OMPD_taskyield:
+ case OMPD_barrier:
+ case OMPD_taskwait:
+ case OMPD_cancellation_point:
+ case OMPD_flush:
+ case OMPD_declare_reduction:
+ case OMPD_declare_simd:
+ case OMPD_declare_target:
+ case OMPD_end_declare_target:
+ case OMPD_teams:
+ case OMPD_simd:
+ case OMPD_for:
+ case OMPD_for_simd:
+ case OMPD_sections:
+ case OMPD_section:
+ case OMPD_single:
+ case OMPD_master:
+ case OMPD_critical:
+ case OMPD_taskgroup:
+ case OMPD_distribute:
+ case OMPD_ordered:
+ case OMPD_atomic:
+ case OMPD_distribute_simd:
+ case OMPD_teams_distribute:
+ case OMPD_teams_distribute_simd:
+ llvm_unreachable("Unexpected OpenMP directive with num_threads-clause");
+ case OMPD_unknown:
+ llvm_unreachable("Unknown OpenMP directive");
+ }
+ break;
+ case OMPC_num_teams:
+ switch (DKind) {
case OMPD_target_teams:
case OMPD_target_teams_distribute:
case OMPD_target_teams_distribute_simd:
case OMPD_target_teams_distribute_parallel_for:
case OMPD_target_teams_distribute_parallel_for_simd:
+ CaptureRegion = OMPD_target;
+ break;
case OMPD_teams_distribute_parallel_for:
case OMPD_teams_distribute_parallel_for_simd:
+ case OMPD_teams:
+ case OMPD_teams_distribute:
+ case OMPD_teams_distribute_simd:
+ // Do not capture num_teams-clause expressions.
+ break;
case OMPD_distribute_parallel_for:
case OMPD_distribute_parallel_for_simd:
case OMPD_task:
@@ -6992,8 +7756,16 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_target_enter_data:
case OMPD_target_exit_data:
case OMPD_target_update:
- // Do not capture num_threads-clause expressions.
- break;
+ case OMPD_cancel:
+ case OMPD_parallel:
+ case OMPD_parallel_sections:
+ case OMPD_parallel_for:
+ case OMPD_parallel_for_simd:
+ case OMPD_target:
+ case OMPD_target_simd:
+ case OMPD_target_parallel:
+ case OMPD_target_parallel_for:
+ case OMPD_target_parallel_for_simd:
case OMPD_threadprivate:
case OMPD_taskyield:
case OMPD_barrier:
@@ -7004,7 +7776,6 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_declare_simd:
case OMPD_declare_target:
case OMPD_end_declare_target:
- case OMPD_teams:
case OMPD_simd:
case OMPD_for:
case OMPD_for_simd:
@@ -7018,18 +7789,36 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_ordered:
case OMPD_atomic:
case OMPD_distribute_simd:
- case OMPD_teams_distribute:
- case OMPD_teams_distribute_simd:
- llvm_unreachable("Unexpected OpenMP directive with num_threads-clause");
+ llvm_unreachable("Unexpected OpenMP directive with num_teams-clause");
case OMPD_unknown:
llvm_unreachable("Unknown OpenMP directive");
}
break;
- case OMPC_num_teams:
+ case OMPC_thread_limit:
switch (DKind) {
case OMPD_target_teams:
+ case OMPD_target_teams_distribute:
+ case OMPD_target_teams_distribute_simd:
+ case OMPD_target_teams_distribute_parallel_for:
+ case OMPD_target_teams_distribute_parallel_for_simd:
CaptureRegion = OMPD_target;
break;
+ case OMPD_teams_distribute_parallel_for:
+ case OMPD_teams_distribute_parallel_for_simd:
+ case OMPD_teams:
+ case OMPD_teams_distribute:
+ case OMPD_teams_distribute_simd:
+ // Do not capture thread_limit-clause expressions.
+ break;
+ case OMPD_distribute_parallel_for:
+ case OMPD_distribute_parallel_for_simd:
+ case OMPD_task:
+ case OMPD_taskloop:
+ case OMPD_taskloop_simd:
+ case OMPD_target_data:
+ case OMPD_target_enter_data:
+ case OMPD_target_exit_data:
+ case OMPD_target_update:
case OMPD_cancel:
case OMPD_parallel:
case OMPD_parallel_sections:
@@ -7040,14 +7829,56 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_target_parallel:
case OMPD_target_parallel_for:
case OMPD_target_parallel_for_simd:
- case OMPD_target_teams_distribute:
- case OMPD_target_teams_distribute_simd:
+ case OMPD_threadprivate:
+ case OMPD_taskyield:
+ case OMPD_barrier:
+ case OMPD_taskwait:
+ case OMPD_cancellation_point:
+ case OMPD_flush:
+ case OMPD_declare_reduction:
+ case OMPD_declare_simd:
+ case OMPD_declare_target:
+ case OMPD_end_declare_target:
+ case OMPD_simd:
+ case OMPD_for:
+ case OMPD_for_simd:
+ case OMPD_sections:
+ case OMPD_section:
+ case OMPD_single:
+ case OMPD_master:
+ case OMPD_critical:
+ case OMPD_taskgroup:
+ case OMPD_distribute:
+ case OMPD_ordered:
+ case OMPD_atomic:
+ case OMPD_distribute_simd:
+ llvm_unreachable("Unexpected OpenMP directive with thread_limit-clause");
+ case OMPD_unknown:
+ llvm_unreachable("Unknown OpenMP directive");
+ }
+ break;
+ case OMPC_schedule:
+ switch (DKind) {
+ case OMPD_target_parallel_for:
+ case OMPD_target_parallel_for_simd:
case OMPD_target_teams_distribute_parallel_for:
case OMPD_target_teams_distribute_parallel_for_simd:
+ CaptureRegion = OMPD_target;
+ break;
case OMPD_teams_distribute_parallel_for:
case OMPD_teams_distribute_parallel_for_simd:
+ CaptureRegion = OMPD_teams;
+ break;
+ case OMPD_parallel_for:
+ case OMPD_parallel_for_simd:
case OMPD_distribute_parallel_for:
case OMPD_distribute_parallel_for_simd:
+ CaptureRegion = OMPD_parallel;
+ break;
+ case OMPD_for:
+ case OMPD_for_simd:
+ // Do not capture schedule-clause expressions.
+ break;
case OMPD_task:
case OMPD_taskloop:
case OMPD_taskloop_simd:
@@ -7058,8 +7889,14 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_teams:
case OMPD_teams_distribute:
case OMPD_teams_distribute_simd:
- // Do not capture num_teams-clause expressions.
- break;
+ case OMPD_target_teams_distribute:
+ case OMPD_target_teams_distribute_simd:
+ case OMPD_target:
+ case OMPD_target_simd:
+ case OMPD_target_parallel:
+ case OMPD_cancel:
+ case OMPD_parallel:
+ case OMPD_parallel_sections:
case OMPD_threadprivate:
case OMPD_taskyield:
case OMPD_barrier:
@@ -7071,8 +7908,6 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_simd:
- case OMPD_for:
- case OMPD_for_simd:
case OMPD_sections:
case OMPD_section:
case OMPD_single:
@@ -7083,46 +7918,112 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_ordered:
case OMPD_atomic:
case OMPD_distribute_simd:
- llvm_unreachable("Unexpected OpenMP directive with num_teams-clause");
+ case OMPD_target_teams:
+ llvm_unreachable("Unexpected OpenMP directive with schedule clause");
case OMPD_unknown:
llvm_unreachable("Unknown OpenMP directive");
}
break;
- case OMPC_thread_limit:
+ case OMPC_dist_schedule:
switch (DKind) {
- case OMPD_target_teams:
+ case OMPD_teams_distribute_parallel_for:
+ case OMPD_teams_distribute_parallel_for_simd:
+ case OMPD_teams_distribute:
+ case OMPD_teams_distribute_simd:
+ CaptureRegion = OMPD_teams;
+ break;
+ case OMPD_target_teams_distribute_parallel_for:
+ case OMPD_target_teams_distribute_parallel_for_simd:
+ case OMPD_target_teams_distribute:
+ case OMPD_target_teams_distribute_simd:
CaptureRegion = OMPD_target;
break;
- case OMPD_cancel:
- case OMPD_parallel:
- case OMPD_parallel_sections:
+ case OMPD_distribute_parallel_for:
+ case OMPD_distribute_parallel_for_simd:
+ CaptureRegion = OMPD_parallel;
+ break;
+ case OMPD_distribute:
+ case OMPD_distribute_simd:
+ // Do not capture thread_limit-clause expressions.
+ break;
case OMPD_parallel_for:
case OMPD_parallel_for_simd:
+ case OMPD_target_parallel_for_simd:
+ case OMPD_target_parallel_for:
+ case OMPD_task:
+ case OMPD_taskloop:
+ case OMPD_taskloop_simd:
+ case OMPD_target_data:
+ case OMPD_target_enter_data:
+ case OMPD_target_exit_data:
+ case OMPD_target_update:
+ case OMPD_teams:
case OMPD_target:
case OMPD_target_simd:
case OMPD_target_parallel:
- case OMPD_target_parallel_for:
- case OMPD_target_parallel_for_simd:
+ case OMPD_cancel:
+ case OMPD_parallel:
+ case OMPD_parallel_sections:
+ case OMPD_threadprivate:
+ case OMPD_taskyield:
+ case OMPD_barrier:
+ case OMPD_taskwait:
+ case OMPD_cancellation_point:
+ case OMPD_flush:
+ case OMPD_declare_reduction:
+ case OMPD_declare_simd:
+ case OMPD_declare_target:
+ case OMPD_end_declare_target:
+ case OMPD_simd:
+ case OMPD_for:
+ case OMPD_for_simd:
+ case OMPD_sections:
+ case OMPD_section:
+ case OMPD_single:
+ case OMPD_master:
+ case OMPD_critical:
+ case OMPD_taskgroup:
+ case OMPD_ordered:
+ case OMPD_atomic:
+ case OMPD_target_teams:
+ llvm_unreachable("Unexpected OpenMP directive with schedule clause");
+ case OMPD_unknown:
+ llvm_unreachable("Unknown OpenMP directive");
+ }
+ break;
+ case OMPC_device:
+ switch (DKind) {
+ case OMPD_target_teams:
case OMPD_target_teams_distribute:
case OMPD_target_teams_distribute_simd:
case OMPD_target_teams_distribute_parallel_for:
case OMPD_target_teams_distribute_parallel_for_simd:
- case OMPD_teams_distribute_parallel_for:
- case OMPD_teams_distribute_parallel_for_simd:
- case OMPD_distribute_parallel_for:
- case OMPD_distribute_parallel_for_simd:
- case OMPD_task:
- case OMPD_taskloop:
- case OMPD_taskloop_simd:
case OMPD_target_data:
case OMPD_target_enter_data:
case OMPD_target_exit_data:
case OMPD_target_update:
+ case OMPD_target:
+ case OMPD_target_simd:
+ case OMPD_target_parallel:
+ case OMPD_target_parallel_for:
+ case OMPD_target_parallel_for_simd:
+ // Do not capture device-clause expressions.
+ break;
+ case OMPD_teams_distribute_parallel_for:
+ case OMPD_teams_distribute_parallel_for_simd:
case OMPD_teams:
case OMPD_teams_distribute:
case OMPD_teams_distribute_simd:
- // Do not capture thread_limit-clause expressions.
- break;
+ case OMPD_distribute_parallel_for:
+ case OMPD_distribute_parallel_for_simd:
+ case OMPD_task:
+ case OMPD_taskloop:
+ case OMPD_taskloop_simd:
+ case OMPD_cancel:
+ case OMPD_parallel:
+ case OMPD_parallel_sections:
+ case OMPD_parallel_for:
+ case OMPD_parallel_for_simd:
case OMPD_threadprivate:
case OMPD_taskyield:
case OMPD_barrier:
@@ -7146,17 +8047,16 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_ordered:
case OMPD_atomic:
case OMPD_distribute_simd:
- llvm_unreachable("Unexpected OpenMP directive with thread_limit-clause");
+ llvm_unreachable("Unexpected OpenMP directive with num_teams-clause");
case OMPD_unknown:
llvm_unreachable("Unknown OpenMP directive");
}
break;
- case OMPC_schedule:
- case OMPC_dist_schedule:
case OMPC_firstprivate:
case OMPC_lastprivate:
case OMPC_reduction:
case OMPC_task_reduction:
+ case OMPC_in_reduction:
case OMPC_linear:
case OMPC_default:
case OMPC_proc_bind:
@@ -7181,7 +8081,6 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPC_capture:
case OMPC_seq_cst:
case OMPC_depend:
- case OMPC_device:
case OMPC_threads:
case OMPC_simd:
case OMPC_map:
@@ -7223,7 +8122,7 @@ OMPClause *Sema::ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier,
OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
CaptureRegion =
getOpenMPCaptureRegionForClause(DKind, OMPC_if, NameModifier);
- if (CaptureRegion != OMPD_unknown) {
+ if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
llvm::MapVector<Expr *, DeclRefExpr *> Captures;
ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
HelperValStmt = buildPreInits(Context, Captures);
@@ -7329,7 +8228,6 @@ OMPClause *Sema::ActOnOpenMPNumThreadsClause(Expr *NumThreads,
SourceLocation EndLoc) {
Expr *ValExpr = NumThreads;
Stmt *HelperValStmt = nullptr;
- OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
// OpenMP [2.5, Restrictions]
// The num_threads expression must evaluate to a positive integer value.
@@ -7338,8 +8236,9 @@ OMPClause *Sema::ActOnOpenMPNumThreadsClause(Expr *NumThreads,
return nullptr;
OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
- CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_num_threads);
- if (CaptureRegion != OMPD_unknown) {
+ OpenMPDirectiveKind CaptureRegion =
+ getOpenMPCaptureRegionForClause(DKind, OMPC_num_threads);
+ if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
llvm::MapVector<Expr *, DeclRefExpr *> Captures;
ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
HelperValStmt = buildPreInits(Context, Captures);
@@ -7473,6 +8372,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
case OMPC_shared:
case OMPC_reduction:
case OMPC_task_reduction:
+ case OMPC_in_reduction:
case OMPC_linear:
case OMPC_aligned:
case OMPC_copyin:
@@ -7631,6 +8531,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
case OMPC_shared:
case OMPC_reduction:
case OMPC_task_reduction:
+ case OMPC_in_reduction:
case OMPC_linear:
case OMPC_aligned:
case OMPC_copyin:
@@ -7761,7 +8662,9 @@ OMPClause *Sema::ActOnOpenMPScheduleClause(
<< "schedule" << 1 << ChunkSize->getSourceRange();
return nullptr;
}
- } else if (isParallelOrTaskRegion(DSAStack->getCurrentDirective()) &&
+ } else if (getOpenMPCaptureRegionForClause(
+ DSAStack->getCurrentDirective(), OMPC_schedule) !=
+ OMPD_unknown &&
!CurContext->isDependentContext()) {
llvm::MapVector<Expr *, DeclRefExpr *> Captures;
ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
@@ -7829,6 +8732,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
case OMPC_shared:
case OMPC_reduction:
case OMPC_task_reduction:
+ case OMPC_in_reduction:
case OMPC_linear:
case OMPC_aligned:
case OMPC_copyin:
@@ -7946,6 +8850,11 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
EndLoc, ReductionIdScopeSpec,
ReductionId);
break;
+ case OMPC_in_reduction:
+ Res =
+ ActOnOpenMPInReductionClause(VarList, StartLoc, LParenLoc, ColonLoc,
+ EndLoc, ReductionIdScopeSpec, ReductionId);
+ break;
case OMPC_linear:
Res = ActOnOpenMPLinearClause(VarList, TailExpr, StartLoc, LParenLoc,
LinKind, DepLinMapLoc, ColonLoc, EndLoc);
@@ -8097,7 +9006,8 @@ getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
}
return std::make_pair(nullptr, false);
}
- return std::make_pair(DE ? DE->getDecl() : ME->getMemberDecl(), false);
+ return std::make_pair(
+ getCanonicalDecl(DE ? DE->getDecl() : ME->getMemberDecl()), false);
}
OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
@@ -8299,13 +9209,19 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
if (!IsImplicitClause) {
DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, false);
TopDVar = DVar;
+ OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
bool IsConstant = ElemType.isConstant(Context);
// OpenMP [2.4.13, Data-sharing Attribute Clauses]
// A list item that specifies a given variable may not appear in more
// than one clause on the same directive, except that a variable may be
// specified in both firstprivate and lastprivate clauses.
+ // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
+ // A list item may appear in a firstprivate or lastprivate clause but not
+ // both.
if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
- DVar.CKind != OMPC_lastprivate && DVar.RefExpr) {
+ (isOpenMPDistributeDirective(CurrDir) ||
+ DVar.CKind != OMPC_lastprivate) &&
+ DVar.RefExpr) {
Diag(ELoc, diag::err_omp_wrong_dsa)
<< getOpenMPClauseName(DVar.CKind)
<< getOpenMPClauseName(OMPC_firstprivate);
@@ -8333,18 +9249,29 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
continue;
}
- OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
// OpenMP [2.9.3.4, Restrictions, p.2]
// A list item that is private within a parallel region must not appear
// in a firstprivate clause on a worksharing construct if any of the
// worksharing regions arising from the worksharing construct ever bind
// to any of the parallel regions arising from the parallel construct.
- if (isOpenMPWorksharingDirective(CurrDir) &&
+ // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
+ // A list item that is private within a teams region must not appear in a
+ // firstprivate clause on a distribute construct if any of the distribute
+ // regions arising from the distribute construct ever bind to any of the
+ // teams regions arising from the teams construct.
+ // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
+ // A list item that appears in a reduction clause of a teams construct
+ // must not appear in a firstprivate clause on a distribute construct if
+ // any of the distribute regions arising from the distribute construct
+ // ever bind to any of the teams regions arising from the teams construct.
+ if ((isOpenMPWorksharingDirective(CurrDir) ||
+ isOpenMPDistributeDirective(CurrDir)) &&
!isOpenMPParallelDirective(CurrDir) &&
!isOpenMPTeamsDirective(CurrDir)) {
DVar = DSAStack->getImplicitDSA(D, true);
if (DVar.CKind != OMPC_shared &&
(isOpenMPParallelDirective(DVar.DKind) ||
+ isOpenMPTeamsDirective(DVar.DKind) ||
DVar.DKind == OMPD_unknown)) {
Diag(ELoc, diag::err_omp_required_access)
<< getOpenMPClauseName(OMPC_firstprivate)
@@ -8369,12 +9296,14 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
D, [](OpenMPClauseKind C) -> bool { return C == OMPC_reduction; },
[](OpenMPDirectiveKind K) -> bool {
return isOpenMPParallelDirective(K) ||
- isOpenMPWorksharingDirective(K);
+ isOpenMPWorksharingDirective(K) ||
+ isOpenMPTeamsDirective(K);
},
- false);
+ /*FromParent=*/true);
if (DVar.CKind == OMPC_reduction &&
(isOpenMPParallelDirective(DVar.DKind) ||
- isOpenMPWorksharingDirective(DVar.DKind))) {
+ isOpenMPWorksharingDirective(DVar.DKind) ||
+ isOpenMPTeamsDirective(DVar.DKind))) {
Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
<< getOpenMPDirectiveName(DVar.DKind);
ReportOriginalDSA(*this, DSAStack, D, DVar);
@@ -8382,61 +9311,10 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
}
}
- // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
- // A list item that is private within a teams region must not appear in a
- // firstprivate clause on a distribute construct if any of the distribute
- // regions arising from the distribute construct ever bind to any of the
- // teams regions arising from the teams construct.
- // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
- // A list item that appears in a reduction clause of a teams construct
- // must not appear in a firstprivate clause on a distribute construct if
- // any of the distribute regions arising from the distribute construct
- // ever bind to any of the teams regions arising from the teams construct.
- // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
- // A list item may appear in a firstprivate or lastprivate clause but not
- // both.
- if (CurrDir == OMPD_distribute) {
- DVar = DSAStack->hasInnermostDSA(
- D, [](OpenMPClauseKind C) -> bool { return C == OMPC_private; },
- [](OpenMPDirectiveKind K) -> bool {
- return isOpenMPTeamsDirective(K);
- },
- false);
- if (DVar.CKind == OMPC_private && isOpenMPTeamsDirective(DVar.DKind)) {
- Diag(ELoc, diag::err_omp_firstprivate_distribute_private_teams);
- ReportOriginalDSA(*this, DSAStack, D, DVar);
- continue;
- }
- DVar = DSAStack->hasInnermostDSA(
- D, [](OpenMPClauseKind C) -> bool { return C == OMPC_reduction; },
- [](OpenMPDirectiveKind K) -> bool {
- return isOpenMPTeamsDirective(K);
- },
- false);
- if (DVar.CKind == OMPC_reduction &&
- isOpenMPTeamsDirective(DVar.DKind)) {
- Diag(ELoc, diag::err_omp_firstprivate_distribute_in_teams_reduction);
- ReportOriginalDSA(*this, DSAStack, D, DVar);
- continue;
- }
- DVar = DSAStack->getTopDSA(D, false);
- if (DVar.CKind == OMPC_lastprivate) {
- Diag(ELoc, diag::err_omp_firstprivate_and_lastprivate_in_distribute);
- ReportOriginalDSA(*this, DSAStack, D, DVar);
- continue;
- }
- }
// OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
// A list item cannot appear in both a map clause and a data-sharing
// attribute clause on the same construct
- if (CurrDir == OMPD_target || CurrDir == OMPD_target_parallel ||
- CurrDir == OMPD_target_teams ||
- CurrDir == OMPD_target_teams_distribute ||
- CurrDir == OMPD_target_teams_distribute_parallel_for ||
- CurrDir == OMPD_target_teams_distribute_parallel_for_simd ||
- CurrDir == OMPD_target_teams_distribute_simd ||
- CurrDir == OMPD_target_parallel_for_simd ||
- CurrDir == OMPD_target_parallel_for) {
+ if (isOpenMPTargetExecutionDirective(CurrDir)) {
OpenMPClauseKind ConflictKind;
if (DSAStack->checkMappableExprComponentListsForDecl(
VD, /*CurrentRegionOnly=*/true,
@@ -8585,14 +9463,19 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
continue;
Type = Type.getNonReferenceType();
+ OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
// OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
// in a Construct]
// Variables with the predetermined data-sharing attributes may not be
// listed in data-sharing attributes clauses, except for the cases
// listed below.
+ // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
+ // A list item may appear in a firstprivate or lastprivate clause but not
+ // both.
DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, false);
if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
- DVar.CKind != OMPC_firstprivate &&
+ (isOpenMPDistributeDirective(CurrDir) ||
+ DVar.CKind != OMPC_firstprivate) &&
(DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
Diag(ELoc, diag::err_omp_wrong_dsa)
<< getOpenMPClauseName(DVar.CKind)
@@ -8601,7 +9484,6 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
continue;
}
- OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
// OpenMP [2.14.3.5, Restrictions, p.2]
// A list item that is private within a parallel region, or that appears in
// the reduction clause of a parallel construct, must not appear in a
@@ -8622,18 +9504,6 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
}
}
- // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
- // A list item may appear in a firstprivate or lastprivate clause but not
- // both.
- if (CurrDir == OMPD_distribute) {
- DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, false);
- if (DVar.CKind == OMPC_firstprivate) {
- Diag(ELoc, diag::err_omp_firstprivate_and_lastprivate_in_distribute);
- ReportOriginalDSA(*this, DSAStack, D, DVar);
- continue;
- }
- }
-
// OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
// A variable of class type (or array thereof) that appears in a
// lastprivate clause requires an accessible, unambiguous default
@@ -8770,7 +9640,7 @@ public:
return true;
DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
VD, isOpenMPPrivate, [](OpenMPDirectiveKind) -> bool { return true; },
- false);
+ /*FromParent=*/true);
if (DVarPrivate.CKind != OMPC_unknown)
return true;
return false;
@@ -8928,6 +9798,9 @@ struct ReductionData {
SmallVector<Expr *, 8> RHSs;
/// Reduction operation expression.
SmallVector<Expr *, 8> ReductionOps;
+ /// Taskgroup descriptors for the corresponding reduction items in
+ /// in_reduction clauses.
+ SmallVector<Expr *, 8> TaskgroupDescriptors;
/// List of captures for clause.
SmallVector<Decl *, 4> ExprCaptures;
/// List of postupdate expressions.
@@ -8940,6 +9813,7 @@ struct ReductionData {
LHSs.reserve(Size);
RHSs.reserve(Size);
ReductionOps.reserve(Size);
+ TaskgroupDescriptors.reserve(Size);
ExprCaptures.reserve(Size);
ExprPostUpdates.reserve(Size);
}
@@ -8951,19 +9825,83 @@ struct ReductionData {
LHSs.emplace_back(nullptr);
RHSs.emplace_back(nullptr);
ReductionOps.emplace_back(ReductionOp);
+ TaskgroupDescriptors.emplace_back(nullptr);
}
/// Stores reduction data.
- void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS,
- Expr *ReductionOp) {
+ void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
+ Expr *TaskgroupDescriptor) {
Vars.emplace_back(Item);
Privates.emplace_back(Private);
LHSs.emplace_back(LHS);
RHSs.emplace_back(RHS);
ReductionOps.emplace_back(ReductionOp);
+ TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
}
};
} // namespace
+static bool CheckOMPArraySectionConstantForReduction(
+ ASTContext &Context, const OMPArraySectionExpr *OASE, bool &SingleElement,
+ SmallVectorImpl<llvm::APSInt> &ArraySizes) {
+ const Expr *Length = OASE->getLength();
+ if (Length == nullptr) {
+ // For array sections of the form [1:] or [:], we would need to analyze
+ // the lower bound...
+ if (OASE->getColonLoc().isValid())
+ return false;
+
+ // This is an array subscript which has implicit length 1!
+ SingleElement = true;
+ ArraySizes.push_back(llvm::APSInt::get(1));
+ } else {
+ llvm::APSInt ConstantLengthValue;
+ if (!Length->EvaluateAsInt(ConstantLengthValue, Context))
+ return false;
+
+ SingleElement = (ConstantLengthValue.getSExtValue() == 1);
+ ArraySizes.push_back(ConstantLengthValue);
+ }
+
+ // Get the base of this array section and walk up from there.
+ const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
+
+ // We require length = 1 for all array sections except the right-most to
+ // guarantee that the memory region is contiguous and has no holes in it.
+ while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) {
+ Length = TempOASE->getLength();
+ if (Length == nullptr) {
+ // For array sections of the form [1:] or [:], we would need to analyze
+ // the lower bound...
+ if (OASE->getColonLoc().isValid())
+ return false;
+
+ // This is an array subscript which has implicit length 1!
+ ArraySizes.push_back(llvm::APSInt::get(1));
+ } else {
+ llvm::APSInt ConstantLengthValue;
+ if (!Length->EvaluateAsInt(ConstantLengthValue, Context) ||
+ ConstantLengthValue.getSExtValue() != 1)
+ return false;
+
+ ArraySizes.push_back(ConstantLengthValue);
+ }
+ Base = TempOASE->getBase()->IgnoreParenImpCasts();
+ }
+
+ // If we have a single element, we don't need to add the implicit lengths.
+ if (!SingleElement) {
+ while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) {
+ // Has implicit length 1!
+ ArraySizes.push_back(llvm::APSInt::get(1));
+ Base = TempASE->getBase()->IgnoreParenImpCasts();
+ }
+ }
+
+ // This array section can be privatized as a single value or as a constant
+ // sized array.
+ return true;
+}
+
static bool ActOnOMPReductionKindClause(
Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
@@ -8982,7 +9920,6 @@ static bool ActOnOMPReductionKindClause(
// C++
// reduction-identifier is either an id-expression or one of the following
// operators: +, -, *, &, |, ^, && and ||
- // FIXME: Only 'min' and 'max' identifiers are supported for now.
switch (OOK) {
case OO_Plus:
case OO_Minus:
@@ -9033,6 +9970,7 @@ static bool ActOnOMPReductionKindClause(
case OO_GreaterGreaterEqual:
case OO_EqualEqual:
case OO_ExclaimEqual:
+ case OO_Spaceship:
case OO_PlusPlus:
case OO_MinusMinus:
case OO_Comma:
@@ -9045,7 +9983,7 @@ static bool ActOnOMPReductionKindClause(
case NUM_OVERLOADED_OPERATORS:
llvm_unreachable("Unexpected reduction identifier");
case OO_None:
- if (auto II = DN.getAsIdentifierInfo()) {
+ if (auto *II = DN.getAsIdentifierInfo()) {
if (II->isStr("max"))
BOK = BO_GT;
else if (II->isStr("min"))
@@ -9056,6 +9994,8 @@ static bool ActOnOMPReductionKindClause(
SourceRange ReductionIdRange;
if (ReductionIdScopeSpec.isValid())
ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
+ else
+ ReductionIdRange.setBegin(ReductionId.getBeginLoc());
ReductionIdRange.setEnd(ReductionId.getEndLoc());
auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
@@ -9097,6 +10037,7 @@ static bool ActOnOMPReductionKindClause(
if (!D)
continue;
+ Expr *TaskgroupDescriptor = nullptr;
QualType Type;
auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
auto *OASE = dyn_cast<OMPArraySectionExpr>(RefExpr->IgnoreParens());
@@ -9167,6 +10108,7 @@ static bool ActOnOMPReductionKindClause(
<< getOpenMPClauseName(ClauseKind);
if (DVar.RefExpr)
S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
+ continue;
} else if (DVar.CKind != OMPC_unknown) {
S.Diag(ELoc, diag::err_omp_wrong_dsa)
<< getOpenMPClauseName(DVar.CKind)
@@ -9259,9 +10201,34 @@ static bool ActOnOMPReductionKindClause(
auto *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
D->hasAttrs() ? &D->getAttrs() : nullptr);
auto PrivateTy = Type;
- if (OASE ||
- (!ASE &&
+
+ // Try if we can determine constant lengths for all array sections and avoid
+ // the VLA.
+ bool ConstantLengthOASE = false;
+ if (OASE) {
+ bool SingleElement;
+ llvm::SmallVector<llvm::APSInt, 4> ArraySizes;
+ ConstantLengthOASE = CheckOMPArraySectionConstantForReduction(
+ Context, OASE, SingleElement, ArraySizes);
+
+ // If we don't have a single element, we must emit a constant array type.
+ if (ConstantLengthOASE && !SingleElement) {
+ for (auto &Size : ArraySizes) {
+ PrivateTy = Context.getConstantArrayType(
+ PrivateTy, Size, ArrayType::Normal, /*IndexTypeQuals=*/0);
+ }
+ }
+ }
+
+ if ((OASE && !ConstantLengthOASE) ||
+ (!OASE && !ASE &&
D->getType().getNonReferenceType()->isVariablyModifiedType())) {
+ if (!Context.getTargetInfo().isVLASupported() &&
+ S.shouldDiagnoseTargetSupportFromOpenMP()) {
+ S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
+ S.Diag(ELoc, diag::note_vla_unsupported);
+ continue;
+ }
// For arrays/array sections only:
// Create pseudo array type for private copy. The size for this array will
// be generated during codegen.
@@ -9269,8 +10236,7 @@ static bool ActOnOMPReductionKindClause(
// (type of the variable or single array element).
PrivateTy = Context.getVariableArrayType(
Type,
- new (Context) OpaqueValueExpr(SourceLocation(), Context.getSizeType(),
- VK_RValue),
+ new (Context) OpaqueValueExpr(ELoc, Context.getSizeType(), VK_RValue),
ArrayType::Normal, /*IndexTypeQuals=*/0, SourceRange());
} else if (!ASE && !OASE &&
Context.getAsArrayType(D->getType().getNonReferenceType()))
@@ -9352,8 +10318,7 @@ static bool ActOnOMPReductionKindClause(
if (Type->isPointerType()) {
// Cast to pointer type.
auto CastExpr = S.BuildCStyleCastExpr(
- SourceLocation(), Context.getTrivialTypeSourceInfo(Type, ELoc),
- SourceLocation(), Init);
+ ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
if (CastExpr.isInvalid())
continue;
Init = CastExpr.get();
@@ -9378,6 +10343,7 @@ static bool ActOnOMPReductionKindClause(
case BO_GE:
case BO_EQ:
case BO_NE:
+ case BO_Cmp:
case BO_AndAssign:
case BO_XorAssign:
case BO_OrAssign:
@@ -9447,17 +10413,70 @@ static bool ActOnOMPReductionKindClause(
S.BuildBinOp(Stack->getCurScope(), ReductionId.getLocStart(),
BO_Assign, LHSDRE, ReductionOp.get());
} else {
- auto *ConditionalOp = new (Context) ConditionalOperator(
- ReductionOp.get(), SourceLocation(), LHSDRE, SourceLocation(),
- RHSDRE, Type, VK_LValue, OK_Ordinary);
+ auto *ConditionalOp = new (Context)
+ ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc, RHSDRE,
+ Type, VK_LValue, OK_Ordinary);
ReductionOp =
S.BuildBinOp(Stack->getCurScope(), ReductionId.getLocStart(),
BO_Assign, LHSDRE, ConditionalOp);
}
- ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get());
+ if (ReductionOp.isUsable())
+ ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get());
}
- if (ReductionOp.isInvalid())
+ if (!ReductionOp.isUsable())
+ continue;
+ }
+
+ // OpenMP [2.15.4.6, Restrictions, p.2]
+ // A list item that appears in an in_reduction clause of a task construct
+ // must appear in a task_reduction clause of a construct associated with a
+ // taskgroup region that includes the participating task in its taskgroup
+ // set. The construct associated with the innermost region that meets this
+ // condition must specify the same reduction-identifier as the in_reduction
+ // clause.
+ if (ClauseKind == OMPC_in_reduction) {
+ SourceRange ParentSR;
+ BinaryOperatorKind ParentBOK;
+ const Expr *ParentReductionOp;
+ Expr *ParentBOKTD, *ParentReductionOpTD;
+ DSAStackTy::DSAVarData ParentBOKDSA =
+ Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
+ ParentBOKTD);
+ DSAStackTy::DSAVarData ParentReductionOpDSA =
+ Stack->getTopMostTaskgroupReductionData(
+ D, ParentSR, ParentReductionOp, ParentReductionOpTD);
+ bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
+ bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
+ if (!IsParentBOK && !IsParentReductionOp) {
+ S.Diag(ELoc, diag::err_omp_in_reduction_not_task_reduction);
continue;
+ }
+ if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
+ (DeclareReductionRef.isUsable() && IsParentBOK) || BOK != ParentBOK ||
+ IsParentReductionOp) {
+ bool EmitError = true;
+ if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
+ llvm::FoldingSetNodeID RedId, ParentRedId;
+ ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
+ DeclareReductionRef.get()->Profile(RedId, Context,
+ /*Canonical=*/true);
+ EmitError = RedId != ParentRedId;
+ }
+ if (EmitError) {
+ S.Diag(ReductionId.getLocStart(),
+ diag::err_omp_reduction_identifier_mismatch)
+ << ReductionIdRange << RefExpr->getSourceRange();
+ S.Diag(ParentSR.getBegin(),
+ diag::note_omp_previous_reduction_identifier)
+ << ParentSR
+ << (IsParentBOK ? ParentBOKDSA.RefExpr
+ : ParentReductionOpDSA.RefExpr)
+ ->getSourceRange();
+ continue;
+ }
+ }
+ TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
+ assert(TaskgroupDescriptor && "Taskgroup descriptor must be defined.");
}
DeclRefExpr *Ref = nullptr;
@@ -9497,7 +10516,15 @@ static bool ActOnOMPReductionKindClause(
// All reduction items are still marked as reduction (to do not increase
// code base size).
Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref);
- RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get());
+ if (CurrDir == OMPD_taskgroup) {
+ if (DeclareReductionRef.isUsable())
+ Stack->addTaskgroupReductionData(D, ReductionIdRange,
+ DeclareReductionRef.get());
+ else
+ Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
+ }
+ RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
+ TaskgroupDescriptor);
}
return RD.Vars.empty();
}
@@ -9544,6 +10571,27 @@ OMPClause *Sema::ActOnOpenMPTaskReductionClause(
buildPostUpdate(*this, RD.ExprPostUpdates));
}
+OMPClause *Sema::ActOnOpenMPInReductionClause(
+ ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation ColonLoc, SourceLocation EndLoc,
+ CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
+ ArrayRef<Expr *> UnresolvedReductions) {
+ ReductionData RD(VarList.size());
+
+ if (ActOnOMPReductionKindClause(*this, DSAStack, OMPC_in_reduction, VarList,
+ StartLoc, LParenLoc, ColonLoc, EndLoc,
+ ReductionIdScopeSpec, ReductionId,
+ UnresolvedReductions, RD))
+ return nullptr;
+
+ return OMPInReductionClause::Create(
+ Context, StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
+ ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId,
+ RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
+ buildPreInits(Context, RD.ExprCaptures),
+ buildPostUpdate(*this, RD.ExprPostUpdates));
+}
+
bool Sema::CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,
SourceLocation LinLoc) {
if ((!LangOpts.CPlusPlus && LinKind != OMPC_LINEAR_val) ||
@@ -9768,11 +10816,19 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
HasErrors = true;
continue;
}
- if (auto *CED = dyn_cast<OMPCapturedExprDecl>(D)) {
- D = cast<MemberExpr>(CED->getInit()->IgnoreParenImpCasts())
- ->getMemberDecl();
- }
auto &&Info = Stack->isLoopControlVariable(D);
+ // OpenMP [2.15.11, distribute simd Construct]
+ // A list item may not appear in a linear clause, unless it is the loop
+ // iteration variable.
+ if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) &&
+ isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) {
+ SemaRef.Diag(ELoc,
+ diag::err_omp_linear_distribute_var_non_loop_iteration);
+ Updates.push_back(nullptr);
+ Finals.push_back(nullptr);
+ HasErrors = true;
+ continue;
+ }
Expr *InitExpr = *CurInit;
// Build privatized reference to the current linear var.
@@ -10239,23 +11295,26 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,
}
OpsOffs.push_back({RHS, OOK});
} else {
- // OpenMP [2.11.1.1, Restrictions, p.3]
- // A variable that is part of another variable (such as a field of a
- // structure) but is not an array element or an array section cannot
- // appear in a depend clause.
- auto *DE = dyn_cast<DeclRefExpr>(SimpleExpr);
auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
- auto *OASE = dyn_cast<OMPArraySectionExpr>(SimpleExpr);
if (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
- (!ASE && !DE && !OASE) || (DE && !isa<VarDecl>(DE->getDecl())) ||
(ASE &&
!ASE->getBase()
->getType()
.getNonReferenceType()
->isPointerType() &&
!ASE->getBase()->getType().getNonReferenceType()->isArrayType())) {
- Diag(ELoc, diag::err_omp_expected_var_name_member_expr_or_array_item)
- << 0 << RefExpr->getSourceRange();
+ Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
+ << RefExpr->getSourceRange();
+ continue;
+ }
+ bool Suppress = getDiagnostics().getSuppressAllDiagnostics();
+ getDiagnostics().setSuppressAllDiagnostics(/*Val=*/true);
+ ExprResult Res = CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
+ RefExpr->IgnoreParenImpCasts());
+ getDiagnostics().setSuppressAllDiagnostics(Suppress);
+ if (!Res.isUsable() && !isa<OMPArraySectionExpr>(SimpleExpr)) {
+ Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
+ << RefExpr->getSourceRange();
continue;
}
}
@@ -10284,6 +11343,7 @@ OMPClause *Sema::ActOnOpenMPDeviceClause(Expr *Device, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
Expr *ValExpr = Device;
+ Stmt *HelperValStmt = nullptr;
// OpenMP [2.9.1, Restrictions]
// The device expression must evaluate to a non-negative integer value.
@@ -10291,48 +11351,17 @@ OMPClause *Sema::ActOnOpenMPDeviceClause(Expr *Device, SourceLocation StartLoc,
/*StrictlyPositive=*/false))
return nullptr;
- return new (Context) OMPDeviceClause(ValExpr, StartLoc, LParenLoc, EndLoc);
-}
-
-static bool IsCXXRecordForMappable(Sema &SemaRef, SourceLocation Loc,
- DSAStackTy *Stack, CXXRecordDecl *RD) {
- if (!RD || RD->isInvalidDecl())
- return true;
-
- auto QTy = SemaRef.Context.getRecordType(RD);
- if (RD->isDynamicClass()) {
- SemaRef.Diag(Loc, diag::err_omp_not_mappable_type) << QTy;
- SemaRef.Diag(RD->getLocation(), diag::note_omp_polymorphic_in_target);
- return false;
- }
- auto *DC = RD;
- bool IsCorrect = true;
- for (auto *I : DC->decls()) {
- if (I) {
- if (auto *MD = dyn_cast<CXXMethodDecl>(I)) {
- if (MD->isStatic()) {
- SemaRef.Diag(Loc, diag::err_omp_not_mappable_type) << QTy;
- SemaRef.Diag(MD->getLocation(),
- diag::note_omp_static_member_in_target);
- IsCorrect = false;
- }
- } else if (auto *VD = dyn_cast<VarDecl>(I)) {
- if (VD->isStaticDataMember()) {
- SemaRef.Diag(Loc, diag::err_omp_not_mappable_type) << QTy;
- SemaRef.Diag(VD->getLocation(),
- diag::note_omp_static_member_in_target);
- IsCorrect = false;
- }
- }
- }
+ OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
+ OpenMPDirectiveKind CaptureRegion =
+ getOpenMPCaptureRegionForClause(DKind, OMPC_device);
+ if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
+ llvm::MapVector<Expr *, DeclRefExpr *> Captures;
+ ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
+ HelperValStmt = buildPreInits(Context, Captures);
}
- for (auto &I : RD->bases()) {
- if (!IsCXXRecordForMappable(SemaRef, I.getLocStart(), Stack,
- I.getType()->getAsCXXRecordDecl()))
- IsCorrect = false;
- }
- return IsCorrect;
+ return new (Context)
+ OMPDeviceClause(ValExpr, HelperValStmt, StartLoc, LParenLoc, EndLoc);
}
static bool CheckTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef,
@@ -10341,9 +11370,6 @@ static bool CheckTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef,
if (QTy->isIncompleteType(&ND)) {
SemaRef.Diag(SL, diag::err_incomplete_type) << QTy << SR;
return false;
- } else if (CXXRecordDecl *RD = dyn_cast_or_null<CXXRecordDecl>(ND)) {
- if (!RD->isInvalidDecl() && !IsCXXRecordForMappable(SemaRef, SL, Stack, RD))
- return false;
}
return true;
}
@@ -10443,7 +11469,7 @@ static bool CheckArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef,
static Expr *CheckMapClauseExpressionBase(
Sema &SemaRef, Expr *E,
OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
- OpenMPClauseKind CKind) {
+ OpenMPClauseKind CKind, bool NoDiagnose) {
SourceLocation ELoc = E->getExprLoc();
SourceRange ERange = E->getSourceRange();
@@ -10493,7 +11519,7 @@ static Expr *CheckMapClauseExpressionBase(
if (auto *CurE = dyn_cast<DeclRefExpr>(E)) {
if (!isa<VarDecl>(CurE->getDecl()))
- break;
+ return nullptr;
RelevantExpr = CurE;
@@ -10503,12 +11529,8 @@ static Expr *CheckMapClauseExpressionBase(
AllowWholeSizeArraySection = false;
// Record the component.
- CurComponents.push_back(OMPClauseMappableExprCommon::MappableComponent(
- CurE, CurE->getDecl()));
- continue;
- }
-
- if (auto *CurE = dyn_cast<MemberExpr>(E)) {
+ CurComponents.emplace_back(CurE, CurE->getDecl());
+ } else if (auto *CurE = dyn_cast<MemberExpr>(E)) {
auto *BaseE = CurE->getBase()->IgnoreParenImpCasts();
if (isa<CXXThisExpr>(BaseE))
@@ -10518,9 +11540,14 @@ static Expr *CheckMapClauseExpressionBase(
E = BaseE;
if (!isa<FieldDecl>(CurE->getMemberDecl())) {
- SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
- << CurE->getSourceRange();
- break;
+ if (!NoDiagnose) {
+ SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
+ << CurE->getSourceRange();
+ return nullptr;
+ }
+ if (RelevantExpr)
+ return nullptr;
+ continue;
}
auto *FD = cast<FieldDecl>(CurE->getMemberDecl());
@@ -10529,9 +11556,14 @@ static Expr *CheckMapClauseExpressionBase(
// A bit-field cannot appear in a map clause.
//
if (FD->isBitField()) {
- SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
- << CurE->getSourceRange() << getOpenMPClauseName(CKind);
- break;
+ if (!NoDiagnose) {
+ SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
+ << CurE->getSourceRange() << getOpenMPClauseName(CKind);
+ return nullptr;
+ }
+ if (RelevantExpr)
+ return nullptr;
+ continue;
}
// OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
@@ -10543,12 +11575,16 @@ static Expr *CheckMapClauseExpressionBase(
// A list item cannot be a variable that is a member of a structure with
// a union type.
//
- if (auto *RT = CurType->getAs<RecordType>())
+ if (auto *RT = CurType->getAs<RecordType>()) {
if (RT->isUnionType()) {
- SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
- << CurE->getSourceRange();
- break;
+ if (!NoDiagnose) {
+ SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
+ << CurE->getSourceRange();
+ return nullptr;
+ }
+ continue;
}
+ }
// If we got a member expression, we should not expect any array section
// before that:
@@ -10561,18 +11597,17 @@ static Expr *CheckMapClauseExpressionBase(
AllowWholeSizeArraySection = false;
// Record the component.
- CurComponents.push_back(
- OMPClauseMappableExprCommon::MappableComponent(CurE, FD));
- continue;
- }
-
- if (auto *CurE = dyn_cast<ArraySubscriptExpr>(E)) {
+ CurComponents.emplace_back(CurE, FD);
+ } else if (auto *CurE = dyn_cast<ArraySubscriptExpr>(E)) {
E = CurE->getBase()->IgnoreParenImpCasts();
if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
- SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
- << 0 << CurE->getSourceRange();
- break;
+ if (!NoDiagnose) {
+ SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
+ << 0 << CurE->getSourceRange();
+ return nullptr;
+ }
+ continue;
}
// If we got an array subscript that express the whole dimension we
@@ -10583,15 +11618,12 @@ static Expr *CheckMapClauseExpressionBase(
AllowWholeSizeArraySection = false;
// Record the component - we don't have any declaration associated.
- CurComponents.push_back(
- OMPClauseMappableExprCommon::MappableComponent(CurE, nullptr));
- continue;
- }
-
- if (auto *CurE = dyn_cast<OMPArraySectionExpr>(E)) {
+ CurComponents.emplace_back(CurE, nullptr);
+ } else if (auto *CurE = dyn_cast<OMPArraySectionExpr>(E)) {
+ assert(!NoDiagnose && "Array sections cannot be implicitly mapped.");
E = CurE->getBase()->IgnoreParenImpCasts();
- auto CurType =
+ QualType CurType =
OMPArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
// OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
@@ -10605,7 +11637,7 @@ static Expr *CheckMapClauseExpressionBase(
if (!IsPointer && !CurType->isArrayType()) {
SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
<< 0 << CurE->getSourceRange();
- break;
+ return nullptr;
}
bool NotWhole =
@@ -10628,20 +11660,20 @@ static Expr *CheckMapClauseExpressionBase(
SemaRef.Diag(
ELoc, diag::err_array_section_does_not_specify_contiguous_storage)
<< CurE->getSourceRange();
- break;
+ return nullptr;
}
// Record the component - we don't have any declaration associated.
- CurComponents.push_back(
- OMPClauseMappableExprCommon::MappableComponent(CurE, nullptr));
- continue;
+ CurComponents.emplace_back(CurE, nullptr);
+ } else {
+ if (!NoDiagnose) {
+ // If nothing else worked, this is not a valid map clause expression.
+ SemaRef.Diag(
+ ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
+ << ERange;
+ }
+ return nullptr;
}
-
- // If nothing else worked, this is not a valid map clause expression.
- SemaRef.Diag(ELoc,
- diag::err_omp_expected_named_var_member_or_array_expression)
- << ERange;
- break;
}
return RelevantExpr;
@@ -10932,8 +11964,8 @@ checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS,
// Obtain the array or member expression bases if required. Also, fill the
// components array with all the components identified in the process.
- auto *BE =
- CheckMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind);
+ auto *BE = CheckMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents,
+ CKind, /*NoDiagnose=*/false);
if (!BE)
continue;
@@ -11123,7 +12155,7 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareReductionDirectiveStart(
Decls.reserve(ReductionTypes.size());
LookupResult Lookup(*this, Name, SourceLocation(), LookupOMPReductionName,
- ForRedeclaration);
+ forRedeclarationInCurContext());
// [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
// A reduction-identifier may not be re-declared in the current scope for the
// same type or for a type that is compatible according to the base language
@@ -11253,7 +12285,7 @@ void Sema::ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner) {
DRD->setInvalidDecl();
}
-void Sema::ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D) {
+VarDecl *Sema::ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D) {
auto *DRD = cast<OMPDeclareReductionDecl>(D);
// Enter new function scope.
@@ -11292,10 +12324,11 @@ void Sema::ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D) {
DRD->addDecl(OmpPrivParm);
DRD->addDecl(OmpOrigParm);
}
+ return OmpPrivParm;
}
-void Sema::ActOnOpenMPDeclareReductionInitializerEnd(Decl *D,
- Expr *Initializer) {
+void Sema::ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer,
+ VarDecl *OmpPrivParm) {
auto *DRD = cast<OMPDeclareReductionDecl>(D);
DiscardCleanupsInEvaluationContext();
PopExpressionEvaluationContext();
@@ -11303,10 +12336,16 @@ void Sema::ActOnOpenMPDeclareReductionInitializerEnd(Decl *D,
PopDeclContext();
PopFunctionScopeInfo();
- if (Initializer != nullptr)
- DRD->setInitializer(Initializer);
- else
+ if (Initializer != nullptr) {
+ DRD->setInitializer(Initializer, OMPDeclareReductionDecl::CallInit);
+ } else if (OmpPrivParm->hasInit()) {
+ DRD->setInitializer(OmpPrivParm->getInit(),
+ OmpPrivParm->isDirectInit()
+ ? OMPDeclareReductionDecl::DirectInit
+ : OMPDeclareReductionDecl::CopyInit);
+ } else {
DRD->setInvalidDecl();
+ }
}
Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareReductionDirectiveEnd(
@@ -11328,7 +12367,6 @@ OMPClause *Sema::ActOnOpenMPNumTeamsClause(Expr *NumTeams,
SourceLocation EndLoc) {
Expr *ValExpr = NumTeams;
Stmt *HelperValStmt = nullptr;
- OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
// OpenMP [teams Constrcut, Restrictions]
// The num_teams expression must evaluate to a positive integer value.
@@ -11337,8 +12375,9 @@ OMPClause *Sema::ActOnOpenMPNumTeamsClause(Expr *NumTeams,
return nullptr;
OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
- CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_num_teams);
- if (CaptureRegion != OMPD_unknown) {
+ OpenMPDirectiveKind CaptureRegion =
+ getOpenMPCaptureRegionForClause(DKind, OMPC_num_teams);
+ if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
llvm::MapVector<Expr *, DeclRefExpr *> Captures;
ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
HelperValStmt = buildPreInits(Context, Captures);
@@ -11354,7 +12393,6 @@ OMPClause *Sema::ActOnOpenMPThreadLimitClause(Expr *ThreadLimit,
SourceLocation EndLoc) {
Expr *ValExpr = ThreadLimit;
Stmt *HelperValStmt = nullptr;
- OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
// OpenMP [teams Constrcut, Restrictions]
// The thread_limit expression must evaluate to a positive integer value.
@@ -11363,8 +12401,9 @@ OMPClause *Sema::ActOnOpenMPThreadLimitClause(Expr *ThreadLimit,
return nullptr;
OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
- CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_thread_limit);
- if (CaptureRegion != OMPD_unknown) {
+ OpenMPDirectiveKind CaptureRegion =
+ getOpenMPCaptureRegionForClause(DKind, OMPC_thread_limit);
+ if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
llvm::MapVector<Expr *, DeclRefExpr *> Captures;
ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
HelperValStmt = buildPreInits(Context, Captures);
@@ -11471,7 +12510,9 @@ OMPClause *Sema::ActOnOpenMPDistScheduleClause(
<< "dist_schedule" << ChunkSize->getSourceRange();
return nullptr;
}
- } else if (isParallelOrTaskRegion(DSAStack->getCurrentDirective()) &&
+ } else if (getOpenMPCaptureRegionForClause(
+ DSAStack->getCurrentDirective(), OMPC_dist_schedule) !=
+ OMPD_unknown &&
!CurContext->isDependentContext()) {
llvm::MapVector<Expr *, DeclRefExpr *> Captures;
ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
@@ -11508,6 +12549,7 @@ OMPClause *Sema::ActOnOpenMPDefaultmapClause(
<< Value << getOpenMPClauseName(OMPC_defaultmap);
return nullptr;
}
+ DSAStack->setDefaultDMAToFromScalar(StartLoc);
return new (Context)
OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
@@ -11517,7 +12559,11 @@ bool Sema::ActOnStartOpenMPDeclareTargetDirective(SourceLocation Loc) {
DeclContext *CurLexicalContext = getCurLexicalContext();
if (!CurLexicalContext->isFileContext() &&
!CurLexicalContext->isExternCContext() &&
- !CurLexicalContext->isExternCXXContext()) {
+ !CurLexicalContext->isExternCXXContext() &&
+ !isa<CXXRecordDecl>(CurLexicalContext) &&
+ !isa<ClassTemplateDecl>(CurLexicalContext) &&
+ !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
+ !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
Diag(Loc, diag::err_omp_region_not_file_context);
return false;
}
@@ -11574,7 +12620,7 @@ void Sema::ActOnOpenMPDeclareTargetName(Scope *CurScope,
ND->addAttr(A);
if (ASTMutationListener *ML = Context.getASTMutationListener())
ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
- checkDeclIsAllowedInOpenMPTarget(nullptr, ND);
+ checkDeclIsAllowedInOpenMPTarget(nullptr, ND, Id.getLoc());
} else if (ND->getAttr<OMPDeclareTargetDeclAttr>()->getMapType() != MT) {
Diag(Id.getLoc(), diag::err_omp_declare_target_to_and_link)
<< Id.getName();
@@ -11663,7 +12709,8 @@ static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR,
return true;
}
-void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D) {
+void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
+ SourceLocation IdLoc) {
if (!D || D->isInvalidDecl())
return;
SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
@@ -11692,6 +12739,16 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D) {
return;
}
}
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (FD->hasAttr<OMPDeclareTargetDeclAttr>() &&
+ (FD->getAttr<OMPDeclareTargetDeclAttr>()->getMapType() ==
+ OMPDeclareTargetDeclAttr::MT_Link)) {
+ assert(IdLoc.isValid() && "Source location is expected");
+ Diag(IdLoc, diag::err_omp_function_in_link_clause);
+ Diag(FD->getLocation(), diag::note_defined_here) << FD;
+ return;
+ }
+ }
if (!E) {
// Checking declaration inside declare target region.
if (!D->hasAttr<OMPDeclareTargetDeclAttr>() &&
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
index 36f24fd9c463a..268be9430a56e 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
@@ -837,12 +837,13 @@ void OverloadCandidateSet::destroyCandidates() {
}
}
-void OverloadCandidateSet::clear() {
+void OverloadCandidateSet::clear(CandidateSetKind CSK) {
destroyCandidates();
SlabAllocator.Reset();
NumInlineBytesUsed = 0;
Candidates.clear();
Functions.clear();
+ Kind = CSK;
}
namespace {
@@ -1481,6 +1482,23 @@ bool Sema::IsFunctionConversion(QualType FromType, QualType ToType,
.getTypePtr());
Changed = true;
}
+
+ // Convert FromFPT's ExtParameterInfo if necessary. The conversion is valid
+ // only if the ExtParameterInfo lists of the two function prototypes can be
+ // merged and the merged list is identical to ToFPT's ExtParameterInfo list.
+ SmallVector<FunctionProtoType::ExtParameterInfo, 4> NewParamInfos;
+ bool CanUseToFPT, CanUseFromFPT;
+ if (Context.mergeExtParameterInfo(ToFPT, FromFPT, CanUseToFPT,
+ CanUseFromFPT, NewParamInfos) &&
+ CanUseToFPT && !CanUseFromFPT) {
+ FunctionProtoType::ExtProtoInfo ExtInfo = FromFPT->getExtProtoInfo();
+ ExtInfo.ExtParameterInfos =
+ NewParamInfos.empty() ? nullptr : NewParamInfos.data();
+ QualType QT = Context.getFunctionType(FromFPT->getReturnType(),
+ FromFPT->getParamTypes(), ExtInfo);
+ FromFn = QT->getAs<FunctionType>();
+ Changed = true;
+ }
}
if (!Changed)
@@ -2663,8 +2681,12 @@ bool Sema::IsBlockPointerConversion(QualType FromType, QualType ToType,
// Argument types are too different. Abort.
return false;
}
- if (!Context.doFunctionTypesMatchOnExtParameterInfos(FromFunctionType,
- ToFunctionType))
+
+ SmallVector<FunctionProtoType::ExtParameterInfo, 4> NewParamInfos;
+ bool CanUseToFPT, CanUseFromFPT;
+ if (!Context.mergeExtParameterInfo(ToFunctionType, FromFunctionType,
+ CanUseToFPT, CanUseFromFPT,
+ NewParamInfos))
return false;
ConvertedType = ToType;
@@ -3154,6 +3176,7 @@ IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType,
UserDefinedConversionSequence &User,
OverloadCandidateSet &CandidateSet,
bool AllowExplicit) {
+ CandidateSet.clear(OverloadCandidateSet::CSK_InitByUserDefinedConversion);
for (auto *D : S.LookupConstructors(To)) {
auto Info = getConstructorInfo(D);
if (!Info)
@@ -3182,7 +3205,7 @@ IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType,
OverloadCandidateSet::iterator Best;
switch (auto Result =
CandidateSet.BestViableFunction(S, From->getLocStart(),
- Best, true)) {
+ Best)) {
case OR_Deleted:
case OR_Success: {
// Record the standard conversion we used and the conversion function.
@@ -3229,6 +3252,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
bool AllowExplicit,
bool AllowObjCConversionOnExplicit) {
assert(AllowExplicit || !AllowObjCConversionOnExplicit);
+ CandidateSet.clear(OverloadCandidateSet::CSK_InitByUserDefinedConversion);
// Whether we will only visit constructors.
bool ConstructorsOnly = false;
@@ -3264,7 +3288,8 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
if (Result != OR_No_Viable_Function)
return Result;
// Never mind.
- CandidateSet.clear();
+ CandidateSet.clear(
+ OverloadCandidateSet::CSK_InitByUserDefinedConversion);
// If we're list-initializing, we pass the individual elements as
// arguments, not the entire list.
@@ -3354,7 +3379,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
OverloadCandidateSet::iterator Best;
switch (auto Result = CandidateSet.BestViableFunction(S, From->getLocStart(),
- Best, true)) {
+ Best)) {
case OR_Success:
case OR_Deleted:
// Record the standard conversion we used and the conversion function.
@@ -4288,7 +4313,8 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
CXXRecordDecl *T2RecordDecl
= dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl());
- OverloadCandidateSet CandidateSet(DeclLoc, OverloadCandidateSet::CSK_Normal);
+ OverloadCandidateSet CandidateSet(
+ DeclLoc, OverloadCandidateSet::CSK_InitByUserDefinedConversion);
const auto &Conversions = T2RecordDecl->getVisibleConversionFunctions();
for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) {
NamedDecl *D = *I;
@@ -4358,7 +4384,7 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
bool HadMultipleCandidates = (CandidateSet.size() > 1);
OverloadCandidateSet::iterator Best;
- switch (CandidateSet.BestViableFunction(S, DeclLoc, Best, true)) {
+ switch (CandidateSet.BestViableFunction(S, DeclLoc, Best)) {
case OR_Success:
// C++ [over.ics.ref]p1:
//
@@ -6317,24 +6343,36 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
OverloadCandidateSet& CandidateSet,
TemplateArgumentListInfo *ExplicitTemplateArgs,
bool SuppressUserConversions,
- bool PartialOverloading) {
+ bool PartialOverloading,
+ bool FirstArgumentIsBase) {
for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) {
NamedDecl *D = F.getDecl()->getUnderlyingDecl();
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ ArrayRef<Expr *> FunctionArgs = Args;
if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic()) {
QualType ObjectType;
Expr::Classification ObjectClassification;
- if (Expr *E = Args[0]) {
- // Use the explit base to restrict the lookup:
- ObjectType = E->getType();
- ObjectClassification = E->Classify(Context);
- } // .. else there is an implit base.
+ if (Args.size() > 0) {
+ if (Expr *E = Args[0]) {
+ // Use the explit base to restrict the lookup:
+ ObjectType = E->getType();
+ ObjectClassification = E->Classify(Context);
+ } // .. else there is an implit base.
+ FunctionArgs = Args.slice(1);
+ }
AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(),
cast<CXXMethodDecl>(FD)->getParent(), ObjectType,
- ObjectClassification, Args.slice(1), CandidateSet,
+ ObjectClassification, FunctionArgs, CandidateSet,
SuppressUserConversions, PartialOverloading);
} else {
- AddOverloadCandidate(FD, F.getPair(), Args, CandidateSet,
+ // Slice the first argument (which is the base) when we access
+ // static method as non-static
+ if (Args.size() > 0 && (!Args[0] || (FirstArgumentIsBase && isa<CXXMethodDecl>(FD) &&
+ !isa<CXXConstructorDecl>(FD)))) {
+ assert(cast<CXXMethodDecl>(FD)->isStatic());
+ FunctionArgs = Args.slice(1);
+ }
+ AddOverloadCandidate(FD, F.getPair(), FunctionArgs, CandidateSet,
SuppressUserConversions, PartialOverloading);
}
} else {
@@ -6767,7 +6805,8 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
CXXRecordDecl *ActingContext,
Expr *From, QualType ToType,
OverloadCandidateSet& CandidateSet,
- bool AllowObjCConversionOnExplicit) {
+ bool AllowObjCConversionOnExplicit,
+ bool AllowResultConversion) {
assert(!Conversion->getDescribedFunctionTemplate() &&
"Conversion function templates use AddTemplateConversionCandidate");
QualType ConvType = Conversion->getConversionType().getNonReferenceType();
@@ -6782,6 +6821,12 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
ConvType = Conversion->getConversionType().getNonReferenceType();
}
+ // If we don't allow any conversion of the result type, ignore conversion
+ // functions that don't convert to exactly (possibly cv-qualified) T.
+ if (!AllowResultConversion &&
+ !Context.hasSameUnqualifiedType(Conversion->getConversionType(), ToType))
+ return;
+
// Per C++ [over.match.conv]p1, [over.match.ref]p1, an explicit conversion
// operator is only a candidate if its return type is the target type or
// can be converted to the target type with a qualification conversion.
@@ -6935,7 +6980,8 @@ Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
CXXRecordDecl *ActingDC,
Expr *From, QualType ToType,
OverloadCandidateSet &CandidateSet,
- bool AllowObjCConversionOnExplicit) {
+ bool AllowObjCConversionOnExplicit,
+ bool AllowResultConversion) {
assert(isa<CXXConversionDecl>(FunctionTemplate->getTemplatedDecl()) &&
"Only conversion function templates permitted here");
@@ -6964,7 +7010,8 @@ Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
// template argument deduction as a candidate.
assert(Specialization && "Missing function template specialization?");
AddConversionCandidate(Specialization, FoundDecl, ActingDC, From, ToType,
- CandidateSet, AllowObjCConversionOnExplicit);
+ CandidateSet, AllowObjCConversionOnExplicit,
+ AllowResultConversion);
}
/// AddSurrogateCandidate - Adds a "surrogate" candidate function that
@@ -7568,53 +7615,62 @@ class BuiltinOperatorOverloadBuilder {
SmallVectorImpl<BuiltinCandidateTypeSet> &CandidateTypes;
OverloadCandidateSet &CandidateSet;
- // Define some constants used to index and iterate over the arithemetic types
- // provided via the getArithmeticType() method below.
- // The "promoted arithmetic types" are the arithmetic
+ static constexpr int ArithmeticTypesCap = 24;
+ SmallVector<CanQualType, ArithmeticTypesCap> ArithmeticTypes;
+
+ // Define some indices used to iterate over the arithemetic types in
+ // ArithmeticTypes. The "promoted arithmetic types" are the arithmetic
// types are that preserved by promotion (C++ [over.built]p2).
- static const unsigned FirstIntegralType = 4;
- static const unsigned LastIntegralType = 21;
- static const unsigned FirstPromotedIntegralType = 4,
- LastPromotedIntegralType = 12;
- static const unsigned FirstPromotedArithmeticType = 0,
- LastPromotedArithmeticType = 12;
- static const unsigned NumArithmeticTypes = 21;
+ unsigned FirstIntegralType,
+ LastIntegralType;
+ unsigned FirstPromotedIntegralType,
+ LastPromotedIntegralType;
+ unsigned FirstPromotedArithmeticType,
+ LastPromotedArithmeticType;
+ unsigned NumArithmeticTypes;
- /// \brief Get the canonical type for a given arithmetic type index.
- CanQualType getArithmeticType(unsigned index) {
- assert(index < NumArithmeticTypes);
- static CanQualType ASTContext::* const
- ArithmeticTypes[NumArithmeticTypes] = {
- // Start of promoted types.
- &ASTContext::FloatTy,
- &ASTContext::DoubleTy,
- &ASTContext::LongDoubleTy,
- &ASTContext::Float128Ty,
+ void InitArithmeticTypes() {
+ // Start of promoted types.
+ FirstPromotedArithmeticType = 0;
+ ArithmeticTypes.push_back(S.Context.FloatTy);
+ ArithmeticTypes.push_back(S.Context.DoubleTy);
+ ArithmeticTypes.push_back(S.Context.LongDoubleTy);
+ if (S.Context.getTargetInfo().hasFloat128Type())
+ ArithmeticTypes.push_back(S.Context.Float128Ty);
- // Start of integral types.
- &ASTContext::IntTy,
- &ASTContext::LongTy,
- &ASTContext::LongLongTy,
- &ASTContext::Int128Ty,
- &ASTContext::UnsignedIntTy,
- &ASTContext::UnsignedLongTy,
- &ASTContext::UnsignedLongLongTy,
- &ASTContext::UnsignedInt128Ty,
- // End of promoted types.
+ // Start of integral types.
+ FirstIntegralType = ArithmeticTypes.size();
+ FirstPromotedIntegralType = ArithmeticTypes.size();
+ ArithmeticTypes.push_back(S.Context.IntTy);
+ ArithmeticTypes.push_back(S.Context.LongTy);
+ ArithmeticTypes.push_back(S.Context.LongLongTy);
+ if (S.Context.getTargetInfo().hasInt128Type())
+ ArithmeticTypes.push_back(S.Context.Int128Ty);
+ ArithmeticTypes.push_back(S.Context.UnsignedIntTy);
+ ArithmeticTypes.push_back(S.Context.UnsignedLongTy);
+ ArithmeticTypes.push_back(S.Context.UnsignedLongLongTy);
+ if (S.Context.getTargetInfo().hasInt128Type())
+ ArithmeticTypes.push_back(S.Context.UnsignedInt128Ty);
+ LastPromotedIntegralType = ArithmeticTypes.size();
+ LastPromotedArithmeticType = ArithmeticTypes.size();
+ // End of promoted types.
- &ASTContext::BoolTy,
- &ASTContext::CharTy,
- &ASTContext::WCharTy,
- &ASTContext::Char16Ty,
- &ASTContext::Char32Ty,
- &ASTContext::SignedCharTy,
- &ASTContext::ShortTy,
- &ASTContext::UnsignedCharTy,
- &ASTContext::UnsignedShortTy,
- // End of integral types.
- // FIXME: What about complex? What about half?
- };
- return S.Context.*ArithmeticTypes[index];
+ ArithmeticTypes.push_back(S.Context.BoolTy);
+ ArithmeticTypes.push_back(S.Context.CharTy);
+ ArithmeticTypes.push_back(S.Context.WCharTy);
+ ArithmeticTypes.push_back(S.Context.Char16Ty);
+ ArithmeticTypes.push_back(S.Context.Char32Ty);
+ ArithmeticTypes.push_back(S.Context.SignedCharTy);
+ ArithmeticTypes.push_back(S.Context.ShortTy);
+ ArithmeticTypes.push_back(S.Context.UnsignedCharTy);
+ ArithmeticTypes.push_back(S.Context.UnsignedShortTy);
+ LastIntegralType = ArithmeticTypes.size();
+ NumArithmeticTypes = ArithmeticTypes.size();
+ // End of integral types.
+ // FIXME: What about complex? What about half?
+
+ assert(ArithmeticTypes.size() <= ArithmeticTypesCap &&
+ "Enough inline storage for all arithmetic types.");
}
/// \brief Helper method to factor out the common pattern of adding overloads
@@ -7673,18 +7729,8 @@ public:
HasArithmeticOrEnumeralCandidateType),
CandidateTypes(CandidateTypes),
CandidateSet(CandidateSet) {
- // Validate some of our static helper constants in debug builds.
- assert(getArithmeticType(FirstPromotedIntegralType) == S.Context.IntTy &&
- "Invalid first promoted integral type");
- assert(getArithmeticType(LastPromotedIntegralType - 1)
- == S.Context.UnsignedInt128Ty &&
- "Invalid last promoted integral type");
- assert(getArithmeticType(FirstPromotedArithmeticType)
- == S.Context.FloatTy &&
- "Invalid first promoted arithmetic type");
- assert(getArithmeticType(LastPromotedArithmeticType - 1)
- == S.Context.UnsignedInt128Ty &&
- "Invalid last promoted arithmetic type");
+
+ InitArithmeticTypes();
}
// C++ [over.built]p3:
@@ -7711,7 +7757,7 @@ public:
for (unsigned Arith = (Op == OO_PlusPlus? 0 : 1);
Arith < NumArithmeticTypes; ++Arith) {
addPlusPlusMinusMinusStyleOverloads(
- getArithmeticType(Arith),
+ ArithmeticTypes[Arith],
VisibleTypeConversionsQuals.hasVolatile(),
VisibleTypeConversionsQuals.hasRestrict());
}
@@ -7784,7 +7830,7 @@ public:
for (unsigned Arith = FirstPromotedArithmeticType;
Arith < LastPromotedArithmeticType; ++Arith) {
- QualType ArithTy = getArithmeticType(Arith);
+ QualType ArithTy = ArithmeticTypes[Arith];
S.AddBuiltinCandidate(&ArithTy, Args, CandidateSet);
}
@@ -7824,7 +7870,7 @@ public:
for (unsigned Int = FirstPromotedIntegralType;
Int < LastPromotedIntegralType; ++Int) {
- QualType IntTy = getArithmeticType(Int);
+ QualType IntTy = ArithmeticTypes[Int];
S.AddBuiltinCandidate(&IntTy, Args, CandidateSet);
}
@@ -8052,8 +8098,8 @@ public:
Left < LastPromotedArithmeticType; ++Left) {
for (unsigned Right = FirstPromotedArithmeticType;
Right < LastPromotedArithmeticType; ++Right) {
- QualType LandR[2] = { getArithmeticType(Left),
- getArithmeticType(Right) };
+ QualType LandR[2] = { ArithmeticTypes[Left],
+ ArithmeticTypes[Right] };
S.AddBuiltinCandidate(LandR, Args, CandidateSet);
}
}
@@ -8096,8 +8142,8 @@ public:
Left < LastPromotedIntegralType; ++Left) {
for (unsigned Right = FirstPromotedIntegralType;
Right < LastPromotedIntegralType; ++Right) {
- QualType LandR[2] = { getArithmeticType(Left),
- getArithmeticType(Right) };
+ QualType LandR[2] = { ArithmeticTypes[Left],
+ ArithmeticTypes[Right] };
S.AddBuiltinCandidate(LandR, Args, CandidateSet);
}
}
@@ -8277,18 +8323,18 @@ public:
for (unsigned Right = FirstPromotedArithmeticType;
Right < LastPromotedArithmeticType; ++Right) {
QualType ParamTypes[2];
- ParamTypes[1] = getArithmeticType(Right);
+ ParamTypes[1] = ArithmeticTypes[Right];
// Add this built-in operator as a candidate (VQ is empty).
ParamTypes[0] =
- S.Context.getLValueReferenceType(getArithmeticType(Left));
+ S.Context.getLValueReferenceType(ArithmeticTypes[Left]);
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
/*IsAssigmentOperator=*/isEqualOp);
// Add this built-in operator as a candidate (VQ is 'volatile').
if (VisibleTypeConversionsQuals.hasVolatile()) {
ParamTypes[0] =
- S.Context.getVolatileType(getArithmeticType(Left));
+ S.Context.getVolatileType(ArithmeticTypes[Left]);
ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]);
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
/*IsAssigmentOperator=*/isEqualOp);
@@ -8343,15 +8389,15 @@ public:
for (unsigned Right = FirstPromotedIntegralType;
Right < LastPromotedIntegralType; ++Right) {
QualType ParamTypes[2];
- ParamTypes[1] = getArithmeticType(Right);
+ ParamTypes[1] = ArithmeticTypes[Right];
// Add this built-in operator as a candidate (VQ is empty).
ParamTypes[0] =
- S.Context.getLValueReferenceType(getArithmeticType(Left));
+ S.Context.getLValueReferenceType(ArithmeticTypes[Left]);
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
if (VisibleTypeConversionsQuals.hasVolatile()) {
// Add this built-in operator as a candidate (VQ is 'volatile').
- ParamTypes[0] = getArithmeticType(Left);
+ ParamTypes[0] = ArithmeticTypes[Left];
ParamTypes[0] = S.Context.getVolatileType(ParamTypes[0]);
ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]);
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
@@ -8646,6 +8692,9 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
OpBuilder.addGenericBinaryArithmeticOverloads();
break;
+ case OO_Spaceship:
+ llvm_unreachable("<=> expressions not supported yet");
+
case OO_Percent:
case OO_Caret:
case OO_Pipe:
@@ -8823,10 +8872,9 @@ static Comparison compareEnableIfAttrs(const Sema &S, const FunctionDecl *Cand1,
/// isBetterOverloadCandidate - Determines whether the first overload
/// candidate is a better candidate than the second (C++ 13.3.3p1).
-bool clang::isBetterOverloadCandidate(Sema &S, const OverloadCandidate &Cand1,
- const OverloadCandidate &Cand2,
- SourceLocation Loc,
- bool UserDefinedConversion) {
+bool clang::isBetterOverloadCandidate(
+ Sema &S, const OverloadCandidate &Cand1, const OverloadCandidate &Cand2,
+ SourceLocation Loc, OverloadCandidateSet::CandidateSetKind Kind) {
// Define viable functions to be better candidates than non-viable
// functions.
if (!Cand2.Viable)
@@ -8908,7 +8956,8 @@ bool clang::isBetterOverloadCandidate(Sema &S, const OverloadCandidate &Cand1,
// the type of the entity being initialized) is a better
// conversion sequence than the standard conversion sequence
// from the return type of F2 to the destination type.
- if (UserDefinedConversion && Cand1.Function && Cand2.Function &&
+ if (Kind == OverloadCandidateSet::CSK_InitByUserDefinedConversion &&
+ Cand1.Function && Cand2.Function &&
isa<CXXConversionDecl>(Cand1.Function) &&
isa<CXXConversionDecl>(Cand2.Function)) {
// First check whether we prefer one of the conversion functions over the
@@ -8930,11 +8979,17 @@ bool clang::isBetterOverloadCandidate(Sema &S, const OverloadCandidate &Cand1,
// C++14 [over.match.best]p1 section 2 bullet 3.
}
- // -- F1 is generated from a deduction-guide and F2 is not
- auto *Guide1 = dyn_cast_or_null<CXXDeductionGuideDecl>(Cand1.Function);
- auto *Guide2 = dyn_cast_or_null<CXXDeductionGuideDecl>(Cand2.Function);
- if (Guide1 && Guide2 && Guide1->isImplicit() != Guide2->isImplicit())
- return Guide2->isImplicit();
+ // FIXME: Work around a defect in the C++17 guaranteed copy elision wording,
+ // as combined with the resolution to CWG issue 243.
+ //
+ // When the context is initialization by constructor ([over.match.ctor] or
+ // either phase of [over.match.list]), a constructor is preferred over
+ // a conversion function.
+ if (Kind == OverloadCandidateSet::CSK_InitByConstructor && NumArgs == 1 &&
+ Cand1.Function && Cand2.Function &&
+ isa<CXXConstructorDecl>(Cand1.Function) !=
+ isa<CXXConstructorDecl>(Cand2.Function))
+ return isa<CXXConstructorDecl>(Cand1.Function);
// -- F1 is a non-template function and F2 is a function template
// specialization, or, if not that,
@@ -8980,6 +9035,21 @@ bool clang::isBetterOverloadCandidate(Sema &S, const OverloadCandidate &Cand1,
// Inherited from sibling base classes: still ambiguous.
}
+ // Check C++17 tie-breakers for deduction guides.
+ {
+ auto *Guide1 = dyn_cast_or_null<CXXDeductionGuideDecl>(Cand1.Function);
+ auto *Guide2 = dyn_cast_or_null<CXXDeductionGuideDecl>(Cand2.Function);
+ if (Guide1 && Guide2) {
+ // -- F1 is generated from a deduction-guide and F2 is not
+ if (Guide1->isImplicit() != Guide2->isImplicit())
+ return Guide2->isImplicit();
+
+ // -- F1 is the copy deduction candidate(16.3.1.8) and F2 is not
+ if (Guide1->isCopyDeductionCandidate())
+ return true;
+ }
+ }
+
// Check for enable_if value-based overload resolution.
if (Cand1.Function && Cand2.Function) {
Comparison Cmp = compareEnableIfAttrs(S, Cand1.Function, Cand2.Function);
@@ -9079,8 +9149,7 @@ void Sema::diagnoseEquivalentInternalLinkageDeclarations(
/// \returns The result of overload resolution.
OverloadingResult
OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
- iterator &Best,
- bool UserDefinedConversion) {
+ iterator &Best) {
llvm::SmallVector<OverloadCandidate *, 16> Candidates;
std::transform(begin(), end(), std::back_inserter(Candidates),
[](OverloadCandidate &Cand) { return &Cand; });
@@ -9114,8 +9183,8 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
Best = end();
for (auto *Cand : Candidates)
if (Cand->Viable)
- if (Best == end() || isBetterOverloadCandidate(S, *Cand, *Best, Loc,
- UserDefinedConversion))
+ if (Best == end() ||
+ isBetterOverloadCandidate(S, *Cand, *Best, Loc, Kind))
Best = Cand;
// If we didn't find any viable functions, abort.
@@ -9127,10 +9196,8 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
// Make sure that this function is better than every other viable
// function. If not, we have an ambiguity.
for (auto *Cand : Candidates) {
- if (Cand->Viable &&
- Cand != Best &&
- !isBetterOverloadCandidate(S, *Best, *Cand, Loc,
- UserDefinedConversion)) {
+ if (Cand->Viable && Cand != Best &&
+ !isBetterOverloadCandidate(S, *Best, *Cand, Loc, Kind)) {
if (S.isEquivalentInternalLinkageDeclaration(Best->Function,
Cand->Function)) {
EquivalentCands.push_back(Cand->Function);
@@ -10222,9 +10289,12 @@ struct CompareOverloadCandidatesForDisplay {
Sema &S;
SourceLocation Loc;
size_t NumArgs;
+ OverloadCandidateSet::CandidateSetKind CSK;
- CompareOverloadCandidatesForDisplay(Sema &S, SourceLocation Loc, size_t nArgs)
- : S(S), NumArgs(nArgs) {}
+ CompareOverloadCandidatesForDisplay(
+ Sema &S, SourceLocation Loc, size_t NArgs,
+ OverloadCandidateSet::CandidateSetKind CSK)
+ : S(S), NumArgs(NArgs), CSK(CSK) {}
bool operator()(const OverloadCandidate *L,
const OverloadCandidate *R) {
@@ -10238,8 +10308,10 @@ struct CompareOverloadCandidatesForDisplay {
// TODO: introduce a tri-valued comparison for overload
// candidates. Would be more worthwhile if we had a sort
// that could exploit it.
- if (isBetterOverloadCandidate(S, *L, *R, SourceLocation())) return true;
- if (isBetterOverloadCandidate(S, *R, *L, SourceLocation())) return false;
+ if (isBetterOverloadCandidate(S, *L, *R, SourceLocation(), CSK))
+ return true;
+ if (isBetterOverloadCandidate(S, *R, *L, SourceLocation(), CSK))
+ return false;
} else if (R->Viable)
return false;
@@ -10446,8 +10518,8 @@ void OverloadCandidateSet::NoteCandidates(
}
}
- std::sort(Cands.begin(), Cands.end(),
- CompareOverloadCandidatesForDisplay(S, OpLoc, Args.size()));
+ std::stable_sort(Cands.begin(), Cands.end(),
+ CompareOverloadCandidatesForDisplay(S, OpLoc, Args.size(), Kind));
bool ReportedAmbiguousConversions = false;
@@ -10627,7 +10699,7 @@ static bool completeFunctionType(Sema &S, FunctionDecl *FD, SourceLocation Loc,
return true;
auto *FPT = FD->getType()->castAs<FunctionProtoType>();
- if (S.getLangOpts().CPlusPlus1z &&
+ if (S.getLangOpts().CPlusPlus17 &&
isUnresolvedExceptionSpec(FPT->getExceptionSpecType()) &&
!S.ResolveExceptionSpec(Loc, FPT))
return true;
@@ -11878,7 +11950,7 @@ static bool IsOverloaded(const UnresolvedSetImpl &Functions) {
ExprResult
Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
const UnresolvedSetImpl &Fns,
- Expr *Input) {
+ Expr *Input, bool PerformADL) {
OverloadedOperatorKind Op = UnaryOperator::getOverloadedOperator(Opc);
assert(Op != OO_None && "Invalid opcode for overloaded unary operator");
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
@@ -11929,9 +12001,11 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
AddMemberOperatorCandidates(Op, OpLoc, ArgsArray, CandidateSet);
// Add candidates from ADL.
- AddArgumentDependentLookupCandidates(OpName, OpLoc, ArgsArray,
- /*ExplicitTemplateArgs*/nullptr,
- CandidateSet);
+ if (PerformADL) {
+ AddArgumentDependentLookupCandidates(OpName, OpLoc, ArgsArray,
+ /*ExplicitTemplateArgs*/nullptr,
+ CandidateSet);
+ }
// Add builtin operator candidates.
AddBuiltinOperatorCandidates(Op, OpLoc, ArgsArray, CandidateSet);
@@ -12069,7 +12143,7 @@ ExprResult
Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
BinaryOperatorKind Opc,
const UnresolvedSetImpl &Fns,
- Expr *LHS, Expr *RHS) {
+ Expr *LHS, Expr *RHS, bool PerformADL) {
Expr *Args[2] = { LHS, RHS };
LHS=RHS=nullptr; // Please use only Args instead of LHS/RHS couple
@@ -12100,7 +12174,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
UnresolvedLookupExpr *Fn
= UnresolvedLookupExpr::Create(Context, NamingClass,
NestedNameSpecifierLoc(), OpNameInfo,
- /*ADL*/ true, IsOverloaded(Fns),
+ /*ADL*/PerformADL, IsOverloaded(Fns),
Fns.begin(), Fns.end());
return new (Context)
CXXOperatorCallExpr(Context, Op, Fn, Args, Context.DependentTy,
@@ -12143,7 +12217,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// Add candidates from ADL. Per [over.match.oper]p2, this lookup is not
// performed for an assignment operator (nor for operator[] nor operator->,
// which don't get here).
- if (Opc != BO_Assign)
+ if (Opc != BO_Assign && PerformADL)
AddArgumentDependentLookupCandidates(OpName, OpLoc, Args,
/*ExplicitTemplateArgs*/ nullptr,
CandidateSet);
@@ -12896,7 +12970,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
// Perform overload resolution.
OverloadCandidateSet::iterator Best;
switch (CandidateSet.BestViableFunction(*this, Object.get()->getLocStart(),
- Best)) {
+ Best)) {
case OR_Success:
// Overload resolution succeeded; we'll build the appropriate call
// below.
@@ -13290,7 +13364,7 @@ Sema::BuildForRangeBeginEndCall(SourceLocation Loc,
Expr *Range, ExprResult *CallExpr) {
Scope *S = nullptr;
- CandidateSet->clear();
+ CandidateSet->clear(OverloadCandidateSet::CSK_Normal);
if (!MemberLookup.empty()) {
ExprResult MemberRef =
BuildMemberReferenceExpr(Range, Range->getType(), Loc,
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp
index d159172a69908..58980be64a30f 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp
@@ -1442,8 +1442,7 @@ MSPropertyOpBuilder::getBaseMSProperty(MSPropertySubscriptExpr *E) {
Expr *MSPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
InstanceBase = capture(RefExpr->getBaseExpr());
- std::for_each(CallArgs.begin(), CallArgs.end(),
- [this](Expr *&Arg) { Arg = capture(Arg); });
+ llvm::for_each(CallArgs, [this](Expr *&Arg) { Arg = capture(Arg); });
syntacticBase = Rebuilder(S, [=](Expr *, unsigned Idx) -> Expr * {
switch (Idx) {
case 0:
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
index 2a38a1f8e1d87..ff0f4d9958512 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
@@ -127,34 +127,47 @@ void Sema::ActOnForEachDeclStmt(DeclGroupPtrTy dg) {
/// warning from firing.
static bool DiagnoseUnusedComparison(Sema &S, const Expr *E) {
SourceLocation Loc;
- bool IsNotEqual, CanAssign, IsRelational;
+ bool CanAssign;
+ enum { Equality, Inequality, Relational, ThreeWay } Kind;
if (const BinaryOperator *Op = dyn_cast<BinaryOperator>(E)) {
if (!Op->isComparisonOp())
return false;
- IsRelational = Op->isRelationalOp();
+ if (Op->getOpcode() == BO_EQ)
+ Kind = Equality;
+ else if (Op->getOpcode() == BO_NE)
+ Kind = Inequality;
+ else if (Op->getOpcode() == BO_Cmp)
+ Kind = ThreeWay;
+ else {
+ assert(Op->isRelationalOp());
+ Kind = Relational;
+ }
Loc = Op->getOperatorLoc();
- IsNotEqual = Op->getOpcode() == BO_NE;
CanAssign = Op->getLHS()->IgnoreParenImpCasts()->isLValue();
} else if (const CXXOperatorCallExpr *Op = dyn_cast<CXXOperatorCallExpr>(E)) {
switch (Op->getOperator()) {
- default:
- return false;
case OO_EqualEqual:
+ Kind = Equality;
+ break;
case OO_ExclaimEqual:
- IsRelational = false;
+ Kind = Inequality;
break;
case OO_Less:
case OO_Greater:
case OO_GreaterEqual:
case OO_LessEqual:
- IsRelational = true;
+ Kind = Relational;
+ break;
+ case OO_Spaceship:
+ Kind = ThreeWay;
break;
+ default:
+ return false;
}
Loc = Op->getOperatorLoc();
- IsNotEqual = Op->getOperator() == OO_ExclaimEqual;
CanAssign = Op->getArg(0)->IgnoreParenImpCasts()->isLValue();
} else {
// Not a typo-prone comparison.
@@ -167,15 +180,15 @@ static bool DiagnoseUnusedComparison(Sema &S, const Expr *E) {
return false;
S.Diag(Loc, diag::warn_unused_comparison)
- << (unsigned)IsRelational << (unsigned)IsNotEqual << E->getSourceRange();
+ << (unsigned)Kind << E->getSourceRange();
// If the LHS is a plausible entity to assign to, provide a fixit hint to
// correct common typos.
- if (!IsRelational && CanAssign) {
- if (IsNotEqual)
+ if (CanAssign) {
+ if (Kind == Inequality)
S.Diag(Loc, diag::note_inequality_comparison_to_or_assign)
<< FixItHint::CreateReplacement(Loc, "|=");
- else
+ else if (Kind == Equality)
S.Diag(Loc, diag::note_equality_comparison_to_assign)
<< FixItHint::CreateReplacement(Loc, "=");
}
@@ -602,14 +615,14 @@ static bool EqEnumVals(const std::pair<llvm::APSInt, EnumConstantDecl*>& lhs,
/// GetTypeBeforeIntegralPromotion - Returns the pre-promotion type of
/// potentially integral-promoted expression @p expr.
-static QualType GetTypeBeforeIntegralPromotion(Expr *&expr) {
- if (ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(expr))
- expr = cleanups->getSubExpr();
- while (ImplicitCastExpr *impcast = dyn_cast<ImplicitCastExpr>(expr)) {
- if (impcast->getCastKind() != CK_IntegralCast) break;
- expr = impcast->getSubExpr();
+static QualType GetTypeBeforeIntegralPromotion(const Expr *&E) {
+ if (const auto *CleanUps = dyn_cast<ExprWithCleanups>(E))
+ E = CleanUps->getSubExpr();
+ while (const auto *ImpCast = dyn_cast<ImplicitCastExpr>(E)) {
+ if (ImpCast->getCastKind() != CK_IntegralCast) break;
+ E = ImpCast->getSubExpr();
}
- return expr->getType();
+ return E->getType();
}
ExprResult Sema::CheckSwitchCondition(SourceLocation SwitchLoc, Expr *Cond) {
@@ -743,6 +756,32 @@ static bool ShouldDiagnoseSwitchCaseNotInEnum(const Sema &S,
return true;
}
+static void checkEnumTypesInSwitchStmt(Sema &S, const Expr *Cond,
+ const Expr *Case) {
+ QualType CondType = GetTypeBeforeIntegralPromotion(Cond);
+ QualType CaseType = Case->getType();
+
+ const EnumType *CondEnumType = CondType->getAs<EnumType>();
+ const EnumType *CaseEnumType = CaseType->getAs<EnumType>();
+ if (!CondEnumType || !CaseEnumType)
+ return;
+
+ // Ignore anonymous enums.
+ if (!CondEnumType->getDecl()->getIdentifier() &&
+ !CondEnumType->getDecl()->getTypedefNameForAnonDecl())
+ return;
+ if (!CaseEnumType->getDecl()->getIdentifier() &&
+ !CaseEnumType->getDecl()->getTypedefNameForAnonDecl())
+ return;
+
+ if (S.Context.hasSameUnqualifiedType(CondType, CaseType))
+ return;
+
+ S.Diag(Case->getExprLoc(), diag::warn_comparison_of_mixed_enum_types_switch)
+ << CondType << CaseType << Cond->getSourceRange()
+ << Case->getSourceRange();
+}
+
StmtResult
Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
Stmt *BodyStmt) {
@@ -760,7 +799,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
QualType CondType = CondExpr->getType();
- Expr *CondExprBeforePromotion = CondExpr;
+ const Expr *CondExprBeforePromotion = CondExpr;
QualType CondTypeBeforePromotion =
GetTypeBeforeIntegralPromotion(CondExprBeforePromotion);
@@ -843,6 +882,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
break;
}
+ checkEnumTypesInSwitchStmt(*this, CondExpr, Lo);
+
llvm::APSInt LoVal;
if (getLangOpts().CPlusPlus11) {
@@ -2452,7 +2493,7 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc,
// C++1z removes this restriction.
QualType BeginType = BeginVar->getType(), EndType = EndVar->getType();
if (!Context.hasSameType(BeginType, EndType)) {
- Diag(RangeLoc, getLangOpts().CPlusPlus1z
+ Diag(RangeLoc, getLangOpts().CPlusPlus17
? diag::warn_for_range_begin_end_types_differ
: diag::ext_for_range_begin_end_types_differ)
<< BeginType << EndType;
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp
index c182b35bfad4c..fc1cc7bbe544b 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp
@@ -48,10 +48,10 @@ static bool CheckAsmLValue(const Expr *E, Sema &S) {
if (E != E2 && E2->isLValue()) {
if (!S.getLangOpts().HeinousExtensions)
S.Diag(E2->getLocStart(), diag::err_invalid_asm_cast_lvalue)
- << E->getSourceRange();
+ << E->getSourceRange();
else
S.Diag(E2->getLocStart(), diag::warn_invalid_asm_cast_lvalue)
- << E->getSourceRange();
+ << E->getSourceRange();
// Accept, even if we emitted an error diagnostic.
return false;
}
@@ -62,11 +62,13 @@ static bool CheckAsmLValue(const Expr *E, Sema &S) {
/// isOperandMentioned - Return true if the specified operand # is mentioned
/// anywhere in the decomposed asm string.
-static bool isOperandMentioned(unsigned OpNo,
- ArrayRef<GCCAsmStmt::AsmStringPiece> AsmStrPieces) {
+static bool
+isOperandMentioned(unsigned OpNo,
+ ArrayRef<GCCAsmStmt::AsmStringPiece> AsmStrPieces) {
for (unsigned p = 0, e = AsmStrPieces.size(); p != e; ++p) {
const GCCAsmStmt::AsmStringPiece &Piece = AsmStrPieces[p];
- if (!Piece.isOperand()) continue;
+ if (!Piece.isOperand())
+ continue;
// If this is a reference to the input and if the input was the smaller
// one, then we have to reject this asm.
@@ -605,23 +607,31 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
return NS;
}
-static void fillInlineAsmTypeInfo(const ASTContext &Context, QualType T,
- llvm::InlineAsmIdentifierInfo &Info) {
- // Compute the type size (and array length if applicable?).
- Info.Type = Info.Size = Context.getTypeSizeInChars(T).getQuantity();
- if (T->isArrayType()) {
- const ArrayType *ATy = Context.getAsArrayType(T);
- Info.Type = Context.getTypeSizeInChars(ATy->getElementType()).getQuantity();
- Info.Length = Info.Size / Info.Type;
+void Sema::FillInlineAsmIdentifierInfo(Expr *Res,
+ llvm::InlineAsmIdentifierInfo &Info) {
+ QualType T = Res->getType();
+ Expr::EvalResult Eval;
+ if (T->isFunctionType() || T->isDependentType())
+ return Info.setLabel(Res);
+ if (Res->isRValue()) {
+ if (isa<clang::EnumType>(T) && Res->EvaluateAsRValue(Eval, Context))
+ return Info.setEnum(Eval.Val.getInt().getSExtValue());
+ return Info.setLabel(Res);
}
+ unsigned Size = Context.getTypeSizeInChars(T).getQuantity();
+ unsigned Type = Size;
+ if (const auto *ATy = Context.getAsArrayType(T))
+ Type = Context.getTypeSizeInChars(ATy->getElementType()).getQuantity();
+ bool IsGlobalLV = false;
+ if (Res->EvaluateAsLValue(Eval, Context))
+ IsGlobalLV = Eval.isGlobalLValue();
+ Info.setVar(Res, IsGlobalLV, Size, Type);
}
ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
UnqualifiedId &Id,
- llvm::InlineAsmIdentifierInfo &Info,
bool IsUnevaluatedContext) {
- Info.clear();
if (IsUnevaluatedContext)
PushExpressionEvaluationContext(
@@ -662,12 +672,6 @@ ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS,
return ExprError();
}
- fillInlineAsmTypeInfo(Context, T, Info);
-
- // We can work with the expression as long as it's not an r-value.
- if (!Result.get()->isRValue())
- Info.IsVarDecl = true;
-
return Result;
}
@@ -677,22 +681,33 @@ bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member,
SmallVector<StringRef, 2> Members;
Member.split(Members, ".");
- LookupResult BaseResult(*this, &Context.Idents.get(Base), SourceLocation(),
- LookupOrdinaryName);
+ NamedDecl *FoundDecl = nullptr;
- if (!LookupName(BaseResult, getCurScope()))
- return true;
-
- if(!BaseResult.isSingleResult())
+ // MS InlineAsm uses 'this' as a base
+ if (getLangOpts().CPlusPlus && Base.equals("this")) {
+ if (const Type *PT = getCurrentThisType().getTypePtrOrNull())
+ FoundDecl = PT->getPointeeType()->getAsTagDecl();
+ } else {
+ LookupResult BaseResult(*this, &Context.Idents.get(Base), SourceLocation(),
+ LookupOrdinaryName);
+ if (LookupName(BaseResult, getCurScope()) && BaseResult.isSingleResult())
+ FoundDecl = BaseResult.getFoundDecl();
+ }
+
+ if (!FoundDecl)
return true;
- NamedDecl *FoundDecl = BaseResult.getFoundDecl();
+
for (StringRef NextMember : Members) {
const RecordType *RT = nullptr;
if (VarDecl *VD = dyn_cast<VarDecl>(FoundDecl))
RT = VD->getType()->getAs<RecordType>();
else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(FoundDecl)) {
MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false);
- RT = TD->getUnderlyingType()->getAs<RecordType>();
+ // MS InlineAsm often uses struct pointer aliases as a base
+ QualType QT = TD->getUnderlyingType();
+ if (const auto *PT = QT->getAs<PointerType>())
+ QT = PT->getPointeeType();
+ RT = QT->getAs<RecordType>();
} else if (TypeDecl *TD = dyn_cast<TypeDecl>(FoundDecl))
RT = TD->getTypeForDecl()->getAs<RecordType>();
else if (FieldDecl *TD = dyn_cast<FieldDecl>(FoundDecl))
@@ -730,9 +745,7 @@ bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member,
ExprResult
Sema::LookupInlineAsmVarDeclField(Expr *E, StringRef Member,
- llvm::InlineAsmIdentifierInfo &Info,
SourceLocation AsmLoc) {
- Info.clear();
QualType T = E->getType();
if (T->isDependentType()) {
@@ -767,14 +780,6 @@ Sema::LookupInlineAsmVarDeclField(Expr *E, StringRef Member,
ExprResult Result = BuildMemberReferenceExpr(
E, E->getType(), AsmLoc, /*IsArrow=*/false, CXXScopeSpec(),
SourceLocation(), nullptr, FieldResult, nullptr, nullptr);
- if (Result.isInvalid())
- return Result;
- Info.OpDecl = Result.get();
-
- fillInlineAsmTypeInfo(Context, Result.get()->getType(), Info);
-
- // Fields are "variables" as far as inline assembly is concerned.
- Info.IsVarDecl = true;
return Result;
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp
index 4ee3412170a85..e55e20c2827f0 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp
@@ -43,11 +43,11 @@ static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const AttributeList &A,
return nullptr;
}
- // If this is spelled as the standard C++1z attribute, but not in C++1z, warn
+ // If this is spelled as the standard C++17 attribute, but not in C++17, warn
// about using it as an extension.
- if (!S.getLangOpts().CPlusPlus1z && A.isCXX11Attribute() &&
+ if (!S.getLangOpts().CPlusPlus17 && A.isCXX11Attribute() &&
!A.getScopeName())
- S.Diag(A.getLoc(), diag::ext_cxx1z_attr) << A.getName();
+ S.Diag(A.getLoc(), diag::ext_cxx17_attr) << A.getName();
FnScope->setHasFallthroughStmt();
return ::new (S.Context) auto(Attr);
@@ -100,16 +100,15 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
return nullptr;
}
- LoopHintAttr::Spelling Spelling;
+ LoopHintAttr::Spelling Spelling =
+ LoopHintAttr::Spelling(A.getAttributeSpellingListIndex());
LoopHintAttr::OptionType Option;
LoopHintAttr::LoopHintState State;
if (PragmaNoUnroll) {
// #pragma nounroll
- Spelling = LoopHintAttr::Pragma_nounroll;
Option = LoopHintAttr::Unroll;
State = LoopHintAttr::Disable;
} else if (PragmaUnroll) {
- Spelling = LoopHintAttr::Pragma_unroll;
if (ValueExpr) {
// #pragma unroll N
Option = LoopHintAttr::UnrollCount;
@@ -121,7 +120,6 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
}
} else {
// #pragma clang loop ...
- Spelling = LoopHintAttr::Pragma_clang_loop;
assert(OptionLoc && OptionLoc->Ident &&
"Attribute must have valid option info.");
Option = llvm::StringSwitch<LoopHintAttr::OptionType>(
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
index e9b38551683cf..c70a8ba8f1269 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
@@ -778,7 +778,7 @@ static void maybeDiagnoseTemplateParameterShadow(Sema &SemaRef, Scope *S,
SourceLocation Loc,
IdentifierInfo *Name) {
NamedDecl *PrevDecl = SemaRef.LookupSingleName(
- S, Name, Loc, Sema::LookupOrdinaryName, Sema::ForRedeclaration);
+ S, Name, Loc, Sema::LookupOrdinaryName, Sema::ForVisibleRedeclaration);
if (PrevDecl && PrevDecl->isTemplateParameter())
SemaRef.DiagnoseTemplateParameterShadow(Loc, PrevDecl);
}
@@ -1080,7 +1080,7 @@ Sema::ActOnTemplateParameterList(unsigned Depth,
SourceLocation ExportLoc,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
- ArrayRef<Decl *> Params,
+ ArrayRef<NamedDecl *> Params,
SourceLocation RAngleLoc,
Expr *RequiresClause) {
if (ExportLoc.isValid())
@@ -1088,7 +1088,7 @@ Sema::ActOnTemplateParameterList(unsigned Depth,
return TemplateParameterList::Create(
Context, TemplateLoc, LAngleLoc,
- llvm::makeArrayRef((NamedDecl *const *)Params.data(), Params.size()),
+ llvm::makeArrayRef(Params.data(), Params.size()),
RAngleLoc, RequiresClause);
}
@@ -1133,7 +1133,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
LookupResult Previous(*this, Name, NameLoc,
(SS.isEmpty() && TUK == TUK_Friend)
? LookupTagName : LookupOrdinaryName,
- ForRedeclaration);
+ forRedeclarationInCurContext());
if (SS.isNotEmpty() && !SS.isInvalid()) {
SemanticContext = computeDeclContext(SS, true);
if (!SemanticContext) {
@@ -1192,8 +1192,8 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
// If there is a previous declaration with the same name, check
// whether this is a valid redeclaration.
- ClassTemplateDecl *PrevClassTemplate
- = dyn_cast_or_null<ClassTemplateDecl>(PrevDecl);
+ ClassTemplateDecl *PrevClassTemplate =
+ dyn_cast_or_null<ClassTemplateDecl>(PrevDecl);
// We may have found the injected-class-name of a class template,
// class template partial specialization, or class template specialization.
@@ -1484,6 +1484,9 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
CurContext->addDecl(Friend);
}
+ if (PrevClassTemplate)
+ CheckRedeclarationModuleOwnership(NewTemplate, PrevClassTemplate);
+
if (Invalid) {
NewTemplate->setInvalidDecl();
NewClass->setInvalidDecl();
@@ -1834,7 +1837,6 @@ void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template,
// for which some class template parameter without a default argument never
// appears in a deduced context).
bool AddedAny = false;
- bool AddedCopyOrMove = false;
for (NamedDecl *D : LookupConstructors(Transform.Primary)) {
D = D->getUnderlyingDecl();
if (D->isInvalidDecl() || D->isImplicit())
@@ -1851,20 +1853,22 @@ void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template,
Transform.transformConstructor(FTD, CD);
AddedAny = true;
-
- AddedCopyOrMove |= CD->isCopyOrMoveConstructor();
}
- // Synthesize an X() -> X<...> guide if there were no declared constructors.
- // FIXME: The standard doesn't say (how) to do this.
+ // C++17 [over.match.class.deduct]
+ // -- If C is not defined or does not declare any constructors, an
+ // additional function template derived as above from a hypothetical
+ // constructor C().
if (!AddedAny)
Transform.buildSimpleDeductionGuide(None);
- // Synthesize an X(X<...>) -> X<...> guide if there was no declared constructor
- // resembling a copy or move constructor.
- // FIXME: The standard doesn't say (how) to do this.
- if (!AddedCopyOrMove)
- Transform.buildSimpleDeductionGuide(Transform.DeducedType);
+ // -- An additional function template derived as above from a hypothetical
+ // constructor C(C), called the copy deduction candidate.
+ cast<CXXDeductionGuideDecl>(
+ cast<FunctionTemplateDecl>(
+ Transform.buildSimpleDeductionGuide(Transform.DeducedType))
+ ->getTemplatedDecl())
+ ->setIsCopyDeductionCandidate();
}
/// \brief Diagnose the presence of a default template argument on a
@@ -2863,11 +2867,9 @@ static Expr *lookThroughRangesV3Condition(Preprocessor &PP, Expr *Cond) {
return Cond;
}
-/// Find the failed subexpression within enable_if, and describe it
-/// with a string.
-static std::pair<Expr *, std::string>
-findFailedEnableIfCondition(Sema &S, Expr *Cond) {
- Cond = lookThroughRangesV3Condition(S.PP, Cond);
+std::pair<Expr *, std::string>
+Sema::findFailedBooleanCondition(Expr *Cond, bool AllowTopLevelCond) {
+ Cond = lookThroughRangesV3Condition(PP, Cond);
// Separate out all of the terms in a conjunction.
SmallVector<Expr *, 4> Terms;
@@ -2876,27 +2878,37 @@ findFailedEnableIfCondition(Sema &S, Expr *Cond) {
// Determine which term failed.
Expr *FailedCond = nullptr;
for (Expr *Term : Terms) {
+ Expr *TermAsWritten = Term->IgnoreParenImpCasts();
+
+ // Literals are uninteresting.
+ if (isa<CXXBoolLiteralExpr>(TermAsWritten) ||
+ isa<IntegerLiteral>(TermAsWritten))
+ continue;
+
// The initialization of the parameter from the argument is
// a constant-evaluated context.
EnterExpressionEvaluationContext ConstantEvaluated(
- S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
+ *this, Sema::ExpressionEvaluationContext::ConstantEvaluated);
bool Succeeded;
- if (Term->EvaluateAsBooleanCondition(Succeeded, S.Context) &&
+ if (Term->EvaluateAsBooleanCondition(Succeeded, Context) &&
!Succeeded) {
- FailedCond = Term->IgnoreParenImpCasts();
+ FailedCond = TermAsWritten;
break;
}
}
- if (!FailedCond)
+ if (!FailedCond) {
+ if (!AllowTopLevelCond)
+ return { nullptr, "" };
+
FailedCond = Cond->IgnoreParenImpCasts();
+ }
std::string Description;
{
llvm::raw_string_ostream Out(Description);
- FailedCond->printPretty(Out, nullptr,
- PrintingPolicy(S.Context.getLangOpts()));
+ FailedCond->printPretty(Out, nullptr, getPrintingPolicy());
}
return { FailedCond, Description };
}
@@ -2980,8 +2992,9 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
Expr *FailedCond;
std::string FailedDescription;
std::tie(FailedCond, FailedDescription) =
- findFailedEnableIfCondition(
- *this, TemplateArgs[0].getSourceExpression());
+ findFailedBooleanCondition(
+ TemplateArgs[0].getSourceExpression(),
+ /*AllowTopLevelCond=*/true);
// Remove the old SFINAE diagnostic.
PartialDiagnosticAt OldDiag =
@@ -3668,7 +3681,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
// Check that this isn't a redefinition of this specialization,
// merging with previous declarations.
LookupResult PrevSpec(*this, GetNameForDeclarator(D), LookupOrdinaryName,
- ForRedeclaration);
+ forRedeclarationInCurContext());
PrevSpec.addDecl(PrevDecl);
D.setRedeclaration(CheckVariableDeclaration(Specialization, PrevSpec));
} else if (Specialization->isStaticDataMember() &&
@@ -4792,7 +4805,12 @@ bool Sema::CheckTemplateArgumentList(
// template.
TemplateArgumentListInfo NewArgs = TemplateArgs;
- TemplateParameterList *Params = Template->getTemplateParameters();
+ // Make sure we get the template parameter list from the most
+ // recentdeclaration, since that is the only one that has is guaranteed to
+ // have all the default template argument information.
+ TemplateParameterList *Params =
+ cast<TemplateDecl>(Template->getMostRecentDecl())
+ ->getTemplateParameters();
SourceLocation RAngleLoc = NewArgs.getRAngleLoc();
@@ -5116,6 +5134,11 @@ bool UnnamedLocalNoLinkageFinder::VisitDependentSizedExtVectorType(
return Visit(T->getElementType());
}
+bool UnnamedLocalNoLinkageFinder::VisitDependentAddressSpaceType(
+ const DependentAddressSpaceType *T) {
+ return Visit(T->getPointeeType());
+}
+
bool UnnamedLocalNoLinkageFinder::VisitVectorType(const VectorType* T) {
return Visit(T->getElementType());
}
@@ -5900,7 +5923,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
SourceLocation StartLoc = Arg->getLocStart();
// If the parameter type somehow involves auto, deduce the type now.
- if (getLangOpts().CPlusPlus1z && ParamType->isUndeducedType()) {
+ if (getLangOpts().CPlusPlus17 && ParamType->isUndeducedType()) {
// During template argument deduction, we allow 'decltype(auto)' to
// match an arbitrary dependent argument.
// FIXME: The language rules don't say what happens in this case.
@@ -5984,8 +6007,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
EnterExpressionEvaluationContext ConstantEvaluated(
*this, Sema::ExpressionEvaluationContext::ConstantEvaluated);
- if (getLangOpts().CPlusPlus1z) {
- // C++1z [temp.arg.nontype]p1:
+ if (getLangOpts().CPlusPlus17) {
+ // C++17 [temp.arg.nontype]p1:
// A template-argument for a non-type template parameter shall be
// a converted constant expression of the type of the template-parameter.
APValue Value;
@@ -6152,7 +6175,6 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// -- an integral constant-expression of integral or enumeration
// type; or
// -- the name of a non-type template-parameter; or
- SourceLocation NonConstantLoc;
llvm::APSInt Value;
if (!ArgType->isIntegralOrEnumerationType()) {
Diag(Arg->getLocStart(),
@@ -8015,15 +8037,6 @@ bool Sema::CheckFunctionTemplateSpecialization(
// Ignore access information; it doesn't figure into redeclaration checking.
FunctionDecl *Specialization = cast<FunctionDecl>(*Result);
- // C++ Concepts TS [dcl.spec.concept]p7: A program shall not declare [...]
- // an explicit specialization (14.8.3) [...] of a concept definition.
- if (Specialization->getPrimaryTemplate()->isConcept()) {
- Diag(FD->getLocation(), diag::err_concept_specialized)
- << 0 /*function*/ << 1 /*explicitly specialized*/;
- Diag(Specialization->getLocation(), diag::note_previous_declaration);
- return true;
- }
-
FunctionTemplateSpecializationInfo *SpecInfo
= Specialization->getTemplateSpecializationInfo();
assert(SpecInfo && "Function template specialization info missing?");
@@ -8910,15 +8923,6 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
Diag(D.getDeclSpec().getConstexprSpecLoc(),
diag::err_explicit_instantiation_constexpr);
- // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be
- // applied only to the definition of a function template or variable template,
- // declared in namespace scope.
- if (D.getDeclSpec().isConceptSpecified()) {
- Diag(D.getDeclSpec().getConceptSpecLoc(),
- diag::err_concept_specified_specialization) << 0;
- return true;
- }
-
// A deduction guide is not on the list of entities that can be explicitly
// instantiated.
if (Name.getNameKind() == DeclarationName::CXXDeductionGuideName) {
@@ -8998,15 +9002,6 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
return true;
}
- // C++ Concepts TS [dcl.spec.concept]p7: A program shall not declare an
- // explicit instantiation (14.8.2) [...] of a concept definition.
- if (PrevTemplate->isConcept()) {
- Diag(D.getIdentifierLoc(), diag::err_concept_specialized)
- << 1 /*variable*/ << 0 /*explicitly instantiated*/;
- Diag(PrevTemplate->getLocation(), diag::note_previous_declaration);
- return true;
- }
-
// Translate the parser's template argument list into our AST format.
TemplateArgumentListInfo TemplateArgs =
makeTemplateArgumentListInfo(*this, *D.getName().TemplateId);
@@ -9049,7 +9044,6 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
if (!HasNoEffect) {
// Instantiate static data member or variable template.
-
Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
if (PrevTemplate) {
// Merge attributes.
@@ -9217,10 +9211,18 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
return (Decl*) nullptr;
}
- Specialization->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
if (Attr)
ProcessDeclAttributeList(S, Specialization, Attr);
+ // In MSVC mode, dllimported explicit instantiation definitions are treated as
+ // instantiation declarations.
+ if (TSK == TSK_ExplicitInstantiationDefinition &&
+ Specialization->hasAttr<DLLImportAttr>() &&
+ Context.getTargetInfo().getCXXABI().isMicrosoft())
+ TSK = TSK_ExplicitInstantiationDeclaration;
+
+ Specialization->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
+
if (Specialization->isDefined()) {
// Let the ASTConsumer know that this function has been explicitly
// instantiated now, and its linkage might have changed.
@@ -9243,16 +9245,6 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
diag::ext_explicit_instantiation_without_qualified_id)
<< Specialization << D.getCXXScopeSpec().getRange();
- // C++ Concepts TS [dcl.spec.concept]p7: A program shall not declare an
- // explicit instantiation (14.8.2) [...] of a concept definition.
- if (FunTmpl && FunTmpl->isConcept() &&
- !D.getDeclSpec().isConceptSpecified()) {
- Diag(D.getIdentifierLoc(), diag::err_concept_specialized)
- << 0 /*function*/ << 0 /*explicitly instantiated*/;
- Diag(FunTmpl->getLocation(), diag::note_previous_declaration);
- return true;
- }
-
CheckExplicitInstantiationScope(*this,
FunTmpl? (NamedDecl *)FunTmpl
: Specialization->getInstantiatedFromMemberFunction(),
@@ -9513,7 +9505,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
Expr *FailedCond;
std::string FailedDescription;
std::tie(FailedCond, FailedDescription) =
- findFailedEnableIfCondition(*this, Cond);
+ findFailedBooleanCondition(Cond, /*AllowTopLevelCond=*/true);
Diag(FailedCond->getExprLoc(),
diag::err_typename_nested_not_found_requirement)
@@ -9591,7 +9583,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
// A type-specifier of the form
// typename[opt] nested-name-specifier[opt] template-name
// is a placeholder for a deduced class type [...].
- if (getLangOpts().CPlusPlus1z) {
+ if (getLangOpts().CPlusPlus17) {
if (auto *TD = getAsTypeTemplateDecl(Result.getFoundDecl())) {
return Context.getElaboratedType(
Keyword, QualifierLoc.getNestedNameSpecifier(),
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
index 983b1ea795dda..564692b030200 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -344,7 +344,7 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
}
Deduced[NTTP->getIndex()] = Result;
- if (!S.getLangOpts().CPlusPlus1z)
+ if (!S.getLangOpts().CPlusPlus17)
return Sema::TDK_Success;
if (NTTP->isExpandedParameterPack())
@@ -354,8 +354,9 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
// expanded NTTP should be a pack expansion type?
return Sema::TDK_Success;
- // Get the type of the parameter for deduction.
- QualType ParamType = NTTP->getType();
+ // Get the type of the parameter for deduction. If it's a (dependent) array
+ // or function type, we will not have decayed it yet, so do that now.
+ QualType ParamType = S.Context.getAdjustedParameterType(NTTP->getType());
if (auto *Expansion = dyn_cast<PackExpansionType>(ParamType))
ParamType = Expansion->getPattern();
@@ -1843,6 +1844,59 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
return Sema::TDK_NonDeducedMismatch;
}
+ // (clang extension)
+ //
+ // T __attribute__(((address_space(N))))
+ case Type::DependentAddressSpace: {
+ const DependentAddressSpaceType *AddressSpaceParam =
+ cast<DependentAddressSpaceType>(Param);
+
+ if (const DependentAddressSpaceType *AddressSpaceArg =
+ dyn_cast<DependentAddressSpaceType>(Arg)) {
+ // Perform deduction on the pointer type.
+ if (Sema::TemplateDeductionResult Result =
+ DeduceTemplateArgumentsByTypeMatch(
+ S, TemplateParams, AddressSpaceParam->getPointeeType(),
+ AddressSpaceArg->getPointeeType(), Info, Deduced, TDF))
+ return Result;
+
+ // Perform deduction on the address space, if we can.
+ NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(
+ Info, AddressSpaceParam->getAddrSpaceExpr());
+ if (!NTTP)
+ return Sema::TDK_Success;
+
+ return DeduceNonTypeTemplateArgument(
+ S, TemplateParams, NTTP, AddressSpaceArg->getAddrSpaceExpr(), Info,
+ Deduced);
+ }
+
+ if (isTargetAddressSpace(Arg.getAddressSpace())) {
+ llvm::APSInt ArgAddressSpace(S.Context.getTypeSize(S.Context.IntTy),
+ false);
+ ArgAddressSpace = toTargetAddressSpace(Arg.getAddressSpace());
+
+ // Perform deduction on the pointer types.
+ if (Sema::TemplateDeductionResult Result =
+ DeduceTemplateArgumentsByTypeMatch(
+ S, TemplateParams, AddressSpaceParam->getPointeeType(),
+ S.Context.removeAddrSpaceQualType(Arg), Info, Deduced, TDF))
+ return Result;
+
+ // Perform deduction on the address space, if we can.
+ NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(
+ Info, AddressSpaceParam->getAddrSpaceExpr());
+ if (!NTTP)
+ return Sema::TDK_Success;
+
+ return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
+ ArgAddressSpace, S.Context.IntTy,
+ true, Info, Deduced);
+ }
+
+ return Sema::TDK_NonDeducedMismatch;
+ }
+
case Type::TypeOfExpr:
case Type::TypeOf:
case Type::DependentName:
@@ -2695,6 +2749,17 @@ static bool isSimpleTemplateIdType(QualType T) {
= T->getAs<TemplateSpecializationType>())
return Spec->getTemplateName().getAsTemplateDecl() != nullptr;
+ // C++17 [temp.local]p2:
+ // the injected-class-name [...] is equivalent to the template-name followed
+ // by the template-arguments of the class template specialization or partial
+ // specialization enclosed in <>
+ // ... which means it's equivalent to a simple-template-id.
+ //
+ // This only arises during class template argument deduction for a copy
+ // deduction candidate, where it permits slicing.
+ if (T->getAs<InjectedClassNameType>())
+ return true;
+
return false;
}
@@ -2869,7 +2934,7 @@ Sema::SubstituteExplicitTemplateArguments(
// so substitution into the type must also substitute into the exception
// specification.
SmallVector<QualType, 4> ExceptionStorage;
- if (getLangOpts().CPlusPlus1z &&
+ if (getLangOpts().CPlusPlus17 &&
SubstExceptionSpec(
Function->getLocation(), EPI.ExceptionSpec, ExceptionStorage,
MultiLevelTemplateArgumentList(*ExplicitArgumentList)))
@@ -2907,17 +2972,26 @@ Sema::SubstituteExplicitTemplateArguments(
/// \brief Check whether the deduced argument type for a call to a function
/// template matches the actual argument type per C++ [temp.deduct.call]p4.
-static bool
-CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg,
+static Sema::TemplateDeductionResult
+CheckOriginalCallArgDeduction(Sema &S, TemplateDeductionInfo &Info,
+ Sema::OriginalCallArg OriginalArg,
QualType DeducedA) {
ASTContext &Context = S.Context;
+ auto Failed = [&]() -> Sema::TemplateDeductionResult {
+ Info.FirstArg = TemplateArgument(DeducedA);
+ Info.SecondArg = TemplateArgument(OriginalArg.OriginalArgType);
+ Info.CallArgIndex = OriginalArg.ArgIdx;
+ return OriginalArg.DecomposedParam ? Sema::TDK_DeducedMismatchNested
+ : Sema::TDK_DeducedMismatch;
+ };
+
QualType A = OriginalArg.OriginalArgType;
QualType OriginalParamType = OriginalArg.OriginalParamType;
// Check for type equality (top-level cv-qualifiers are ignored).
if (Context.hasSameUnqualifiedType(A, DeducedA))
- return false;
+ return Sema::TDK_Success;
// Strip off references on the argument types; they aren't needed for
// the following checks.
@@ -2941,7 +3015,7 @@ CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg,
// the deduced A can be F.
QualType Tmp;
if (A->isFunctionType() && S.IsFunctionConversion(A, DeducedA, Tmp))
- return false;
+ return Sema::TDK_Success;
Qualifiers AQuals = A.getQualifiers();
Qualifiers DeducedAQuals = DeducedA.getQualifiers();
@@ -2961,7 +3035,7 @@ CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg,
if (AQuals == DeducedAQuals) {
// Qualifiers match; there's nothing to do.
} else if (!DeducedAQuals.compatiblyIncludes(AQuals)) {
- return true;
+ return Failed();
} else {
// Qualifiers are compatible, so have the argument type adopt the
// deduced argument type's qualifiers as if we had performed the
@@ -2982,7 +3056,7 @@ CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg,
(S.IsQualificationConversion(A, DeducedA, false,
ObjCLifetimeConversion) ||
S.IsFunctionConversion(A, DeducedA, ResultTy)))
- return false;
+ return Sema::TDK_Success;
// - If P is a class and P has the form simple-template-id, then the
// transformed A can be a derived class of the deduced A. [...]
@@ -3003,13 +3077,13 @@ CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg,
}
if (Context.hasSameUnqualifiedType(A, DeducedA))
- return false;
+ return Sema::TDK_Success;
if (A->isRecordType() && isSimpleTemplateIdType(OriginalParamType) &&
S.IsDerivedFrom(SourceLocation(), A, DeducedA))
- return false;
+ return Sema::TDK_Success;
- return true;
+ return Failed();
}
/// Find the pack index for a particular parameter index in an instantiation of
@@ -3165,13 +3239,9 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
DeducedA = CacheEntry;
}
- if (CheckOriginalCallArgDeduction(*this, OriginalArg, DeducedA)) {
- Info.FirstArg = TemplateArgument(DeducedA);
- Info.SecondArg = TemplateArgument(OriginalArg.OriginalArgType);
- Info.CallArgIndex = OriginalArg.ArgIdx;
- return OriginalArg.DecomposedParam ? TDK_DeducedMismatchNested
- : TDK_DeducedMismatch;
- }
+ if (auto TDK =
+ CheckOriginalCallArgDeduction(*this, Info, OriginalArg, DeducedA))
+ return TDK;
}
}
@@ -3838,7 +3908,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
// so we can check that the exception specification matches.
auto *SpecializationFPT =
Specialization->getType()->castAs<FunctionProtoType>();
- if (getLangOpts().CPlusPlus1z &&
+ if (getLangOpts().CPlusPlus17 &&
isUnresolvedExceptionSpec(SpecializationFPT->getExceptionSpecType()) &&
!ResolveExceptionSpec(Info.getLocation(), SpecializationFPT))
return TDK_MiscellaneousDeductionFailure;
@@ -4231,6 +4301,31 @@ Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *&Init, QualType &Result,
DependentDeductionDepth);
}
+/// Attempt to produce an informative diagostic explaining why auto deduction
+/// failed.
+/// \return \c true if diagnosed, \c false if not.
+static bool diagnoseAutoDeductionFailure(Sema &S,
+ Sema::TemplateDeductionResult TDK,
+ TemplateDeductionInfo &Info,
+ ArrayRef<SourceRange> Ranges) {
+ switch (TDK) {
+ case Sema::TDK_Inconsistent: {
+ // Inconsistent deduction means we were deducing from an initializer list.
+ auto D = S.Diag(Info.getLocation(), diag::err_auto_inconsistent_deduction);
+ D << Info.FirstArg << Info.SecondArg;
+ for (auto R : Ranges)
+ D << R;
+ return true;
+ }
+
+ // FIXME: Are there other cases for which a custom diagnostic is more useful
+ // than the basic "types don't match" diagnostic?
+
+ default:
+ return false;
+ }
+}
+
/// \brief Deduce the type for an auto type-specifier (C++11 [dcl.spec.auto]p6)
///
/// Note that this is done even if the initializer is dependent. (This is
@@ -4318,12 +4413,15 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result,
// If deduction failed, don't diagnose if the initializer is dependent; it
// might acquire a matching type in the instantiation.
- auto DeductionFailed = [&]() -> DeduceAutoResult {
+ auto DeductionFailed = [&](TemplateDeductionResult TDK,
+ ArrayRef<SourceRange> Ranges) -> DeduceAutoResult {
if (Init->isTypeDependent()) {
Result = SubstituteDeducedTypeTransform(*this, QualType()).Apply(Type);
assert(!Result.isNull() && "substituting DependentTy can't fail");
return DAR_Succeeded;
}
+ if (diagnoseAutoDeductionFailure(*this, TDK, Info, Ranges))
+ return DAR_FailedAlreadyDiagnosed;
return DAR_Failed;
};
@@ -4337,12 +4435,20 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result,
if (!Type.getType().getNonReferenceType()->getAs<AutoType>())
return DAR_Failed;
+ SourceRange DeducedFromInitRange;
for (unsigned i = 0, e = InitList->getNumInits(); i < e; ++i) {
- if (DeduceTemplateArgumentsFromCallArgument(
- *this, TemplateParamsSt.get(), 0, TemplArg, InitList->getInit(i),
+ Expr *Init = InitList->getInit(i);
+
+ if (auto TDK = DeduceTemplateArgumentsFromCallArgument(
+ *this, TemplateParamsSt.get(), 0, TemplArg, Init,
Info, Deduced, OriginalCallArgs, /*Decomposed*/ true,
/*ArgIdx*/ 0, /*TDF*/ 0))
- return DeductionFailed();
+ return DeductionFailed(TDK, {DeducedFromInitRange,
+ Init->getSourceRange()});
+
+ if (DeducedFromInitRange.isInvalid() &&
+ Deduced[0].getKind() != TemplateArgument::Null)
+ DeducedFromInitRange = Init->getSourceRange();
}
} else {
if (!getLangOpts().CPlusPlus && Init->refersToBitField()) {
@@ -4350,15 +4456,15 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result,
return DAR_FailedAlreadyDiagnosed;
}
- if (DeduceTemplateArgumentsFromCallArgument(
+ if (auto TDK = DeduceTemplateArgumentsFromCallArgument(
*this, TemplateParamsSt.get(), 0, FuncParam, Init, Info, Deduced,
OriginalCallArgs, /*Decomposed*/ false, /*ArgIdx*/ 0, /*TDF*/ 0))
- return DeductionFailed();
+ return DeductionFailed(TDK, {});
}
// Could be null if somehow 'auto' appears in a non-deduced context.
if (Deduced[0].getKind() != TemplateArgument::Type)
- return DeductionFailed();
+ return DeductionFailed(TDK_Incomplete, {});
QualType DeducedType = Deduced[0].getAsType();
@@ -4378,9 +4484,10 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result,
for (const OriginalCallArg &OriginalArg : OriginalCallArgs) {
assert((bool)InitList == OriginalArg.DecomposedParam &&
"decomposed non-init-list in auto deduction?");
- if (CheckOriginalCallArgDeduction(*this, OriginalArg, DeducedA)) {
+ if (auto TDK =
+ CheckOriginalCallArgDeduction(*this, Info, OriginalArg, DeducedA)) {
Result = QualType();
- return DeductionFailed();
+ return DeductionFailed(TDK, {});
}
}
@@ -5045,9 +5152,9 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
if (NTTP->getDepth() == Depth)
Used[NTTP->getIndex()] = true;
- // In C++1z mode, additional arguments may be deduced from the type of a
+ // In C++17 mode, additional arguments may be deduced from the type of a
// non-type argument.
- if (Ctx.getLangOpts().CPlusPlus1z)
+ if (Ctx.getLangOpts().CPlusPlus17)
MarkUsedTemplateParameters(Ctx, NTTP->getType(), OnlyDeduced, Depth, Used);
}
@@ -5174,6 +5281,17 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
break;
}
+ case Type::DependentAddressSpace: {
+ const DependentAddressSpaceType *DependentASType =
+ cast<DependentAddressSpaceType>(T);
+ MarkUsedTemplateParameters(Ctx, DependentASType->getPointeeType(),
+ OnlyDeduced, Depth, Used);
+ MarkUsedTemplateParameters(Ctx,
+ DependentASType->getAddrSpaceExpr(),
+ OnlyDeduced, Depth, Used);
+ break;
+ }
+
case Type::FunctionProto: {
const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
MarkUsedTemplateParameters(Ctx, Proto->getReturnType(), OnlyDeduced, Depth,
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
index f4f0c804aee1a..a48e2466a84d4 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -496,8 +496,8 @@ void Sema::PrintInstantiationStack() {
SmallVector<char, 128> TemplateArgsStr;
llvm::raw_svector_ostream OS(TemplateArgsStr);
Template->printName(OS);
- TemplateSpecializationType::PrintTemplateArgumentList(
- OS, Active->template_arguments(), getPrintingPolicy());
+ printTemplateArgumentList(OS, Active->template_arguments(),
+ getPrintingPolicy());
Diags.Report(Active->PointOfInstantiation,
diag::note_default_arg_instantiation_here)
<< OS.str()
@@ -562,8 +562,8 @@ void Sema::PrintInstantiationStack() {
SmallVector<char, 128> TemplateArgsStr;
llvm::raw_svector_ostream OS(TemplateArgsStr);
FD->printName(OS);
- TemplateSpecializationType::PrintTemplateArgumentList(
- OS, Active->template_arguments(), getPrintingPolicy());
+ printTemplateArgumentList(OS, Active->template_arguments(),
+ getPrintingPolicy());
Diags.Report(Active->PointOfInstantiation,
diag::note_default_function_arg_instantiation_here)
<< OS.str()
@@ -975,7 +975,7 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
}
- TemplateName Template = Arg.getAsTemplate();
+ TemplateName Template = Arg.getAsTemplate().getNameToSubstitute();
assert(!Template.isNull() && Template.getAsTemplateDecl() &&
"Wrong kind of template template argument");
return Template.getAsTemplateDecl();
@@ -1122,14 +1122,10 @@ TemplateName TemplateInstantiator::TransformTemplateName(
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
}
- TemplateName Template = Arg.getAsTemplate();
+ TemplateName Template = Arg.getAsTemplate().getNameToSubstitute();
assert(!Template.isNull() && "Null template template argument");
-
- // We don't ever want to substitute for a qualified template name, since
- // the qualifier is handled separately. So, look through the qualified
- // template name to its underlying declaration.
- if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
- Template = TemplateName(QTN->getTemplateDecl());
+ assert(!Template.getAsQualifiedTemplateName() &&
+ "template decl to substitute is qualified?");
Template = getSema().Context.getSubstTemplateTemplateParm(TTP, Template);
return Template;
@@ -1143,7 +1139,7 @@ TemplateName TemplateInstantiator::TransformTemplateName(
TemplateArgument Arg = SubstPack->getArgumentPack();
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
- return Arg.getAsTemplate();
+ return Arg.getAsTemplate().getNameToSubstitute();
}
return inherited::TransformTemplateName(SS, Name, NameLoc, ObjectType,
@@ -2030,12 +2026,11 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
bool MergeWithParentScope = !Instantiation->isDefinedOutsideFunctionOrMethod();
LocalInstantiationScope Scope(*this, MergeWithParentScope);
- // All dllexported classes created during instantiation should be fully
- // emitted after instantiation completes. We may not be ready to emit any
- // delayed classes already on the stack, so save them away and put them back
- // later.
- decltype(DelayedDllExportClasses) ExportedClasses;
- std::swap(ExportedClasses, DelayedDllExportClasses);
+ // Some class state isn't processed immediately but delayed till class
+ // instantiation completes. We may not be ready to handle any delayed state
+ // already on the stack as it might correspond to a different class, so save
+ // it now and put it back later.
+ SavePendingParsedClassStateRAII SavedPendingParsedClassState(*this);
// Pull attributes from the pattern onto the instantiation.
InstantiateAttrs(TemplateArgs, Pattern, Instantiation);
@@ -2122,9 +2117,6 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
// default arg exprs for default constructors if necessary now.
ActOnFinishCXXNonNestedClass(Instantiation);
- // Put back the delayed exported classes that we moved out of the way.
- std::swap(ExportedClasses, DelayedDllExportClasses);
-
// Instantiate late parsed attributes, and attach them to their decls.
// See Sema::InstantiateAttrs
for (LateInstantiatedAttrVec::iterator I = LateAttrs.begin(),
@@ -2621,7 +2613,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
continue;
Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
- InstantiateStaticDataMemberDefinition(PointOfInstantiation, Var);
+ InstantiateVariableDefinition(PointOfInstantiation, Var);
} else {
Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 4a26efcc9431e..f627f6017f382 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1195,7 +1195,8 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
// Look for a previous declaration of the template in the owning
// context.
LookupResult R(SemaRef, Pattern->getDeclName(), Pattern->getLocation(),
- Sema::LookupOrdinaryName, Sema::ForRedeclaration);
+ Sema::LookupOrdinaryName,
+ SemaRef.forRedeclarationInCurContext());
SemaRef.LookupQualifiedName(R, DC);
if (R.isSingleResult()) {
@@ -1650,11 +1651,13 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
}
FunctionDecl *Function;
- if (auto *DGuide = dyn_cast<CXXDeductionGuideDecl>(D))
+ if (auto *DGuide = dyn_cast<CXXDeductionGuideDecl>(D)) {
Function = CXXDeductionGuideDecl::Create(
- SemaRef.Context, DC, D->getInnerLocStart(), DGuide->isExplicit(),
- D->getNameInfo(), T, TInfo, D->getSourceRange().getEnd());
- else {
+ SemaRef.Context, DC, D->getInnerLocStart(), DGuide->isExplicit(),
+ D->getNameInfo(), T, TInfo, D->getSourceRange().getEnd());
+ if (DGuide->isCopyDeductionCandidate())
+ cast<CXXDeductionGuideDecl>(Function)->setIsCopyDeductionCandidate();
+ } else {
Function = FunctionDecl::Create(
SemaRef.Context, DC, D->getInnerLocStart(), D->getNameInfo(), T, TInfo,
D->getCanonicalDecl()->getStorageClass(), D->isInlineSpecified(),
@@ -1685,7 +1688,6 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
Params[P]->setOwningFunction(Function);
Function->setParams(Params);
- SourceLocation InstantiateAtPOI;
if (TemplateParams) {
// Our resulting instantiation is actually a function template, since we
// are substituting only the outer template parameters. For example, given
@@ -1736,7 +1738,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
SemaRef, Function->getDeclName(), SourceLocation(),
D->isLocalExternDecl() ? Sema::LookupRedeclarationWithLinkage
: Sema::LookupOrdinaryName,
- Sema::ForRedeclaration);
+ D->isLocalExternDecl() ? Sema::ForExternalRedeclaration
+ : SemaRef.forRedeclarationInCurContext());
if (DependentFunctionTemplateSpecializationInfo *Info
= D->getDependentSpecializationInfo()) {
@@ -2054,7 +2057,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
Method->setInvalidDecl();
LookupResult Previous(SemaRef, NameInfo, Sema::LookupOrdinaryName,
- Sema::ForRedeclaration);
+ Sema::ForExternalRedeclaration);
if (!FunctionTemplate || TemplateParams || isFriend) {
SemaRef.LookupQualifiedName(Previous, Record);
@@ -2493,7 +2496,7 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
bool CheckRedeclaration = Owner->isRecord();
LookupResult Prev(SemaRef, NameInfo, Sema::LookupUsingDeclName,
- Sema::ForRedeclaration);
+ Sema::ForVisibleRedeclaration);
UsingDecl *NewUD = UsingDecl::Create(SemaRef.Context, Owner,
D->getUsingLoc(),
@@ -2712,7 +2715,7 @@ Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl(
return nullptr;
LookupResult Previous(SemaRef, NewFD->getNameInfo(), Sema::LookupOrdinaryName,
- Sema::ForRedeclaration);
+ Sema::ForExternalRedeclaration);
TemplateArgumentListInfo TemplateArgs;
TemplateArgumentListInfo *TemplateArgsPtr = nullptr;
@@ -2800,8 +2803,9 @@ Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl(
SemaRef.ActOnOpenMPDeclareReductionCombinerEnd(NewDRD, SubstCombiner);
// Initializers instantiation sequence.
if (D->getInitializer()) {
- SemaRef.ActOnOpenMPDeclareReductionInitializerStart(
- /*S=*/nullptr, NewDRD);
+ VarDecl *OmpPrivParm =
+ SemaRef.ActOnOpenMPDeclareReductionInitializerStart(
+ /*S=*/nullptr, NewDRD);
const char *Names[] = {"omp_orig", "omp_priv"};
for (auto &Name : Names) {
DeclarationName DN(&SemaRef.Context.Idents.get(Name));
@@ -2809,17 +2813,28 @@ Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl(
auto Lookup = NewDRD->lookup(DN);
if (!OldLookup.empty() && !Lookup.empty()) {
assert(Lookup.size() == 1 && OldLookup.size() == 1);
- SemaRef.CurrentInstantiationScope->InstantiatedLocal(
- OldLookup.front(), Lookup.front());
+ auto *OldVD = cast<VarDecl>(OldLookup.front());
+ auto *NewVD = cast<VarDecl>(Lookup.front());
+ SemaRef.InstantiateVariableInitializer(NewVD, OldVD, TemplateArgs);
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldVD, NewVD);
}
}
- SubstInitializer =
- SemaRef.SubstExpr(D->getInitializer(), TemplateArgs).get();
- SemaRef.ActOnOpenMPDeclareReductionInitializerEnd(NewDRD,
- SubstInitializer);
+ if (D->getInitializerKind() == OMPDeclareReductionDecl::CallInit) {
+ SubstInitializer =
+ SemaRef.SubstExpr(D->getInitializer(), TemplateArgs).get();
+ } else {
+ IsCorrect = IsCorrect && OmpPrivParm->hasInit();
+ }
+ SemaRef.ActOnOpenMPDeclareReductionInitializerEnd(
+ NewDRD, SubstInitializer, OmpPrivParm);
}
- IsCorrect = IsCorrect && SubstCombiner &&
- (!D->getInitializer() || SubstInitializer);
+ IsCorrect =
+ IsCorrect && SubstCombiner &&
+ (!D->getInitializer() ||
+ (D->getInitializerKind() == OMPDeclareReductionDecl::CallInit &&
+ SubstInitializer) ||
+ (D->getInitializerKind() != OMPDeclareReductionDecl::CallInit &&
+ !SubstInitializer && !SubstInitializer));
} else
IsCorrect = false;
@@ -3753,7 +3768,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
bool Recursive,
bool DefinitionRequired,
bool AtEndOfTU) {
- if (Function->isInvalidDecl() || Function->isDefined())
+ if (Function->isInvalidDecl() || Function->isDefined() ||
+ isa<CXXDeductionGuideDecl>(Function))
return;
// Never instantiate an explicit specialization except if it is a class scope
@@ -4005,6 +4021,8 @@ VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation(
VarTemplateSpecializationDecl *Sema::CompleteVarTemplateSpecializationDecl(
VarTemplateSpecializationDecl *VarSpec, VarDecl *PatternDecl,
const MultiLevelTemplateArgumentList &TemplateArgs) {
+ assert(PatternDecl->isThisDeclarationADefinition() &&
+ "don't have a definition to instantiate from");
// Do substitution on the type of the declaration
TypeSourceInfo *DI =
@@ -4016,6 +4034,9 @@ VarTemplateSpecializationDecl *Sema::CompleteVarTemplateSpecializationDecl(
// Update the type of this variable template specialization.
VarSpec->setType(DI->getType());
+ // Convert the declaration into a definition now.
+ VarSpec->setCompleteDefinition();
+
// Instantiate the initializer.
InstantiateVariableInitializer(VarSpec, PatternDecl, TemplateArgs);
@@ -4063,7 +4084,8 @@ void Sema::BuildVariableInstantiation(
*this, NewVar->getDeclName(), NewVar->getLocation(),
NewVar->isLocalExternDecl() ? Sema::LookupRedeclarationWithLinkage
: Sema::LookupOrdinaryName,
- Sema::ForRedeclaration);
+ NewVar->isLocalExternDecl() ? Sema::ForExternalRedeclaration
+ : forRedeclarationInCurContext());
if (NewVar->isLocalExternDecl() && OldVar->getPreviousDecl() &&
(!OldVar->getPreviousDecl()->getDeclContext()->isDependentContext() ||
@@ -4120,6 +4142,9 @@ void Sema::BuildVariableInstantiation(
void Sema::InstantiateVariableInitializer(
VarDecl *Var, VarDecl *OldVar,
const MultiLevelTemplateArgumentList &TemplateArgs) {
+ if (ASTMutationListener *L = getASTContext().getASTMutationListener())
+ L->VariableDefinitionInstantiated(Var);
+
// We propagate the 'inline' flag with the initializer, because it
// would otherwise imply that the variable is a definition for a
// non-static data member.
@@ -4129,12 +4154,8 @@ void Sema::InstantiateVariableInitializer(
Var->setImplicitlyInline();
if (OldVar->getInit()) {
- if (Var->isStaticDataMember() && !OldVar->isOutOfLine())
- PushExpressionEvaluationContext(
- Sema::ExpressionEvaluationContext::ConstantEvaluated, OldVar);
- else
- PushExpressionEvaluationContext(
- Sema::ExpressionEvaluationContext::PotentiallyEvaluated, OldVar);
+ EnterExpressionEvaluationContext Evaluated(
+ *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, Var);
// Instantiate the initializer.
ExprResult Init;
@@ -4162,8 +4183,6 @@ void Sema::InstantiateVariableInitializer(
// because of a bogus initializer.
Var->setInvalidDecl();
}
-
- PopExpressionEvaluationContext();
} else {
if (Var->isStaticDataMember()) {
if (!Var->isOutOfLine())
@@ -4188,26 +4207,16 @@ void Sema::InstantiateVariableInitializer(
///
/// \param PointOfInstantiation the point at which the instantiation was
/// required. Note that this is not precisely a "point of instantiation"
-/// for the function, but it's close.
+/// for the variable, but it's close.
///
-/// \param Var the already-instantiated declaration of a static member
-/// variable of a class template specialization.
+/// \param Var the already-instantiated declaration of a templated variable.
///
/// \param Recursive if true, recursively instantiates any functions that
/// are required by this instantiation.
///
/// \param DefinitionRequired if true, then we are performing an explicit
-/// instantiation where an out-of-line definition of the member variable
-/// is required. Complain if there is no such definition.
-void Sema::InstantiateStaticDataMemberDefinition(
- SourceLocation PointOfInstantiation,
- VarDecl *Var,
- bool Recursive,
- bool DefinitionRequired) {
- InstantiateVariableDefinition(PointOfInstantiation, Var, Recursive,
- DefinitionRequired);
-}
-
+/// instantiation where a definition of the variable is required. Complain
+/// if there is no such definition.
void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
VarDecl *Var, bool Recursive,
bool DefinitionRequired, bool AtEndOfTU) {
@@ -4264,6 +4273,11 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
// If this is a static data member template, there might be an
// uninstantiated initializer on the declaration. If so, instantiate
// it now.
+ //
+ // FIXME: This largely duplicates what we would do below. The difference
+ // is that along this path we may instantiate an initializer from an
+ // in-class declaration of the template and instantiate the definition
+ // from a separate out-of-class definition.
if (PatternDecl->isStaticDataMember() &&
(PatternDecl = PatternDecl->getFirstDecl())->hasInit() &&
!Var->hasInit()) {
@@ -4351,10 +4365,12 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
return;
// C++11 [temp.explicit]p10:
- // Except for inline functions, [...] explicit instantiation declarations
+ // Except for inline functions, const variables of literal types, variables
+ // of reference types, [...] explicit instantiation declarations
// have the effect of suppressing the implicit instantiation of the entity
// to which they refer.
- if (TSK == TSK_ExplicitInstantiationDeclaration)
+ if (TSK == TSK_ExplicitInstantiationDeclaration &&
+ !Var->isUsableInConstantExpressions(getASTContext()))
return;
// Make sure to pass the instantiated variable to the consumer at the end.
@@ -4427,7 +4443,7 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
// Merge the definition with the declaration.
LookupResult R(*this, Var->getDeclName(), Var->getLocation(),
- LookupOrdinaryName, ForRedeclaration);
+ LookupOrdinaryName, forRedeclarationInCurContext());
R.addDecl(OldVar);
MergeVarDecl(Var, R);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp
index 9f572007d8a77..d81837dad5085 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -26,6 +26,19 @@ using namespace clang;
// Visitor that collects unexpanded parameter packs
//----------------------------------------------------------------------------
+/// \brief Retrieve the depth and index of a parameter pack.
+static std::pair<unsigned, unsigned>
+getDepthAndIndex(NamedDecl *ND) {
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND))
+ return std::make_pair(TTP->getDepth(), TTP->getIndex());
+
+ if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(ND))
+ return std::make_pair(NTTP->getDepth(), NTTP->getIndex());
+
+ TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(ND);
+ return std::make_pair(TTP->getDepth(), TTP->getIndex());
+}
+
namespace {
/// \brief A class that collects unexpanded parameter packs.
class CollectUnexpandedParameterPacksVisitor :
@@ -36,15 +49,36 @@ namespace {
SmallVectorImpl<UnexpandedParameterPack> &Unexpanded;
- bool InLambda;
+ bool InLambda = false;
+ unsigned DepthLimit = (unsigned)-1;
+
+ void addUnexpanded(NamedDecl *ND, SourceLocation Loc = SourceLocation()) {
+ if (auto *PVD = dyn_cast<ParmVarDecl>(ND)) {
+ // For now, the only problematic case is a generic lambda's templated
+ // call operator, so we don't need to look for all the other ways we
+ // could have reached a dependent parameter pack.
+ auto *FD = dyn_cast<FunctionDecl>(PVD->getDeclContext());
+ auto *FTD = FD ? FD->getDescribedFunctionTemplate() : nullptr;
+ if (FTD && FTD->getTemplateParameters()->getDepth() >= DepthLimit)
+ return;
+ } else if (getDepthAndIndex(ND).first >= DepthLimit)
+ return;
+ Unexpanded.push_back({ND, Loc});
+ }
+ void addUnexpanded(const TemplateTypeParmType *T,
+ SourceLocation Loc = SourceLocation()) {
+ if (T->getDepth() < DepthLimit)
+ Unexpanded.push_back({T, Loc});
+ }
+
public:
explicit CollectUnexpandedParameterPacksVisitor(
- SmallVectorImpl<UnexpandedParameterPack> &Unexpanded)
- : Unexpanded(Unexpanded), InLambda(false) { }
+ SmallVectorImpl<UnexpandedParameterPack> &Unexpanded)
+ : Unexpanded(Unexpanded) {}
bool shouldWalkTypesOfTypeLocs() const { return false; }
-
+
//------------------------------------------------------------------------
// Recording occurrences of (unexpanded) parameter packs.
//------------------------------------------------------------------------
@@ -52,7 +86,7 @@ namespace {
/// \brief Record occurrences of template type parameter packs.
bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
if (TL.getTypePtr()->isParameterPack())
- Unexpanded.push_back(std::make_pair(TL.getTypePtr(), TL.getNameLoc()));
+ addUnexpanded(TL.getTypePtr(), TL.getNameLoc());
return true;
}
@@ -63,7 +97,7 @@ namespace {
/// Ideally, this routine would never be used.
bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {
if (T->isParameterPack())
- Unexpanded.push_back(std::make_pair(T, SourceLocation()));
+ addUnexpanded(T);
return true;
}
@@ -72,18 +106,18 @@ namespace {
/// parameter packs in an expression.
bool VisitDeclRefExpr(DeclRefExpr *E) {
if (E->getDecl()->isParameterPack())
- Unexpanded.push_back(std::make_pair(E->getDecl(), E->getLocation()));
+ addUnexpanded(E->getDecl(), E->getLocation());
return true;
}
/// \brief Record occurrences of template template parameter packs.
bool TraverseTemplateName(TemplateName Template) {
- if (TemplateTemplateParmDecl *TTP
- = dyn_cast_or_null<TemplateTemplateParmDecl>(
- Template.getAsTemplateDecl()))
+ if (auto *TTP = dyn_cast_or_null<TemplateTemplateParmDecl>(
+ Template.getAsTemplateDecl())) {
if (TTP->isParameterPack())
- Unexpanded.push_back(std::make_pair(TTP, SourceLocation()));
+ addUnexpanded(TTP);
+ }
return inherited::TraverseTemplateName(Template);
}
@@ -127,7 +161,7 @@ namespace {
return true;
}
- /// \brief Suppress traversel into types with location information
+ /// \brief Suppress traversal into types with location information
/// that do not contain unexpanded parameter packs.
bool TraverseTypeLoc(TypeLoc TL) {
if ((!TL.getType().isNull() &&
@@ -138,13 +172,48 @@ namespace {
return true;
}
- /// \brief Suppress traversal of non-parameter declarations, since
- /// they cannot contain unexpanded parameter packs.
+ /// \brief Suppress traversal of parameter packs.
bool TraverseDecl(Decl *D) {
- if ((D && isa<ParmVarDecl>(D)) || InLambda)
- return inherited::TraverseDecl(D);
+ // A function parameter pack is a pack expansion, so cannot contain
+ // an unexpanded parameter pack. Likewise for a template parameter
+ // pack that contains any references to other packs.
+ if (D->isParameterPack())
+ return true;
- return true;
+ return inherited::TraverseDecl(D);
+ }
+
+ /// \brief Suppress traversal of pack-expanded attributes.
+ bool TraverseAttr(Attr *A) {
+ if (A->isPackExpansion())
+ return true;
+
+ return inherited::TraverseAttr(A);
+ }
+
+ /// \brief Suppress traversal of pack expansion expressions and types.
+ ///@{
+ bool TraversePackExpansionType(PackExpansionType *T) { return true; }
+ bool TraversePackExpansionTypeLoc(PackExpansionTypeLoc TL) { return true; }
+ bool TraversePackExpansionExpr(PackExpansionExpr *E) { return true; }
+ bool TraverseCXXFoldExpr(CXXFoldExpr *E) { return true; }
+
+ ///@}
+
+ /// \brief Suppress traversal of using-declaration pack expansion.
+ bool TraverseUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
+ if (D->isPackExpansion())
+ return true;
+
+ return inherited::TraverseUnresolvedUsingValueDecl(D);
+ }
+
+ /// \brief Suppress traversal of using-declaration pack expansion.
+ bool TraverseUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
+ if (D->isPackExpansion())
+ return true;
+
+ return inherited::TraverseUnresolvedUsingTypenameDecl(D);
}
/// \brief Suppress traversal of template argument pack expansions.
@@ -163,6 +232,22 @@ namespace {
return inherited::TraverseTemplateArgumentLoc(ArgLoc);
}
+ /// \brief Suppress traversal of base specifier pack expansions.
+ bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &Base) {
+ if (Base.isPackExpansion())
+ return true;
+
+ return inherited::TraverseCXXBaseSpecifier(Base);
+ }
+
+ /// \brief Suppress traversal of mem-initializer pack expansions.
+ bool TraverseConstructorInitializer(CXXCtorInitializer *Init) {
+ if (Init->isPackExpansion())
+ return true;
+
+ return inherited::TraverseConstructorInitializer(Init);
+ }
+
/// \brief Note whether we're traversing a lambda containing an unexpanded
/// parameter pack. In this case, the unexpanded pack can occur anywhere,
/// including all the places where we normally wouldn't look. Within a
@@ -175,25 +260,27 @@ namespace {
return true;
bool WasInLambda = InLambda;
- InLambda = true;
+ unsigned OldDepthLimit = DepthLimit;
- // If any capture names a function parameter pack, that pack is expanded
- // when the lambda is expanded.
- for (LambdaExpr::capture_iterator I = Lambda->capture_begin(),
- E = Lambda->capture_end();
- I != E; ++I) {
- if (I->capturesVariable()) {
- VarDecl *VD = I->getCapturedVar();
- if (VD->isParameterPack())
- Unexpanded.push_back(std::make_pair(VD, I->getLocation()));
- }
- }
+ InLambda = true;
+ if (auto *TPL = Lambda->getTemplateParameterList())
+ DepthLimit = TPL->getDepth();
inherited::TraverseLambdaExpr(Lambda);
InLambda = WasInLambda;
+ DepthLimit = OldDepthLimit;
return true;
}
+
+ /// Suppress traversal within pack expansions in lambda captures.
+ bool TraverseLambdaCapture(LambdaExpr *Lambda, const LambdaCapture *C,
+ Expr *Init) {
+ if (C->isPackExpansion())
+ return true;
+
+ return inherited::TraverseLambdaCapture(Lambda, C, Init);
+ }
};
}
@@ -220,13 +307,33 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
if (Unexpanded.empty())
return false;
- // If we are within a lambda expression, that lambda contains an unexpanded
+ // If we are within a lambda expression and referencing a pack that is not
+ // a parameter of the lambda itself, that lambda contains an unexpanded
// parameter pack, and we are done.
// FIXME: Store 'Unexpanded' on the lambda so we don't need to recompute it
// later.
+ SmallVector<UnexpandedParameterPack, 4> LambdaParamPackReferences;
for (unsigned N = FunctionScopes.size(); N; --N) {
if (sema::LambdaScopeInfo *LSI =
dyn_cast<sema::LambdaScopeInfo>(FunctionScopes[N-1])) {
+ if (N == FunctionScopes.size()) {
+ for (auto &Param : Unexpanded) {
+ auto *PD = dyn_cast_or_null<ParmVarDecl>(
+ Param.first.dyn_cast<NamedDecl *>());
+ if (PD && PD->getDeclContext() == LSI->CallOperator)
+ LambdaParamPackReferences.push_back(Param);
+ }
+ }
+
+ // If we have references to a parameter pack of the innermost enclosing
+ // lambda, only diagnose those ones. We don't know whether any other
+ // unexpanded parameters referenced herein are actually unexpanded;
+ // they might be expanded at an outer level.
+ if (!LambdaParamPackReferences.empty()) {
+ Unexpanded = LambdaParamPackReferences;
+ break;
+ }
+
LSI->ContainsUnexpandedParameterPack = true;
return false;
}
@@ -520,19 +627,6 @@ ExprResult Sema::CheckPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc,
PackExpansionExpr(Context.DependentTy, Pattern, EllipsisLoc, NumExpansions);
}
-/// \brief Retrieve the depth and index of a parameter pack.
-static std::pair<unsigned, unsigned>
-getDepthAndIndex(NamedDecl *ND) {
- if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND))
- return std::make_pair(TTP->getDepth(), TTP->getIndex());
-
- if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(ND))
- return std::make_pair(NTTP->getDepth(), NTTP->getIndex());
-
- TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(ND);
- return std::make_pair(TTP->getDepth(), TTP->getIndex());
-}
-
bool Sema::CheckParameterPacksForExpansion(
SourceLocation EllipsisLoc, SourceRange PatternRange,
ArrayRef<UnexpandedParameterPack> Unexpanded,
@@ -725,6 +819,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
case TST_half:
case TST_float:
case TST_double:
+ case TST_Float16:
case TST_float128:
case TST_bool:
case TST_decimal32:
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
index 598a11300b876..2fffe8e179707 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
@@ -1392,8 +1392,9 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
else
Result = Context.Int128Ty;
break;
- case DeclSpec::TST_half: Result = Context.HalfTy; break;
- case DeclSpec::TST_float: Result = Context.FloatTy; break;
+ case DeclSpec::TST_float16: Result = Context.Float16Ty; break;
+ case DeclSpec::TST_half: Result = Context.HalfTy; break;
+ case DeclSpec::TST_float: Result = Context.FloatTy; break;
case DeclSpec::TST_double:
if (DS.getTypeSpecWidth() == DeclSpec::TSW_long)
Result = Context.LongDoubleTy;
@@ -2179,9 +2180,18 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
Diag(Loc, diag::err_opencl_vla);
return QualType();
}
- // CUDA device code doesn't support VLAs.
- if (getLangOpts().CUDA && T->isVariableArrayType())
- CUDADiagIfDeviceCode(Loc, diag::err_cuda_vla) << CurrentCUDATarget();
+
+ if (T->isVariableArrayType() && !Context.getTargetInfo().isVLASupported()) {
+ if (getLangOpts().CUDA) {
+ // CUDA device code doesn't support VLAs.
+ CUDADiagIfDeviceCode(Loc, diag::err_cuda_vla) << CurrentCUDATarget();
+ } else if (!getLangOpts().OpenMP ||
+ shouldDiagnoseTargetSupportFromOpenMP()) {
+ // Some targets don't support VLAs.
+ Diag(Loc, diag::err_vla_unsupported);
+ return QualType();
+ }
+ }
// If this is not C99, extwarn about VLA's and C99 array size modifiers.
if (!getLangOpts().C99) {
@@ -2834,8 +2844,8 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
case Declarator::TemplateParamContext:
if (isa<DeducedTemplateSpecializationType>(Deduced))
Error = 19; // Template parameter
- else if (!SemaRef.getLangOpts().CPlusPlus1z)
- Error = 8; // Template parameter (until C++1z)
+ else if (!SemaRef.getLangOpts().CPlusPlus17)
+ Error = 8; // Template parameter (until C++17)
break;
case Declarator::BlockLiteralContext:
Error = 9; // Block literal
@@ -3064,6 +3074,7 @@ static void warnAboutAmbiguousFunction(Sema &S, Declarator &D,
S.Diag(D.getCommaLoc(), diag::note_empty_parens_function_call)
<< FixItHint::CreateReplacement(D.getCommaLoc(), ";")
<< D.getIdentifier();
+ Result.suppressDiagnostics();
}
}
@@ -3105,6 +3116,99 @@ static void warnAboutAmbiguousFunction(Sema &S, Declarator &D,
}
}
+/// Produce an appropriate diagnostic for a declarator with top-level
+/// parentheses.
+static void warnAboutRedundantParens(Sema &S, Declarator &D, QualType T) {
+ DeclaratorChunk &Paren = D.getTypeObject(D.getNumTypeObjects() - 1);
+ assert(Paren.Kind == DeclaratorChunk::Paren &&
+ "do not have redundant top-level parentheses");
+
+ // This is a syntactic check; we're not interested in cases that arise
+ // during template instantiation.
+ if (S.inTemplateInstantiation())
+ return;
+
+ // Check whether this could be intended to be a construction of a temporary
+ // object in C++ via a function-style cast.
+ bool CouldBeTemporaryObject =
+ S.getLangOpts().CPlusPlus && D.isExpressionContext() &&
+ !D.isInvalidType() && D.getIdentifier() &&
+ D.getDeclSpec().getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier &&
+ (T->isRecordType() || T->isDependentType()) &&
+ D.getDeclSpec().getTypeQualifiers() == 0 && D.isFirstDeclarator();
+
+ for (auto &C : D.type_objects()) {
+ switch (C.Kind) {
+ case DeclaratorChunk::Pointer:
+ case DeclaratorChunk::Paren:
+ continue;
+
+ case DeclaratorChunk::Array:
+ if (!C.Arr.NumElts)
+ CouldBeTemporaryObject = false;
+ continue;
+
+ case DeclaratorChunk::Reference:
+ // FIXME: Suppress the warning here if there is no initializer; we're
+ // going to give an error anyway.
+ // We assume that something like 'T (&x) = y;' is highly likely to not
+ // be intended to be a temporary object.
+ CouldBeTemporaryObject = false;
+ continue;
+
+ case DeclaratorChunk::Function:
+ // In a new-type-id, function chunks require parentheses.
+ if (D.getContext() == Declarator::CXXNewContext)
+ return;
+ LLVM_FALLTHROUGH;
+ case DeclaratorChunk::BlockPointer:
+ case DeclaratorChunk::MemberPointer:
+ case DeclaratorChunk::Pipe:
+ // These cannot appear in expressions.
+ CouldBeTemporaryObject = false;
+ continue;
+ }
+ }
+
+ // FIXME: If there is an initializer, assume that this is not intended to be
+ // a construction of a temporary object.
+
+ // Check whether the name has already been declared; if not, this is not a
+ // function-style cast.
+ if (CouldBeTemporaryObject) {
+ LookupResult Result(S, D.getIdentifier(), SourceLocation(),
+ Sema::LookupOrdinaryName);
+ if (!S.LookupName(Result, S.getCurScope()))
+ CouldBeTemporaryObject = false;
+ Result.suppressDiagnostics();
+ }
+
+ SourceRange ParenRange(Paren.Loc, Paren.EndLoc);
+
+ if (!CouldBeTemporaryObject) {
+ S.Diag(Paren.Loc, diag::warn_redundant_parens_around_declarator)
+ << ParenRange << FixItHint::CreateRemoval(Paren.Loc)
+ << FixItHint::CreateRemoval(Paren.EndLoc);
+ return;
+ }
+
+ S.Diag(Paren.Loc, diag::warn_parens_disambiguated_as_variable_declaration)
+ << ParenRange << D.getIdentifier();
+ auto *RD = T->getAsCXXRecordDecl();
+ if (!RD || !RD->hasDefinition() || RD->hasNonTrivialDestructor())
+ S.Diag(Paren.Loc, diag::note_raii_guard_add_name)
+ << FixItHint::CreateInsertion(Paren.Loc, " varname") << T
+ << D.getIdentifier();
+ // FIXME: A cast to void is probably a better suggestion in cases where it's
+ // valid (when there is no initializer and we're not in a condition).
+ S.Diag(D.getLocStart(), diag::note_function_style_cast_add_parentheses)
+ << FixItHint::CreateInsertion(D.getLocStart(), "(")
+ << FixItHint::CreateInsertion(S.getLocForEndOfToken(D.getLocEnd()), ")");
+ S.Diag(Paren.Loc, diag::note_remove_parens_for_variable_declaration)
+ << FixItHint::CreateRemoval(Paren.Loc)
+ << FixItHint::CreateRemoval(Paren.EndLoc);
+}
+
/// Helper for figuring out the default CC for a function declarator type. If
/// this is the outermost chunk, then we can determine the CC from the
/// declarator context. If not, then this could be either a member function
@@ -3387,13 +3491,20 @@ classifyPointerDeclarator(Sema &S, QualType type, Declarator &declarator,
isCFError = (S.CFError == recordDecl);
} else {
// Check whether this is CFError, which we identify based on its bridge
- // to NSError.
+ // to NSError. CFErrorRef used to be declared with "objc_bridge" but is
+ // now declared with "objc_bridge_mutable", so look for either one of
+ // the two attributes.
if (recordDecl->getTagKind() == TTK_Struct && numNormalPointers > 0) {
- if (auto bridgeAttr = recordDecl->getAttr<ObjCBridgeAttr>()) {
- if (bridgeAttr->getBridgedType() == S.getNSErrorIdent()) {
- S.CFError = recordDecl;
- isCFError = true;
- }
+ IdentifierInfo *bridgedType = nullptr;
+ if (auto bridgeAttr = recordDecl->getAttr<ObjCBridgeAttr>())
+ bridgedType = bridgeAttr->getBridgedType();
+ else if (auto bridgeAttr =
+ recordDecl->getAttr<ObjCBridgeMutableAttr>())
+ bridgedType = bridgeAttr->getBridgedType();
+
+ if (bridgedType == S.getNSErrorIdent()) {
+ S.CFError = recordDecl;
+ isCFError = true;
}
}
}
@@ -3499,7 +3610,8 @@ static void fixItNullability(Sema &S, DiagnosticBuilder &Diag,
static void emitNullabilityConsistencyWarning(Sema &S,
SimplePointerKind PointerKind,
- SourceLocation PointerLoc) {
+ SourceLocation PointerLoc,
+ SourceLocation PointerEndLoc) {
assert(PointerLoc.isValid());
if (PointerKind == SimplePointerKind::Array) {
@@ -3509,14 +3621,15 @@ static void emitNullabilityConsistencyWarning(Sema &S,
<< static_cast<unsigned>(PointerKind);
}
- if (PointerLoc.isMacroID())
+ auto FixItLoc = PointerEndLoc.isValid() ? PointerEndLoc : PointerLoc;
+ if (FixItLoc.isMacroID())
return;
auto addFixIt = [&](NullabilityKind Nullability) {
- auto Diag = S.Diag(PointerLoc, diag::note_nullability_fix_it);
+ auto Diag = S.Diag(FixItLoc, diag::note_nullability_fix_it);
Diag << static_cast<unsigned>(Nullability);
Diag << static_cast<unsigned>(PointerKind);
- fixItNullability(S, Diag, PointerLoc, Nullability);
+ fixItNullability(S, Diag, FixItLoc, Nullability);
};
addFixIt(NullabilityKind::Nullable);
addFixIt(NullabilityKind::NonNull);
@@ -3528,9 +3641,10 @@ static void emitNullabilityConsistencyWarning(Sema &S,
///
/// If the file has \e not seen other uses of nullability, this particular
/// pointer is saved for possible later diagnosis. See recordNullabilitySeen().
-static void checkNullabilityConsistency(Sema &S,
- SimplePointerKind pointerKind,
- SourceLocation pointerLoc) {
+static void
+checkNullabilityConsistency(Sema &S, SimplePointerKind pointerKind,
+ SourceLocation pointerLoc,
+ SourceLocation pointerEndLoc = SourceLocation()) {
// Determine which file we're performing consistency checking for.
FileID file = getNullabilityCompletenessCheckFileID(S, pointerLoc);
if (file.isInvalid())
@@ -3551,6 +3665,7 @@ static void checkNullabilityConsistency(Sema &S,
if (fileNullability.PointerLoc.isInvalid() &&
!S.Context.getDiagnostics().isIgnored(diagKind, pointerLoc)) {
fileNullability.PointerLoc = pointerLoc;
+ fileNullability.PointerEndLoc = pointerEndLoc;
fileNullability.PointerKind = static_cast<unsigned>(pointerKind);
}
@@ -3558,7 +3673,7 @@ static void checkNullabilityConsistency(Sema &S,
}
// Complain about missing nullability.
- emitNullabilityConsistencyWarning(S, pointerKind, pointerLoc);
+ emitNullabilityConsistencyWarning(S, pointerKind, pointerLoc, pointerEndLoc);
}
/// Marks that a nullability feature has been used in the file containing
@@ -3584,7 +3699,8 @@ static void recordNullabilitySeen(Sema &S, SourceLocation loc) {
return;
auto kind = static_cast<SimplePointerKind>(fileNullability.PointerKind);
- emitNullabilityConsistencyWarning(S, kind, fileNullability.PointerLoc);
+ emitNullabilityConsistencyWarning(S, kind, fileNullability.PointerLoc,
+ fileNullability.PointerEndLoc);
}
/// Returns true if any of the declarator chunks before \p endIndex include a
@@ -3894,6 +4010,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Returns true if _Nonnull was inferred.
auto inferPointerNullability = [&](SimplePointerKind pointerKind,
SourceLocation pointerLoc,
+ SourceLocation pointerEndLoc,
AttributeList *&attrs) -> AttributeList * {
// We've seen a pointer.
if (NumPointersRemaining > 0)
@@ -3949,7 +4066,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Fallthrough.
case CAMN_Yes:
- checkNullabilityConsistency(S, pointerKind, pointerLoc);
+ checkNullabilityConsistency(S, pointerKind, pointerLoc, pointerEndLoc);
}
return nullptr;
};
@@ -3972,6 +4089,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if (auto *attr = inferPointerNullability(
pointerKind, D.getDeclSpec().getTypeSpecTypeLoc(),
+ D.getDeclSpec().getLocEnd(),
D.getMutableDeclSpec().getAttributes().getListRef())) {
T = Context.getAttributedType(
AttributedType::getNullabilityAttrKind(*inferNullability),T,T);
@@ -3999,6 +4117,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
IsQualifiedFunction &= DeclType.Kind == DeclaratorChunk::Paren;
switch (DeclType.Kind) {
case DeclaratorChunk::Paren:
+ if (i == 0)
+ warnAboutRedundantParens(S, D, T);
T = S.BuildParenType(T);
break;
case DeclaratorChunk::BlockPointer:
@@ -4007,8 +4127,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
S.Diag(DeclType.Loc, diag::err_blocks_disable) << LangOpts.OpenCL;
// Handle pointer nullability.
- inferPointerNullability(SimplePointerKind::BlockPointer,
- DeclType.Loc, DeclType.getAttrListRef());
+ inferPointerNullability(SimplePointerKind::BlockPointer, DeclType.Loc,
+ DeclType.EndLoc, DeclType.getAttrListRef());
T = S.BuildBlockPointerType(T, D.getIdentifierLoc(), Name);
if (DeclType.Cls.TypeQuals || LangOpts.OpenCL) {
@@ -4030,7 +4150,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Handle pointer nullability
inferPointerNullability(SimplePointerKind::Pointer, DeclType.Loc,
- DeclType.getAttrListRef());
+ DeclType.EndLoc, DeclType.getAttrListRef());
if (LangOpts.ObjC1 && T->getAs<ObjCObjectType>()) {
T = Context.getObjCObjectPointerType(T);
@@ -4175,7 +4295,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
<< T << D.getSourceRange();
D.setInvalidType(true);
} else if (D.getName().getKind() ==
- UnqualifiedId::IK_DeductionGuideName) {
+ UnqualifiedId::IK_DeductionGuideName) {
if (T != Context.DependentTy) {
S.Diag(D.getDeclSpec().getLocStart(),
diag::err_deduction_guide_with_complex_decl)
@@ -4343,7 +4463,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Exception specs are not allowed in typedefs. Complain, but add it
// anyway.
- if (IsTypedefName && FTI.getExceptionSpecType() && !LangOpts.CPlusPlus1z)
+ if (IsTypedefName && FTI.getExceptionSpecType() && !LangOpts.CPlusPlus17)
S.Diag(FTI.getExceptionSpecLocBeg(),
diag::err_exception_spec_in_typedef)
<< (D.getContext() == Declarator::AliasDeclContext ||
@@ -4356,7 +4476,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
FunctionType::ExtInfo EI(getCCForDeclaratorChunk(S, D, FTI, chunkIndex));
- if (!FTI.NumParams && !FTI.isVariadic && !LangOpts.CPlusPlus) {
+ if (!FTI.NumParams && !FTI.isVariadic && !LangOpts.CPlusPlus
+ && !LangOpts.OpenCL) {
// Simple void foo(), where the incoming T is the result type.
T = Context.getFunctionNoProtoType(T, EI);
} else {
@@ -4478,6 +4599,11 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
HasAnyInterestingExtParameterInfos = true;
}
+ if (Param->hasAttr<NoEscapeAttr>()) {
+ ExtParameterInfos[i] = ExtParameterInfos[i].withIsNoEscape(true);
+ HasAnyInterestingExtParameterInfos = true;
+ }
+
ParamTys.push_back(ParamTy);
}
@@ -4524,8 +4650,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
QualType ClsType;
// Handle pointer nullability.
- inferPointerNullability(SimplePointerKind::MemberPointer,
- DeclType.Loc, DeclType.getAttrListRef());
+ inferPointerNullability(SimplePointerKind::MemberPointer, DeclType.Loc,
+ DeclType.EndLoc, DeclType.getAttrListRef());
if (SS.isInvalid()) {
// Avoid emitting extra errors if we already errored on the scope.
@@ -4828,7 +4954,6 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S) {
TypeSourceInfo *ReturnTypeInfo = nullptr;
QualType T = GetDeclSpecTypeForDeclarator(state, ReturnTypeInfo);
-
if (D.isPrototypeContext() && getLangOpts().ObjCAutoRefCount)
inferARCWriteback(state, T);
@@ -5378,6 +5503,18 @@ static void fillAtomicQualLoc(AtomicTypeLoc ATL, const DeclaratorChunk &Chunk) {
ATL.setParensRange(SourceRange());
}
+static void fillDependentAddressSpaceTypeLoc(DependentAddressSpaceTypeLoc DASTL,
+ const AttributeList *Attrs) {
+ while (Attrs && Attrs->getKind() != AttributeList::AT_AddressSpace)
+ Attrs = Attrs->getNext();
+
+ assert(Attrs && "no address_space attribute found at the expected location!");
+
+ DASTL.setAttrNameLoc(Attrs->getLoc());
+ DASTL.setAttrExprOperand(Attrs->getArgAsExpr(0));
+ DASTL.setAttrOperandParensRange(SourceRange());
+}
+
/// \brief Create and instantiate a TypeSourceInfo with type source information.
///
/// \param T QualType referring to the type as written in source code.
@@ -5400,6 +5537,13 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
}
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
+
+ if (DependentAddressSpaceTypeLoc DASTL =
+ CurrTL.getAs<DependentAddressSpaceTypeLoc>()) {
+ fillDependentAddressSpaceTypeLoc(DASTL, D.getTypeObject(i).getAttrs());
+ CurrTL = DASTL.getPointeeTypeLoc().getUnqualifiedLoc();
+ }
+
// An AtomicTypeLoc might be produced by an atomic qualifier in this
// declarator chunk.
if (AtomicTypeLoc ATL = CurrTL.getAs<AtomicTypeLoc>()) {
@@ -5492,16 +5636,77 @@ ParsedType Sema::ActOnObjCInstanceType(SourceLocation Loc) {
// Type Attribute Processing
//===----------------------------------------------------------------------===//
+/// BuildAddressSpaceAttr - Builds a DependentAddressSpaceType if an expression
+/// is uninstantiated. If instantiated it will apply the appropriate address space
+/// to the type. This function allows dependent template variables to be used in
+/// conjunction with the address_space attribute
+QualType Sema::BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace,
+ SourceLocation AttrLoc) {
+ if (!AddrSpace->isValueDependent()) {
+
+ // If this type is already address space qualified, reject it.
+ // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "No type shall be qualified
+ // by qualifiers for two or more different address spaces."
+ if (T.getAddressSpace() != LangAS::Default) {
+ Diag(AttrLoc, diag::err_attribute_address_multiple_qualifiers);
+ return QualType();
+ }
+
+ llvm::APSInt addrSpace(32);
+ if (!AddrSpace->isIntegerConstantExpr(addrSpace, Context)) {
+ Diag(AttrLoc, diag::err_attribute_argument_type)
+ << "'address_space'" << AANT_ArgumentIntegerConstant
+ << AddrSpace->getSourceRange();
+ return QualType();
+ }
+
+ // Bounds checking.
+ if (addrSpace.isSigned()) {
+ if (addrSpace.isNegative()) {
+ Diag(AttrLoc, diag::err_attribute_address_space_negative)
+ << AddrSpace->getSourceRange();
+ return QualType();
+ }
+ addrSpace.setIsSigned(false);
+ }
+
+ llvm::APSInt max(addrSpace.getBitWidth());
+ max =
+ Qualifiers::MaxAddressSpace - (unsigned)LangAS::FirstTargetAddressSpace;
+ if (addrSpace > max) {
+ Diag(AttrLoc, diag::err_attribute_address_space_too_high)
+ << (unsigned)max.getZExtValue() << AddrSpace->getSourceRange();
+ return QualType();
+ }
+
+ LangAS ASIdx =
+ getLangASFromTargetAS(static_cast<unsigned>(addrSpace.getZExtValue()));
+
+ return Context.getAddrSpaceQualType(T, ASIdx);
+ }
+
+ // A check with similar intentions as checking if a type already has an
+ // address space except for on a dependent types, basically if the
+ // current type is already a DependentAddressSpaceType then its already
+ // lined up to have another address space on it and we can't have
+ // multiple address spaces on the one pointer indirection
+ if (T->getAs<DependentAddressSpaceType>()) {
+ Diag(AttrLoc, diag::err_attribute_address_multiple_qualifiers);
+ return QualType();
+ }
+
+ return Context.getDependentAddressSpaceType(T, AddrSpace, AttrLoc);
+}
+
/// HandleAddressSpaceTypeAttribute - Process an address_space attribute on the
/// specified type. The attribute contains 1 argument, the id of the address
/// space for the type.
static void HandleAddressSpaceTypeAttribute(QualType &Type,
const AttributeList &Attr, Sema &S){
-
// If this type is already address space qualified, reject it.
// ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "No type shall be qualified by
// qualifiers for two or more different address spaces."
- if (Type.getAddressSpace()) {
+ if (Type.getAddressSpace() != LangAS::Default) {
S.Diag(Attr.getLoc(), diag::err_attribute_address_multiple_qualifiers);
Attr.setInvalid();
return;
@@ -5515,46 +5720,43 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
return;
}
- unsigned ASIdx;
+ LangAS ASIdx;
if (Attr.getKind() == AttributeList::AT_AddressSpace) {
+
// Check the attribute arguments.
if (Attr.getNumArgs() != 1) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr.getName() << 1;
- Attr.setInvalid();
- return;
- }
- Expr *ASArgExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
- llvm::APSInt addrSpace(32);
- if (ASArgExpr->isTypeDependent() || ASArgExpr->isValueDependent() ||
- !ASArgExpr->isIntegerConstantExpr(addrSpace, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
- << Attr.getName() << AANT_ArgumentIntegerConstant
- << ASArgExpr->getSourceRange();
+ << Attr.getName() << 1;
Attr.setInvalid();
return;
}
- // Bounds checking.
- if (addrSpace.isSigned()) {
- if (addrSpace.isNegative()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_address_space_negative)
- << ASArgExpr->getSourceRange();
- Attr.setInvalid();
+ Expr *ASArgExpr;
+ if (Attr.isArgIdent(0)) {
+ // Special case where the argument is a template id.
+ CXXScopeSpec SS;
+ SourceLocation TemplateKWLoc;
+ UnqualifiedId id;
+ id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc());
+
+ ExprResult AddrSpace = S.ActOnIdExpression(
+ S.getCurScope(), SS, TemplateKWLoc, id, false, false);
+ if (AddrSpace.isInvalid())
return;
- }
- addrSpace.setIsSigned(false);
+
+ ASArgExpr = static_cast<Expr *>(AddrSpace.get());
+ } else {
+ ASArgExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
}
- llvm::APSInt max(addrSpace.getBitWidth());
- max = Qualifiers::MaxAddressSpace - LangAS::FirstTargetAddressSpace;
- if (addrSpace > max) {
- S.Diag(Attr.getLoc(), diag::err_attribute_address_space_too_high)
- << (unsigned)max.getZExtValue() << ASArgExpr->getSourceRange();
+
+ // Create the DependentAddressSpaceType or append an address space onto
+ // the type.
+ QualType T = S.BuildAddressSpaceAttr(Type, ASArgExpr, Attr.getLoc());
+
+ if (!T.isNull())
+ Type = T;
+ else
Attr.setInvalid();
- return;
- }
- ASIdx = static_cast<unsigned>(addrSpace.getZExtValue()) +
- LangAS::FirstTargetAddressSpace;
} else {
// The keyword-based type attributes imply which address space to use.
switch (Attr.getKind()) {
@@ -5566,13 +5768,14 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
ASIdx = LangAS::opencl_constant; break;
case AttributeList::AT_OpenCLGenericAddressSpace:
ASIdx = LangAS::opencl_generic; break;
+ case AttributeList::AT_OpenCLPrivateAddressSpace:
+ ASIdx = LangAS::opencl_private; break;
default:
- assert(Attr.getKind() == AttributeList::AT_OpenCLPrivateAddressSpace);
- ASIdx = 0; break;
+ llvm_unreachable("Invalid address space");
}
+
+ Type = S.Context.getAddrSpaceQualType(Type, ASIdx);
}
-
- Type = S.Context.getAddrSpaceQualType(Type, ASIdx);
}
/// Does this type have a "direct" ownership qualifier? That is,
@@ -6800,6 +7003,92 @@ static void HandleOpenCLAccessAttr(QualType &CurType, const AttributeList &Attr,
}
}
+static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State,
+ QualType &T, TypeAttrLocation TAL) {
+ Declarator &D = State.getDeclarator();
+
+ // Handle the cases where address space should not be deduced.
+ //
+ // The pointee type of a pointer type is alwasy deduced since a pointer always
+ // points to some memory location which should has an address space.
+ //
+ // There are situations that at the point of certain declarations, the address
+ // space may be unknown and better to be left as default. For example, when
+ // definining a typedef or struct type, they are not associated with any
+ // specific address space. Later on, they may be used with any address space
+ // to declare a variable.
+ //
+ // The return value of a function is r-value, therefore should not have
+ // address space.
+ //
+ // The void type does not occupy memory, therefore should not have address
+ // space, except when it is used as a pointee type.
+ //
+ // Since LLVM assumes function type is in default address space, it should not
+ // have address space.
+ auto ChunkIndex = State.getCurrentChunkIndex();
+ bool IsPointee =
+ ChunkIndex > 0 &&
+ (D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::Pointer ||
+ D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::BlockPointer);
+ bool IsFuncReturnType =
+ ChunkIndex > 0 &&
+ D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::Function;
+ bool IsFuncType =
+ ChunkIndex < D.getNumTypeObjects() &&
+ D.getTypeObject(ChunkIndex).Kind == DeclaratorChunk::Function;
+ if ( // Do not deduce addr space for function return type and function type,
+ // otherwise it will fail some sema check.
+ IsFuncReturnType || IsFuncType ||
+ // Do not deduce addr space for member types of struct, except the pointee
+ // type of a pointer member type.
+ (D.getContext() == Declarator::MemberContext && !IsPointee) ||
+ // Do not deduce addr space for types used to define a typedef and the
+ // typedef itself, except the pointee type of a pointer type which is used
+ // to define the typedef.
+ (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef &&
+ !IsPointee) ||
+ // Do not deduce addr space of the void type, e.g. in f(void), otherwise
+ // it will fail some sema check.
+ (T->isVoidType() && !IsPointee))
+ return;
+
+ LangAS ImpAddr;
+ // Put OpenCL automatic variable in private address space.
+ // OpenCL v1.2 s6.5:
+ // The default address space name for arguments to a function in a
+ // program, or local variables of a function is __private. All function
+ // arguments shall be in the __private address space.
+ if (State.getSema().getLangOpts().OpenCLVersion <= 120) {
+ ImpAddr = LangAS::opencl_private;
+ } else {
+ // If address space is not set, OpenCL 2.0 defines non private default
+ // address spaces for some cases:
+ // OpenCL 2.0, section 6.5:
+ // The address space for a variable at program scope or a static variable
+ // inside a function can either be __global or __constant, but defaults to
+ // __global if not specified.
+ // (...)
+ // Pointers that are declared without pointing to a named address space
+ // point to the generic address space.
+ if (IsPointee) {
+ ImpAddr = LangAS::opencl_generic;
+ } else {
+ if (D.getContext() == Declarator::FileContext) {
+ ImpAddr = LangAS::opencl_global;
+ } else {
+ if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static ||
+ D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern) {
+ ImpAddr = LangAS::opencl_global;
+ } else {
+ ImpAddr = LangAS::opencl_private;
+ }
+ }
+ }
+ }
+ T = State.getSema().Context.getAddrSpaceQualType(T, ImpAddr);
+}
+
static void processTypeAttrs(TypeProcessingState &state, QualType &type,
TypeAttrLocation TAL, AttributeList *attrs) {
// Scan through and apply attributes to this type where it makes sense. Some
@@ -6807,7 +7096,6 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
// type, but others can be present in the type specifiers even though they
// apply to the decl. Here we apply type attributes and ignore the rest.
- bool hasOpenCLAddressSpace = false;
while (attrs) {
AttributeList &attr = *attrs;
attrs = attr.getNext(); // reset to the next here due to early loop continue
@@ -6870,7 +7158,6 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
case AttributeList::AT_AddressSpace:
HandleAddressSpaceTypeAttribute(type, attr, state.getSema());
attr.setUsedAsTypeAttr();
- hasOpenCLAddressSpace = true;
break;
OBJC_POINTER_TYPE_ATTRS_CASELIST:
if (!handleObjCPointerTypeAttr(state, attr, type))
@@ -6971,70 +7258,40 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
}
}
- // If address space is not set, OpenCL 2.0 defines non private default
- // address spaces for some cases:
- // OpenCL 2.0, section 6.5:
- // The address space for a variable at program scope or a static variable
- // inside a function can either be __global or __constant, but defaults to
- // __global if not specified.
- // (...)
- // Pointers that are declared without pointing to a named address space point
- // to the generic address space.
- if (state.getSema().getLangOpts().OpenCLVersion >= 200 &&
- !hasOpenCLAddressSpace && type.getAddressSpace() == 0 &&
- (TAL == TAL_DeclSpec || TAL == TAL_DeclChunk)) {
- Declarator &D = state.getDeclarator();
- if (state.getCurrentChunkIndex() > 0 &&
- (D.getTypeObject(state.getCurrentChunkIndex() - 1).Kind ==
- DeclaratorChunk::Pointer ||
- D.getTypeObject(state.getCurrentChunkIndex() - 1).Kind ==
- DeclaratorChunk::BlockPointer)) {
- type = state.getSema().Context.getAddrSpaceQualType(
- type, LangAS::opencl_generic);
- } else if (state.getCurrentChunkIndex() == 0 &&
- D.getContext() == Declarator::FileContext &&
- !D.isFunctionDeclarator() && !D.isFunctionDefinition() &&
- D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
- !type->isSamplerT())
- type = state.getSema().Context.getAddrSpaceQualType(
- type, LangAS::opencl_global);
- else if (state.getCurrentChunkIndex() == 0 &&
- D.getContext() == Declarator::BlockContext &&
- D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)
- type = state.getSema().Context.getAddrSpaceQualType(
- type, LangAS::opencl_global);
- }
+ if (!state.getSema().getLangOpts().OpenCL ||
+ type.getAddressSpace() != LangAS::Default)
+ return;
+
+ deduceOpenCLImplicitAddrSpace(state, type, TAL);
}
void Sema::completeExprArrayBound(Expr *E) {
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
if (isTemplateInstantiation(Var->getTemplateSpecializationKind())) {
- SourceLocation PointOfInstantiation = E->getExprLoc();
-
- if (MemberSpecializationInfo *MSInfo =
- Var->getMemberSpecializationInfo()) {
- // If we don't already have a point of instantiation, this is it.
- if (MSInfo->getPointOfInstantiation().isInvalid()) {
- MSInfo->setPointOfInstantiation(PointOfInstantiation);
+ auto *Def = Var->getDefinition();
+ if (!Def) {
+ SourceLocation PointOfInstantiation = E->getExprLoc();
+ InstantiateVariableDefinition(PointOfInstantiation, Var);
+ Def = Var->getDefinition();
- // This is a modification of an existing AST node. Notify
- // listeners.
- if (ASTMutationListener *L = getASTMutationListener())
- L->StaticDataMemberInstantiated(Var);
+ // If we don't already have a point of instantiation, and we managed
+ // to instantiate a definition, this is the point of instantiation.
+ // Otherwise, we don't request an end-of-TU instantiation, so this is
+ // not a point of instantiation.
+ // FIXME: Is this really the right behavior?
+ if (Var->getPointOfInstantiation().isInvalid() && Def) {
+ assert(Var->getTemplateSpecializationKind() ==
+ TSK_ImplicitInstantiation &&
+ "explicit instantiation with no point of instantiation");
+ Var->setTemplateSpecializationKind(
+ Var->getTemplateSpecializationKind(), PointOfInstantiation);
}
- } else {
- VarTemplateSpecializationDecl *VarSpec =
- cast<VarTemplateSpecializationDecl>(Var);
- if (VarSpec->getPointOfInstantiation().isInvalid())
- VarSpec->setPointOfInstantiation(PointOfInstantiation);
}
- InstantiateVariableDefinition(PointOfInstantiation, Var);
-
- // Update the type to the newly instantiated definition's type both
- // here and within the expression.
- if (VarDecl *Def = Var->getDefinition()) {
+ // Update the type to the definition's type both here and within the
+ // expression.
+ if (Def) {
DRE->setDecl(Def);
QualType T = Def->getType();
DRE->setType(T);
@@ -7303,11 +7560,15 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
// Give the external AST source a chance to complete the type.
if (auto *Source = Context.getExternalSource()) {
- if (Tag)
- Source->CompleteType(Tag->getDecl());
- else
- Source->CompleteType(IFace->getDecl());
-
+ if (Tag) {
+ TagDecl *TagD = Tag->getDecl();
+ if (TagD->hasExternalLexicalStorage())
+ Source->CompleteType(TagD);
+ } else {
+ ObjCInterfaceDecl *IFaceD = IFace->getDecl();
+ if (IFaceD->hasExternalLexicalStorage())
+ Source->CompleteType(IFace->getDecl());
+ }
// If the external source completed the type, go through the motions
// again to ensure we're allowed to use the completed type.
if (!T->isIncompleteType())
diff --git a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
index 91da9f88c59b8..96969ea87a135 100644
--- a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
+++ b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
@@ -835,6 +835,18 @@ public:
Expr *SizeExpr,
SourceLocation AttributeLoc);
+ /// \brief Build a new DependentAddressSpaceType or return the pointee
+ /// type variable with the correct address space (retrieved from
+ /// AddrSpaceExpr) applied to it. The former will be returned in cases
+ /// where the address space remains dependent.
+ ///
+ /// By default, performs semantic analysis when building the type with address
+ /// space applied. Subclasses may override this routine to provide different
+ /// behavior.
+ QualType RebuildDependentAddressSpaceType(QualType PointeeType,
+ Expr *AddrSpaceExpr,
+ SourceLocation AttributeLoc);
+
/// \brief Build a new function type.
///
/// By default, performs semantic analysis when building the function type.
@@ -1666,6 +1678,22 @@ public:
ReductionId, UnresolvedReductions);
}
+ /// Build a new OpenMP 'in_reduction' clause.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *
+ RebuildOMPInReductionClause(ArrayRef<Expr *> VarList, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation ColonLoc,
+ SourceLocation EndLoc,
+ CXXScopeSpec &ReductionIdScopeSpec,
+ const DeclarationNameInfo &ReductionId,
+ ArrayRef<Expr *> UnresolvedReductions) {
+ return getSema().ActOnOpenMPInReductionClause(
+ VarList, StartLoc, LParenLoc, ColonLoc, EndLoc, ReductionIdScopeSpec,
+ ReductionId, UnresolvedReductions);
+ }
+
/// \brief Build a new OpenMP 'linear' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
@@ -4171,7 +4199,6 @@ TreeTransform<Derived>::TransformTypeWithDeducedTST(TypeSourceInfo *DI) {
TypeLoc TL = DI->getTypeLoc();
TLB.reserve(TL.getFullDataSize());
- Qualifiers Quals;
auto QTL = TL.getAs<QualifiedTypeLoc>();
if (QTL)
TL = QTL.getUnqualifiedLoc();
@@ -4769,7 +4796,53 @@ QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType(
return Result;
}
-template<typename Derived>
+template <typename Derived>
+QualType TreeTransform<Derived>::TransformDependentAddressSpaceType(
+ TypeLocBuilder &TLB, DependentAddressSpaceTypeLoc TL) {
+ const DependentAddressSpaceType *T = TL.getTypePtr();
+
+ QualType pointeeType = getDerived().TransformType(T->getPointeeType());
+
+ if (pointeeType.isNull())
+ return QualType();
+
+ // Address spaces are constant expressions.
+ EnterExpressionEvaluationContext Unevaluated(
+ SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated);
+
+ ExprResult AddrSpace = getDerived().TransformExpr(T->getAddrSpaceExpr());
+ AddrSpace = SemaRef.ActOnConstantExpression(AddrSpace);
+ if (AddrSpace.isInvalid())
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() || pointeeType != T->getPointeeType() ||
+ AddrSpace.get() != T->getAddrSpaceExpr()) {
+ Result = getDerived().RebuildDependentAddressSpaceType(
+ pointeeType, AddrSpace.get(), T->getAttributeLoc());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ // Result might be dependent or not.
+ if (isa<DependentAddressSpaceType>(Result)) {
+ DependentAddressSpaceTypeLoc NewTL =
+ TLB.push<DependentAddressSpaceTypeLoc>(Result);
+
+ NewTL.setAttrOperandParensRange(TL.getAttrOperandParensRange());
+ NewTL.setAttrExprOperand(TL.getAttrExprOperand());
+ NewTL.setAttrNameLoc(TL.getAttrNameLoc());
+
+ } else {
+ TypeSourceInfo *DI = getSema().Context.getTrivialTypeSourceInfo(
+ Result, getDerived().getBaseLocation());
+ TransformType(TLB, DI->getTypeLoc());
+ }
+
+ return Result;
+}
+
+template <typename Derived>
QualType TreeTransform<Derived>::TransformVectorType(TypeLocBuilder &TLB,
VectorTypeLoc TL) {
const VectorType *T = TL.getTypePtr();
@@ -6585,8 +6658,7 @@ TreeTransform<Derived>::TransformSwitchStmt(SwitchStmt *S) {
// Rebuild the switch statement.
StmtResult Switch
- = getDerived().RebuildSwitchStmtStart(S->getSwitchLoc(),
- S->getInit(), Cond);
+ = getDerived().RebuildSwitchStmtStart(S->getSwitchLoc(), Init.get(), Cond);
if (Switch.isInvalid())
return StmtError();
@@ -8461,6 +8533,51 @@ OMPClause *TreeTransform<Derived>::TransformOMPTaskReductionClause(
template <typename Derived>
OMPClause *
+TreeTransform<Derived>::TransformOMPInReductionClause(OMPInReductionClause *C) {
+ llvm::SmallVector<Expr *, 16> Vars;
+ Vars.reserve(C->varlist_size());
+ for (auto *VE : C->varlists()) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
+ if (EVar.isInvalid())
+ return nullptr;
+ Vars.push_back(EVar.get());
+ }
+ CXXScopeSpec ReductionIdScopeSpec;
+ ReductionIdScopeSpec.Adopt(C->getQualifierLoc());
+
+ DeclarationNameInfo NameInfo = C->getNameInfo();
+ if (NameInfo.getName()) {
+ NameInfo = getDerived().TransformDeclarationNameInfo(NameInfo);
+ if (!NameInfo.getName())
+ return nullptr;
+ }
+ // Build a list of all UDR decls with the same names ranged by the Scopes.
+ // The Scope boundary is a duplication of the previous decl.
+ llvm::SmallVector<Expr *, 16> UnresolvedReductions;
+ for (auto *E : C->reduction_ops()) {
+ // Transform all the decls.
+ if (E) {
+ auto *ULE = cast<UnresolvedLookupExpr>(E);
+ UnresolvedSet<8> Decls;
+ for (auto *D : ULE->decls()) {
+ NamedDecl *InstD =
+ cast<NamedDecl>(getDerived().TransformDecl(E->getExprLoc(), D));
+ Decls.addDecl(InstD, InstD->getAccess());
+ }
+ UnresolvedReductions.push_back(UnresolvedLookupExpr::Create(
+ SemaRef.Context, /*NamingClass=*/nullptr,
+ ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), NameInfo,
+ /*ADL=*/true, ULE->isOverloaded(), Decls.begin(), Decls.end()));
+ } else
+ UnresolvedReductions.push_back(nullptr);
+ }
+ return getDerived().RebuildOMPInReductionClause(
+ Vars, C->getLocStart(), C->getLParenLoc(), C->getColonLoc(),
+ C->getLocEnd(), ReductionIdScopeSpec, NameInfo, UnresolvedReductions);
+}
+
+template <typename Derived>
+OMPClause *
TreeTransform<Derived>::TransformOMPLinearClause(OMPLinearClause *C) {
llvm::SmallVector<Expr *, 16> Vars;
Vars.reserve(C->varlist_size());
@@ -12253,10 +12370,18 @@ TreeTransform<Derived>::RebuildDependentSizedArrayType(QualType ElementType,
IndexTypeQuals, BracketsRange);
}
-template<typename Derived>
-QualType TreeTransform<Derived>::RebuildVectorType(QualType ElementType,
- unsigned NumElements,
- VectorType::VectorKind VecKind) {
+template <typename Derived>
+QualType TreeTransform<Derived>::RebuildDependentAddressSpaceType(
+ QualType PointeeType, Expr *AddrSpaceExpr, SourceLocation AttributeLoc) {
+ return SemaRef.BuildAddressSpaceAttr(PointeeType, AddrSpaceExpr,
+ AttributeLoc);
+}
+
+template <typename Derived>
+QualType
+TreeTransform<Derived>::RebuildVectorType(QualType ElementType,
+ unsigned NumElements,
+ VectorType::VectorKind VecKind) {
// FIXME: semantic checking!
return SemaRef.Context.getVectorType(ElementType, NumElements, VecKind);
}
@@ -12510,10 +12635,14 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
// Compute the transformed set of functions (and function templates) to be
// used during overload resolution.
UnresolvedSet<16> Functions;
+ bool RequiresADL;
if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(Callee)) {
- assert(ULE->requiresADL());
Functions.append(ULE->decls_begin(), ULE->decls_end());
+ // If the overload could not be resolved in the template definition
+ // (because we had a dependent argument), ADL is performed as part of
+ // template instantiation.
+ RequiresADL = ULE->requiresADL();
} else {
// If we've resolved this to a particular non-member function, just call
// that function. If we resolved it to a member function,
@@ -12521,6 +12650,7 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
NamedDecl *ND = cast<DeclRefExpr>(Callee)->getDecl();
if (!isa<CXXMethodDecl>(ND))
Functions.addDecl(ND);
+ RequiresADL = false;
}
// Add any functions found via argument-dependent lookup.
@@ -12531,7 +12661,8 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
if (NumArgs == 1 || isPostIncDec) {
UnaryOperatorKind Opc
= UnaryOperator::getOverloadedOpcode(Op, isPostIncDec);
- return SemaRef.CreateOverloadedUnaryOp(OpLoc, Opc, Functions, First);
+ return SemaRef.CreateOverloadedUnaryOp(OpLoc, Opc, Functions, First,
+ RequiresADL);
}
if (Op == OO_Subscript) {
@@ -12555,8 +12686,8 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
// Create the overloaded operator invocation for binary operators.
BinaryOperatorKind Opc = BinaryOperator::getOverloadedOpcode(Op);
- ExprResult Result
- = SemaRef.CreateOverloadedBinOp(OpLoc, Opc, Functions, Args[0], Args[1]);
+ ExprResult Result = SemaRef.CreateOverloadedBinOp(
+ OpLoc, Opc, Functions, Args[0], Args[1], RequiresADL);
if (Result.isInvalid())
return ExprError();
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp
index 684ec243035e9..9c6f03cd0bb7d 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp
@@ -91,6 +91,9 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) {
case BuiltinType::LongDouble:
ID = PREDEF_TYPE_LONGDOUBLE_ID;
break;
+ case BuiltinType::Float16:
+ ID = PREDEF_TYPE_FLOAT16_ID;
+ break;
case BuiltinType::Float128:
ID = PREDEF_TYPE_FLOAT128_ID;
break;
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h
index cbc5f04738b14..6aca453bbb890 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h
@@ -27,7 +27,8 @@ enum DeclUpdateKind {
UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION,
UPD_CXX_ADDED_ANONYMOUS_NAMESPACE,
UPD_CXX_ADDED_FUNCTION_DEFINITION,
- UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER,
+ UPD_CXX_ADDED_VAR_DEFINITION,
+ UPD_CXX_POINT_OF_INSTANTIATION,
UPD_CXX_INSTANTIATED_CLASS_DEFINITION,
UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT,
UPD_CXX_INSTANTIATED_DEFAULT_MEMBER_INITIALIZER,
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
index 50be74f6bf6e8..111ac4fcdaa42 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
@@ -1,4 +1,4 @@
-//===-- ASTReader.cpp - AST File Reader -----------------------------------===//
+//===- ASTReader.cpp - AST File Reader ------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -19,28 +19,41 @@
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/ASTUnresolvedSet.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclGroup.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/ODRHash.h"
#include "clang/AST/RawCommentList.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeLocVisitor.h"
#include "clang/AST/UnresolvedSet.h"
#include "clang/Basic/CommentOptions.h"
+#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/ExceptionSpecificationType.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemOptions.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/MemoryBufferCache.h"
+#include "clang/Basic/Module.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/OperatorKinds.h"
+#include "clang/Basic/PragmaKinds.h"
#include "clang/Basic/Sanitizers.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/SourceManagerInternals.h"
#include "clang/Basic/Specifiers.h"
@@ -57,41 +70,61 @@
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorOptions.h"
+#include "clang/Lex/Token.h"
+#include "clang/Sema/ObjCMethodList.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/Weak.h"
+#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Serialization/ASTDeserializationListener.h"
+#include "clang/Serialization/ContinuousRangeMap.h"
#include "clang/Serialization/GlobalModuleIndex.h"
+#include "clang/Serialization/Module.h"
+#include "clang/Serialization/ModuleFileExtension.h"
#include "clang/Serialization/ModuleManager.h"
#include "clang/Serialization/SerializationDiagnostic.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SaveAndRestore.h"
+#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
+#include <cstddef>
#include <cstdint>
#include <cstdio>
-#include <cstring>
#include <ctime>
#include <iterator>
#include <limits>
#include <map>
#include <memory>
-#include <new>
#include <string>
#include <system_error>
#include <tuple>
@@ -171,19 +204,23 @@ bool ChainedASTReaderListener::ReadPreprocessorOptions(
SuggestedPredefines) ||
Second->ReadPreprocessorOptions(PPOpts, Complain, SuggestedPredefines);
}
+
void ChainedASTReaderListener::ReadCounter(const serialization::ModuleFile &M,
unsigned Value) {
First->ReadCounter(M, Value);
Second->ReadCounter(M, Value);
}
+
bool ChainedASTReaderListener::needsInputFileVisitation() {
return First->needsInputFileVisitation() ||
Second->needsInputFileVisitation();
}
+
bool ChainedASTReaderListener::needsSystemInputFileVisitation() {
return First->needsSystemInputFileVisitation() ||
Second->needsSystemInputFileVisitation();
}
+
void ChainedASTReaderListener::visitModuleFile(StringRef Filename,
ModuleKind Kind) {
First->visitModuleFile(Filename, Kind);
@@ -216,7 +253,7 @@ void ChainedASTReaderListener::readModuleFileExtension(
// PCH validator implementation
//===----------------------------------------------------------------------===//
-ASTReaderListener::~ASTReaderListener() {}
+ASTReaderListener::~ASTReaderListener() = default;
/// \brief Compare the given set of language options against an existing set of
/// language options.
@@ -409,17 +446,16 @@ bool PCHValidator::ReadTargetOptions(const TargetOptions &TargetOpts,
namespace {
- typedef llvm::StringMap<std::pair<StringRef, bool /*IsUndef*/> >
- MacroDefinitionsMap;
- typedef llvm::DenseMap<DeclarationName, SmallVector<NamedDecl *, 8> >
- DeclsMap;
+using MacroDefinitionsMap =
+ llvm::StringMap<std::pair<StringRef, bool /*IsUndef*/>>;
+using DeclsMap = llvm::DenseMap<DeclarationName, SmallVector<NamedDecl *, 8>>;
-} // end anonymous namespace
+} // namespace
static bool checkDiagnosticGroupMappings(DiagnosticsEngine &StoredDiags,
DiagnosticsEngine &Diags,
bool Complain) {
- typedef DiagnosticsEngine::Level Level;
+ using Level = DiagnosticsEngine::Level;
// Check current mappings for new -Werror mappings, and the stored mappings
// for cases that were explicitly mapped to *not* be errors that are now
@@ -603,8 +639,8 @@ static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts,
std::pair<StringRef, bool> Existing = ExistingMacros[MacroName];
// Check whether we know anything about this macro name or not.
- llvm::StringMap<std::pair<StringRef, bool /*IsUndef*/> >::iterator Known
- = ASTFileMacros.find(MacroName);
+ llvm::StringMap<std::pair<StringRef, bool /*IsUndef*/>>::iterator Known =
+ ASTFileMacros.find(MacroName);
if (!Validate || Known == ASTFileMacros.end()) {
// FIXME: Check whether this identifier was referenced anywhere in the
// AST file. If so, we should reject the AST file. Unfortunately, this
@@ -770,6 +806,7 @@ unsigned ASTSelectorLookupTrait::ComputeHash(Selector Sel) {
std::pair<unsigned, unsigned>
ASTSelectorLookupTrait::ReadKeyDataLength(const unsigned char*& d) {
using namespace llvm::support;
+
unsigned KeyLen = endian::readNext<uint16_t, little, unaligned>(d);
unsigned DataLen = endian::readNext<uint16_t, little, unaligned>(d);
return std::make_pair(KeyLen, DataLen);
@@ -778,6 +815,7 @@ ASTSelectorLookupTrait::ReadKeyDataLength(const unsigned char*& d) {
ASTSelectorLookupTrait::internal_key_type
ASTSelectorLookupTrait::ReadKey(const unsigned char* d, unsigned) {
using namespace llvm::support;
+
SelectorTable &SelTable = Reader.getContext().Selectors;
unsigned N = endian::readNext<uint16_t, little, unaligned>(d);
IdentifierInfo *FirstII = Reader.getLocalIdentifier(
@@ -838,6 +876,7 @@ unsigned ASTIdentifierLookupTraitBase::ComputeHash(const internal_key_type& a) {
std::pair<unsigned, unsigned>
ASTIdentifierLookupTraitBase::ReadKeyDataLength(const unsigned char*& d) {
using namespace llvm::support;
+
unsigned DataLen = endian::readNext<uint16_t, little, unaligned>(d);
unsigned KeyLen = endian::readNext<uint16_t, little, unaligned>(d);
return std::make_pair(KeyLen, DataLen);
@@ -868,6 +907,7 @@ static bool readBit(unsigned &Bits) {
IdentID ASTIdentifierLookupTrait::ReadIdentifierID(const unsigned char *d) {
using namespace llvm::support;
+
unsigned RawID = endian::readNext<uint32_t, little, unaligned>(d);
return Reader.getGlobalIdentifierID(F, RawID >> 1);
}
@@ -885,6 +925,7 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
const unsigned char* d,
unsigned DataLen) {
using namespace llvm::support;
+
unsigned RawID = endian::readNext<uint32_t, little, unaligned>(d);
bool IsInteresting = RawID & 0x01;
@@ -1027,6 +1068,7 @@ unsigned DeclarationNameKey::getHash() const {
ModuleFile *
ASTDeclContextNameLookupTrait::ReadFileRef(const unsigned char *&d) {
using namespace llvm::support;
+
uint32_t ModuleFileID = endian::readNext<uint32_t, little, unaligned>(d);
return Reader.getLocalModuleFile(F, ModuleFileID);
}
@@ -1034,6 +1076,7 @@ ASTDeclContextNameLookupTrait::ReadFileRef(const unsigned char *&d) {
std::pair<unsigned, unsigned>
ASTDeclContextNameLookupTrait::ReadKeyDataLength(const unsigned char *&d) {
using namespace llvm::support;
+
unsigned KeyLen = endian::readNext<uint16_t, little, unaligned>(d);
unsigned DataLen = endian::readNext<uint16_t, little, unaligned>(d);
return std::make_pair(KeyLen, DataLen);
@@ -1079,6 +1122,7 @@ void ASTDeclContextNameLookupTrait::ReadDataInto(internal_key_type,
unsigned DataLen,
data_type_builder &Val) {
using namespace llvm::support;
+
for (unsigned NumDecls = DataLen / 4; NumDecls; --NumDecls) {
uint32_t LocalID = endian::readNext<uint32_t, little, unaligned>(d);
Val.insert(Reader.getGlobalDeclID(F, LocalID));
@@ -1176,6 +1220,7 @@ bool ASTReader::ParseLineTable(ModuleFile &F,
// Parse the file names
std::map<int, int> FileIDs;
+ FileIDs[-1] = -1; // For unspecified filenames.
for (unsigned I = 0; Record[Idx]; ++I) {
// Extract the file name
auto Filename = ReadPath(F, Record, Idx);
@@ -1278,7 +1323,9 @@ resolveFileRelativeToOriginalDir(const std::string &Filename,
const std::string &CurrDir) {
assert(OriginalDir != CurrDir &&
"No point trying to resolve the file if the PCH dir didn't change");
+
using namespace llvm::sys;
+
SmallString<128> filePath(Filename);
fs::make_absolute(filePath);
assert(path::is_absolute(OriginalDir));
@@ -1672,6 +1719,7 @@ bool HeaderFileInfoTrait::EqualKey(internal_key_ref a, internal_key_ref b) {
std::pair<unsigned, unsigned>
HeaderFileInfoTrait::ReadKeyDataLength(const unsigned char*& d) {
using namespace llvm::support;
+
unsigned KeyLen = (unsigned) endian::readNext<uint16_t, little, unaligned>(d);
unsigned DataLen = (unsigned) *d++;
return std::make_pair(KeyLen, DataLen);
@@ -1680,6 +1728,7 @@ HeaderFileInfoTrait::ReadKeyDataLength(const unsigned char*& d) {
HeaderFileInfoTrait::internal_key_type
HeaderFileInfoTrait::ReadKey(const unsigned char *d, unsigned) {
using namespace llvm::support;
+
internal_key_type ikey;
ikey.Size = off_t(endian::readNext<uint64_t, little, unaligned>(d));
ikey.ModTime = time_t(endian::readNext<uint64_t, little, unaligned>(d));
@@ -1691,8 +1740,9 @@ HeaderFileInfoTrait::ReadKey(const unsigned char *d, unsigned) {
HeaderFileInfoTrait::data_type
HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d,
unsigned DataLen) {
- const unsigned char *End = d + DataLen;
using namespace llvm::support;
+
+ const unsigned char *End = d + DataLen;
HeaderFileInfo HFI;
unsigned Flags = *d++;
// FIXME: Refactor with mergeHeaderFileInfo in HeaderSearch.cpp.
@@ -1813,7 +1863,7 @@ namespace {
unsigned PriorGeneration;
unsigned &NumIdentifierLookups;
unsigned &NumIdentifierLookupHits;
- IdentifierInfo *Found;
+ IdentifierInfo *Found = nullptr;
public:
IdentifierLookupVisitor(StringRef Name, unsigned PriorGeneration,
@@ -1822,10 +1872,7 @@ namespace {
: Name(Name), NameHash(ASTIdentifierLookupTrait::ComputeHash(Name)),
PriorGeneration(PriorGeneration),
NumIdentifierLookups(NumIdentifierLookups),
- NumIdentifierLookupHits(NumIdentifierLookupHits),
- Found()
- {
- }
+ NumIdentifierLookupHits(NumIdentifierLookupHits) {}
bool operator()(ModuleFile &M) {
// If we've already searched this module file, skip it now.
@@ -1858,7 +1905,7 @@ namespace {
IdentifierInfo *getIdentifierInfo() const { return Found; }
};
-} // end anonymous namespace
+} // namespace
void ASTReader::updateOutOfDateIdentifier(IdentifierInfo &II) {
// Note that we are loading an identifier.
@@ -1985,10 +2032,9 @@ void ASTReader::resolvePendingMacro(IdentifierInfo *II,
MD = PP.AllocateDefMacroDirective(MI, Loc);
break;
}
- case MacroDirective::MD_Undefine: {
+ case MacroDirective::MD_Undefine:
MD = PP.AllocateUndefMacroDirective(Loc);
break;
- }
case MacroDirective::MD_Visibility:
bool isPublic = Record[Idx++];
MD = PP.AllocateVisibilityMacroDirective(Loc, isPublic);
@@ -2060,14 +2106,12 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
StringRef Filename = FI.Filename;
const FileEntry *File = FileMgr.getFile(Filename, /*OpenFile=*/false);
-
// If we didn't find the file, resolve it relative to the
// original directory from which this AST file was created.
- if (File == nullptr && !F.OriginalDir.empty() && !CurrentDir.empty() &&
- F.OriginalDir != CurrentDir) {
- std::string Resolved = resolveFileRelativeToOriginalDir(Filename,
- F.OriginalDir,
- CurrentDir);
+ if (File == nullptr && !F.OriginalDir.empty() && !F.BaseDirectory.empty() &&
+ F.OriginalDir != F.BaseDirectory) {
+ std::string Resolved = resolveFileRelativeToOriginalDir(
+ Filename, F.OriginalDir, F.BaseDirectory);
if (!Resolved.empty())
File = FileMgr.getFile(Resolved);
}
@@ -2126,7 +2170,7 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
if (Complain) {
// Build a list of the PCH imports that got us here (in reverse).
SmallVector<ModuleFile *, 4> ImportStack(1, &F);
- while (ImportStack.back()->ImportedBy.size() > 0)
+ while (!ImportStack.back()->ImportedBy.empty())
ImportStack.push_back(ImportStack.back()->ImportedBy[0]);
// The top-level PCH is stale.
@@ -2487,7 +2531,23 @@ ASTReader::ReadControlBlock(ModuleFile &F,
{{(uint32_t)Record[Idx++], (uint32_t)Record[Idx++],
(uint32_t)Record[Idx++], (uint32_t)Record[Idx++],
(uint32_t)Record[Idx++]}}};
- auto ImportedFile = ReadPath(F, Record, Idx);
+
+ std::string ImportedName = ReadString(Record, Idx);
+ std::string ImportedFile;
+
+ // For prebuilt and explicit modules first consult the file map for
+ // an override. Note that here we don't search prebuilt module
+ // directories, only the explicit name to file mappings. Also, we will
+ // still verify the size/signature making sure it is essentially the
+ // same file but perhaps in a different location.
+ if (ImportedKind == MK_PrebuiltModule || ImportedKind == MK_ExplicitModule)
+ ImportedFile = PP.getHeaderSearchInfo().getPrebuiltModuleFileName(
+ ImportedName, /*FileMapOnly*/ true);
+
+ if (ImportedFile.empty())
+ ImportedFile = ReadPath(F, Record, Idx);
+ else
+ SkipPath(Record, Idx);
// If our client can't cope with us being out of date, we can't cope with
// our dependency being missing.
@@ -2608,7 +2668,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
case llvm::BitstreamEntry::Error:
Error("error at end of module block in AST file");
return Failure;
- case llvm::BitstreamEntry::EndBlock: {
+ case llvm::BitstreamEntry::EndBlock:
// Outside of C++, we do not store a lookup map for the translation unit.
// Instead, mark it as needing a lookup map to be built if this module
// contains any declarations lexically within it (which it always does!).
@@ -2621,7 +2681,6 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
return Success;
- }
case llvm::BitstreamEntry::SubBlock:
switch (Entry.ID) {
case DECLTYPES_BLOCK_ID:
@@ -2981,8 +3040,20 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
case PP_CONDITIONAL_STACK:
if (!Record.empty()) {
+ unsigned Idx = 0, End = Record.size() - 1;
+ bool ReachedEOFWhileSkipping = Record[Idx++];
+ llvm::Optional<Preprocessor::PreambleSkipInfo> SkipInfo;
+ if (ReachedEOFWhileSkipping) {
+ SourceLocation HashToken = ReadSourceLocation(F, Record, Idx);
+ SourceLocation IfTokenLoc = ReadSourceLocation(F, Record, Idx);
+ bool FoundNonSkipPortion = Record[Idx++];
+ bool FoundElse = Record[Idx++];
+ SourceLocation ElseLoc = ReadSourceLocation(F, Record, Idx);
+ SkipInfo.emplace(HashToken, IfTokenLoc, FoundNonSkipPortion,
+ FoundElse, ElseLoc);
+ }
SmallVector<PPConditionalInfo, 4> ConditionalStack;
- for (unsigned Idx = 0, N = Record.size() - 1; Idx < N; /* in loop */) {
+ while (Idx < End) {
auto Loc = ReadSourceLocation(F, Record, Idx);
bool WasSkipping = Record[Idx++];
bool FoundNonSkip = Record[Idx++];
@@ -2990,7 +3061,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
ConditionalStack.push_back(
{Loc, WasSkipping, FoundNonSkip, FoundElse});
}
- PP.setReplayablePreambleConditionalStack(ConditionalStack);
+ PP.setReplayablePreambleConditionalStack(ConditionalStack, SkipInfo);
}
break;
@@ -3144,7 +3215,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
}
- case DECL_UPDATE_OFFSETS: {
+ case DECL_UPDATE_OFFSETS:
if (Record.size() % 2 != 0) {
Error("invalid DECL_UPDATE_OFFSETS block in AST file");
return Failure;
@@ -3160,9 +3231,8 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
PendingUpdateRecord(ID, D, /*JustLoaded=*/false));
}
break;
- }
- case OBJC_CATEGORIES_MAP: {
+ case OBJC_CATEGORIES_MAP:
if (F.LocalNumObjCCategoriesInMap != 0) {
Error("duplicate OBJC_CATEGORIES_MAP record in AST file");
return Failure;
@@ -3171,7 +3241,6 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
F.LocalNumObjCCategoriesInMap = Record[0];
F.ObjCCategoriesMap = (const ObjCCategoriesInfo *)Blob.data();
break;
- }
case OBJC_CATEGORIES:
F.ObjCCategories.swap(Record);
@@ -3185,7 +3254,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
CUDASpecialDeclRefs.push_back(getGlobalDeclID(F, Record[I]));
break;
- case HEADER_SEARCH_TABLE: {
+ case HEADER_SEARCH_TABLE:
F.HeaderFileInfoTableData = Blob.data();
F.LocalNumHeaderFileInfos = Record[1];
if (Record[0]) {
@@ -3202,7 +3271,6 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
PP.getHeaderSearchInfo().SetExternalLookup(this);
}
break;
- }
case FP_PRAGMA_OPTIONS:
// Later tables overwrite earlier ones.
@@ -3270,6 +3338,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
ReadSourceLocation(F, Record, I).getRawEncoding());
}
break;
+
case DELETE_EXPRS_TO_ANALYZE:
for (unsigned I = 0, N = Record.size(); I != N;) {
DelayedDeleteExprs.push_back(getGlobalDeclID(F, Record[I++]));
@@ -3283,7 +3352,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
break;
- case IMPORTED_MODULES: {
+ case IMPORTED_MODULES:
if (!F.isModule()) {
// If we aren't loading a module (which has its own exports), make
// all of the imported modules visible.
@@ -3299,7 +3368,6 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
}
break;
- }
case MACRO_OFFSET: {
if (F.LocalNumMacros != 0) {
@@ -3325,10 +3393,9 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
}
- case LATE_PARSED_TEMPLATE: {
+ case LATE_PARSED_TEMPLATE:
LateParsedTemplates.append(Record.begin(), Record.end());
break;
- }
case OPTIMIZE_PRAGMA_OPTIONS:
if (Record.size() != 1) {
@@ -3384,6 +3451,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
PragmaPackStackEntry Entry;
Entry.Value = Record[Idx++];
Entry.Location = ReadSourceLocation(F, Record[Idx++]);
+ Entry.PushLocation = ReadSourceLocation(F, Record[Idx++]);
PragmaPackStrings.push_back(ReadString(Record, Idx));
Entry.SlotLabel = PragmaPackStrings.back();
PragmaPackStack.push_back(Entry);
@@ -3409,8 +3477,7 @@ void ASTReader::ReadModuleOffsetMap(ModuleFile &F) const {
}
// Continuous range maps we may be updating in our module.
- typedef ContinuousRangeMap<uint32_t, int, 2>::Builder
- RemapBuilder;
+ using RemapBuilder = ContinuousRangeMap<uint32_t, int, 2>::Builder;
RemapBuilder SLocRemap(F.SLocRemap);
RemapBuilder IdentifierRemap(F.IdentifierRemap);
RemapBuilder MacroRemap(F.MacroRemap);
@@ -3421,12 +3488,18 @@ void ASTReader::ReadModuleOffsetMap(ModuleFile &F) const {
RemapBuilder TypeRemap(F.TypeRemap);
while (Data < DataEnd) {
- // FIXME: Looking up dependency modules by filename is horrible.
+ // FIXME: Looking up dependency modules by filename is horrible. Let's
+ // start fixing this with prebuilt and explicit modules and see how it
+ // goes...
using namespace llvm::support;
+ ModuleKind Kind = static_cast<ModuleKind>(
+ endian::readNext<uint8_t, little, unaligned>(Data));
uint16_t Len = endian::readNext<uint16_t, little, unaligned>(Data);
StringRef Name = StringRef((const char*)Data, Len);
Data += Len;
- ModuleFile *OM = ModuleMgr.lookup(Name);
+ ModuleFile *OM = (Kind == MK_PrebuiltModule || Kind == MK_ExplicitModule
+ ? ModuleMgr.lookupByModuleName(Name)
+ : ModuleMgr.lookupByFileName(Name));
if (!OM) {
std::string Msg =
"SourceLocation remap refers to unknown module, cannot find ";
@@ -3497,15 +3570,22 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F,
if (!ModMap) {
assert(ImportedBy && "top-level import should be verified");
if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) {
- if (auto *ASTFE = M ? M->getASTFile() : nullptr)
+ if (auto *ASTFE = M ? M->getASTFile() : nullptr) {
// This module was defined by an imported (explicit) module.
Diag(diag::err_module_file_conflict) << F.ModuleName << F.FileName
<< ASTFE->getName();
- else
+ } else {
// This module was built with a different module map.
Diag(diag::err_imported_module_not_found)
<< F.ModuleName << F.FileName << ImportedBy->FileName
<< F.ModuleMapPath;
+ // In case it was imported by a PCH, there's a chance the user is
+ // just missing to include the search path to the directory containing
+ // the modulemap.
+ if (ImportedBy->Kind == MK_PCH)
+ Diag(diag::note_imported_by_pch_module_not_found)
+ << llvm::sys::path::parent_path(F.ModuleMapPath);
+ }
}
return OutOfDate;
}
@@ -3568,7 +3648,6 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F,
return Success;
}
-
/// \brief Move the given method to the back of the global list of methods.
static void moveMethodToBackOfGlobalList(Sema &S, ObjCMethodDecl *Method) {
// Find the entry for this selector in the method pool.
@@ -4065,13 +4144,6 @@ ASTReader::ReadASTCore(StringRef FileName,
assert(M && "Missing module file");
- // FIXME: This seems rather a hack. Should CurrentDir be part of the
- // module?
- if (FileName != "-") {
- CurrentDir = llvm::sys::path::parent_path(FileName);
- if (CurrentDir.empty()) CurrentDir = ".";
- }
-
ModuleFile &F = *M;
BitstreamCursor &Stream = F.Stream;
Stream = BitstreamCursor(PCHContainerRdr.ExtractPCH(*F.Buffer));
@@ -4228,7 +4300,7 @@ ASTReader::ASTReadResult ASTReader::readUnhashedControlBlockImpl(
// Read all of the records in the options block.
RecordData Record;
ASTReadResult Result = Success;
- while (1) {
+ while (true) {
llvm::BitstreamEntry Entry = Stream.advance();
switch (Entry.Kind) {
@@ -4248,11 +4320,10 @@ ASTReader::ASTReadResult ASTReader::readUnhashedControlBlockImpl(
Record.clear();
switch (
(UnhashedControlBlockRecordTypes)Stream.readRecord(Entry.ID, Record)) {
- case SIGNATURE: {
+ case SIGNATURE:
if (F)
std::copy(Record.begin(), Record.end(), F->Signature.data());
break;
- }
case DIAGNOSTIC_OPTIONS: {
bool Complain = (ClientLoadCapabilities & ARR_OutOfDate) == 0;
if (Listener && ValidateDiagnosticOptions &&
@@ -4581,9 +4652,7 @@ namespace {
ExistingTargetOpts(ExistingTargetOpts),
ExistingPPOpts(ExistingPPOpts),
ExistingModuleCachePath(ExistingModuleCachePath),
- FileMgr(FileMgr)
- {
- }
+ FileMgr(FileMgr) {}
bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain,
bool AllowCompatibleDifferences) override {
@@ -4613,7 +4682,7 @@ namespace {
}
};
-} // end anonymous namespace
+} // namespace
bool ASTReader::readASTFileControlBlock(
StringRef Filename, FileManager &FileMgr,
@@ -4697,15 +4766,12 @@ bool ASTReader::readASTFileControlBlock(
StringRef Blob;
unsigned RecCode = Stream.readRecord(Entry.ID, Record, &Blob);
switch ((ControlRecordTypes)RecCode) {
- case METADATA: {
+ case METADATA:
if (Record[0] != VERSION_MAJOR)
return true;
-
if (Listener.ReadFullVersionInformation(Blob))
return true;
-
break;
- }
case MODULE_NAME:
Listener.ReadModuleName(Blob);
break;
@@ -4764,6 +4830,7 @@ bool ASTReader::readASTFileControlBlock(
while (Idx < N) {
// Read information about the AST file.
Idx += 5; // ImportLoc, Size, ModTime, Signature
+ SkipString(Record, Idx); // Module name; FIXME: pass to listener?
std::string Filename = ReadString(Record, Idx);
ResolveImportedPath(Filename, ModuleDir);
Listener.visitImport(Filename);
@@ -4856,7 +4923,6 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap();
bool First = true;
Module *CurrentModule = nullptr;
- Module::ModuleKind ModuleKind = Module::ModuleMapModule;
RecordData Record;
while (true) {
llvm::BitstreamEntry Entry = F.Stream.advanceSkippingSubblocks();
@@ -4904,6 +4970,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
unsigned Idx = 0;
SubmoduleID GlobalID = getGlobalSubmoduleID(F, Record[Idx++]);
SubmoduleID Parent = getGlobalSubmoduleID(F, Record[Idx++]);
+ Module::ModuleKind Kind = (Module::ModuleKind)Record[Idx++];
bool IsFramework = Record[Idx++];
bool IsExplicit = Record[Idx++];
bool IsSystem = Record[Idx++];
@@ -4950,7 +5017,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
CurrentModule->PresumedModuleMapFile = F.ModuleMapPath;
}
- CurrentModule->Kind = ModuleKind;
+ CurrentModule->Kind = Kind;
CurrentModule->Signature = F.Signature;
CurrentModule->IsFromModuleFile = true;
CurrentModule->IsSystem = IsSystem || CurrentModule->IsSystem;
@@ -5012,10 +5079,9 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
// them here.
break;
- case SUBMODULE_TOPHEADER: {
+ case SUBMODULE_TOPHEADER:
CurrentModule->addTopHeaderFilename(Blob);
break;
- }
case SUBMODULE_UMBRELLA_DIR: {
std::string Dirname = Blob;
@@ -5049,11 +5115,10 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
SubmodulesLoaded.resize(SubmodulesLoaded.size() + F.LocalNumSubmodules);
}
- ModuleKind = (Module::ModuleKind)Record[2];
break;
}
- case SUBMODULE_IMPORTS: {
+ case SUBMODULE_IMPORTS:
for (unsigned Idx = 0; Idx != Record.size(); ++Idx) {
UnresolvedModuleRef Unresolved;
Unresolved.File = &F;
@@ -5064,9 +5129,8 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
UnresolvedModuleRefs.push_back(Unresolved);
}
break;
- }
- case SUBMODULE_EXPORTS: {
+ case SUBMODULE_EXPORTS:
for (unsigned Idx = 0; Idx + 1 < Record.size(); Idx += 2) {
UnresolvedModuleRef Unresolved;
Unresolved.File = &F;
@@ -5081,12 +5145,11 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
// the parsed, unresolved exports around.
CurrentModule->UnresolvedExports.clear();
break;
- }
- case SUBMODULE_REQUIRES: {
+
+ case SUBMODULE_REQUIRES:
CurrentModule->addRequirement(Blob, Record[0], PP.getLangOpts(),
PP.getTargetInfo());
break;
- }
case SUBMODULE_LINK_LIBRARY:
CurrentModule->LinkLibraries.push_back(
@@ -5109,7 +5172,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
}
- case SUBMODULE_INITIALIZERS:
+ case SUBMODULE_INITIALIZERS: {
if (!ContextObj)
break;
SmallVector<uint32_t, 16> Inits;
@@ -5118,6 +5181,11 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
ContextObj->addLazyModuleInitializers(CurrentModule, Inits);
break;
}
+
+ case SUBMODULE_EXPORT_AS:
+ CurrentModule->ExportAsModule = Blob.str();
+ break;
+ }
}
}
@@ -5406,10 +5474,12 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) {
llvm_unreachable("Invalid PreprocessorDetailRecordTypes");
}
-/// \brief \arg SLocMapI points at a chunk of a module that contains no
-/// preprocessed entities or the entities it contains are not the ones we are
-/// looking for. Find the next module that contains entities and return the ID
+/// \brief Find the next module that contains entities and return the ID
/// of the first entry.
+///
+/// \param SLocMapI points at a chunk of a module that contains no
+/// preprocessed entities or the entities it contains are not the ones we are
+/// looking for.
PreprocessedEntityID ASTReader::findNextPreprocessedEntity(
GlobalSLocOffsetMapType::const_iterator SLocMapI) const {
++SLocMapI;
@@ -5429,7 +5499,7 @@ struct PPEntityComp {
const ASTReader &Reader;
ModuleFile &M;
- PPEntityComp(const ASTReader &Reader, ModuleFile &M) : Reader(Reader), M(M) { }
+ PPEntityComp(const ASTReader &Reader, ModuleFile &M) : Reader(Reader), M(M) {}
bool operator()(const PPEntityOffset &L, const PPEntityOffset &R) const {
SourceLocation LHS = getLoc(L);
@@ -5452,7 +5522,7 @@ struct PPEntityComp {
}
};
-} // end anonymous namespace
+} // namespace
PreprocessedEntityID ASTReader::findPreprocessedEntity(SourceLocation Loc,
bool EndsAfter) const {
@@ -5468,7 +5538,9 @@ PreprocessedEntityID ASTReader::findPreprocessedEntity(SourceLocation Loc,
return findNextPreprocessedEntity(SLocMapI);
ModuleFile &M = *SLocMapI->second;
- typedef const PPEntityOffset *pp_iterator;
+
+ using pp_iterator = const PPEntityOffset *;
+
pp_iterator pp_begin = M.PreprocessedEntityOffsets;
pp_iterator pp_end = pp_begin + M.NumPreprocessedEntities;
@@ -5546,12 +5618,10 @@ namespace {
/// \brief Visitor used to search for information about a header file.
class HeaderFileInfoVisitor {
const FileEntry *FE;
-
Optional<HeaderFileInfo> HFI;
public:
- explicit HeaderFileInfoVisitor(const FileEntry *FE)
- : FE(FE) { }
+ explicit HeaderFileInfoVisitor(const FileEntry *FE) : FE(FE) {}
bool operator()(ModuleFile &M) {
HeaderFileInfoLookupTable *Table
@@ -5571,7 +5641,7 @@ namespace {
Optional<HeaderFileInfo> getHeaderFileInfo() const { return HFI; }
};
-} // end anonymous namespace
+} // namespace
HeaderFileInfo ASTReader::GetHeaderFileInfo(const FileEntry *FE) {
HeaderFileInfoVisitor Visitor(FE);
@@ -5709,7 +5779,8 @@ void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) {
// Preserve the property that the imaginary root file describes the
// current state.
- auto &T = Diag.DiagStatesByLoc.Files[FileID()].StateTransitions;
+ FileID NullFile;
+ auto &T = Diag.DiagStatesByLoc.Files[NullFile].StateTransitions;
if (T.empty())
T.push_back({CurState, 0});
else
@@ -6091,6 +6162,7 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
Protos.push_back(ReadDeclAs<ObjCProtocolDecl>(*Loc.F, Record, Idx));
return Context.getObjCTypeParamType(Decl, Protos);
}
+
case TYPE_OBJC_OBJECT: {
unsigned Idx = 0;
QualType Base = readType(*Loc.F, Record, Idx);
@@ -6250,6 +6322,18 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
return Context.getDependentSizedExtVectorType(ElementType, SizeExpr,
AttrLoc);
}
+
+ case TYPE_DEPENDENT_ADDRESS_SPACE: {
+ unsigned Idx = 0;
+
+ // DependentAddressSpaceType
+ QualType PointeeType = readType(*Loc.F, Record, Idx);
+ Expr *AddrSpaceExpr = ReadExpr(*Loc.F);
+ SourceLocation AttrLoc = ReadSourceLocation(*Loc.F, Record, Idx);
+
+ return Context.getDependentAddressSpaceType(PointeeType, AddrSpaceExpr,
+ AttrLoc);
+ }
}
llvm_unreachable("Invalid TypeCode!");
}
@@ -6275,7 +6359,9 @@ void ASTReader::readExceptionSpec(ModuleFile &ModuleFile,
}
}
-class clang::TypeLocReader : public TypeLocVisitor<TypeLocReader> {
+namespace clang {
+
+class TypeLocReader : public TypeLocVisitor<TypeLocReader> {
ModuleFile *F;
ASTReader *Reader;
const ASTReader::RecordData &Record;
@@ -6310,6 +6396,8 @@ public:
void VisitArrayTypeLoc(ArrayTypeLoc);
};
+} // namespace clang
+
void TypeLocReader::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
// nothing to do
}
@@ -6383,6 +6471,17 @@ void TypeLocReader::VisitDependentSizedArrayTypeLoc(
VisitArrayTypeLoc(TL);
}
+void TypeLocReader::VisitDependentAddressSpaceTypeLoc(
+ DependentAddressSpaceTypeLoc TL) {
+
+ TL.setAttrNameLoc(ReadSourceLocation());
+ SourceRange range;
+ range.setBegin(ReadSourceLocation());
+ range.setEnd(ReadSourceLocation());
+ TL.setAttrOperandParensRange(range);
+ TL.setAttrExprOperand(Reader->ReadExpr(*F));
+}
+
void TypeLocReader::VisitDependentSizedExtVectorTypeLoc(
DependentSizedExtVectorTypeLoc TL) {
TL.setNameLoc(ReadSourceLocation());
@@ -6415,23 +6514,28 @@ void TypeLocReader::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {
void TypeLocReader::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
VisitFunctionTypeLoc(TL);
}
+
void TypeLocReader::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
TL.setNameLoc(ReadSourceLocation());
}
+
void TypeLocReader::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
TL.setNameLoc(ReadSourceLocation());
}
+
void TypeLocReader::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
TL.setTypeofLoc(ReadSourceLocation());
TL.setLParenLoc(ReadSourceLocation());
TL.setRParenLoc(ReadSourceLocation());
}
+
void TypeLocReader::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
TL.setTypeofLoc(ReadSourceLocation());
TL.setLParenLoc(ReadSourceLocation());
TL.setRParenLoc(ReadSourceLocation());
TL.setUnderlyingTInfo(GetTypeSourceInfo());
}
+
void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
TL.setNameLoc(ReadSourceLocation());
}
@@ -6485,10 +6589,12 @@ void TypeLocReader::VisitSubstTemplateTypeParmTypeLoc(
SubstTemplateTypeParmTypeLoc TL) {
TL.setNameLoc(ReadSourceLocation());
}
+
void TypeLocReader::VisitSubstTemplateTypeParmPackTypeLoc(
SubstTemplateTypeParmPackTypeLoc TL) {
TL.setNameLoc(ReadSourceLocation());
}
+
void TypeLocReader::VisitTemplateSpecializationTypeLoc(
TemplateSpecializationTypeLoc TL) {
TL.setTemplateKeywordLoc(ReadSourceLocation());
@@ -6501,6 +6607,7 @@ void TypeLocReader::VisitTemplateSpecializationTypeLoc(
Reader->GetTemplateArgumentLocInfo(
*F, TL.getTypePtr()->getArg(i).getKind(), Record, Idx));
}
+
void TypeLocReader::VisitParenTypeLoc(ParenTypeLoc TL) {
TL.setLParenLoc(ReadSourceLocation());
TL.setRParenLoc(ReadSourceLocation());
@@ -6611,13 +6718,11 @@ QualType ASTReader::GetType(TypeID ID) {
case PREDEF_TYPE_BOOL_ID:
T = Context.BoolTy;
break;
-
case PREDEF_TYPE_CHAR_U_ID:
case PREDEF_TYPE_CHAR_S_ID:
// FIXME: Check that the signedness of CharTy is correct!
T = Context.CharTy;
break;
-
case PREDEF_TYPE_UCHAR_ID:
T = Context.UnsignedCharTy;
break;
@@ -6669,6 +6774,9 @@ QualType ASTReader::GetType(TypeID ID) {
case PREDEF_TYPE_LONGDOUBLE_ID:
T = Context.LongDoubleTy;
break;
+ case PREDEF_TYPE_FLOAT16_ID:
+ T = Context.Float16Ty;
+ break;
case PREDEF_TYPE_FLOAT128_ID:
T = Context.Float128Ty;
break;
@@ -6728,19 +6836,15 @@ QualType ASTReader::GetType(TypeID ID) {
case PREDEF_TYPE_AUTO_DEDUCT:
T = Context.getAutoDeductType();
break;
-
case PREDEF_TYPE_AUTO_RREF_DEDUCT:
T = Context.getAutoRRefDeductType();
break;
-
case PREDEF_TYPE_ARC_UNBRIDGED_CAST:
T = Context.ARCUnbridgedCastTy;
break;
-
case PREDEF_TYPE_BUILTIN_FN:
T = Context.BuiltinFnTy;
break;
-
case PREDEF_TYPE_OMP_ARRAY_SECTION:
T = Context.OMPArraySectionTy;
break;
@@ -7227,7 +7331,7 @@ public:
}
};
-} // end anonymous namespace
+} // namespace
void ASTReader::FindFileRegionDecls(FileID File,
unsigned Offset, unsigned Length,
@@ -7423,30 +7527,25 @@ void ASTReader::PrintStats() {
NumVisibleDeclContextsRead, TotalVisibleDeclContexts,
((float)NumVisibleDeclContextsRead/TotalVisibleDeclContexts
* 100));
- if (TotalNumMethodPoolEntries) {
+ if (TotalNumMethodPoolEntries)
std::fprintf(stderr, " %u/%u method pool entries read (%f%%)\n",
NumMethodPoolEntriesRead, TotalNumMethodPoolEntries,
((float)NumMethodPoolEntriesRead/TotalNumMethodPoolEntries
* 100));
- }
- if (NumMethodPoolLookups) {
+ if (NumMethodPoolLookups)
std::fprintf(stderr, " %u/%u method pool lookups succeeded (%f%%)\n",
NumMethodPoolHits, NumMethodPoolLookups,
((float)NumMethodPoolHits/NumMethodPoolLookups * 100.0));
- }
- if (NumMethodPoolTableLookups) {
+ if (NumMethodPoolTableLookups)
std::fprintf(stderr, " %u/%u method pool table lookups succeeded (%f%%)\n",
NumMethodPoolTableHits, NumMethodPoolTableLookups,
((float)NumMethodPoolTableHits/NumMethodPoolTableLookups
* 100.0));
- }
-
- if (NumIdentifierLookupHits) {
+ if (NumIdentifierLookupHits)
std::fprintf(stderr,
" %u / %u identifier table lookups succeeded (%f%%)\n",
NumIdentifierLookupHits, NumIdentifierLookups,
(double)NumIdentifierLookupHits*100.0/NumIdentifierLookups);
- }
if (GlobalIndex) {
std::fprintf(stderr, "\n");
@@ -7466,7 +7565,8 @@ dumpModuleIDMap(StringRef Name,
if (Map.begin() == Map.end())
return;
- typedef ContinuousRangeMap<Key, ModuleFile *, InitialCapacity> MapType;
+ using MapType = ContinuousRangeMap<Key, ModuleFile *, InitialCapacity>;
+
llvm::errs() << Name << ":\n";
for (typename MapType::const_iterator I = Map.begin(), IEnd = Map.end();
I != IEnd; ++I) {
@@ -7579,13 +7679,14 @@ void ASTReader::UpdateSema() {
"Expected a default alignment value");
SemaObj->PackStack.Stack.emplace_back(
PragmaPackStack.front().SlotLabel, SemaObj->PackStack.CurrentValue,
- SemaObj->PackStack.CurrentPragmaLocation);
+ SemaObj->PackStack.CurrentPragmaLocation,
+ PragmaPackStack.front().PushLocation);
DropFirst = true;
}
for (const auto &Entry :
llvm::makeArrayRef(PragmaPackStack).drop_front(DropFirst ? 1 : 0))
SemaObj->PackStack.Stack.emplace_back(Entry.SlotLabel, Entry.Value,
- Entry.Location);
+ Entry.Location, Entry.PushLocation);
if (PragmaPackCurrentLocation.isInvalid()) {
assert(*PragmaPackCurrentValue == SemaObj->PackStack.DefaultValue &&
"Expected a default alignment value");
@@ -7662,7 +7763,7 @@ namespace clang {
StringRef Next() override;
};
-} // end namespace clang
+} // namespace clang
ASTIdentifierIterator::ASTIdentifierIterator(const ASTReader &Reader,
bool SkipModules)
@@ -7720,7 +7821,7 @@ public:
}
};
-} // end anonymous namespace.
+} // namespace
IdentifierIterator *ASTReader::getIdentifiers() {
if (!loadGlobalIndex()) {
@@ -7742,19 +7843,17 @@ namespace serialization {
ASTReader &Reader;
Selector Sel;
unsigned PriorGeneration;
- unsigned InstanceBits;
- unsigned FactoryBits;
- bool InstanceHasMoreThanOneDecl;
- bool FactoryHasMoreThanOneDecl;
+ unsigned InstanceBits = 0;
+ unsigned FactoryBits = 0;
+ bool InstanceHasMoreThanOneDecl = false;
+ bool FactoryHasMoreThanOneDecl = false;
SmallVector<ObjCMethodDecl *, 4> InstanceMethods;
SmallVector<ObjCMethodDecl *, 4> FactoryMethods;
public:
ReadMethodPoolVisitor(ASTReader &Reader, Selector Sel,
unsigned PriorGeneration)
- : Reader(Reader), Sel(Sel), PriorGeneration(PriorGeneration),
- InstanceBits(0), FactoryBits(0), InstanceHasMoreThanOneDecl(false),
- FactoryHasMoreThanOneDecl(false) {}
+ : Reader(Reader), Sel(Sel), PriorGeneration(PriorGeneration) {}
bool operator()(ModuleFile &M) {
if (!M.SelectorLookupTable)
@@ -7802,14 +7901,16 @@ namespace serialization {
unsigned getInstanceBits() const { return InstanceBits; }
unsigned getFactoryBits() const { return FactoryBits; }
+
bool instanceHasMoreThanOneDecl() const {
return InstanceHasMoreThanOneDecl;
}
+
bool factoryHasMoreThanOneDecl() const { return FactoryHasMoreThanOneDecl; }
};
-} // end namespace serialization
-} // end namespace clang
+} // namespace serialization
+} // namespace clang
/// \brief Add the given set of methods to the method list.
static void addMethodsToPool(Sema &S, ArrayRef<ObjCMethodDecl *> Methods,
@@ -7952,7 +8053,7 @@ void ASTReader::ReadUnusedLocalTypedefNameCandidates(
}
void ASTReader::ReadReferencedSelectors(
- SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels) {
+ SmallVectorImpl<std::pair<Selector, SourceLocation>> &Sels) {
if (ReferencedSelectorsData.empty())
return;
@@ -7970,7 +8071,7 @@ void ASTReader::ReadReferencedSelectors(
}
void ASTReader::ReadWeakUndeclaredIdentifiers(
- SmallVectorImpl<std::pair<IdentifierInfo *, WeakInfo> > &WeakIDs) {
+ SmallVectorImpl<std::pair<IdentifierInfo *, WeakInfo>> &WeakIDs) {
if (WeakUndeclaredIdentifiers.empty())
return;
@@ -8002,7 +8103,7 @@ void ASTReader::ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables) {
}
void ASTReader::ReadPendingInstantiations(
- SmallVectorImpl<std::pair<ValueDecl *, SourceLocation> > &Pending) {
+ SmallVectorImpl<std::pair<ValueDecl *, SourceLocation>> &Pending) {
for (unsigned Idx = 0, N = PendingInstantiations.size(); Idx < N;) {
ValueDecl *D = cast<ValueDecl>(GetDecl(PendingInstantiations[Idx++]));
SourceLocation Loc
@@ -8276,8 +8377,8 @@ ASTReader::getSourceDescriptor(unsigned ID) {
}
ExternalASTSource::ExtKind ASTReader::hasExternalDefinitions(const Decl *FD) {
- auto I = BodySource.find(FD);
- if (I == BodySource.end())
+ auto I = DefinitionSource.find(FD);
+ if (I == DefinitionSource.end())
return EK_ReplyHazy;
return I->second ? EK_Never : EK_Always;
}
@@ -8714,11 +8815,10 @@ ASTReader::ReadNestedNameSpecifier(ModuleFile &F,
break;
}
- case NestedNameSpecifier::Global: {
+ case NestedNameSpecifier::Global:
NNS = NestedNameSpecifier::GlobalSpecifier(Context);
// No associated value, and there can't be a prefix.
break;
- }
case NestedNameSpecifier::Super: {
CXXRecordDecl *RD = ReadDeclAs<CXXRecordDecl>(F, Record, Idx);
@@ -8895,7 +8995,7 @@ void ASTReader::ReadComments() {
ASTContext &Context = getContext();
std::vector<RawComment *> Comments;
for (SmallVectorImpl<std::pair<BitstreamCursor,
- serialization::ModuleFile *> >::iterator
+ serialization::ModuleFile *>>::iterator
I = CommentsCursors.begin(),
E = CommentsCursors.end();
I != E; ++I) {
@@ -8985,7 +9085,7 @@ std::string ASTReader::getOwningModuleNameForDiagnostic(const Decl *D) {
return M->ModuleName;
// Not from a module.
- return "";
+ return {};
}
void ASTReader::finishPendingActions() {
@@ -8995,8 +9095,8 @@ void ASTReader::finishPendingActions() {
!PendingUpdateRecords.empty()) {
// If any identifiers with corresponding top-level declarations have
// been loaded, load those declarations now.
- typedef llvm::DenseMap<IdentifierInfo *, SmallVector<Decl *, 2> >
- TopLevelDeclsMap;
+ using TopLevelDeclsMap =
+ llvm::DenseMap<IdentifierInfo *, SmallVector<Decl *, 2>>;
TopLevelDeclsMap TopLevelDecls;
while (!PendingIdentifierInfos.empty()) {
@@ -9167,7 +9267,8 @@ void ASTReader::diagnoseOdrViolations() {
Merge.first->decls_begin();
Merge.first->bases_begin();
Merge.first->vbases_begin();
- for (auto *RD : Merge.second) {
+ for (auto &RecordPair : Merge.second) {
+ auto *RD = RecordPair.first;
RD->decls_begin();
RD->bases_begin();
RD->vbases_begin();
@@ -9273,14 +9374,326 @@ void ASTReader::diagnoseOdrViolations() {
bool Diagnosed = false;
CXXRecordDecl *FirstRecord = Merge.first;
std::string FirstModule = getOwningModuleNameForDiagnostic(FirstRecord);
- for (CXXRecordDecl *SecondRecord : Merge.second) {
+ for (auto &RecordPair : Merge.second) {
+ CXXRecordDecl *SecondRecord = RecordPair.first;
// Multiple different declarations got merged together; tell the user
// where they came from.
if (FirstRecord == SecondRecord)
continue;
std::string SecondModule = getOwningModuleNameForDiagnostic(SecondRecord);
+
+ auto *FirstDD = FirstRecord->DefinitionData;
+ auto *SecondDD = RecordPair.second;
+
+ assert(FirstDD && SecondDD && "Definitions without DefinitionData");
+
+ // Diagnostics from DefinitionData are emitted here.
+ if (FirstDD != SecondDD) {
+ enum ODRDefinitionDataDifference {
+ NumBases,
+ NumVBases,
+ BaseType,
+ BaseVirtual,
+ BaseAccess,
+ };
+ auto ODRDiagError = [FirstRecord, &FirstModule,
+ this](SourceLocation Loc, SourceRange Range,
+ ODRDefinitionDataDifference DiffType) {
+ return Diag(Loc, diag::err_module_odr_violation_definition_data)
+ << FirstRecord << FirstModule.empty() << FirstModule << Range
+ << DiffType;
+ };
+ auto ODRDiagNote = [&SecondModule,
+ this](SourceLocation Loc, SourceRange Range,
+ ODRDefinitionDataDifference DiffType) {
+ return Diag(Loc, diag::note_module_odr_violation_definition_data)
+ << SecondModule << Range << DiffType;
+ };
+
+ ODRHash Hash;
+ auto ComputeQualTypeODRHash = [&Hash](QualType Ty) {
+ Hash.clear();
+ Hash.AddQualType(Ty);
+ return Hash.CalculateHash();
+ };
+
+ unsigned FirstNumBases = FirstDD->NumBases;
+ unsigned FirstNumVBases = FirstDD->NumVBases;
+ unsigned SecondNumBases = SecondDD->NumBases;
+ unsigned SecondNumVBases = SecondDD->NumVBases;
+
+ auto GetSourceRange = [](struct CXXRecordDecl::DefinitionData *DD) {
+ unsigned NumBases = DD->NumBases;
+ if (NumBases == 0) return SourceRange();
+ auto bases = DD->bases();
+ return SourceRange(bases[0].getLocStart(),
+ bases[NumBases - 1].getLocEnd());
+ };
+
+ if (FirstNumBases != SecondNumBases) {
+ ODRDiagError(FirstRecord->getLocation(), GetSourceRange(FirstDD),
+ NumBases)
+ << FirstNumBases;
+ ODRDiagNote(SecondRecord->getLocation(), GetSourceRange(SecondDD),
+ NumBases)
+ << SecondNumBases;
+ Diagnosed = true;
+ break;
+ }
+
+ if (FirstNumVBases != SecondNumVBases) {
+ ODRDiagError(FirstRecord->getLocation(), GetSourceRange(FirstDD),
+ NumVBases)
+ << FirstNumVBases;
+ ODRDiagNote(SecondRecord->getLocation(), GetSourceRange(SecondDD),
+ NumVBases)
+ << SecondNumVBases;
+ Diagnosed = true;
+ break;
+ }
+
+ auto FirstBases = FirstDD->bases();
+ auto SecondBases = SecondDD->bases();
+ unsigned i = 0;
+ for (i = 0; i < FirstNumBases; ++i) {
+ auto FirstBase = FirstBases[i];
+ auto SecondBase = SecondBases[i];
+ if (ComputeQualTypeODRHash(FirstBase.getType()) !=
+ ComputeQualTypeODRHash(SecondBase.getType())) {
+ ODRDiagError(FirstRecord->getLocation(), FirstBase.getSourceRange(),
+ BaseType)
+ << (i + 1) << FirstBase.getType();
+ ODRDiagNote(SecondRecord->getLocation(),
+ SecondBase.getSourceRange(), BaseType)
+ << (i + 1) << SecondBase.getType();
+ break;
+ }
+
+ if (FirstBase.isVirtual() != SecondBase.isVirtual()) {
+ ODRDiagError(FirstRecord->getLocation(), FirstBase.getSourceRange(),
+ BaseVirtual)
+ << (i + 1) << FirstBase.isVirtual() << FirstBase.getType();
+ ODRDiagNote(SecondRecord->getLocation(),
+ SecondBase.getSourceRange(), BaseVirtual)
+ << (i + 1) << SecondBase.isVirtual() << SecondBase.getType();
+ break;
+ }
+
+ if (FirstBase.getAccessSpecifierAsWritten() !=
+ SecondBase.getAccessSpecifierAsWritten()) {
+ ODRDiagError(FirstRecord->getLocation(), FirstBase.getSourceRange(),
+ BaseAccess)
+ << (i + 1) << FirstBase.getType()
+ << (int)FirstBase.getAccessSpecifierAsWritten();
+ ODRDiagNote(SecondRecord->getLocation(),
+ SecondBase.getSourceRange(), BaseAccess)
+ << (i + 1) << SecondBase.getType()
+ << (int)SecondBase.getAccessSpecifierAsWritten();
+ break;
+ }
+ }
+
+ if (i != FirstNumBases) {
+ Diagnosed = true;
+ break;
+ }
+ }
+
using DeclHashes = llvm::SmallVector<std::pair<Decl *, unsigned>, 4>;
+
+ const ClassTemplateDecl *FirstTemplate =
+ FirstRecord->getDescribedClassTemplate();
+ const ClassTemplateDecl *SecondTemplate =
+ SecondRecord->getDescribedClassTemplate();
+
+ assert(!FirstTemplate == !SecondTemplate &&
+ "Both pointers should be null or non-null");
+
+ enum ODRTemplateDifference {
+ ParamEmptyName,
+ ParamName,
+ ParamSingleDefaultArgument,
+ ParamDifferentDefaultArgument,
+ };
+
+ if (FirstTemplate && SecondTemplate) {
+ DeclHashes FirstTemplateHashes;
+ DeclHashes SecondTemplateHashes;
+ ODRHash Hash;
+
+ auto PopulateTemplateParameterHashs =
+ [&Hash](DeclHashes &Hashes, const ClassTemplateDecl *TD) {
+ for (auto *D : TD->getTemplateParameters()->asArray()) {
+ Hash.clear();
+ Hash.AddSubDecl(D);
+ Hashes.emplace_back(D, Hash.CalculateHash());
+ }
+ };
+
+ PopulateTemplateParameterHashs(FirstTemplateHashes, FirstTemplate);
+ PopulateTemplateParameterHashs(SecondTemplateHashes, SecondTemplate);
+
+ assert(FirstTemplateHashes.size() == SecondTemplateHashes.size() &&
+ "Number of template parameters should be equal.");
+
+ auto FirstIt = FirstTemplateHashes.begin();
+ auto FirstEnd = FirstTemplateHashes.end();
+ auto SecondIt = SecondTemplateHashes.begin();
+ for (; FirstIt != FirstEnd; ++FirstIt, ++SecondIt) {
+ if (FirstIt->second == SecondIt->second)
+ continue;
+
+ auto ODRDiagError = [FirstRecord, &FirstModule,
+ this](SourceLocation Loc, SourceRange Range,
+ ODRTemplateDifference DiffType) {
+ return Diag(Loc, diag::err_module_odr_violation_template_parameter)
+ << FirstRecord << FirstModule.empty() << FirstModule << Range
+ << DiffType;
+ };
+ auto ODRDiagNote = [&SecondModule,
+ this](SourceLocation Loc, SourceRange Range,
+ ODRTemplateDifference DiffType) {
+ return Diag(Loc, diag::note_module_odr_violation_template_parameter)
+ << SecondModule << Range << DiffType;
+ };
+
+ const NamedDecl* FirstDecl = cast<NamedDecl>(FirstIt->first);
+ const NamedDecl* SecondDecl = cast<NamedDecl>(SecondIt->first);
+
+ assert(FirstDecl->getKind() == SecondDecl->getKind() &&
+ "Parameter Decl's should be the same kind.");
+
+ DeclarationName FirstName = FirstDecl->getDeclName();
+ DeclarationName SecondName = SecondDecl->getDeclName();
+
+ if (FirstName != SecondName) {
+ const bool FirstNameEmpty =
+ FirstName.isIdentifier() && !FirstName.getAsIdentifierInfo();
+ const bool SecondNameEmpty =
+ SecondName.isIdentifier() && !SecondName.getAsIdentifierInfo();
+ assert((!FirstNameEmpty || !SecondNameEmpty) &&
+ "Both template parameters cannot be unnamed.");
+ ODRDiagError(FirstDecl->getLocation(), FirstDecl->getSourceRange(),
+ FirstNameEmpty ? ParamEmptyName : ParamName)
+ << FirstName;
+ ODRDiagNote(SecondDecl->getLocation(), SecondDecl->getSourceRange(),
+ SecondNameEmpty ? ParamEmptyName : ParamName)
+ << SecondName;
+ break;
+ }
+
+ switch (FirstDecl->getKind()) {
+ default:
+ llvm_unreachable("Invalid template parameter type.");
+ case Decl::TemplateTypeParm: {
+ const auto *FirstParam = cast<TemplateTypeParmDecl>(FirstDecl);
+ const auto *SecondParam = cast<TemplateTypeParmDecl>(SecondDecl);
+ const bool HasFirstDefaultArgument =
+ FirstParam->hasDefaultArgument() &&
+ !FirstParam->defaultArgumentWasInherited();
+ const bool HasSecondDefaultArgument =
+ SecondParam->hasDefaultArgument() &&
+ !SecondParam->defaultArgumentWasInherited();
+
+ if (HasFirstDefaultArgument != HasSecondDefaultArgument) {
+ ODRDiagError(FirstDecl->getLocation(),
+ FirstDecl->getSourceRange(),
+ ParamSingleDefaultArgument)
+ << HasFirstDefaultArgument;
+ ODRDiagNote(SecondDecl->getLocation(),
+ SecondDecl->getSourceRange(),
+ ParamSingleDefaultArgument)
+ << HasSecondDefaultArgument;
+ break;
+ }
+
+ assert(HasFirstDefaultArgument && HasSecondDefaultArgument &&
+ "Expecting default arguments.");
+
+ ODRDiagError(FirstDecl->getLocation(), FirstDecl->getSourceRange(),
+ ParamDifferentDefaultArgument);
+ ODRDiagNote(SecondDecl->getLocation(), SecondDecl->getSourceRange(),
+ ParamDifferentDefaultArgument);
+
+ break;
+ }
+ case Decl::NonTypeTemplateParm: {
+ const auto *FirstParam = cast<NonTypeTemplateParmDecl>(FirstDecl);
+ const auto *SecondParam = cast<NonTypeTemplateParmDecl>(SecondDecl);
+ const bool HasFirstDefaultArgument =
+ FirstParam->hasDefaultArgument() &&
+ !FirstParam->defaultArgumentWasInherited();
+ const bool HasSecondDefaultArgument =
+ SecondParam->hasDefaultArgument() &&
+ !SecondParam->defaultArgumentWasInherited();
+
+ if (HasFirstDefaultArgument != HasSecondDefaultArgument) {
+ ODRDiagError(FirstDecl->getLocation(),
+ FirstDecl->getSourceRange(),
+ ParamSingleDefaultArgument)
+ << HasFirstDefaultArgument;
+ ODRDiagNote(SecondDecl->getLocation(),
+ SecondDecl->getSourceRange(),
+ ParamSingleDefaultArgument)
+ << HasSecondDefaultArgument;
+ break;
+ }
+
+ assert(HasFirstDefaultArgument && HasSecondDefaultArgument &&
+ "Expecting default arguments.");
+
+ ODRDiagError(FirstDecl->getLocation(), FirstDecl->getSourceRange(),
+ ParamDifferentDefaultArgument);
+ ODRDiagNote(SecondDecl->getLocation(), SecondDecl->getSourceRange(),
+ ParamDifferentDefaultArgument);
+
+ break;
+ }
+ case Decl::TemplateTemplateParm: {
+ const auto *FirstParam = cast<TemplateTemplateParmDecl>(FirstDecl);
+ const auto *SecondParam =
+ cast<TemplateTemplateParmDecl>(SecondDecl);
+ const bool HasFirstDefaultArgument =
+ FirstParam->hasDefaultArgument() &&
+ !FirstParam->defaultArgumentWasInherited();
+ const bool HasSecondDefaultArgument =
+ SecondParam->hasDefaultArgument() &&
+ !SecondParam->defaultArgumentWasInherited();
+
+ if (HasFirstDefaultArgument != HasSecondDefaultArgument) {
+ ODRDiagError(FirstDecl->getLocation(),
+ FirstDecl->getSourceRange(),
+ ParamSingleDefaultArgument)
+ << HasFirstDefaultArgument;
+ ODRDiagNote(SecondDecl->getLocation(),
+ SecondDecl->getSourceRange(),
+ ParamSingleDefaultArgument)
+ << HasSecondDefaultArgument;
+ break;
+ }
+
+ assert(HasFirstDefaultArgument && HasSecondDefaultArgument &&
+ "Expecting default arguments.");
+
+ ODRDiagError(FirstDecl->getLocation(), FirstDecl->getSourceRange(),
+ ParamDifferentDefaultArgument);
+ ODRDiagNote(SecondDecl->getLocation(), SecondDecl->getSourceRange(),
+ ParamDifferentDefaultArgument);
+
+ break;
+ }
+ }
+
+ break;
+ }
+
+ if (FirstIt != FirstEnd) {
+ Diagnosed = true;
+ break;
+ }
+ }
+
DeclHashes FirstHashes;
DeclHashes SecondHashes;
ODRHash Hash;
@@ -10050,7 +10463,7 @@ void ASTReader::diagnoseOdrViolations() {
}
}
- if (Diagnosed == true)
+ if (Diagnosed)
continue;
Diag(FirstDecl->getLocation(),
@@ -10160,7 +10573,8 @@ ASTReader::ASTReader(Preprocessor &PP, ASTContext *Context,
SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()),
PCHContainerRdr(PCHContainerRdr), Diags(PP.getDiagnostics()), PP(PP),
ContextObj(Context),
- ModuleMgr(PP.getFileManager(), PP.getPCMCache(), PCHContainerRdr),
+ ModuleMgr(PP.getFileManager(), PP.getPCMCache(), PCHContainerRdr,
+ PP.getHeaderSearchInfo()),
PCMCache(PP.getPCMCache()), DummyIdResolver(PP),
ReadTimer(std::move(ReadTimer)), isysroot(isysroot),
DisableValidation(DisableValidation),
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp
index 085341571ced4..a3bf0d9712673 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -453,7 +453,7 @@ uint64_t ASTDeclReader::GetCurrentCursorOffset() {
void ASTDeclReader::ReadFunctionDefinition(FunctionDecl *FD) {
if (Record.readInt())
- Reader.BodySource[FD] = Loc.F->Kind == ModuleKind::MK_MainFile;
+ Reader.DefinitionSource[FD] = Loc.F->Kind == ModuleKind::MK_MainFile;
if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) {
CD->NumCtorInitializers = Record.readInt();
if (CD->NumCtorInitializers)
@@ -1219,16 +1219,17 @@ void ASTDeclReader::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
void ASTDeclReader::VisitFieldDecl(FieldDecl *FD) {
VisitDeclaratorDecl(FD);
FD->Mutable = Record.readInt();
- if (int BitWidthOrInitializer = Record.readInt()) {
- FD->InitStorage.setInt(
- static_cast<FieldDecl::InitStorageKind>(BitWidthOrInitializer - 1));
- if (FD->InitStorage.getInt() == FieldDecl::ISK_CapturedVLAType) {
- // Read captured variable length array.
- FD->InitStorage.setPointer(Record.readType().getAsOpaquePtr());
- } else {
- FD->InitStorage.setPointer(Record.readExpr());
- }
+
+ if (auto ISK = static_cast<FieldDecl::InitStorageKind>(Record.readInt())) {
+ FD->InitStorage.setInt(ISK);
+ FD->InitStorage.setPointer(ISK == FieldDecl::ISK_CapturedVLAType
+ ? Record.readType().getAsOpaquePtr()
+ : Record.readExpr());
}
+
+ if (auto *BW = Record.readExpr())
+ FD->setBitWidth(BW);
+
if (!FD->getDeclName()) {
if (FieldDecl *Tmpl = ReadDeclAs<FieldDecl>())
Reader.getContext().setInstantiatedFromUnnamedFieldDecl(FD, Tmpl);
@@ -1293,6 +1294,9 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) {
}
}
+ if (VD->getStorageDuration() == SD_Static && Record.readInt())
+ Reader.DefinitionSource[VD] = Loc.F->Kind == ModuleKind::MK_MainFile;
+
enum VarKind {
VarNotTemplate = 0, VarTemplate, StaticDataMemberSpecialization
};
@@ -1587,11 +1591,8 @@ void ASTDeclReader::ReadCXXDefinitionData(
Data.ODRHash = Record.readInt();
Data.HasODRHash = true;
- if (Record.readInt()) {
- Reader.BodySource[D] = Loc.F->Kind == ModuleKind::MK_MainFile
- ? ExternalASTSource::EK_Never
- : ExternalASTSource::EK_Always;
- }
+ if (Record.readInt())
+ Reader.DefinitionSource[D] = Loc.F->Kind == ModuleKind::MK_MainFile;
Data.NumBases = Record.readInt();
if (Data.NumBases)
@@ -1754,7 +1755,8 @@ void ASTDeclReader::MergeDefinitionData(
}
if (DetectedOdrViolation)
- Reader.PendingOdrMergeFailures[DD.Definition].push_back(MergeDD.Definition);
+ Reader.PendingOdrMergeFailures[DD.Definition].push_back(
+ {MergeDD.Definition, &MergeDD});
}
void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update) {
@@ -1861,6 +1863,7 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
void ASTDeclReader::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) {
VisitFunctionDecl(D);
+ D->IsCopyDeductionCandidate = Record.readInt();
}
void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) {
@@ -1899,9 +1902,12 @@ void ASTDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
if (auto *OperatorDelete = ReadDeclAs<FunctionDecl>()) {
auto *Canon = cast<CXXDestructorDecl>(D->getCanonicalDecl());
+ auto *ThisArg = Record.readExpr();
// FIXME: Check consistency if we have an old and new operator delete.
- if (!Canon->OperatorDelete)
+ if (!Canon->OperatorDelete) {
Canon->OperatorDelete = OperatorDelete;
+ Canon->OperatorDeleteThisArg = ThisArg;
+ }
}
}
@@ -2192,6 +2198,7 @@ ASTDeclReader::VisitVarTemplateSpecializationDeclImpl(
D->TemplateArgs = TemplateArgumentList::CreateCopy(C, TemplArgs);
D->PointOfInstantiation = ReadSourceLocation();
D->SpecializationKind = (TemplateSpecializationKind)Record.readInt();
+ D->IsCompleteDefinition = Record.readInt();
bool writtenAsCanonicalDecl = Record.readInt();
if (writtenAsCanonicalDecl) {
@@ -2514,7 +2521,9 @@ void ASTDeclReader::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) {
VisitValueDecl(D);
D->setLocation(ReadSourceLocation());
D->setCombiner(Record.readExpr());
- D->setInitializer(Record.readExpr());
+ D->setInitializer(
+ Record.readExpr(),
+ static_cast<OMPDeclareReductionDecl::InitKind>(Record.readInt()));
D->PrevDeclInScope = ReadDeclID();
}
@@ -2567,11 +2576,14 @@ static bool isConsumerInterestedIn(ASTContext &Ctx, Decl *D, bool HasBody) {
// An ObjCMethodDecl is never considered as "interesting" because its
// implementation container always is.
- // An ImportDecl or VarDecl imported from a module will get emitted when
- // we import the relevant module.
- if ((isa<ImportDecl>(D) || isa<VarDecl>(D)) && D->getImportedOwningModule() &&
- Ctx.DeclMustBeEmitted(D))
- return false;
+ // An ImportDecl or VarDecl imported from a module map module will get
+ // emitted when we import the relevant module.
+ if (isa<ImportDecl>(D) || isa<VarDecl>(D)) {
+ auto *M = D->getImportedOwningModule();
+ if (M && M->Kind == Module::ModuleMapModule &&
+ Ctx.DeclMustBeEmitted(D))
+ return false;
+ }
if (isa<FileScopeAsmDecl>(D) ||
isa<ObjCProtocolDecl>(D) ||
@@ -2810,7 +2822,7 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
// FIXME: Do we need to check for C++14 deduced return types here too?
auto *XFPT = FuncX->getType()->getAs<FunctionProtoType>();
auto *YFPT = FuncY->getType()->getAs<FunctionProtoType>();
- if (C.getLangOpts().CPlusPlus1z && XFPT && YFPT &&
+ if (C.getLangOpts().CPlusPlus17 && XFPT && YFPT &&
(isUnresolvedExceptionSpec(XFPT->getExceptionSpecType()) ||
isUnresolvedExceptionSpec(YFPT->getExceptionSpecType())) &&
C.hasSameFunctionTypeIgnoringExceptionSpec(FuncX->getType(),
@@ -3972,10 +3984,10 @@ void ASTDeclReader::UpdateDecl(Decl *D,
break;
}
- case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER: {
+ case UPD_CXX_ADDED_VAR_DEFINITION: {
VarDecl *VD = cast<VarDecl>(D);
- VD->getMemberSpecializationInfo()->setPointOfInstantiation(
- ReadSourceLocation());
+ VD->NonParmVarDeclBits.IsInline = Record.readInt();
+ VD->NonParmVarDeclBits.IsInlineSpecified = Record.readInt();
uint64_t Val = Record.readInt();
if (Val && !VD->getInit()) {
VD->setInit(Record.readExpr());
@@ -3988,6 +4000,25 @@ void ASTDeclReader::UpdateDecl(Decl *D,
break;
}
+ case UPD_CXX_POINT_OF_INSTANTIATION: {
+ SourceLocation POI = Record.readSourceLocation();
+ if (VarTemplateSpecializationDecl *VTSD =
+ dyn_cast<VarTemplateSpecializationDecl>(D)) {
+ VTSD->setPointOfInstantiation(POI);
+ } else if (auto *VD = dyn_cast<VarDecl>(D)) {
+ VD->getMemberSpecializationInfo()->setPointOfInstantiation(POI);
+ } else {
+ auto *FD = cast<FunctionDecl>(D);
+ if (auto *FTSInfo = FD->TemplateOrSpecialization
+ .dyn_cast<FunctionTemplateSpecializationInfo *>())
+ FTSInfo->setPointOfInstantiation(POI);
+ else
+ FD->TemplateOrSpecialization.get<MemberSpecializationInfo *>()
+ ->setPointOfInstantiation(POI);
+ }
+ break;
+ }
+
case UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT: {
auto Param = cast<ParmVarDecl>(D);
@@ -4106,9 +4137,12 @@ void ASTDeclReader::UpdateDecl(Decl *D,
// record.
auto *Del = ReadDeclAs<FunctionDecl>();
auto *First = cast<CXXDestructorDecl>(D->getCanonicalDecl());
+ auto *ThisArg = Record.readExpr();
// FIXME: Check consistency if we have an old and new operator delete.
- if (!First->OperatorDelete)
+ if (!First->OperatorDelete) {
First->OperatorDelete = Del;
+ First->OperatorDeleteThisArg = ThisArg;
+ }
break;
}
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h
index 6cb4d662e3389..2b92ae65ea84c 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h
@@ -1,4 +1,4 @@
-//===--- ASTReaderInternals.h - AST Reader Internals ------------*- C++ -*-===//
+//===- ASTReaderInternals.h - AST Reader Internals --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,23 +10,29 @@
// This file provides internal definitions used in the AST reader.
//
//===----------------------------------------------------------------------===//
+
#ifndef LLVM_CLANG_LIB_SERIALIZATION_ASTREADERINTERNALS_H
#define LLVM_CLANG_LIB_SERIALIZATION_ASTREADERINTERNALS_H
#include "MultiOnDiskHashTable.h"
#include "clang/AST/DeclarationName.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "llvm/ADT/DenseSet.h"
-#include "llvm/Support/Endian.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/OnDiskHashTable.h"
+#include <ctime>
#include <utility>
namespace clang {
class ASTReader;
-class HeaderSearch;
-struct HeaderFileInfo;
class FileEntry;
+struct HeaderFileInfo;
+class HeaderSearch;
+class IdentifierTable;
+class ObjCMethodDecl;
namespace serialization {
@@ -45,12 +51,14 @@ public:
static const int MaxTables = 4;
/// The lookup result is a list of global declaration IDs.
- typedef llvm::SmallVector<DeclID, 4> data_type;
+ using data_type = SmallVector<DeclID, 4>;
+
struct data_type_builder {
data_type &Data;
llvm::DenseSet<DeclID> Found;
data_type_builder(data_type &D) : Data(D) {}
+
void insert(DeclID ID) {
// Just use a linear scan unless we have more than a few IDs.
if (Found.empty() && !Data.empty()) {
@@ -70,15 +78,15 @@ public:
Data.push_back(ID);
}
};
- typedef unsigned hash_value_type;
- typedef unsigned offset_type;
- typedef ModuleFile *file_type;
+ using hash_value_type = unsigned;
+ using offset_type = unsigned;
+ using file_type = ModuleFile *;
- typedef DeclarationName external_key_type;
- typedef DeclarationNameKey internal_key_type;
+ using external_key_type = DeclarationName;
+ using internal_key_type = DeclarationNameKey;
explicit ASTDeclContextNameLookupTrait(ASTReader &Reader, ModuleFile &F)
- : Reader(Reader), F(F) { }
+ : Reader(Reader), F(F) {}
static bool EqualKey(const internal_key_type &a, const internal_key_type &b) {
return a == b;
@@ -87,6 +95,7 @@ public:
static hash_value_type ComputeHash(const internal_key_type &Key) {
return Key.getHash();
}
+
static internal_key_type GetInternalKey(const external_key_type &Name) {
return Name;
}
@@ -119,14 +128,13 @@ struct DeclContextLookupTable {
/// functionality for accessing the on-disk hash table of identifiers
/// in an AST file. Different subclasses customize that functionality
/// based on what information they are interested in. Those subclasses
-/// must provide the \c data_type typedef and the ReadData operation,
-/// only.
+/// must provide the \c data_type type and the ReadData operation, only.
class ASTIdentifierLookupTraitBase {
public:
- typedef StringRef external_key_type;
- typedef StringRef internal_key_type;
- typedef unsigned hash_value_type;
- typedef unsigned offset_type;
+ using external_key_type = StringRef;
+ using internal_key_type = StringRef;
+ using hash_value_type = unsigned;
+ using offset_type = unsigned;
static bool EqualKey(const internal_key_type& a, const internal_key_type& b) {
return a == b;
@@ -159,11 +167,11 @@ class ASTIdentifierLookupTrait : public ASTIdentifierLookupTraitBase {
IdentifierInfo *KnownII;
public:
- typedef IdentifierInfo * data_type;
+ using data_type = IdentifierInfo *;
ASTIdentifierLookupTrait(ASTReader &Reader, ModuleFile &F,
IdentifierInfo *II = nullptr)
- : Reader(Reader), F(F), KnownII(II) { }
+ : Reader(Reader), F(F), KnownII(II) {}
data_type ReadData(const internal_key_type& k,
const unsigned char* d,
@@ -176,8 +184,8 @@ public:
/// \brief The on-disk hash table used to contain information about
/// all of the identifiers in the program.
-typedef llvm::OnDiskIterableChainedHashTable<ASTIdentifierLookupTrait>
- ASTIdentifierLookupTable;
+using ASTIdentifierLookupTable =
+ llvm::OnDiskIterableChainedHashTable<ASTIdentifierLookupTrait>;
/// \brief Class that performs lookup for a selector's entries in the global
/// method pool stored in an AST file.
@@ -196,13 +204,13 @@ public:
SmallVector<ObjCMethodDecl *, 2> Factory;
};
- typedef Selector external_key_type;
- typedef external_key_type internal_key_type;
- typedef unsigned hash_value_type;
- typedef unsigned offset_type;
+ using external_key_type = Selector;
+ using internal_key_type = external_key_type;
+ using hash_value_type = unsigned;
+ using offset_type = unsigned;
- ASTSelectorLookupTrait(ASTReader &Reader, ModuleFile &F)
- : Reader(Reader), F(F) { }
+ ASTSelectorLookupTrait(ASTReader &Reader, ModuleFile &F)
+ : Reader(Reader), F(F) {}
static bool EqualKey(const internal_key_type& a,
const internal_key_type& b) {
@@ -222,8 +230,8 @@ public:
};
/// \brief The on-disk hash table used for the global method pool.
-typedef llvm::OnDiskChainedHashTable<ASTSelectorLookupTrait>
- ASTSelectorLookupTable;
+using ASTSelectorLookupTable =
+ llvm::OnDiskChainedHashTable<ASTSelectorLookupTrait>;
/// \brief Trait class used to search the on-disk hash table containing all of
/// the header search information.
@@ -241,7 +249,7 @@ class HeaderFileInfoTrait {
const char *FrameworkStrings;
public:
- typedef const FileEntry *external_key_type;
+ using external_key_type = const FileEntry *;
struct internal_key_type {
off_t Size;
@@ -249,15 +257,16 @@ public:
StringRef Filename;
bool Imported;
};
- typedef const internal_key_type &internal_key_ref;
+
+ using internal_key_ref = const internal_key_type &;
- typedef HeaderFileInfo data_type;
- typedef unsigned hash_value_type;
- typedef unsigned offset_type;
+ using data_type = HeaderFileInfo;
+ using hash_value_type = unsigned;
+ using offset_type = unsigned;
HeaderFileInfoTrait(ASTReader &Reader, ModuleFile &M, HeaderSearch *HS,
const char *FrameworkStrings)
- : Reader(Reader), M(M), HS(HS), FrameworkStrings(FrameworkStrings) { }
+ : Reader(Reader), M(M), HS(HS), FrameworkStrings(FrameworkStrings) {}
static hash_value_type ComputeHash(internal_key_ref ikey);
internal_key_type GetInternalKey(const FileEntry *FE);
@@ -272,12 +281,13 @@ public:
};
/// \brief The on-disk hash table used for known header files.
-typedef llvm::OnDiskChainedHashTable<HeaderFileInfoTrait>
- HeaderFileInfoLookupTable;
+using HeaderFileInfoLookupTable =
+ llvm::OnDiskChainedHashTable<HeaderFileInfoTrait>;
-} // end namespace clang::serialization::reader
-} // end namespace clang::serialization
-} // end namespace clang
+} // namespace reader
+
+} // namespace serialization
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_LIB_SERIALIZATION_ASTREADERINTERNALS_H
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp
index 3f5da029947c5..8ef1491eb2da7 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -1854,6 +1854,9 @@ OMPClause *OMPClauseReader::readClause() {
case OMPC_task_reduction:
C = OMPTaskReductionClause::CreateEmpty(Context, Reader->Record.readInt());
break;
+ case OMPC_in_reduction:
+ C = OMPInReductionClause::CreateEmpty(Context, Reader->Record.readInt());
+ break;
case OMPC_linear:
C = OMPLinearClause::CreateEmpty(Context, Reader->Record.readInt());
break;
@@ -2192,6 +2195,44 @@ void OMPClauseReader::VisitOMPTaskReductionClause(OMPTaskReductionClause *C) {
C->setReductionOps(Vars);
}
+void OMPClauseReader::VisitOMPInReductionClause(OMPInReductionClause *C) {
+ VisitOMPClauseWithPostUpdate(C);
+ C->setLParenLoc(Reader->ReadSourceLocation());
+ C->setColonLoc(Reader->ReadSourceLocation());
+ NestedNameSpecifierLoc NNSL = Reader->Record.readNestedNameSpecifierLoc();
+ DeclarationNameInfo DNI;
+ Reader->ReadDeclarationNameInfo(DNI);
+ C->setQualifierLoc(NNSL);
+ C->setNameInfo(DNI);
+
+ unsigned NumVars = C->varlist_size();
+ SmallVector<Expr *, 16> Vars;
+ Vars.reserve(NumVars);
+ for (unsigned I = 0; I != NumVars; ++I)
+ Vars.push_back(Reader->Record.readSubExpr());
+ C->setVarRefs(Vars);
+ Vars.clear();
+ for (unsigned I = 0; I != NumVars; ++I)
+ Vars.push_back(Reader->Record.readSubExpr());
+ C->setPrivates(Vars);
+ Vars.clear();
+ for (unsigned I = 0; I != NumVars; ++I)
+ Vars.push_back(Reader->Record.readSubExpr());
+ C->setLHSExprs(Vars);
+ Vars.clear();
+ for (unsigned I = 0; I != NumVars; ++I)
+ Vars.push_back(Reader->Record.readSubExpr());
+ C->setRHSExprs(Vars);
+ Vars.clear();
+ for (unsigned I = 0; I != NumVars; ++I)
+ Vars.push_back(Reader->Record.readSubExpr());
+ C->setReductionOps(Vars);
+ Vars.clear();
+ for (unsigned I = 0; I != NumVars; ++I)
+ Vars.push_back(Reader->Record.readSubExpr());
+ C->setTaskgroupDescriptors(Vars);
+}
+
void OMPClauseReader::VisitOMPLinearClause(OMPLinearClause *C) {
VisitOMPClauseWithPostUpdate(C);
C->setLParenLoc(Reader->ReadSourceLocation());
@@ -2306,6 +2347,7 @@ void OMPClauseReader::VisitOMPDependClause(OMPDependClause *C) {
}
void OMPClauseReader::VisitOMPDeviceClause(OMPDeviceClause *C) {
+ VisitOMPClauseWithPreInit(C);
C->setDevice(Reader->Record.readSubExpr());
C->setLParenLoc(Reader->ReadSourceLocation());
}
@@ -2766,6 +2808,7 @@ void ASTStmtReader::VisitOMPTaskgroupDirective(OMPTaskgroupDirective *D) {
// The NumClauses field was read in ReadStmtFromStream.
Record.skipInts(1);
VisitOMPExecutableDirective(D);
+ D->setReductionRef(Record.readSubExpr());
}
void ASTStmtReader::VisitOMPFlushDirective(OMPFlushDirective *D) {
@@ -2877,6 +2920,7 @@ void ASTStmtReader::VisitOMPTargetUpdateDirective(OMPTargetUpdateDirective *D) {
void ASTStmtReader::VisitOMPDistributeParallelForDirective(
OMPDistributeParallelForDirective *D) {
VisitOMPLoopDirective(D);
+ D->setHasCancel(Record.readInt());
}
void ASTStmtReader::VisitOMPDistributeParallelForSimdDirective(
@@ -2916,6 +2960,7 @@ void ASTStmtReader::VisitOMPTeamsDistributeParallelForSimdDirective(
void ASTStmtReader::VisitOMPTeamsDistributeParallelForDirective(
OMPTeamsDistributeParallelForDirective *D) {
VisitOMPLoopDirective(D);
+ D->setHasCancel(Record.readInt());
}
void ASTStmtReader::VisitOMPTargetTeamsDirective(OMPTargetTeamsDirective *D) {
@@ -2933,6 +2978,7 @@ void ASTStmtReader::VisitOMPTargetTeamsDistributeDirective(
void ASTStmtReader::VisitOMPTargetTeamsDistributeParallelForDirective(
OMPTargetTeamsDistributeParallelForDirective *D) {
VisitOMPLoopDirective(D);
+ D->setHasCancel(Record.readInt());
}
void ASTStmtReader::VisitOMPTargetTeamsDistributeParallelForSimdDirective(
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp
index 128e53b91b1d1..1e72ced2ee364 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp
@@ -1,4 +1,4 @@
-//===--- ASTWriter.cpp - AST File Writer ------------------------*- C++ -*-===//
+//===- ASTWriter.cpp - AST File Writer ------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,11 +17,15 @@
#include "MultiOnDiskHashTable.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTUnresolvedSet.h"
+#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclContextInternals.h"
#include "clang/AST/DeclFriend.h"
+#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/LambdaCapture.h"
@@ -30,16 +34,22 @@
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLocVisitor.h"
+#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemOptions.h"
+#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
+#include "clang/Basic/Lambda.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/MemoryBufferCache.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/ObjCRuntime.h"
+#include "clang/Basic/OpenCLOptions.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/SourceManagerInternals.h"
+#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/Version.h"
@@ -62,24 +72,30 @@
#include "clang/Serialization/SerializationDiagnostic.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Hashing.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Bitcode/BitCodes.h"
#include "llvm/Bitcode/BitstreamWriter.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compression.h"
+#include "llvm/Support/Endian.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/OnDiskHashTable.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/Process.h"
#include "llvm/Support/SHA1.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
@@ -87,11 +103,14 @@
#include <cstdint>
#include <cstdlib>
#include <cstring>
+#include <ctime>
#include <deque>
#include <limits>
-#include <new>
+#include <memory>
+#include <queue>
#include <tuple>
#include <utility>
+#include <vector>
using namespace clang;
using namespace clang::serialization;
@@ -120,13 +139,14 @@ namespace clang {
ASTRecordWriter Record;
/// \brief Type code that corresponds to the record generated.
- TypeCode Code;
+ TypeCode Code = static_cast<TypeCode>(0);
+
/// \brief Abbreviation to use for the record, if any.
- unsigned AbbrevToUse;
+ unsigned AbbrevToUse = 0;
public:
ASTTypeWriter(ASTWriter &Writer, ASTWriter::RecordDataImpl &Record)
- : Writer(Writer), Record(Writer, Record), Code((TypeCode)0), AbbrevToUse(0) { }
+ : Writer(Writer), Record(Writer, Record) {}
uint64_t Emit() {
return Record.Emit(Code, AbbrevToUse);
@@ -160,7 +180,7 @@ namespace clang {
#include "clang/AST/TypeNodes.def"
};
-} // end namespace clang
+} // namespace clang
void ASTTypeWriter::VisitBuiltinType(const BuiltinType *T) {
llvm_unreachable("Built-in types are never serialized");
@@ -433,6 +453,15 @@ ASTTypeWriter::VisitDependentSizedExtVectorType(
Code = TYPE_DEPENDENT_SIZED_EXT_VECTOR;
}
+void
+ASTTypeWriter::VisitDependentAddressSpaceType(
+ const DependentAddressSpaceType *T) {
+ Record.AddTypeRef(T->getPointeeType());
+ Record.AddStmt(T->getAddrSpaceExpr());
+ Record.AddSourceLocation(T->getAttributeLoc());
+ Code = TYPE_DEPENDENT_ADDRESS_SPACE;
+}
+
void
ASTTypeWriter::VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
Record.push_back(T->getDepth());
@@ -541,8 +570,7 @@ class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> {
ASTRecordWriter &Record;
public:
- TypeLocWriter(ASTRecordWriter &Record)
- : Record(Record) { }
+ TypeLocWriter(ASTRecordWriter &Record) : Record(Record) {}
#define ABSTRACT_TYPELOC(CLASS, PARENT)
#define TYPELOC(CLASS, PARENT) \
@@ -553,7 +581,7 @@ public:
void VisitFunctionTypeLoc(FunctionTypeLoc TyLoc);
};
-} // end anonymous namespace
+} // namespace
void TypeLocWriter::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
// nothing to do
@@ -627,6 +655,15 @@ void TypeLocWriter::VisitDependentSizedArrayTypeLoc(
VisitArrayTypeLoc(TL);
}
+void TypeLocWriter::VisitDependentAddressSpaceTypeLoc(
+ DependentAddressSpaceTypeLoc TL) {
+ Record.AddSourceLocation(TL.getAttrNameLoc());
+ SourceRange range = TL.getAttrOperandParensRange();
+ Record.AddSourceLocation(range.getBegin());
+ Record.AddSourceLocation(range.getEnd());
+ Record.AddStmt(TL.getAttrExprOperand());
+}
+
void TypeLocWriter::VisitDependentSizedExtVectorTypeLoc(
DependentSizedExtVectorTypeLoc TL) {
Record.AddSourceLocation(TL.getNameLoc());
@@ -649,18 +686,23 @@ void TypeLocWriter::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
for (unsigned i = 0, e = TL.getNumParams(); i != e; ++i)
Record.AddDeclRef(TL.getParam(i));
}
+
void TypeLocWriter::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {
VisitFunctionTypeLoc(TL);
}
+
void TypeLocWriter::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
VisitFunctionTypeLoc(TL);
}
+
void TypeLocWriter::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
Record.AddSourceLocation(TL.getNameLoc());
}
+
void TypeLocWriter::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
Record.AddSourceLocation(TL.getNameLoc());
}
+
void TypeLocWriter::VisitObjCTypeParamTypeLoc(ObjCTypeParamTypeLoc TL) {
if (TL.getNumProtocols()) {
Record.AddSourceLocation(TL.getProtocolLAngleLoc());
@@ -669,6 +711,7 @@ void TypeLocWriter::VisitObjCTypeParamTypeLoc(ObjCTypeParamTypeLoc TL) {
for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
Record.AddSourceLocation(TL.getProtocolLoc(i));
}
+
void TypeLocWriter::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
Record.AddSourceLocation(TL.getTypeofLoc());
Record.AddSourceLocation(TL.getLParenLoc());
@@ -1130,6 +1173,7 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(SUBMODULE_TEXTUAL_HEADER);
RECORD(SUBMODULE_PRIVATE_TEXTUAL_HEADER);
RECORD(SUBMODULE_INITIALIZERS);
+ RECORD(SUBMODULE_EXPORT_AS);
// Comments Block.
BLOCK(COMMENTS_BLOCK);
@@ -1397,6 +1441,7 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
StringRef isysroot,
const std::string &OutputFile) {
using namespace llvm;
+
Stream.EnterSubblock(CONTROL_BLOCK_ID, 5);
RecordData Record;
@@ -1505,6 +1550,7 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
for (auto I : M.Signature)
Record.push_back(I);
+ AddString(M.ModuleName, Record);
AddPath(M.FileName, Record);
}
Stream.EmitRecord(IMPORTS, Record);
@@ -1686,21 +1732,22 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
namespace {
- /// \brief An input file.
- struct InputFileEntry {
- const FileEntry *File;
- bool IsSystemFile;
- bool IsTransient;
- bool BufferOverridden;
- bool IsTopLevelModuleMap;
- };
+/// \brief An input file.
+struct InputFileEntry {
+ const FileEntry *File;
+ bool IsSystemFile;
+ bool IsTransient;
+ bool BufferOverridden;
+ bool IsTopLevelModuleMap;
+};
-} // end anonymous namespace
+} // namespace
void ASTWriter::WriteInputFiles(SourceManager &SourceMgr,
HeaderSearchOptions &HSOpts,
bool Modules) {
using namespace llvm;
+
Stream.EnterSubblock(INPUT_FILES_BLOCK_ID, 4);
// Create input-file abbreviation.
@@ -1877,7 +1924,7 @@ namespace {
off_t Size;
time_t ModTime;
};
- typedef const key_type &key_type_ref;
+ using key_type_ref = const key_type &;
using UnresolvedModule =
llvm::PointerIntPair<Module *, 2, ModuleMap::ModuleHeaderRole>;
@@ -1887,10 +1934,10 @@ namespace {
ArrayRef<ModuleMap::KnownHeader> KnownHeaders;
UnresolvedModule Unresolved;
};
- typedef const data_type &data_type_ref;
+ using data_type_ref = const data_type &;
- typedef unsigned hash_value_type;
- typedef unsigned offset_type;
+ using hash_value_type = unsigned;
+ using offset_type = unsigned;
hash_value_type ComputeHash(key_type_ref key) {
// The hash is based only on size/time of the file, so that the reader can
@@ -1899,9 +1946,10 @@ namespace {
return llvm::hash_combine(key.Size, key.ModTime);
}
- std::pair<unsigned,unsigned>
+ std::pair<unsigned, unsigned>
EmitKeyDataLength(raw_ostream& Out, key_type_ref key, data_type_ref Data) {
using namespace llvm::support;
+
endian::Writer<little> LE(Out);
unsigned KeyLen = key.Filename.size() + 1 + 8 + 8;
LE.write<uint16_t>(KeyLen);
@@ -1917,6 +1965,7 @@ namespace {
void EmitKey(raw_ostream& Out, key_type_ref key, unsigned KeyLen) {
using namespace llvm::support;
+
endian::Writer<little> LE(Out);
LE.write<uint64_t>(key.Size);
KeyLen -= 8;
@@ -1928,6 +1977,7 @@ namespace {
void EmitData(raw_ostream &Out, key_type_ref key,
data_type_ref Data, unsigned DataLen) {
using namespace llvm::support;
+
endian::Writer<little> LE(Out);
uint64_t Start = Out.tell(); (void)Start;
@@ -1982,7 +2032,7 @@ namespace {
const char *strings_end() const { return FrameworkStringData.end(); }
};
-} // end anonymous namespace
+} // namespace
/// \brief Write the header search block for the list of files that
///
@@ -2095,6 +2145,7 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) {
uint32_t BucketOffset;
{
using namespace llvm::support;
+
llvm::raw_svector_ostream Out(TableData);
// Make sure that no bucket is at offset 0
endian::Writer<little>(Out).write<uint32_t>(0);
@@ -2126,7 +2177,7 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) {
static void emitBlob(llvm::BitstreamWriter &Stream, StringRef Blob,
unsigned SLocBufferBlobCompressedAbbrv,
unsigned SLocBufferBlobAbbrv) {
- typedef ASTWriter::RecordData::value_type RecordDataType;
+ using RecordDataType = ASTWriter::RecordData::value_type;
// Compress the buffer if possible. We expect that almost all PCM
// consumers will not want its contents.
@@ -2312,12 +2363,13 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
// Emit the needed file names.
llvm::DenseMap<int, int> FilenameMap;
+ FilenameMap[-1] = -1; // For unspecified filenames.
for (const auto &L : LineTable) {
if (L.first.ID < 0)
continue;
for (auto &LE : L.second) {
if (FilenameMap.insert(std::make_pair(LE.FilenameID,
- FilenameMap.size())).second)
+ FilenameMap.size() - 1)).second)
AddPath(LineTable.getFilename(LE.FilenameID), Record);
}
}
@@ -2370,7 +2422,6 @@ static bool shouldIgnoreMacro(MacroDirective *MD, bool IsModule,
/// \brief Writes the block containing the serialized form of the
/// preprocessor.
-///
void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
PreprocessingRecord *PPRec = PP.getPreprocessingRecord();
if (PPRec)
@@ -2387,6 +2438,17 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
if (PP.isRecordingPreamble() && PP.hasRecordedPreamble()) {
assert(!IsModule);
+ auto SkipInfo = PP.getPreambleSkipInfo();
+ if (SkipInfo.hasValue()) {
+ Record.push_back(true);
+ AddSourceLocation(SkipInfo->HashTokenLoc, Record);
+ AddSourceLocation(SkipInfo->IfTokenLoc, Record);
+ Record.push_back(SkipInfo->FoundNonSkipPortion);
+ Record.push_back(SkipInfo->FoundElse);
+ AddSourceLocation(SkipInfo->ElseLoc, Record);
+ } else {
+ Record.push_back(false);
+ }
for (const auto &Cond : PP.getPreambleConditionalStack()) {
AddSourceLocation(Cond.IfLoc, Record);
Record.push_back(Cond.WasSkipping);
@@ -2715,6 +2777,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_DEFINITION));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ID
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Parent
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Kind
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsExplicit
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsSystem
@@ -2789,11 +2852,15 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Message
unsigned ConflictAbbrev = Stream.EmitAbbrev(std::move(Abbrev));
+ Abbrev = std::make_shared<BitCodeAbbrev>();
+ Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_EXPORT_AS));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Macro name
+ unsigned ExportAsAbbrev = Stream.EmitAbbrev(std::move(Abbrev));
+
// Write the submodule metadata block.
RecordData::value_type Record[] = {
getNumberOfModules(WritingModule),
- FirstSubmoduleID - NUM_PREDEF_SUBMODULE_IDS,
- (unsigned)WritingModule->Kind};
+ FirstSubmoduleID - NUM_PREDEF_SUBMODULE_IDS};
Stream.EmitRecord(SUBMODULE_METADATA, Record);
// Write all of the submodules.
@@ -2815,6 +2882,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
RecordData::value_type Record[] = {SUBMODULE_DEFINITION,
ID,
ParentID,
+ (RecordData::value_type)Mod->Kind,
Mod->IsFramework,
Mod->IsExplicit,
Mod->IsSystem,
@@ -2923,6 +2991,12 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
if (!Inits.empty())
Stream.EmitRecord(SUBMODULE_INITIALIZERS, Inits);
+ // Emit the name of the re-exported module, if any.
+ if (!Mod->ExportAsModule.empty()) {
+ RecordData::value_type Record[] = {SUBMODULE_EXPORT_AS};
+ Stream.EmitRecordWithBlob(ExportAsAbbrev, Record, Mod->ExportAsModule);
+ }
+
// Queue up the submodules of this module.
for (auto *M : Mod->submodules())
Q.push(M);
@@ -3164,28 +3238,29 @@ class ASTMethodPoolTrait {
ASTWriter &Writer;
public:
- typedef Selector key_type;
- typedef key_type key_type_ref;
+ using key_type = Selector;
+ using key_type_ref = key_type;
struct data_type {
SelectorID ID;
ObjCMethodList Instance, Factory;
};
- typedef const data_type& data_type_ref;
+ using data_type_ref = const data_type &;
- typedef unsigned hash_value_type;
- typedef unsigned offset_type;
+ using hash_value_type = unsigned;
+ using offset_type = unsigned;
- explicit ASTMethodPoolTrait(ASTWriter &Writer) : Writer(Writer) { }
+ explicit ASTMethodPoolTrait(ASTWriter &Writer) : Writer(Writer) {}
static hash_value_type ComputeHash(Selector Sel) {
return serialization::ComputeHash(Sel);
}
- std::pair<unsigned,unsigned>
+ std::pair<unsigned, unsigned>
EmitKeyDataLength(raw_ostream& Out, Selector Sel,
data_type_ref Methods) {
using namespace llvm::support;
+
endian::Writer<little> LE(Out);
unsigned KeyLen = 2 + (Sel.getNumArgs()? Sel.getNumArgs() * 4 : 4);
LE.write<uint16_t>(KeyLen);
@@ -3204,6 +3279,7 @@ public:
void EmitKey(raw_ostream& Out, Selector Sel, unsigned) {
using namespace llvm::support;
+
endian::Writer<little> LE(Out);
uint64_t Start = Out.tell();
assert((Start >> 32) == 0 && "Selector key offset too large");
@@ -3220,6 +3296,7 @@ public:
void EmitData(raw_ostream& Out, key_type_ref,
data_type_ref Methods, unsigned DataLen) {
using namespace llvm::support;
+
endian::Writer<little> LE(Out);
uint64_t Start = Out.tell(); (void)Start;
LE.write<uint32_t>(Methods.ID);
@@ -3264,7 +3341,7 @@ public:
}
};
-} // end anonymous namespace
+} // namespace
/// \brief Write ObjC data: selectors and the method pool.
///
@@ -3328,6 +3405,7 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) {
uint32_t BucketOffset;
{
using namespace llvm::support;
+
ASTMethodPoolTrait Trait(*this);
llvm::raw_svector_ostream Out(MethodPool);
// Make sure that no bucket is at offset 0
@@ -3372,6 +3450,7 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) {
/// \brief Write the selectors referenced in @selector expression into AST file.
void ASTWriter::WriteReferencedSelectorsPool(Sema &SemaRef) {
using namespace llvm;
+
if (SemaRef.ReferencedSelectors.empty())
return;
@@ -3460,14 +3539,14 @@ class ASTIdentifierTableTrait {
}
public:
- typedef IdentifierInfo* key_type;
- typedef key_type key_type_ref;
+ using key_type = IdentifierInfo *;
+ using key_type_ref = key_type;
- typedef IdentID data_type;
- typedef data_type data_type_ref;
+ using data_type = IdentID;
+ using data_type_ref = data_type;
- typedef unsigned hash_value_type;
- typedef unsigned offset_type;
+ using hash_value_type = unsigned;
+ using offset_type = unsigned;
ASTIdentifierTableTrait(ASTWriter &Writer, Preprocessor &PP,
IdentifierResolver &IdResolver, bool IsModule,
@@ -3491,7 +3570,7 @@ public:
return isInterestingIdentifier(II, 0);
}
- std::pair<unsigned,unsigned>
+ std::pair<unsigned, unsigned>
EmitKeyDataLength(raw_ostream& Out, IdentifierInfo* II, IdentID ID) {
unsigned KeyLen = II->getLength() + 1;
unsigned DataLen = 4; // 4 bytes for the persistent ID << 1
@@ -3509,7 +3588,9 @@ public:
DataLen += 4;
}
}
+
using namespace llvm::support;
+
endian::Writer<little> LE(Out);
assert((uint16_t)DataLen == DataLen && (uint16_t)KeyLen == KeyLen);
@@ -3538,6 +3619,7 @@ public:
void EmitData(raw_ostream& Out, IdentifierInfo* II,
IdentID ID, unsigned) {
using namespace llvm::support;
+
endian::Writer<little> LE(Out);
auto MacroOffset = Writer.getMacroDirectivesOffset(II);
@@ -3581,7 +3663,7 @@ public:
}
};
-} // end anonymous namespace
+} // namespace
/// \brief Write the identifier table into the AST file.
///
@@ -3639,6 +3721,7 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP,
uint32_t BucketOffset;
{
using namespace llvm::support;
+
llvm::raw_svector_ostream Out(IdentifierTable);
// Make sure that no bucket is at offset 0
endian::Writer<little>(Out).write<uint32_t>(0);
@@ -3694,17 +3777,17 @@ class ASTDeclContextNameLookupTrait {
llvm::SmallVector<DeclID, 64> DeclIDs;
public:
- typedef DeclarationNameKey key_type;
- typedef key_type key_type_ref;
+ using key_type = DeclarationNameKey;
+ using key_type_ref = key_type;
/// A start and end index into DeclIDs, representing a sequence of decls.
- typedef std::pair<unsigned, unsigned> data_type;
- typedef const data_type& data_type_ref;
+ using data_type = std::pair<unsigned, unsigned>;
+ using data_type_ref = const data_type &;
- typedef unsigned hash_value_type;
- typedef unsigned offset_type;
+ using hash_value_type = unsigned;
+ using offset_type = unsigned;
- explicit ASTDeclContextNameLookupTrait(ASTWriter &Writer) : Writer(Writer) { }
+ explicit ASTDeclContextNameLookupTrait(ASTWriter &Writer) : Writer(Writer) {}
template<typename Coll>
data_type getData(const Coll &Decls) {
@@ -3736,6 +3819,7 @@ public:
"have reference to loaded module file but no chain?");
using namespace llvm::support;
+
endian::Writer<little>(Out)
.write<uint32_t>(Writer.getChain()->getModuleFileID(F));
}
@@ -3744,6 +3828,7 @@ public:
DeclarationNameKey Name,
data_type_ref Lookup) {
using namespace llvm::support;
+
endian::Writer<little> LE(Out);
unsigned KeyLen = 1;
switch (Name.getKind()) {
@@ -3777,6 +3862,7 @@ public:
void EmitKey(raw_ostream &Out, DeclarationNameKey Name, unsigned) {
using namespace llvm::support;
+
endian::Writer<little> LE(Out);
LE.write<uint8_t>(Name.getKind());
switch (Name.getKind()) {
@@ -3808,6 +3894,7 @@ public:
void EmitData(raw_ostream &Out, key_type_ref, data_type Lookup,
unsigned DataLen) {
using namespace llvm::support;
+
endian::Writer<little> LE(Out);
uint64_t Start = Out.tell(); (void)Start;
for (unsigned I = Lookup.first, N = Lookup.second; I != N; ++I)
@@ -3816,7 +3903,7 @@ public:
}
};
-} // end anonymous namespace
+} // namespace
bool ASTWriter::isLookupResultExternal(StoredDeclsList &Result,
DeclContext *DC) {
@@ -4295,6 +4382,7 @@ void ASTWriter::WritePackPragmaOptions(Sema &SemaRef) {
for (const auto &StackEntry : SemaRef.PackStack.Stack) {
Record.push_back(StackEntry.Value);
AddSourceLocation(StackEntry.PragmaLocation, Record);
+ AddSourceLocation(StackEntry.PragmaPushLocation, Record);
AddString(StackEntry.StackSlotLabel, Record);
}
Stream.EmitRecord(PACK_PRAGMA_OPTIONS, Record);
@@ -4348,7 +4436,6 @@ void ASTRecordWriter::AddAttributes(ArrayRef<const Attr *> Attrs) {
Record.AddSourceRange(A->getRange());
#include "clang/Serialization/AttrPCHWrite.inc"
-
}
}
@@ -4778,7 +4865,8 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
// each of those modules were mapped into our own offset/ID space, so that
// the reader can build the appropriate mapping to its own offset/ID space.
// The map consists solely of a blob with the following format:
- // *(module-name-len:i16 module-name:len*i8
+ // *(module-kind:i8
+ // module-name-len:i16 module-name:len*i8
// source-location-offset:i32
// identifier-id:i32
// preprocessed-entity-id:i32
@@ -4789,6 +4877,9 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
// c++-base-specifiers-id:i32
// type-id:i32)
//
+ // module-kind is the ModuleKind enum value. If it is MK_PrebuiltModule or
+ // MK_ExplicitModule, then the module-name is the module name. Otherwise,
+ // it is the module file name.
auto Abbrev = std::make_shared<BitCodeAbbrev>();
Abbrev->Add(BitCodeAbbrevOp(MODULE_OFFSET_MAP));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
@@ -4798,10 +4889,15 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
llvm::raw_svector_ostream Out(Buffer);
for (ModuleFile &M : Chain->ModuleMgr) {
using namespace llvm::support;
+
endian::Writer<little> LE(Out);
- StringRef FileName = M.FileName;
- LE.write<uint16_t>(FileName.size());
- Out.write(FileName.data(), FileName.size());
+ LE.write<uint8_t>(static_cast<uint8_t>(M.Kind));
+ StringRef Name =
+ M.Kind == MK_PrebuiltModule || M.Kind == MK_ExplicitModule
+ ? M.ModuleName
+ : M.FileName;
+ LE.write<uint16_t>(Name.size());
+ Out.write(Name.data(), Name.size());
// Note: if a base ID was uint max, it would not be possible to load
// another module after it or have more than one entity inside it.
@@ -5039,9 +5135,15 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
case UPD_CXX_ADDED_FUNCTION_DEFINITION:
break;
- case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER: {
- const VarDecl *VD = cast<VarDecl>(D);
+ case UPD_CXX_POINT_OF_INSTANTIATION:
+ // FIXME: Do we need to also save the template specialization kind here?
Record.AddSourceLocation(Update.getLoc());
+ break;
+
+ case UPD_CXX_ADDED_VAR_DEFINITION: {
+ const VarDecl *VD = cast<VarDecl>(D);
+ Record.push_back(VD->isInline());
+ Record.push_back(VD->isInlineSpecified());
if (VD->getInit()) {
Record.push_back(!VD->isInitKnownICE() ? 1
: (VD->isInitICE() ? 3 : 2));
@@ -5109,6 +5211,7 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
case UPD_CXX_RESOLVED_DTOR_DELETE:
Record.AddDeclRef(Update.getDecl());
+ Record.AddStmt(cast<CXXDestructorDecl>(D)->getOperatorDeleteThisArg());
break;
case UPD_CXX_RESOLVED_EXCEPTION_SPEC:
@@ -6136,7 +6239,8 @@ void ASTWriter::DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) {
}
void ASTWriter::ResolvedOperatorDelete(const CXXDestructorDecl *DD,
- const FunctionDecl *Delete) {
+ const FunctionDecl *Delete,
+ Expr *ThisArg) {
if (Chain && Chain->isProcessingUpdateRecords()) return;
assert(!WritingAST && "Already writing the AST!");
assert(Delete && "Not given an operator delete");
@@ -6156,6 +6260,15 @@ void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) {
DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_ADDED_FUNCTION_DEFINITION));
}
+void ASTWriter::VariableDefinitionInstantiated(const VarDecl *D) {
+ if (Chain && Chain->isProcessingUpdateRecords()) return;
+ assert(!WritingAST && "Already writing the AST!");
+ if (!D->isFromASTFile())
+ return;
+
+ DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_ADDED_VAR_DEFINITION));
+}
+
void ASTWriter::FunctionDefinitionInstantiated(const FunctionDecl *D) {
if (Chain && Chain->isProcessingUpdateRecords()) return;
assert(!WritingAST && "Already writing the AST!");
@@ -6165,7 +6278,7 @@ void ASTWriter::FunctionDefinitionInstantiated(const FunctionDecl *D) {
DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_ADDED_FUNCTION_DEFINITION));
}
-void ASTWriter::StaticDataMemberInstantiated(const VarDecl *D) {
+void ASTWriter::InstantiationRequested(const ValueDecl *D) {
if (Chain && Chain->isProcessingUpdateRecords()) return;
assert(!WritingAST && "Already writing the AST!");
if (!D->isFromASTFile())
@@ -6173,9 +6286,12 @@ void ASTWriter::StaticDataMemberInstantiated(const VarDecl *D) {
// Since the actual instantiation is delayed, this really means that we need
// to update the instantiation location.
- DeclUpdates[D].push_back(
- DeclUpdate(UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER,
- D->getMemberSpecializationInfo()->getPointOfInstantiation()));
+ SourceLocation POI;
+ if (auto *VD = dyn_cast<VarDecl>(D))
+ POI = VD->getPointOfInstantiation();
+ else
+ POI = cast<FunctionDecl>(D)->getPointOfInstantiation();
+ DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_POINT_OF_INSTANTIATION, POI));
}
void ASTWriter::DefaultArgumentInstantiated(const ParmVarDecl *D) {
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp
index ec21ca2276c11..3dac3a48297af 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -612,6 +612,7 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
void ASTDeclWriter::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) {
VisitFunctionDecl(D);
+ Record.push_back(D->IsCopyDeductionCandidate);
Code = serialization::DECL_CXX_DEDUCTION_GUIDE;
}
@@ -849,17 +850,16 @@ void ASTDeclWriter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
void ASTDeclWriter::VisitFieldDecl(FieldDecl *D) {
VisitDeclaratorDecl(D);
Record.push_back(D->isMutable());
- if (D->InitStorage.getInt() == FieldDecl::ISK_BitWidthOrNothing &&
- D->InitStorage.getPointer() == nullptr) {
- Record.push_back(0);
- } else if (D->InitStorage.getInt() == FieldDecl::ISK_CapturedVLAType) {
- Record.push_back(D->InitStorage.getInt() + 1);
- Record.AddTypeRef(
- QualType(static_cast<Type *>(D->InitStorage.getPointer()), 0));
- } else {
- Record.push_back(D->InitStorage.getInt() + 1);
- Record.AddStmt(static_cast<Expr *>(D->InitStorage.getPointer()));
- }
+
+ FieldDecl::InitStorageKind ISK = D->InitStorage.getInt();
+ Record.push_back(ISK);
+ if (ISK == FieldDecl::ISK_CapturedVLAType)
+ Record.AddTypeRef(QualType(D->getCapturedVLAType(), 0));
+ else if (ISK)
+ Record.AddStmt(D->getInClassInitializer());
+
+ Record.AddStmt(D->getBitWidth());
+
if (!D->getDeclName())
Record.AddDeclRef(Context.getInstantiatedFromUnnamedFieldDecl(D));
@@ -873,6 +873,7 @@ void ASTDeclWriter::VisitFieldDecl(FieldDecl *D) {
!D->isModulePrivate() &&
!D->getBitWidth() &&
!D->hasInClassInitializer() &&
+ !D->hasCapturedVLAType() &&
!D->hasExtInfo() &&
!ObjCIvarDecl::classofKind(D->getKind()) &&
!ObjCAtDefsFieldDecl::classofKind(D->getKind()) &&
@@ -928,6 +929,24 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
} else {
Record.push_back(0);
}
+
+ if (D->getStorageDuration() == SD_Static) {
+ bool ModulesCodegen = false;
+ if (Writer.WritingModule &&
+ !D->getDescribedVarTemplate() && !D->getMemberSpecializationInfo() &&
+ !isa<VarTemplateSpecializationDecl>(D)) {
+ // When building a C++ Modules TS module interface unit, a strong
+ // definition in the module interface is provided by the compilation of
+ // that module interface unit, not by its users. (Inline variables are
+ // still emitted in module users.)
+ ModulesCodegen =
+ (Writer.WritingModule->Kind == Module::ModuleInterfaceUnit &&
+ Writer.Context->GetGVALinkageForVariable(D) == GVA_StrongExternal);
+ }
+ Record.push_back(ModulesCodegen);
+ if (ModulesCodegen)
+ Writer.ModularCodegenDecls.push_back(Writer.GetDeclRef(D));
+ }
enum {
VarNotTemplate = 0, VarTemplate, StaticDataMemberSpecialization
@@ -963,6 +982,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
!D->isConstexpr() &&
!D->isInitCapture() &&
!D->isPreviousDeclInSameBlockScope() &&
+ D->getStorageDuration() != SD_Static &&
!D->getMemberSpecializationInfo())
AbbrevToUse = Writer.getDeclVarAbbrev();
@@ -1247,10 +1267,8 @@ void ASTDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) {
VisitFunctionDecl(D);
if (D->isCanonicalDecl()) {
Record.push_back(D->size_overridden_methods());
- for (CXXMethodDecl::method_iterator
- I = D->begin_overridden_methods(), E = D->end_overridden_methods();
- I != E; ++I)
- Record.AddDeclRef(*I);
+ for (const CXXMethodDecl *MD : D->overridden_methods())
+ Record.AddDeclRef(MD);
} else {
// We only need to record overridden methods once for the canonical decl.
Record.push_back(0);
@@ -1290,6 +1308,8 @@ void ASTDeclWriter::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
VisitCXXMethodDecl(D);
Record.AddDeclRef(D->getOperatorDelete());
+ if (D->getOperatorDelete())
+ Record.AddStmt(D->getOperatorDeleteThisArg());
Code = serialization::DECL_CXX_DESTRUCTOR;
}
@@ -1472,6 +1492,7 @@ void ASTDeclWriter::VisitVarTemplateSpecializationDecl(
Record.AddTemplateArgumentList(&D->getTemplateArgs());
Record.AddSourceLocation(D->getPointOfInstantiation());
Record.push_back(D->getSpecializationKind());
+ Record.push_back(D->IsCompleteDefinition);
Record.push_back(D->isCanonicalDecl());
if (D->isCanonicalDecl()) {
@@ -1697,6 +1718,7 @@ void ASTDeclWriter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) {
Record.AddSourceLocation(D->getLocStart());
Record.AddStmt(D->getCombiner());
Record.AddStmt(D->getInitializer());
+ Record.push_back(D->getInitializerKind());
Record.AddDeclRef(D->getPrevDeclInScope());
Code = serialization::DECL_OMP_DECLARE_REDUCTION;
}
@@ -1741,7 +1763,7 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo
// FieldDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isMutable
- Abv->Add(BitCodeAbbrevOp(0)); //getBitWidth
+ Abv->Add(BitCodeAbbrevOp(0)); // InitStyle
// Type Source Info
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
@@ -1774,7 +1796,7 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo
// FieldDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isMutable
- Abv->Add(BitCodeAbbrevOp(0)); //getBitWidth
+ Abv->Add(BitCodeAbbrevOp(0)); // InitStyle
// ObjC Ivar
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getAccessControl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getSynthesize
@@ -2235,15 +2257,24 @@ void ASTRecordWriter::AddFunctionDefinition(const FunctionDecl *FD) {
assert(FD->doesThisDeclarationHaveABody());
bool ModulesCodegen = false;
if (Writer->WritingModule && !FD->isDependentContext()) {
- // Under -fmodules-codegen, codegen is performed for all defined functions.
- // When building a C++ Modules TS module interface unit, a strong definition
- // in the module interface is provided by the compilation of that module
- // interface unit, not by its users. (Inline functions are still emitted
- // in module users.)
- ModulesCodegen =
- Writer->Context->getLangOpts().ModulesCodegen ||
- (Writer->WritingModule->Kind == Module::ModuleInterfaceUnit &&
- Writer->Context->GetGVALinkageForFunction(FD) == GVA_StrongExternal);
+ Optional<GVALinkage> Linkage;
+ if (Writer->WritingModule->Kind == Module::ModuleInterfaceUnit) {
+ // When building a C++ Modules TS module interface unit, a strong
+ // definition in the module interface is provided by the compilation of
+ // that module interface unit, not by its users. (Inline functions are
+ // still emitted in module users.)
+ Linkage = Writer->Context->GetGVALinkageForFunction(FD);
+ ModulesCodegen = *Linkage == GVA_StrongExternal;
+ }
+ if (Writer->Context->getLangOpts().ModulesCodegen) {
+ // Under -fmodules-codegen, codegen is performed for all non-internal,
+ // non-always_inline functions.
+ if (!FD->hasAttr<AlwaysInlineAttr>()) {
+ if (!Linkage)
+ Linkage = Writer->Context->GetGVALinkageForFunction(FD);
+ ModulesCodegen = *Linkage != GVA_Internal;
+ }
+ }
}
Record->push_back(ModulesCodegen);
if (ModulesCodegen)
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp
index 6971339663f09..c5f4495d2f013 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -2001,6 +2001,27 @@ void OMPClauseWriter::VisitOMPTaskReductionClause(OMPTaskReductionClause *C) {
Record.AddStmt(E);
}
+void OMPClauseWriter::VisitOMPInReductionClause(OMPInReductionClause *C) {
+ Record.push_back(C->varlist_size());
+ VisitOMPClauseWithPostUpdate(C);
+ Record.AddSourceLocation(C->getLParenLoc());
+ Record.AddSourceLocation(C->getColonLoc());
+ Record.AddNestedNameSpecifierLoc(C->getQualifierLoc());
+ Record.AddDeclarationNameInfo(C->getNameInfo());
+ for (auto *VE : C->varlists())
+ Record.AddStmt(VE);
+ for (auto *VE : C->privates())
+ Record.AddStmt(VE);
+ for (auto *E : C->lhs_exprs())
+ Record.AddStmt(E);
+ for (auto *E : C->rhs_exprs())
+ Record.AddStmt(E);
+ for (auto *E : C->reduction_ops())
+ Record.AddStmt(E);
+ for (auto *E : C->taskgroup_descriptors())
+ Record.AddStmt(E);
+}
+
void OMPClauseWriter::VisitOMPLinearClause(OMPLinearClause *C) {
Record.push_back(C->varlist_size());
VisitOMPClauseWithPostUpdate(C);
@@ -2081,6 +2102,7 @@ void OMPClauseWriter::VisitOMPDependClause(OMPDependClause *C) {
}
void OMPClauseWriter::VisitOMPDeviceClause(OMPDeviceClause *C) {
+ VisitOMPClauseWithPreInit(C);
Record.AddStmt(C->getDevice());
Record.AddSourceLocation(C->getLParenLoc());
}
@@ -2480,6 +2502,7 @@ void ASTStmtWriter::VisitOMPTaskgroupDirective(OMPTaskgroupDirective *D) {
VisitStmt(D);
Record.push_back(D->getNumClauses());
VisitOMPExecutableDirective(D);
+ Record.AddStmt(D->getReductionRef());
Code = serialization::STMT_OMP_TASKGROUP_DIRECTIVE;
}
@@ -2545,6 +2568,7 @@ void ASTStmtWriter::VisitOMPTargetUpdateDirective(OMPTargetUpdateDirective *D) {
void ASTStmtWriter::VisitOMPDistributeParallelForDirective(
OMPDistributeParallelForDirective *D) {
VisitOMPLoopDirective(D);
+ Record.push_back(D->hasCancel() ? 1 : 0);
Code = serialization::STMT_OMP_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE;
}
@@ -2592,6 +2616,7 @@ void ASTStmtWriter::VisitOMPTeamsDistributeParallelForSimdDirective(
void ASTStmtWriter::VisitOMPTeamsDistributeParallelForDirective(
OMPTeamsDistributeParallelForDirective *D) {
VisitOMPLoopDirective(D);
+ Record.push_back(D->hasCancel() ? 1 : 0);
Code = serialization::STMT_OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE;
}
@@ -2611,6 +2636,7 @@ void ASTStmtWriter::VisitOMPTargetTeamsDistributeDirective(
void ASTStmtWriter::VisitOMPTargetTeamsDistributeParallelForDirective(
OMPTargetTeamsDistributeParallelForDirective *D) {
VisitOMPLoopDirective(D);
+ Record.push_back(D->hasCancel() ? 1 : 0);
Code = serialization::STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE;
}
diff --git a/contrib/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp b/contrib/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp
index 6978e7e09774f..20c114297b999 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp
@@ -619,6 +619,10 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) {
(uint32_t)Record[Idx++], (uint32_t)Record[Idx++],
(uint32_t)Record[Idx++]}}};
+ // Skip the module name (currently this is only used for prebuilt
+ // modules while here we are only dealing with cached).
+ Idx += Record[Idx] + 1;
+
// Retrieve the imported file name.
unsigned Length = Record[Idx++];
SmallString<128> ImportedFile(Record.begin() + Idx,
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp b/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp
index 1dee4d0698616..b512fa452cc13 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp
@@ -1,4 +1,4 @@
-//===--- ModuleManager.cpp - Module Manager ---------------------*- C++ -*-===//
+//===- ModuleManager.cpp - Module Manager ---------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,24 +11,38 @@
// modules for the ASTReader.
//
//===----------------------------------------------------------------------===//
+
#include "clang/Serialization/ModuleManager.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/MemoryBufferCache.h"
+#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/ModuleMap.h"
#include "clang/Serialization/GlobalModuleIndex.h"
+#include "clang/Serialization/Module.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/Support/Chrono.h"
+#include "llvm/Support/DOTGraphTraits.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/GraphWriter.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
+#include <algorithm>
+#include <cassert>
+#include <memory>
+#include <string>
#include <system_error>
-#ifndef NDEBUG
-#include "llvm/Support/GraphWriter.h"
-#endif
-
using namespace clang;
using namespace serialization;
-ModuleFile *ModuleManager::lookup(StringRef Name) const {
+ModuleFile *ModuleManager::lookupByFileName(StringRef Name) const {
const FileEntry *Entry = FileMgr.getFile(Name, /*openFile=*/false,
/*cacheFailure=*/false);
if (Entry)
@@ -37,6 +51,14 @@ ModuleFile *ModuleManager::lookup(StringRef Name) const {
return nullptr;
}
+ModuleFile *ModuleManager::lookupByModuleName(StringRef Name) const {
+ if (const Module *Mod = HeaderSearchInfo.getModuleMap().findModule(Name))
+ if (const FileEntry *File = Mod->getASTFile())
+ return lookup(File);
+
+ return nullptr;
+}
+
ModuleFile *ModuleManager::lookup(const FileEntry *File) const {
auto Known = Modules.find(File);
if (Known == Modules.end())
@@ -200,7 +222,6 @@ void ModuleManager::removeModules(
if (First == Last)
return;
-
// Explicitly clear VisitOrder since we might not notice it is stale.
VisitOrder.clear();
@@ -259,7 +280,6 @@ void ModuleManager::removeModules(
void
ModuleManager::addInMemoryBuffer(StringRef FileName,
std::unique_ptr<llvm::MemoryBuffer> Buffer) {
-
const FileEntry *Entry =
FileMgr.getVirtualFile(FileName, Buffer->getBufferSize(), 0);
InMemoryBuffers[Entry] = std::move(Buffer);
@@ -306,9 +326,10 @@ void ModuleManager::moduleFileAccepted(ModuleFile *MF) {
}
ModuleManager::ModuleManager(FileManager &FileMgr, MemoryBufferCache &PCMCache,
- const PCHContainerReader &PCHContainerRdr)
+ const PCHContainerReader &PCHContainerRdr,
+ const HeaderSearch& HeaderSearchInfo)
: FileMgr(FileMgr), PCMCache(&PCMCache), PCHContainerRdr(PCHContainerRdr),
- GlobalIndex(), FirstVisitState(nullptr) {}
+ HeaderSearchInfo(HeaderSearchInfo) {}
ModuleManager::~ModuleManager() { delete FirstVisitState; }
@@ -442,11 +463,12 @@ bool ModuleManager::lookupModuleFile(StringRef FileName,
#ifndef NDEBUG
namespace llvm {
+
template<>
struct GraphTraits<ModuleManager> {
- typedef ModuleFile *NodeRef;
- typedef llvm::SetVector<ModuleFile *>::const_iterator ChildIteratorType;
- typedef pointer_iterator<ModuleManager::ModuleConstIterator> nodes_iterator;
+ using NodeRef = ModuleFile *;
+ using ChildIteratorType = llvm::SetVector<ModuleFile *>::const_iterator;
+ using nodes_iterator = pointer_iterator<ModuleManager::ModuleConstIterator>;
static ChildIteratorType child_begin(NodeRef Node) {
return Node->Imports.begin();
@@ -468,17 +490,16 @@ namespace llvm {
template<>
struct DOTGraphTraits<ModuleManager> : public DefaultDOTGraphTraits {
explicit DOTGraphTraits(bool IsSimple = false)
- : DefaultDOTGraphTraits(IsSimple) { }
+ : DefaultDOTGraphTraits(IsSimple) {}
- static bool renderGraphFromBottomUp() {
- return true;
- }
+ static bool renderGraphFromBottomUp() { return true; }
std::string getNodeLabel(ModuleFile *M, const ModuleManager&) {
return M->ModuleName;
}
};
-}
+
+} // namespace llvm
void ModuleManager::viewGraph() {
llvm::ViewGraph(*this, "Modules");
diff --git a/contrib/llvm/tools/clang/lib/Serialization/MultiOnDiskHashTable.h b/contrib/llvm/tools/clang/lib/Serialization/MultiOnDiskHashTable.h
index fdbbb602b5371..44d1616a01104 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/MultiOnDiskHashTable.h
+++ b/contrib/llvm/tools/clang/lib/Serialization/MultiOnDiskHashTable.h
@@ -1,4 +1,4 @@
-//===--- MultiOnDiskHashTable.h - Merged set of hash tables -----*- C++ -*-===//
+//===- MultiOnDiskHashTable.h - Merged set of hash tables -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,6 +15,7 @@
// files.
//
//===----------------------------------------------------------------------===//
+
#ifndef LLVM_CLANG_LIB_SERIALIZATION_MULTIONDISKHASHTABLE_H
#define LLVM_CLANG_LIB_SERIALIZATION_MULTIONDISKHASHTABLE_H
@@ -22,33 +23,43 @@
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/TinyPtrVector.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Endian.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/OnDiskHashTable.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cstdint>
+#include <vector>
namespace clang {
namespace serialization {
-class ModuleFile;
-
/// \brief A collection of on-disk hash tables, merged when relevant for performance.
template<typename Info> class MultiOnDiskHashTable {
public:
/// A handle to a file, used when overriding tables.
- typedef typename Info::file_type file_type;
+ using file_type = typename Info::file_type;
+
/// A pointer to an on-disk representation of the hash table.
- typedef const unsigned char *storage_type;
+ using storage_type = const unsigned char *;
- typedef typename Info::external_key_type external_key_type;
- typedef typename Info::internal_key_type internal_key_type;
- typedef typename Info::data_type data_type;
- typedef typename Info::data_type_builder data_type_builder;
- typedef unsigned hash_value_type;
+ using external_key_type = typename Info::external_key_type;
+ using internal_key_type = typename Info::internal_key_type;
+ using data_type = typename Info::data_type;
+ using data_type_builder = typename Info::data_type_builder;
+ using hash_value_type = unsigned;
private:
+ /// The generator is permitted to read our merged table.
+ template<typename ReaderInfo, typename WriterInfo>
+ friend class MultiOnDiskHashTableGenerator;
+
/// \brief A hash table stored on disk.
struct OnDiskTable {
- typedef llvm::OnDiskIterableChainedHashTable<Info> HashTable;
+ using HashTable = llvm::OnDiskIterableChainedHashTable<Info>;
file_type File;
HashTable Table;
@@ -65,8 +76,8 @@ private:
llvm::DenseMap<internal_key_type, data_type> Data;
};
- typedef llvm::PointerUnion<OnDiskTable*, MergedTable*> Table;
- typedef llvm::TinyPtrVector<void*> TableVector;
+ using Table = llvm::PointerUnion<OnDiskTable *, MergedTable *>;
+ using TableVector = llvm::TinyPtrVector<void *>;
/// \brief The current set of on-disk and merged tables.
/// We manually store the opaque value of the Table because TinyPtrVector
@@ -80,14 +91,16 @@ private:
llvm::TinyPtrVector<file_type> PendingOverrides;
struct AsOnDiskTable {
- typedef OnDiskTable *result_type;
+ using result_type = OnDiskTable *;
+
result_type operator()(void *P) const {
return Table::getFromOpaqueValue(P).template get<OnDiskTable *>();
}
};
- typedef llvm::mapped_iterator<TableVector::iterator, AsOnDiskTable>
- table_iterator;
- typedef llvm::iterator_range<table_iterator> table_range;
+
+ using table_iterator =
+ llvm::mapped_iterator<TableVector::iterator, AsOnDiskTable>;
+ using table_range = llvm::iterator_range<table_iterator>;
/// \brief The current set of on-disk tables.
table_range tables() {
@@ -160,17 +173,15 @@ private:
Tables.push_back(Table(Merged).getOpaqueValue());
}
- /// The generator is permitted to read our merged table.
- template<typename ReaderInfo, typename WriterInfo>
- friend class MultiOnDiskHashTableGenerator;
-
public:
- MultiOnDiskHashTable() {}
+ MultiOnDiskHashTable() = default;
+
MultiOnDiskHashTable(MultiOnDiskHashTable &&O)
: Tables(std::move(O.Tables)),
PendingOverrides(std::move(O.PendingOverrides)) {
O.Tables.clear();
}
+
MultiOnDiskHashTable &operator=(MultiOnDiskHashTable &&O) {
if (&O == this)
return *this;
@@ -180,11 +191,13 @@ public:
PendingOverrides = std::move(O.PendingOverrides);
return *this;
}
+
~MultiOnDiskHashTable() { clear(); }
/// \brief Add the table \p Data loaded from file \p File.
void add(file_type File, storage_type Data, Info InfoObj = Info()) {
using namespace llvm::support;
+
storage_type Ptr = Data;
uint32_t BucketOffset = endian::readNext<uint32_t, little, unaligned>(Ptr);
@@ -278,8 +291,8 @@ public:
/// \brief Writer for the on-disk hash table.
template<typename ReaderInfo, typename WriterInfo>
class MultiOnDiskHashTableGenerator {
- typedef MultiOnDiskHashTable<ReaderInfo> BaseTable;
- typedef llvm::OnDiskChainedHashTableGenerator<WriterInfo> Generator;
+ using BaseTable = MultiOnDiskHashTable<ReaderInfo>;
+ using Generator = llvm::OnDiskChainedHashTableGenerator<WriterInfo>;
Generator Gen;
@@ -294,6 +307,7 @@ public:
void emit(llvm::SmallVectorImpl<char> &Out, WriterInfo &Info,
const BaseTable *Base) {
using namespace llvm::support;
+
llvm::raw_svector_ostream OutStream(Out);
// Write our header information.
@@ -327,8 +341,7 @@ public:
}
};
-} // end namespace clang::serialization
-} // end namespace clang
-
+} // namespace serialization
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_LIB_SERIALIZATION_MULTIONDISKHASHTABLE_H
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
index 848c2662019a1..b944f90539d42 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
@@ -259,6 +259,7 @@ void ArrayBoundCheckerV2::reportOOB(CheckerContext &checkerContext,
llvm::make_unique<BugReport>(*BT, os.str(), errorNode));
}
+#ifndef NDEBUG
LLVM_DUMP_METHOD void RegionRawOffsetV2::dump() const {
dumpToStream(llvm::errs());
}
@@ -266,7 +267,7 @@ LLVM_DUMP_METHOD void RegionRawOffsetV2::dump() const {
void RegionRawOffsetV2::dumpToStream(raw_ostream &os) const {
os << "raw_offset_v2{" << getRegion() << ',' << getByteOffset() << '}';
}
-
+#endif
// Lazily computes a value to be used by 'computeOffset'. If 'val'
// is unknown or undefined, we lazily substitute '0'. Otherwise,
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
index d19630eeef778..c31f2794df6ab 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
@@ -26,15 +26,22 @@ using namespace ento;
namespace {
-class BlockInCriticalSectionChecker : public Checker<check::PostCall,
- check::PreCall> {
+class BlockInCriticalSectionChecker : public Checker<check::PostCall> {
+
+ mutable IdentifierInfo *IILockGuard, *IIUniqueLock;
CallDescription LockFn, UnlockFn, SleepFn, GetcFn, FgetsFn, ReadFn, RecvFn,
PthreadLockFn, PthreadTryLockFn, PthreadUnlockFn,
MtxLock, MtxTimedLock, MtxTryLock, MtxUnlock;
+ StringRef ClassLockGuard, ClassUniqueLock;
+
+ mutable bool IdentifierInfoInitialized;
+
std::unique_ptr<BugType> BlockInCritSectionBugType;
+ void initIdentifierInfo(ASTContext &Ctx) const;
+
void reportBlockInCritSection(SymbolRef FileDescSym,
const CallEvent &call,
CheckerContext &C) const;
@@ -46,13 +53,10 @@ public:
bool isLockFunction(const CallEvent &Call) const;
bool isUnlockFunction(const CallEvent &Call) const;
- void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
-
/// Process unlock.
/// Process lock.
/// Process blocking functions (sleep, getc, fgets, read, recv)
void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
-
};
} // end anonymous namespace
@@ -60,7 +64,8 @@ public:
REGISTER_TRAIT_WITH_PROGRAMSTATE(MutexCounter, unsigned)
BlockInCriticalSectionChecker::BlockInCriticalSectionChecker()
- : LockFn("lock"), UnlockFn("unlock"), SleepFn("sleep"), GetcFn("getc"),
+ : IILockGuard(nullptr), IIUniqueLock(nullptr),
+ LockFn("lock"), UnlockFn("unlock"), SleepFn("sleep"), GetcFn("getc"),
FgetsFn("fgets"), ReadFn("read"), RecvFn("recv"),
PthreadLockFn("pthread_mutex_lock"),
PthreadTryLockFn("pthread_mutex_trylock"),
@@ -68,13 +73,29 @@ BlockInCriticalSectionChecker::BlockInCriticalSectionChecker()
MtxLock("mtx_lock"),
MtxTimedLock("mtx_timedlock"),
MtxTryLock("mtx_trylock"),
- MtxUnlock("mtx_unlock") {
+ MtxUnlock("mtx_unlock"),
+ ClassLockGuard("lock_guard"),
+ ClassUniqueLock("unique_lock"),
+ IdentifierInfoInitialized(false) {
// Initialize the bug type.
BlockInCritSectionBugType.reset(
new BugType(this, "Call to blocking function in critical section",
"Blocking Error"));
}
+void BlockInCriticalSectionChecker::initIdentifierInfo(ASTContext &Ctx) const {
+ if (!IdentifierInfoInitialized) {
+ /* In case of checking C code, or when the corresponding headers are not
+ * included, we might end up query the identifier table every time when this
+ * function is called instead of early returning it. To avoid this, a bool
+ * variable (IdentifierInfoInitialized) is used and the function will be run
+ * only once. */
+ IILockGuard = &Ctx.Idents.get(ClassLockGuard);
+ IIUniqueLock = &Ctx.Idents.get(ClassUniqueLock);
+ IdentifierInfoInitialized = true;
+ }
+}
+
bool BlockInCriticalSectionChecker::isBlockingFunction(const CallEvent &Call) const {
if (Call.isCalled(SleepFn)
|| Call.isCalled(GetcFn)
@@ -87,6 +108,12 @@ bool BlockInCriticalSectionChecker::isBlockingFunction(const CallEvent &Call) co
}
bool BlockInCriticalSectionChecker::isLockFunction(const CallEvent &Call) const {
+ if (const auto *Ctor = dyn_cast<CXXConstructorCall>(&Call)) {
+ auto IdentifierInfo = Ctor->getDecl()->getParent()->getIdentifier();
+ if (IdentifierInfo == IILockGuard || IdentifierInfo == IIUniqueLock)
+ return true;
+ }
+
if (Call.isCalled(LockFn)
|| Call.isCalled(PthreadLockFn)
|| Call.isCalled(PthreadTryLockFn)
@@ -99,6 +126,13 @@ bool BlockInCriticalSectionChecker::isLockFunction(const CallEvent &Call) const
}
bool BlockInCriticalSectionChecker::isUnlockFunction(const CallEvent &Call) const {
+ if (const auto *Dtor = dyn_cast<CXXDestructorCall>(&Call)) {
+ const auto *DRecordDecl = dyn_cast<CXXRecordDecl>(Dtor->getDecl()->getParent());
+ auto IdentifierInfo = DRecordDecl->getIdentifier();
+ if (IdentifierInfo == IILockGuard || IdentifierInfo == IIUniqueLock)
+ return true;
+ }
+
if (Call.isCalled(UnlockFn)
|| Call.isCalled(PthreadUnlockFn)
|| Call.isCalled(MtxUnlock)) {
@@ -107,12 +141,10 @@ bool BlockInCriticalSectionChecker::isUnlockFunction(const CallEvent &Call) cons
return false;
}
-void BlockInCriticalSectionChecker::checkPreCall(const CallEvent &Call,
- CheckerContext &C) const {
-}
-
void BlockInCriticalSectionChecker::checkPostCall(const CallEvent &Call,
CheckerContext &C) const {
+ initIdentifierInfo(C.getASTContext());
+
if (!isBlockingFunction(Call)
&& !isLockFunction(Call)
&& !isUnlockFunction(Call))
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index 77c24629d71e5..28ad7e9e5071d 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -289,8 +289,8 @@ ProgramStateRef CStringChecker::CheckLocation(CheckerContext &C,
if (!ER)
return state;
- assert(ER->getValueType() == C.getASTContext().CharTy &&
- "CheckLocation should only be called with char* ElementRegions");
+ if (ER->getValueType() != C.getASTContext().CharTy)
+ return state;
// Get the size of the array.
const SubRegion *superReg = cast<SubRegion>(ER->getSuperRegion());
@@ -874,6 +874,8 @@ bool CStringChecker::IsFirstBufInBound(CheckerContext &C,
if (!ER)
return true; // cf top comment.
+ // FIXME: Does this crash when a non-standard definition
+ // of a library function is encountered?
assert(ER->getValueType() == C.getASTContext().CharTy &&
"IsFirstBufInBound should only be called with char* ElementRegions");
@@ -1050,31 +1052,22 @@ void CStringChecker::evalCopyCommon(CheckerContext &C,
// If this is mempcpy, get the byte after the last byte copied and
// bind the expr.
if (IsMempcpy) {
- loc::MemRegionVal destRegVal = destVal.castAs<loc::MemRegionVal>();
-
- // Get the length to copy.
- if (Optional<NonLoc> lenValNonLoc = sizeVal.getAs<NonLoc>()) {
- // Get the byte after the last byte copied.
- SValBuilder &SvalBuilder = C.getSValBuilder();
- ASTContext &Ctx = SvalBuilder.getContext();
- QualType CharPtrTy = Ctx.getPointerType(Ctx.CharTy);
- loc::MemRegionVal DestRegCharVal = SvalBuilder.evalCast(destRegVal,
- CharPtrTy, Dest->getType()).castAs<loc::MemRegionVal>();
- SVal lastElement = C.getSValBuilder().evalBinOpLN(state, BO_Add,
- DestRegCharVal,
- *lenValNonLoc,
- Dest->getType());
-
- // The byte after the last byte copied is the return value.
- state = state->BindExpr(CE, LCtx, lastElement);
- } else {
- // If we don't know how much we copied, we can at least
- // conjure a return value for later.
- SVal result = C.getSValBuilder().conjureSymbolVal(nullptr, CE, LCtx,
+ // Get the byte after the last byte copied.
+ SValBuilder &SvalBuilder = C.getSValBuilder();
+ ASTContext &Ctx = SvalBuilder.getContext();
+ QualType CharPtrTy = Ctx.getPointerType(Ctx.CharTy);
+ SVal DestRegCharVal =
+ SvalBuilder.evalCast(destVal, CharPtrTy, Dest->getType());
+ SVal lastElement = C.getSValBuilder().evalBinOp(
+ state, BO_Add, DestRegCharVal, sizeVal, Dest->getType());
+ // If we don't know how much we copied, we can at least
+ // conjure a return value for later.
+ if (lastElement.isUnknown())
+ lastElement = C.getSValBuilder().conjureSymbolVal(nullptr, CE, LCtx,
C.blockCount());
- state = state->BindExpr(CE, LCtx, result);
- }
+ // The byte after the last byte copied is the return value.
+ state = state->BindExpr(CE, LCtx, lastElement);
} else {
// All other copies return the destination buffer.
// (Well, bcopy() has a void return type, but this won't hurt.)
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
index 391b843ff3dbe..4b5e97b69295a 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
@@ -16,7 +16,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/OperationKinds.h"
#include "clang/AST/StmtVisitor.h"
-#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TypeTraits.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
index 07285d27ed9e1..20a46843e23e2 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
@@ -179,7 +179,7 @@ bool CallAndMessageChecker::uninitRefOrPointer(
if (const MemRegion *SValMemRegion = V.getAsRegion()) {
const ProgramStateRef State = C.getState();
- const SVal PSV = State->getSVal(SValMemRegion);
+ const SVal PSV = State->getSVal(SValMemRegion, C.getASTContext().CharTy);
if (PSV.isUndef()) {
if (ExplodedNode *N = C.generateErrorNode()) {
LazyInit_BT(BD, BT);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
index 60f16188bcf89..6dbacad7f2eab 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
@@ -13,7 +13,7 @@
#include "ClangSACheckers.h"
#include "clang/AST/StmtVisitor.h"
-#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
@@ -32,7 +32,6 @@ static bool isArc4RandomAvailable(const ASTContext &Ctx) {
T.getOS() == llvm::Triple::FreeBSD ||
T.getOS() == llvm::Triple::NetBSD ||
T.getOS() == llvm::Triple::OpenBSD ||
- T.getOS() == llvm::Triple::Bitrig ||
T.getOS() == llvm::Triple::DragonFly;
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CloneChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CloneChecker.cpp
index 83955c586b688..ee517ed977700 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CloneChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CloneChecker.cpp
@@ -64,7 +64,7 @@ void CloneChecker::checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
// the CloneDetector. The only thing left to do is to report the found clones.
int MinComplexity = Mgr.getAnalyzerOptions().getOptionAsInteger(
- "MinimumCloneComplexity", 10, this);
+ "MinimumCloneComplexity", 50, this);
assert(MinComplexity >= 0);
bool ReportSuspiciousClones = Mgr.getAnalyzerOptions().getBooleanOption(
@@ -81,11 +81,11 @@ void CloneChecker::checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
// because reportSuspiciousClones() wants to search them for errors.
std::vector<CloneDetector::CloneGroup> AllCloneGroups;
- Detector.findClones(AllCloneGroups,
- FilenamePatternConstraint(IgnoredFilesPattern),
- RecursiveCloneTypeIIConstraint(),
- MinComplexityConstraint(MinComplexity),
- MinGroupSizeConstraint(2), OnlyLargestCloneConstraint());
+ Detector.findClones(
+ AllCloneGroups, FilenamePatternConstraint(IgnoredFilesPattern),
+ RecursiveCloneTypeIIHashConstraint(), MinGroupSizeConstraint(2),
+ MinComplexityConstraint(MinComplexity),
+ RecursiveCloneTypeIIVerifyConstraint(), OnlyLargestCloneConstraint());
if (ReportSuspiciousClones)
reportSuspiciousClones(BR, Mgr, AllCloneGroups);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp
index ea894c81011c9..17ec2c288777b 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp
@@ -123,57 +123,6 @@ void ConversionChecker::reportBug(ExplodedNode *N, CheckerContext &C,
C.emitReport(std::move(R));
}
-// Is E value greater or equal than Val?
-static bool isGreaterEqual(CheckerContext &C, const Expr *E,
- unsigned long long Val) {
- ProgramStateRef State = C.getState();
- SVal EVal = C.getSVal(E);
- if (EVal.isUnknownOrUndef())
- return false;
- if (!EVal.getAs<NonLoc>() && EVal.getAs<Loc>()) {
- ProgramStateManager &Mgr = C.getStateManager();
- EVal =
- Mgr.getStoreManager().getBinding(State->getStore(), EVal.castAs<Loc>());
- }
- if (EVal.isUnknownOrUndef() || !EVal.getAs<NonLoc>())
- return false;
-
- SValBuilder &Bldr = C.getSValBuilder();
- DefinedSVal V = Bldr.makeIntVal(Val, C.getASTContext().LongLongTy);
-
- // Is DefinedEVal greater or equal with V?
- SVal GE = Bldr.evalBinOp(State, BO_GE, EVal, V, Bldr.getConditionType());
- if (GE.isUnknownOrUndef())
- return false;
- ConstraintManager &CM = C.getConstraintManager();
- ProgramStateRef StGE, StLT;
- std::tie(StGE, StLT) = CM.assumeDual(State, GE.castAs<DefinedSVal>());
- return StGE && !StLT;
-}
-
-// Is E value negative?
-static bool isNegative(CheckerContext &C, const Expr *E) {
- ProgramStateRef State = C.getState();
- SVal EVal = State->getSVal(E, C.getLocationContext());
- if (EVal.isUnknownOrUndef() || !EVal.getAs<NonLoc>())
- return false;
- DefinedSVal DefinedEVal = EVal.castAs<DefinedSVal>();
-
- SValBuilder &Bldr = C.getSValBuilder();
- DefinedSVal V = Bldr.makeIntVal(0, false);
-
- SVal LT =
- Bldr.evalBinOp(State, BO_LT, DefinedEVal, V, Bldr.getConditionType());
-
- // Is E value greater than MaxVal?
- ConstraintManager &CM = C.getConstraintManager();
- ProgramStateRef StNegative, StPositive;
- std::tie(StNegative, StPositive) =
- CM.assumeDual(State, LT.castAs<DefinedSVal>());
-
- return StNegative && !StPositive;
-}
-
bool ConversionChecker::isLossOfPrecision(const ImplicitCastExpr *Cast,
QualType DestType,
CheckerContext &C) const {
@@ -195,18 +144,18 @@ bool ConversionChecker::isLossOfPrecision(const ImplicitCastExpr *Cast,
return false;
unsigned long long MaxVal = 1ULL << W;
- return isGreaterEqual(C, Cast->getSubExpr(), MaxVal);
+ return C.isGreaterOrEqual(Cast->getSubExpr(), MaxVal);
}
bool ConversionChecker::isLossOfSign(const ImplicitCastExpr *Cast,
- CheckerContext &C) const {
+ CheckerContext &C) const {
QualType CastType = Cast->getType();
QualType SubType = Cast->IgnoreParenImpCasts()->getType();
if (!CastType->isUnsignedIntegerType() || !SubType->isSignedIntegerType())
return false;
- return isNegative(C, Cast->getSubExpr());
+ return C.isNegative(Cast->getSubExpr());
}
void ento::registerConversionChecker(CheckerManager &mgr) {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp
index 2eef1688d4c4b..810a33ed404db 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp
@@ -16,7 +16,6 @@
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Analysis/CallGraph.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
-#include "clang/StaticAnalyzer/Core/IssueHash.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
@@ -213,35 +212,3 @@ void ento::registerExplodedGraphViewer(CheckerManager &mgr) {
mgr.registerChecker<ExplodedGraphViewer>();
}
-//===----------------------------------------------------------------------===//
-// DumpBugHash
-//===----------------------------------------------------------------------===//
-
-namespace {
-class BugHashDumper : public Checker<check::PostStmt<Stmt>> {
-public:
- mutable std::unique_ptr<BugType> BT;
-
- void checkPostStmt(const Stmt *S, CheckerContext &C) const {
- if (!BT)
- BT.reset(new BugType(this, "Dump hash components", "debug"));
-
- ExplodedNode *N = C.generateNonFatalErrorNode();
- if (!N)
- return;
-
- const LangOptions &Opts = C.getLangOpts();
- const SourceManager &SM = C.getSourceManager();
- FullSourceLoc FL(S->getLocStart(), SM);
- std::string HashContent =
- GetIssueString(SM, FL, getCheckName().getName(), BT->getCategory(),
- C.getLocationContext()->getDecl(), Opts);
-
- C.emitReport(llvm::make_unique<BugReport>(*BT, HashContent, N));
- }
-};
-}
-
-void ento::registerBugHashDumper(CheckerManager &mgr) {
- mgr.registerChecker<BugHashDumper>();
-}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeleteWithNonVirtualDtorChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeleteWithNonVirtualDtorChecker.cpp
new file mode 100644
index 0000000000000..e04e2ab2c3202
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeleteWithNonVirtualDtorChecker.cpp
@@ -0,0 +1,153 @@
+//===-- DeleteWithNonVirtualDtorChecker.cpp -----------------------*- C++ -*--//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines a checker for the OOP52-CPP CERT rule: Do not delete a polymorphic
+// object without a virtual destructor.
+//
+// Diagnostic flags -Wnon-virtual-dtor and -Wdelete-non-virtual-dtor report if
+// an object with a virtual function but a non-virtual destructor exists or is
+// deleted, respectively.
+//
+// This check exceeds them by comparing the dynamic and static types of the
+// object at the point of destruction and only warns if it happens through a
+// pointer to a base type without a virtual destructor. The check places a note
+// at the last point where the conversion from derived to base happened.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class DeleteWithNonVirtualDtorChecker
+ : public Checker<check::PreStmt<CXXDeleteExpr>> {
+ mutable std::unique_ptr<BugType> BT;
+
+ class DeleteBugVisitor : public BugReporterVisitorImpl<DeleteBugVisitor> {
+ public:
+ DeleteBugVisitor() : Satisfied(false) {}
+ void Profile(llvm::FoldingSetNodeID &ID) const override {
+ static int X = 0;
+ ID.AddPointer(&X);
+ }
+ std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR) override;
+
+ private:
+ bool Satisfied;
+ };
+
+public:
+ void checkPreStmt(const CXXDeleteExpr *DE, CheckerContext &C) const;
+};
+} // end anonymous namespace
+
+void DeleteWithNonVirtualDtorChecker::checkPreStmt(const CXXDeleteExpr *DE,
+ CheckerContext &C) const {
+ const Expr *DeletedObj = DE->getArgument();
+ const MemRegion *MR = C.getSVal(DeletedObj).getAsRegion();
+ if (!MR)
+ return;
+
+ const auto *BaseClassRegion = MR->getAs<TypedValueRegion>();
+ const auto *DerivedClassRegion = MR->getBaseRegion()->getAs<SymbolicRegion>();
+ if (!BaseClassRegion || !DerivedClassRegion)
+ return;
+
+ const auto *BaseClass = BaseClassRegion->getValueType()->getAsCXXRecordDecl();
+ const auto *DerivedClass =
+ DerivedClassRegion->getSymbol()->getType()->getPointeeCXXRecordDecl();
+ if (!BaseClass || !DerivedClass)
+ return;
+
+ if (!BaseClass->hasDefinition() || !DerivedClass->hasDefinition())
+ return;
+
+ if (BaseClass->getDestructor()->isVirtual())
+ return;
+
+ if (!DerivedClass->isDerivedFrom(BaseClass))
+ return;
+
+ if (!BT)
+ BT.reset(new BugType(this,
+ "Destruction of a polymorphic object with no "
+ "virtual destructor",
+ "Logic error"));
+
+ ExplodedNode *N = C.generateNonFatalErrorNode();
+ auto R = llvm::make_unique<BugReport>(*BT, BT->getName(), N);
+
+ // Mark region of problematic base class for later use in the BugVisitor.
+ R->markInteresting(BaseClassRegion);
+ R->addVisitor(llvm::make_unique<DeleteBugVisitor>());
+ C.emitReport(std::move(R));
+}
+
+std::shared_ptr<PathDiagnosticPiece>
+DeleteWithNonVirtualDtorChecker::DeleteBugVisitor::VisitNode(
+ const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC,
+ BugReport &BR) {
+ // Stop traversal after the first conversion was found on a path.
+ if (Satisfied)
+ return nullptr;
+
+ ProgramStateRef State = N->getState();
+ const LocationContext *LC = N->getLocationContext();
+ const Stmt *S = PathDiagnosticLocation::getStmt(N);
+ if (!S)
+ return nullptr;
+
+ const auto *CastE = dyn_cast<CastExpr>(S);
+ if (!CastE)
+ return nullptr;
+
+ // Only interested in DerivedToBase implicit casts.
+ // Explicit casts can have different CastKinds.
+ if (const auto *ImplCastE = dyn_cast<ImplicitCastExpr>(CastE)) {
+ if (ImplCastE->getCastKind() != CK_DerivedToBase)
+ return nullptr;
+ }
+
+ // Region associated with the current cast expression.
+ const MemRegion *M = State->getSVal(CastE, LC).getAsRegion();
+ if (!M)
+ return nullptr;
+
+ // Check if target region was marked as problematic previously.
+ if (!BR.isInteresting(M))
+ return nullptr;
+
+ // Stop traversal on this path.
+ Satisfied = true;
+
+ SmallString<256> Buf;
+ llvm::raw_svector_ostream OS(Buf);
+ OS << "Conversion from derived to base happened here";
+ PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
+ N->getLocationContext());
+ return std::make_shared<PathDiagnosticEventPiece>(Pos, OS.str(), true,
+ nullptr);
+}
+
+void ento::registerDeleteWithNonVirtualDtorChecker(CheckerManager &mgr) {
+ mgr.registerChecker<DeleteWithNonVirtualDtorChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
index 0891ea85a7148..23b43759a34ba 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
@@ -546,8 +546,6 @@ void DynamicTypePropagation::checkPostStmt(const CastExpr *CE,
OrigObjectPtrType = OrigObjectPtrType->stripObjCKindOfTypeAndQuals(ASTCtxt);
DestObjectPtrType = DestObjectPtrType->stripObjCKindOfTypeAndQuals(ASTCtxt);
- // TODO: erase tracked information when there is a cast to unrelated type
- // and everything is unspecialized statically.
if (OrigObjectPtrType->isUnspecialized() &&
DestObjectPtrType->isUnspecialized())
return;
@@ -556,29 +554,31 @@ void DynamicTypePropagation::checkPostStmt(const CastExpr *CE,
if (!Sym)
return;
- // Check which assignments are legal.
- bool OrigToDest =
- ASTCtxt.canAssignObjCInterfaces(DestObjectPtrType, OrigObjectPtrType);
- bool DestToOrig =
- ASTCtxt.canAssignObjCInterfaces(OrigObjectPtrType, DestObjectPtrType);
const ObjCObjectPointerType *const *TrackedType =
State->get<MostSpecializedTypeArgsMap>(Sym);
- // Downcasts and upcasts handled in an uniform way regardless of being
- // explicit. Explicit casts however can happen between mismatched types.
- if (isa<ExplicitCastExpr>(CE) && !OrigToDest && !DestToOrig) {
- // Mismatched types. If the DestType specialized, store it. Forget the
- // tracked type otherwise.
- if (DestObjectPtrType->isSpecialized()) {
- State = State->set<MostSpecializedTypeArgsMap>(Sym, DestObjectPtrType);
- C.addTransition(State, AfterTypeProp);
- } else if (TrackedType) {
+ if (isa<ExplicitCastExpr>(CE)) {
+ // Treat explicit casts as an indication from the programmer that the
+ // Objective-C type system is not rich enough to express the needed
+ // invariant. In such cases, forget any existing information inferred
+ // about the type arguments. We don't assume the casted-to specialized
+ // type here because the invariant the programmer specifies in the cast
+ // may only hold at this particular program point and not later ones.
+ // We don't want a suppressing cast to require a cascade of casts down the
+ // line.
+ if (TrackedType) {
State = State->remove<MostSpecializedTypeArgsMap>(Sym);
C.addTransition(State, AfterTypeProp);
}
return;
}
+ // Check which assignments are legal.
+ bool OrigToDest =
+ ASTCtxt.canAssignObjCInterfaces(DestObjectPtrType, OrigObjectPtrType);
+ bool DestToOrig =
+ ASTCtxt.canAssignObjCInterfaces(OrigObjectPtrType, DestObjectPtrType);
+
// The tracked type should be the sub or super class of the static destination
// type. When an (implicit) upcast or a downcast happens according to static
// types, and there is no subtyping relationship between the tracked and the
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
index 32040e71163dd..0005ec470d203 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
@@ -8,10 +8,11 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/SValExplainer.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/IssueHash.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
-#include "clang/StaticAnalyzer/Checkers/SValExplainer.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ScopedPrinter.h"
@@ -41,6 +42,7 @@ class ExprInspectionChecker : public Checker<eval::Call, check::DeadSymbols,
void analyzerExplain(const CallExpr *CE, CheckerContext &C) const;
void analyzerPrintState(const CallExpr *CE, CheckerContext &C) const;
void analyzerGetExtent(const CallExpr *CE, CheckerContext &C) const;
+ void analyzerHashDump(const CallExpr *CE, CheckerContext &C) const;
typedef void (ExprInspectionChecker::*FnCheck)(const CallExpr *,
CheckerContext &C) const;
@@ -79,6 +81,7 @@ bool ExprInspectionChecker::evalCall(const CallExpr *CE,
&ExprInspectionChecker::analyzerPrintState)
.Case("clang_analyzer_numTimesReached",
&ExprInspectionChecker::analyzerNumTimesReached)
+ .Case("clang_analyzer_hashDump", &ExprInspectionChecker::analyzerHashDump)
.Default(nullptr);
if (!Handler)
@@ -272,6 +275,7 @@ void ExprInspectionChecker::checkEndAnalysis(ExplodedGraph &G, BugReporter &BR,
reportBug(llvm::to_string(NumTimesReached), BR, N);
}
+ ReachedStats.clear();
}
void ExprInspectionChecker::analyzerCrash(const CallExpr *CE,
@@ -279,7 +283,18 @@ void ExprInspectionChecker::analyzerCrash(const CallExpr *CE,
LLVM_BUILTIN_TRAP;
}
+void ExprInspectionChecker::analyzerHashDump(const CallExpr *CE,
+ CheckerContext &C) const {
+ const LangOptions &Opts = C.getLangOpts();
+ const SourceManager &SM = C.getSourceManager();
+ FullSourceLoc FL(CE->getArg(0)->getLocStart(), SM);
+ std::string HashContent =
+ GetIssueString(SM, FL, getCheckName().getName(), "Category",
+ C.getLocationContext()->getDecl(), Opts);
+
+ reportBug(HashContent, C);
+}
+
void ento::registerExprInspectionChecker(CheckerManager &Mgr) {
Mgr.registerChecker<ExprInspectionChecker>();
}
-
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
index 883c6a663291d..43966656cd8d0 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -466,7 +466,7 @@ bool GenericTaintChecker::checkPre(const CallExpr *CE, CheckerContext &C) const{
}
Optional<SVal> GenericTaintChecker::getPointedToSVal(CheckerContext &C,
- const Expr* Arg) {
+ const Expr *Arg) {
ProgramStateRef State = C.getState();
SVal AddrVal = State->getSVal(Arg->IgnoreParens(), C.getLocationContext());
if (AddrVal.isUnknownOrUndef())
@@ -476,9 +476,18 @@ Optional<SVal> GenericTaintChecker::getPointedToSVal(CheckerContext &C,
if (!AddrLoc)
return None;
- const PointerType *ArgTy =
- dyn_cast<PointerType>(Arg->getType().getCanonicalType().getTypePtr());
- return State->getSVal(*AddrLoc, ArgTy ? ArgTy->getPointeeType(): QualType());
+ QualType ArgTy = Arg->getType().getCanonicalType();
+ if (!ArgTy->isPointerType())
+ return None;
+
+ QualType ValTy = ArgTy->getPointeeType();
+
+ // Do not dereference void pointers. Treat them as byte pointers instead.
+ // FIXME: we might want to consider more than just the first byte.
+ if (ValTy->isVoidType())
+ ValTy = C.getASTContext().CharTy;
+
+ return State->getSVal(*AddrLoc, ValTy);
}
ProgramStateRef
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
index 0c3bff5b63b8f..cf57b8dca0638 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
@@ -255,7 +255,10 @@ void FindIdenticalExprVisitor::checkComparisonOp(const BinaryOperator *B) {
PathDiagnosticLocation ELoc =
PathDiagnosticLocation::createOperatorLoc(B, BR.getSourceManager());
StringRef Message;
- if (((Op == BO_EQ) || (Op == BO_LE) || (Op == BO_GE)))
+ if (Op == BO_Cmp)
+ Message = "comparison of identical expressions always evaluates to "
+ "'equal'";
+ else if (((Op == BO_EQ) || (Op == BO_LE) || (Op == BO_GE)))
Message = "comparison of identical expressions always evaluates to true";
else
Message = "comparison of identical expressions always evaluates to false";
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp
index decc552e1213e..497978f078155 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp
@@ -56,8 +56,11 @@ public:
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const LocationContext *LCtx, const CallEvent *Call) const;
+ void printState(raw_ostream &Out, ProgramStateRef State,
+ const char *NL, const char *Sep) const override;
private:
+ enum MisuseKind {MK_FunCall, MK_Copy, MK_Move};
class MovedBugVisitor : public BugReporterVisitorImpl<MovedBugVisitor> {
public:
MovedBugVisitor(const MemRegion *R) : Region(R), Found(false) {}
@@ -81,7 +84,7 @@ private:
mutable std::unique_ptr<BugType> BT;
ExplodedNode *reportBug(const MemRegion *Region, const CallEvent &Call,
- CheckerContext &C, bool isCopy) const;
+ CheckerContext &C, MisuseKind MK) const;
bool isInMoveSafeContext(const LocationContext *LC) const;
bool isStateResetMethod(const CXXMethodDecl *MethodDec) const;
bool isMoveSafeMethod(const CXXMethodDecl *MethodDec) const;
@@ -177,7 +180,7 @@ const ExplodedNode *MisusedMovedObjectChecker::getMoveLocation(
ExplodedNode *MisusedMovedObjectChecker::reportBug(const MemRegion *Region,
const CallEvent &Call,
CheckerContext &C,
- bool isCopy = false) const {
+ MisuseKind MK) const {
if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
if (!BT)
BT.reset(new BugType(this, "Usage of a 'moved-from' object",
@@ -193,10 +196,17 @@ ExplodedNode *MisusedMovedObjectChecker::reportBug(const MemRegion *Region,
// Creating the error message.
std::string ErrorMessage;
- if (isCopy)
- ErrorMessage = "Copying a 'moved-from' object";
- else
- ErrorMessage = "Method call on a 'moved-from' object";
+ switch(MK) {
+ case MK_FunCall:
+ ErrorMessage = "Method call on a 'moved-from' object";
+ break;
+ case MK_Copy:
+ ErrorMessage = "Copying a 'moved-from' object";
+ break;
+ case MK_Move:
+ ErrorMessage = "Moving a 'moved-from' object";
+ break;
+ }
if (const auto DecReg = Region->getAs<DeclRegion>()) {
const auto *RegionDecl = dyn_cast<NamedDecl>(DecReg->getDecl());
ErrorMessage += " '" + RegionDecl->getNameAsString() + "'";
@@ -350,7 +360,7 @@ void MisusedMovedObjectChecker::checkPreCall(const CallEvent &Call,
const LocationContext *LC = C.getLocationContext();
ExplodedNode *N = nullptr;
- // Remove the MemRegions from the map on which a ctor/dtor call or assignement
+ // Remove the MemRegions from the map on which a ctor/dtor call or assignment
// happened.
// Checking constructor calls.
@@ -363,7 +373,10 @@ void MisusedMovedObjectChecker::checkPreCall(const CallEvent &Call,
const RegionState *ArgState = State->get<TrackedRegionMap>(ArgRegion);
if (ArgState && ArgState->isMoved()) {
if (!isInMoveSafeContext(LC)) {
- N = reportBug(ArgRegion, Call, C, /*isCopy=*/true);
+ if(CtorDec->isMoveConstructor())
+ N = reportBug(ArgRegion, Call, C, MK_Move);
+ else
+ N = reportBug(ArgRegion, Call, C, MK_Copy);
State = State->set<TrackedRegionMap>(ArgRegion,
RegionState::getReported());
}
@@ -378,8 +391,11 @@ void MisusedMovedObjectChecker::checkPreCall(const CallEvent &Call,
return;
// In case of destructor call we do not track the object anymore.
const MemRegion *ThisRegion = IC->getCXXThisVal().getAsRegion();
+ if (!ThisRegion)
+ return;
+
if (dyn_cast_or_null<CXXDestructorDecl>(Call.getDecl())) {
- State = removeFromState(State, IC->getCXXThisVal().getAsRegion());
+ State = removeFromState(State, ThisRegion);
C.addTransition(State);
return;
}
@@ -400,7 +416,10 @@ void MisusedMovedObjectChecker::checkPreCall(const CallEvent &Call,
State->get<TrackedRegionMap>(IC->getArgSVal(0).getAsRegion());
if (ArgState && ArgState->isMoved() && !isInMoveSafeContext(LC)) {
const MemRegion *ArgRegion = IC->getArgSVal(0).getAsRegion();
- N = reportBug(ArgRegion, Call, C, /*isCopy=*/true);
+ if(MethodDecl->isMoveAssignmentOperator())
+ N = reportBug(ArgRegion, Call, C, MK_Move);
+ else
+ N = reportBug(ArgRegion, Call, C, MK_Copy);
State =
State->set<TrackedRegionMap>(ArgRegion, RegionState::getReported());
}
@@ -410,28 +429,35 @@ void MisusedMovedObjectChecker::checkPreCall(const CallEvent &Call,
}
// The remaining part is check only for method call on a moved-from object.
+
+ // We want to investigate the whole object, not only sub-object of a parent
+ // class in which the encountered method defined.
+ while (const CXXBaseObjectRegion *BR =
+ dyn_cast<CXXBaseObjectRegion>(ThisRegion))
+ ThisRegion = BR->getSuperRegion();
+
if (isMoveSafeMethod(MethodDecl))
return;
if (isStateResetMethod(MethodDecl)) {
- State = State->remove<TrackedRegionMap>(ThisRegion);
+ State = removeFromState(State, ThisRegion);
C.addTransition(State);
return;
}
- // If it is already reported then we dont report the bug again.
+ // If it is already reported then we don't report the bug again.
const RegionState *ThisState = State->get<TrackedRegionMap>(ThisRegion);
if (!(ThisState && ThisState->isMoved()))
return;
- // Dont report it in case if any base region is already reported
+ // Don't report it in case if any base region is already reported
if (isAnyBaseRegionReported(State, ThisRegion))
return;
if (isInMoveSafeContext(LC))
return;
- N = reportBug(ThisRegion, Call, C);
+ N = reportBug(ThisRegion, Call, C, MK_FunCall);
State = State->set<TrackedRegionMap>(ThisRegion, RegionState::getReported());
C.addTransition(State, N);
}
@@ -476,6 +502,25 @@ ProgramStateRef MisusedMovedObjectChecker::checkRegionChanges(
return State;
}
+void MisusedMovedObjectChecker::printState(raw_ostream &Out,
+ ProgramStateRef State,
+ const char *NL,
+ const char *Sep) const {
+
+ TrackedRegionMapTy RS = State->get<TrackedRegionMap>();
+
+ if (!RS.isEmpty()) {
+ Out << Sep << "Moved-from objects :" << NL;
+ for (auto I: RS) {
+ I.first->dumpToStream(Out);
+ if (I.second.isMoved())
+ Out << ": moved";
+ else
+ Out << ": moved and reported";
+ Out << NL;
+ }
+ }
+}
void ento::registerMisusedMovedObjectChecker(CheckerManager &mgr) {
mgr.registerChecker<MisusedMovedObjectChecker>();
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp
new file mode 100644
index 0000000000000..0b4ecb41d20f3
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp
@@ -0,0 +1,140 @@
+//==- NonnullGlobalConstantsChecker.cpp ---------------------------*- C++ -*--//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This checker adds an assumption that constant globals of certain types* are
+// non-null, as otherwise they generally do not convey any useful information.
+// The assumption is useful, as many framework use e. g. global const strings,
+// and the analyzer might not be able to infer the global value if the
+// definition is in a separate translation unit.
+// The following types (and their typedef aliases) are considered to be
+// non-null:
+// - `char* const`
+// - `const CFStringRef` from CoreFoundation
+// - `NSString* const` from Foundation
+// - `CFBooleanRef` from Foundation
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+class NonnullGlobalConstantsChecker : public Checker<check::Location> {
+ mutable IdentifierInfo *NSStringII = nullptr;
+ mutable IdentifierInfo *CFStringRefII = nullptr;
+ mutable IdentifierInfo *CFBooleanRefII = nullptr;
+
+public:
+ NonnullGlobalConstantsChecker() {}
+
+ void checkLocation(SVal l, bool isLoad, const Stmt *S,
+ CheckerContext &C) const;
+
+private:
+ void initIdentifierInfo(ASTContext &Ctx) const;
+
+ bool isGlobalConstString(SVal V) const;
+
+ bool isNonnullType(QualType Ty) const;
+};
+
+} // namespace
+
+/// Lazily initialize cache for required identifier informations.
+void NonnullGlobalConstantsChecker::initIdentifierInfo(ASTContext &Ctx) const {
+ if (NSStringII)
+ return;
+
+ NSStringII = &Ctx.Idents.get("NSString");
+ CFStringRefII = &Ctx.Idents.get("CFStringRef");
+ CFBooleanRefII = &Ctx.Idents.get("CFBooleanRef");
+}
+
+/// Add an assumption that const string-like globals are non-null.
+void NonnullGlobalConstantsChecker::checkLocation(SVal location, bool isLoad,
+ const Stmt *S,
+ CheckerContext &C) const {
+ initIdentifierInfo(C.getASTContext());
+ if (!isLoad || !location.isValid())
+ return;
+
+ ProgramStateRef State = C.getState();
+ SVal V = State->getSVal(location.castAs<Loc>());
+
+ if (isGlobalConstString(location)) {
+ Optional<DefinedOrUnknownSVal> Constr = V.getAs<DefinedOrUnknownSVal>();
+
+ if (Constr) {
+
+ // Assume that the variable is non-null.
+ ProgramStateRef OutputState = State->assume(*Constr, true);
+ C.addTransition(OutputState);
+ }
+ }
+}
+
+/// \param V loaded lvalue.
+/// \return whether {@code val} is a string-like const global.
+bool NonnullGlobalConstantsChecker::isGlobalConstString(SVal V) const {
+ Optional<loc::MemRegionVal> RegionVal = V.getAs<loc::MemRegionVal>();
+ if (!RegionVal)
+ return false;
+ auto *Region = dyn_cast<VarRegion>(RegionVal->getAsRegion());
+ if (!Region)
+ return false;
+ const VarDecl *Decl = Region->getDecl();
+
+ if (!Decl->hasGlobalStorage())
+ return false;
+
+ QualType Ty = Decl->getType();
+ bool HasConst = Ty.isConstQualified();
+ if (isNonnullType(Ty) && HasConst)
+ return true;
+
+ // Look through the typedefs.
+ while (auto *T = dyn_cast<TypedefType>(Ty)) {
+ Ty = T->getDecl()->getUnderlyingType();
+
+ // It is sufficient for any intermediate typedef
+ // to be classified const.
+ HasConst = HasConst || Ty.isConstQualified();
+ if (isNonnullType(Ty) && HasConst)
+ return true;
+ }
+ return false;
+}
+
+/// \return whether {@code type} is extremely unlikely to be null
+bool NonnullGlobalConstantsChecker::isNonnullType(QualType Ty) const {
+
+ if (Ty->isPointerType() && Ty->getPointeeType()->isCharType())
+ return true;
+
+ if (auto *T = dyn_cast<ObjCObjectPointerType>(Ty)) {
+ return T->getInterfaceDecl() &&
+ T->getInterfaceDecl()->getIdentifier() == NSStringII;
+ } else if (auto *T = dyn_cast<TypedefType>(Ty)) {
+ IdentifierInfo* II = T->getDecl()->getIdentifier();
+ return II == CFStringRefII || II == CFBooleanRefII;
+ }
+ return false;
+}
+
+void ento::registerNonnullGlobalConstantsChecker(CheckerManager &Mgr) {
+ Mgr.registerChecker<NonnullGlobalConstantsChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCContainersASTChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCContainersASTChecker.cpp
index b10ec848ee461..e4737fcee7fb5 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCContainersASTChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCContainersASTChecker.cpp
@@ -13,7 +13,7 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
#include "clang/AST/StmtVisitor.h"
-#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp
index 075ff09dcbfac..69b19a7859381 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp
@@ -107,8 +107,6 @@ void ObjCSuperDeallocChecker::checkPreObjCMessage(const ObjCMethodCall &M,
}
reportUseAfterDealloc(ReceiverSymbol, Desc, M.getOriginExpr(), C);
-
- return;
}
void ObjCSuperDeallocChecker::checkPreCall(const CallEvent &Call,
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
index 0e3a649e88f78..dab29be1c8fb1 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
@@ -81,6 +81,8 @@ class PthreadLockChecker
public:
void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
+ void printState(raw_ostream &Out, ProgramStateRef State,
+ const char *NL, const char *Sep) const override;
void AcquireLock(CheckerContext &C, const CallExpr *CE, SVal lock,
bool isTryLock, enum LockingSemantics semantics) const;
@@ -184,6 +186,39 @@ ProgramStateRef PthreadLockChecker::resolvePossiblyDestroyedMutex(
return state;
}
+void PthreadLockChecker::printState(raw_ostream &Out, ProgramStateRef State,
+ const char *NL, const char *Sep) const {
+ LockMapTy LM = State->get<LockMap>();
+ if (!LM.isEmpty()) {
+ Out << Sep << "Mutex states:" << NL;
+ for (auto I : LM) {
+ I.first->dumpToStream(Out);
+ if (I.second.isLocked())
+ Out << ": locked";
+ else if (I.second.isUnlocked())
+ Out << ": unlocked";
+ else if (I.second.isDestroyed())
+ Out << ": destroyed";
+ else if (I.second.isUntouchedAndPossiblyDestroyed())
+ Out << ": not tracked, possibly destroyed";
+ else if (I.second.isUnlockedAndPossiblyDestroyed())
+ Out << ": unlocked, possibly destroyed";
+ Out << NL;
+ }
+ }
+
+ LockSetTy LS = State->get<LockSet>();
+ if (!LS.isEmpty()) {
+ Out << Sep << "Mutex lock order:" << NL;
+ for (auto I: LS) {
+ I->dumpToStream(Out);
+ Out << NL;
+ }
+ }
+
+ // TODO: Dump destroyed mutex symbols?
+}
+
void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE,
SVal lock, bool isTryLock,
enum LockingSemantics semantics) const {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
index 21ccf21515b3a..e47494a3e90b3 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
@@ -462,6 +462,7 @@ private:
ArgEffect getDefaultArgEffect() const { return DefaultArgEffect; }
friend class RetainSummaryManager;
+ friend class RetainCountChecker;
};
} // end anonymous namespace
@@ -1061,6 +1062,7 @@ RetainSummaryManager::getFunctionSummary(const FunctionDecl *FD) {
// Inspect the result type.
QualType RetTy = FT->getReturnType();
+ std::string RetTyName = RetTy.getAsString();
// FIXME: This should all be refactored into a chain of "summary lookup"
// filters.
@@ -1080,12 +1082,14 @@ RetainSummaryManager::getFunctionSummary(const FunctionDecl *FD) {
AllowAnnotations = false;
} else if (FName == "CFPlugInInstanceCreate") {
S = getPersistentSummary(RetEffect::MakeNoRet());
- } else if (FName == "IOBSDNameMatching" ||
+ } else if (FName == "IORegistryEntrySearchCFProperty"
+ || (RetTyName == "CFMutableDictionaryRef" && (
+ FName == "IOBSDNameMatching" ||
FName == "IOServiceMatching" ||
FName == "IOServiceNameMatching" ||
- FName == "IORegistryEntrySearchCFProperty" ||
FName == "IORegistryEntryIDMatching" ||
- FName == "IOOpenFirmwarePathMatching") {
+ FName == "IOOpenFirmwarePathMatching"
+ ))) {
// Part of <rdar://problem/6961230>. (IOKit)
// This should be addressed using a API table.
S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF),
@@ -1166,6 +1170,11 @@ RetainSummaryManager::getFunctionSummary(const FunctionDecl *FD) {
if (cocoa::isRefType(RetTy, "CF", FName)) {
if (isRetain(FD, FName)) {
S = getUnarySummary(FT, cfretain);
+ // CFRetain isn't supposed to be annotated. However, this may as well
+ // be a user-made "safe" CFRetain function that is incorrectly
+ // annotated as cf_returns_retained due to lack of better options.
+ // We want to ignore such annotation.
+ AllowAnnotations = false;
} else if (isAutorelease(FD, FName)) {
S = getUnarySummary(FT, cfautorelease);
// The headers use cf_consumed, but we can fully model CFAutorelease
@@ -1192,10 +1201,10 @@ RetainSummaryManager::getFunctionSummary(const FunctionDecl *FD) {
break;
}
- // For the Disk Arbitration API (DiskArbitration/DADisk.h)
- if (cocoa::isRefType(RetTy, "DADisk") ||
- cocoa::isRefType(RetTy, "DADissenter") ||
- cocoa::isRefType(RetTy, "DASessionRef")) {
+ // For all other CF-style types, use the Create/Get
+ // rule for summaries but don't support Retain functions
+ // with framework-specific prefixes.
+ if (coreFoundation::isCFObjectRef(RetTy)) {
S = getCFCreateGetRuleSummary(FD);
break;
}
@@ -1210,7 +1219,8 @@ RetainSummaryManager::getFunctionSummary(const FunctionDecl *FD) {
// Check for release functions, the only kind of functions that we care
// about that don't return a pointer type.
- if (FName[0] == 'C' && (FName[1] == 'F' || FName[1] == 'G')) {
+ if (FName.size() >= 2 &&
+ FName[0] == 'C' && (FName[1] == 'F' || FName[1] == 'G')) {
// Test for 'CGCF'.
FName = FName.substr(FName.startswith("CGCF") ? 4 : 2);
@@ -1319,6 +1329,13 @@ static bool isTrustedReferenceCountImplementation(const FunctionDecl *FD) {
return hasRCAnnotation(FD, "rc_ownership_trusted_implementation");
}
+static bool isGeneralizedObjectRef(QualType Ty) {
+ if (Ty.getAsString().substr(0, 4) == "isl_")
+ return true;
+ else
+ return false;
+}
+
//===----------------------------------------------------------------------===//
// Summary creation for Selectors.
//===----------------------------------------------------------------------===//
@@ -1340,6 +1357,8 @@ RetainSummaryManager::getRetEffectFromAnnotations(QualType RetTy,
if (D->hasAttr<CFReturnsRetainedAttr>())
return RetEffect::MakeOwned(RetEffect::CF);
+ else if (hasRCAnnotation(D, "rc_ownership_returns_retained"))
+ return RetEffect::MakeOwned(RetEffect::Generalized);
if (D->hasAttr<CFReturnsNotRetainedAttr>())
return RetEffect::MakeNotOwned(RetEffect::CF);
@@ -1363,9 +1382,11 @@ RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,
const ParmVarDecl *pd = *pi;
if (pd->hasAttr<NSConsumedAttr>())
Template->addArg(AF, parm_idx, DecRefMsg);
- else if (pd->hasAttr<CFConsumedAttr>())
+ else if (pd->hasAttr<CFConsumedAttr>() ||
+ hasRCAnnotation(pd, "rc_ownership_consumed"))
Template->addArg(AF, parm_idx, DecRef);
- else if (pd->hasAttr<CFReturnsRetainedAttr>()) {
+ else if (pd->hasAttr<CFReturnsRetainedAttr>() ||
+ hasRCAnnotation(pd, "rc_ownership_returns_retained")) {
QualType PointeeTy = pd->getType()->getPointeeType();
if (!PointeeTy.isNull())
if (coreFoundation::isCFObjectRef(PointeeTy))
@@ -1844,6 +1865,15 @@ namespace {
class CFRefLeakReport : public CFRefReport {
const MemRegion* AllocBinding;
+ const Stmt *AllocStmt;
+
+ // Finds the function declaration where a leak warning for the parameter 'sym' should be raised.
+ void deriveParamLocation(CheckerContext &Ctx, SymbolRef sym);
+ // Finds the location where a leak warning for 'sym' should be raised.
+ void deriveAllocLocation(CheckerContext &Ctx, SymbolRef sym);
+ // Produces description of a leak warning which is printed on the console.
+ void createDescription(CheckerContext &Ctx, bool GCEnabled, bool IncludeAllocationLine);
+
public:
CFRefLeakReport(CFRefBug &D, const LangOptions &LOpts, bool GCEnabled,
const SummaryLogTy &Log, ExplodedNode *n, SymbolRef sym,
@@ -1999,17 +2029,15 @@ CFRefReportVisitor::VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN,
}
if (CurrV.getObjKind() == RetEffect::CF) {
- if (Sym->getType().isNull()) {
- os << " returns a Core Foundation object with a ";
- } else {
- os << " returns a Core Foundation object of type "
- << Sym->getType().getAsString() << " with a ";
- }
- }
- else {
+ os << " returns a Core Foundation object of type "
+ << Sym->getType().getAsString() << " with a ";
+ } else if (CurrV.getObjKind() == RetEffect::Generalized) {
+ os << " returns an object of type " << Sym->getType().getAsString()
+ << " with a ";
+ } else {
assert (CurrV.getObjKind() == RetEffect::ObjC);
QualType T = Sym->getType();
- if (T.isNull() || !isa<ObjCObjectPointerType>(T)) {
+ if (!isa<ObjCObjectPointerType>(T)) {
os << " returns an Objective-C object with a ";
} else {
const ObjCObjectPointerType *PT = cast<ObjCObjectPointerType>(T);
@@ -2425,13 +2453,25 @@ CFRefLeakReportVisitor::getEndPath(BugReporterContext &BRC,
return llvm::make_unique<PathDiagnosticEventPiece>(L, os.str());
}
-CFRefLeakReport::CFRefLeakReport(CFRefBug &D, const LangOptions &LOpts,
- bool GCEnabled, const SummaryLogTy &Log,
- ExplodedNode *n, SymbolRef sym,
- CheckerContext &Ctx,
- bool IncludeAllocationLine)
- : CFRefReport(D, LOpts, GCEnabled, Log, n, sym, false) {
+void CFRefLeakReport::deriveParamLocation(CheckerContext &Ctx, SymbolRef sym) {
+ const SourceManager& SMgr = Ctx.getSourceManager();
+ if (!sym->getOriginRegion())
+ return;
+
+ auto *Region = dyn_cast<DeclRegion>(sym->getOriginRegion());
+ if (Region) {
+ const Decl *PDecl = Region->getDecl();
+ if (PDecl && isa<ParmVarDecl>(PDecl)) {
+ PathDiagnosticLocation ParamLocation = PathDiagnosticLocation::create(PDecl, SMgr);
+ Location = ParamLocation;
+ UniqueingLocation = ParamLocation;
+ UniqueingDecl = Ctx.getLocationContext()->getDecl();
+ }
+ }
+}
+
+void CFRefLeakReport::deriveAllocLocation(CheckerContext &Ctx,SymbolRef sym) {
// Most bug reports are cached at the location where they occurred.
// With leaks, we want to unique them by the location where they were
// allocated, and only report a single path. To do this, we need to find
@@ -2455,8 +2495,12 @@ CFRefLeakReport::CFRefLeakReport(CFRefBug &D, const LangOptions &LOpts,
// FIXME: This will crash the analyzer if an allocation comes from an
// implicit call (ex: a destructor call).
// (Currently there are no such allocations in Cocoa, though.)
- const Stmt *AllocStmt = PathDiagnosticLocation::getStmt(AllocNode);
- assert(AllocStmt && "Cannot find allocation statement");
+ AllocStmt = PathDiagnosticLocation::getStmt(AllocNode);
+
+ if (!AllocStmt) {
+ AllocBinding = nullptr;
+ return;
+ }
PathDiagnosticLocation AllocLocation =
PathDiagnosticLocation::createBegin(AllocStmt, SMgr,
@@ -2467,8 +2511,10 @@ CFRefLeakReport::CFRefLeakReport(CFRefBug &D, const LangOptions &LOpts,
// leaks should be uniqued on the allocation site.
UniqueingLocation = AllocLocation;
UniqueingDecl = AllocNode->getLocationContext()->getDecl();
+}
- // Fill in the description of the bug.
+void CFRefLeakReport::createDescription(CheckerContext &Ctx, bool GCEnabled, bool IncludeAllocationLine) {
+ assert(Location.isValid() && UniqueingDecl && UniqueingLocation.isValid());
Description.clear();
llvm::raw_string_ostream os(Description);
os << "Potential leak ";
@@ -2483,6 +2529,20 @@ CFRefLeakReport::CFRefLeakReport(CFRefBug &D, const LangOptions &LOpts,
os << " (allocated on line " << SL.getSpellingLineNumber() << ")";
}
}
+}
+
+CFRefLeakReport::CFRefLeakReport(CFRefBug &D, const LangOptions &LOpts,
+ bool GCEnabled, const SummaryLogTy &Log,
+ ExplodedNode *n, SymbolRef sym,
+ CheckerContext &Ctx,
+ bool IncludeAllocationLine)
+ : CFRefReport(D, LOpts, GCEnabled, Log, n, sym, false) {
+
+ deriveAllocLocation(Ctx, sym);
+ if (!AllocBinding)
+ deriveParamLocation(Ctx, sym);
+
+ createDescription(Ctx, GCEnabled, IncludeAllocationLine);
addVisitor(llvm::make_unique<CFRefLeakReportVisitor>(sym, GCEnabled, Log));
}
@@ -2496,6 +2556,7 @@ class RetainCountChecker
: public Checker< check::Bind,
check::DeadSymbols,
check::EndAnalysis,
+ check::BeginFunction,
check::EndFunction,
check::PostStmt<BlockExpr>,
check::PostStmt<CastExpr>,
@@ -2680,6 +2741,7 @@ public:
SymbolRef Sym, ProgramStateRef state) const;
void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
+ void checkBeginFunction(CheckerContext &C) const;
void checkEndFunction(CheckerContext &C) const;
ProgramStateRef updateSymbol(ProgramStateRef state, SymbolRef sym,
@@ -3901,6 +3963,36 @@ RetainCountChecker::processLeaks(ProgramStateRef state,
return N;
}
+void RetainCountChecker::checkBeginFunction(CheckerContext &Ctx) const {
+ if (!Ctx.inTopFrame())
+ return;
+
+ const LocationContext *LCtx = Ctx.getLocationContext();
+ const FunctionDecl *FD = dyn_cast<FunctionDecl>(LCtx->getDecl());
+
+ if (!FD || isTrustedReferenceCountImplementation(FD))
+ return;
+
+ ProgramStateRef state = Ctx.getState();
+
+ const RetainSummary *FunctionSummary = getSummaryManager(Ctx).getFunctionSummary(FD);
+ ArgEffects CalleeSideArgEffects = FunctionSummary->getArgEffects();
+
+ for (unsigned idx = 0, e = FD->getNumParams(); idx != e; ++idx) {
+ const ParmVarDecl *Param = FD->getParamDecl(idx);
+ SymbolRef Sym = state->getSVal(state->getRegion(Param, LCtx)).getAsSymbol();
+
+ QualType Ty = Param->getType();
+ const ArgEffect *AE = CalleeSideArgEffects.lookup(idx);
+ if (AE && *AE == DecRef && isGeneralizedObjectRef(Ty))
+ state = setRefBinding(state, Sym, RefVal::makeOwned(RetEffect::ObjKind::Generalized, Ty));
+ else if (isGeneralizedObjectRef(Ty))
+ state = setRefBinding(state, Sym, RefVal::makeNotOwned(RetEffect::ObjKind::Generalized, Ty));
+ }
+
+ Ctx.addTransition(state);
+}
+
void RetainCountChecker::checkEndFunction(CheckerContext &Ctx) const {
ProgramStateRef state = Ctx.getState();
RefBindingsTy B = state->get<RefBindings>();
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
index 556274d0edb65..25975628c553d 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
@@ -18,6 +18,7 @@
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "llvm/ADT/SmallString.h"
@@ -26,85 +27,139 @@ using namespace clang;
using namespace ento;
namespace {
-class StackAddrEscapeChecker : public Checker< check::PreStmt<ReturnStmt>,
- check::EndFunction > {
+class StackAddrEscapeChecker
+ : public Checker<check::PreCall, check::PreStmt<ReturnStmt>,
+ check::EndFunction> {
+ mutable IdentifierInfo *dispatch_semaphore_tII;
mutable std::unique_ptr<BuiltinBug> BT_stackleak;
mutable std::unique_ptr<BuiltinBug> BT_returnstack;
+ mutable std::unique_ptr<BuiltinBug> BT_capturedstackasync;
+ mutable std::unique_ptr<BuiltinBug> BT_capturedstackret;
public:
+ enum CheckKind {
+ CK_StackAddrEscapeChecker,
+ CK_StackAddrAsyncEscapeChecker,
+ CK_NumCheckKinds
+ };
+
+ DefaultBool ChecksEnabled[CK_NumCheckKinds];
+
+ void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const;
void checkEndFunction(CheckerContext &Ctx) const;
+
private:
+ void checkReturnedBlockCaptures(const BlockDataRegion &B,
+ CheckerContext &C) const;
+ void checkAsyncExecutedBlockCaptures(const BlockDataRegion &B,
+ CheckerContext &C) const;
void EmitStackError(CheckerContext &C, const MemRegion *R,
const Expr *RetE) const;
+ bool isSemaphoreCaptured(const BlockDecl &B) const;
static SourceRange genName(raw_ostream &os, const MemRegion *R,
ASTContext &Ctx);
+ static SmallVector<const MemRegion *, 4>
+ getCapturedStackRegions(const BlockDataRegion &B, CheckerContext &C);
+ static bool isArcManagedBlock(const MemRegion *R, CheckerContext &C);
+ static bool isNotInCurrentFrame(const MemRegion *R, CheckerContext &C);
};
-}
+} // namespace
SourceRange StackAddrEscapeChecker::genName(raw_ostream &os, const MemRegion *R,
ASTContext &Ctx) {
- // Get the base region, stripping away fields and elements.
+ // Get the base region, stripping away fields and elements.
R = R->getBaseRegion();
SourceManager &SM = Ctx.getSourceManager();
SourceRange range;
os << "Address of ";
// Check if the region is a compound literal.
- if (const CompoundLiteralRegion* CR = dyn_cast<CompoundLiteralRegion>(R)) {
+ if (const auto *CR = dyn_cast<CompoundLiteralRegion>(R)) {
const CompoundLiteralExpr *CL = CR->getLiteralExpr();
os << "stack memory associated with a compound literal "
"declared on line "
- << SM.getExpansionLineNumber(CL->getLocStart())
- << " returned to caller";
+ << SM.getExpansionLineNumber(CL->getLocStart()) << " returned to caller";
range = CL->getSourceRange();
- }
- else if (const AllocaRegion* AR = dyn_cast<AllocaRegion>(R)) {
+ } else if (const auto *AR = dyn_cast<AllocaRegion>(R)) {
const Expr *ARE = AR->getExpr();
SourceLocation L = ARE->getLocStart();
range = ARE->getSourceRange();
os << "stack memory allocated by call to alloca() on line "
<< SM.getExpansionLineNumber(L);
- }
- else if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(R)) {
+ } else if (const auto *BR = dyn_cast<BlockDataRegion>(R)) {
const BlockDecl *BD = BR->getCodeRegion()->getDecl();
SourceLocation L = BD->getLocStart();
range = BD->getSourceRange();
os << "stack-allocated block declared on line "
<< SM.getExpansionLineNumber(L);
- }
- else if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
- os << "stack memory associated with local variable '"
- << VR->getString() << '\'';
+ } else if (const auto *VR = dyn_cast<VarRegion>(R)) {
+ os << "stack memory associated with local variable '" << VR->getString()
+ << '\'';
range = VR->getDecl()->getSourceRange();
- }
- else if (const CXXTempObjectRegion *TOR = dyn_cast<CXXTempObjectRegion>(R)) {
+ } else if (const auto *TOR = dyn_cast<CXXTempObjectRegion>(R)) {
QualType Ty = TOR->getValueType().getLocalUnqualifiedType();
os << "stack memory associated with temporary object of type '";
Ty.print(os, Ctx.getPrintingPolicy());
os << "'";
range = TOR->getExpr()->getSourceRange();
- }
- else {
+ } else {
llvm_unreachable("Invalid region in ReturnStackAddressChecker.");
}
return range;
}
-void StackAddrEscapeChecker::EmitStackError(CheckerContext &C, const MemRegion *R,
- const Expr *RetE) const {
- ExplodedNode *N = C.generateErrorNode();
+bool StackAddrEscapeChecker::isArcManagedBlock(const MemRegion *R,
+ CheckerContext &C) {
+ assert(R && "MemRegion should not be null");
+ return C.getASTContext().getLangOpts().ObjCAutoRefCount &&
+ isa<BlockDataRegion>(R);
+}
+bool StackAddrEscapeChecker::isNotInCurrentFrame(const MemRegion *R,
+ CheckerContext &C) {
+ const StackSpaceRegion *S = cast<StackSpaceRegion>(R->getMemorySpace());
+ return S->getStackFrame() != C.getLocationContext()->getCurrentStackFrame();
+}
+
+bool StackAddrEscapeChecker::isSemaphoreCaptured(const BlockDecl &B) const {
+ if (!dispatch_semaphore_tII)
+ dispatch_semaphore_tII = &B.getASTContext().Idents.get("dispatch_semaphore_t");
+ for (const auto &C : B.captures()) {
+ const auto *T = C.getVariable()->getType()->getAs<TypedefType>();
+ if (T && T->getDecl()->getIdentifier() == dispatch_semaphore_tII)
+ return true;
+ }
+ return false;
+}
+
+SmallVector<const MemRegion *, 4>
+StackAddrEscapeChecker::getCapturedStackRegions(const BlockDataRegion &B,
+ CheckerContext &C) {
+ SmallVector<const MemRegion *, 4> Regions;
+ BlockDataRegion::referenced_vars_iterator I = B.referenced_vars_begin();
+ BlockDataRegion::referenced_vars_iterator E = B.referenced_vars_end();
+ for (; I != E; ++I) {
+ SVal Val = C.getState()->getSVal(I.getCapturedRegion());
+ const MemRegion *Region = Val.getAsRegion();
+ if (Region && isa<StackSpaceRegion>(Region->getMemorySpace()))
+ Regions.push_back(Region);
+ }
+ return Regions;
+}
+
+void StackAddrEscapeChecker::EmitStackError(CheckerContext &C,
+ const MemRegion *R,
+ const Expr *RetE) const {
+ ExplodedNode *N = C.generateNonFatalErrorNode();
if (!N)
return;
-
if (!BT_returnstack)
- BT_returnstack.reset(
- new BuiltinBug(this, "Return of address to stack-allocated memory"));
-
+ BT_returnstack = llvm::make_unique<BuiltinBug>(
+ this, "Return of address to stack-allocated memory");
// Generate a report for this bug.
- SmallString<512> buf;
+ SmallString<128> buf;
llvm::raw_svector_ostream os(buf);
SourceRange range = genName(os, R, C.getASTContext());
os << " returned to caller";
@@ -112,12 +167,88 @@ void StackAddrEscapeChecker::EmitStackError(CheckerContext &C, const MemRegion *
report->addRange(RetE->getSourceRange());
if (range.isValid())
report->addRange(range);
-
C.emitReport(std::move(report));
}
+void StackAddrEscapeChecker::checkAsyncExecutedBlockCaptures(
+ const BlockDataRegion &B, CheckerContext &C) const {
+ // There is a not-too-uncommon idiom
+ // where a block passed to dispatch_async captures a semaphore
+ // and then the thread (which called dispatch_async) is blocked on waiting
+ // for the completion of the execution of the block
+ // via dispatch_semaphore_wait. To avoid false-positives (for now)
+ // we ignore all the blocks which have captured
+ // a variable of the type "dispatch_semaphore_t".
+ if (isSemaphoreCaptured(*B.getDecl()))
+ return;
+ for (const MemRegion *Region : getCapturedStackRegions(B, C)) {
+ // The block passed to dispatch_async may capture another block
+ // created on the stack. However, there is no leak in this situaton,
+ // no matter if ARC or no ARC is enabled:
+ // dispatch_async copies the passed "outer" block (via Block_copy)
+ // and if the block has captured another "inner" block,
+ // the "inner" block will be copied as well.
+ if (isa<BlockDataRegion>(Region))
+ continue;
+ ExplodedNode *N = C.generateNonFatalErrorNode();
+ if (!N)
+ continue;
+ if (!BT_capturedstackasync)
+ BT_capturedstackasync = llvm::make_unique<BuiltinBug>(
+ this, "Address of stack-allocated memory is captured");
+ SmallString<128> Buf;
+ llvm::raw_svector_ostream Out(Buf);
+ SourceRange Range = genName(Out, Region, C.getASTContext());
+ Out << " is captured by an asynchronously-executed block";
+ auto Report =
+ llvm::make_unique<BugReport>(*BT_capturedstackasync, Out.str(), N);
+ if (Range.isValid())
+ Report->addRange(Range);
+ C.emitReport(std::move(Report));
+ }
+}
+
+void StackAddrEscapeChecker::checkReturnedBlockCaptures(
+ const BlockDataRegion &B, CheckerContext &C) const {
+ for (const MemRegion *Region : getCapturedStackRegions(B, C)) {
+ if (isArcManagedBlock(Region, C) || isNotInCurrentFrame(Region, C))
+ continue;
+ ExplodedNode *N = C.generateNonFatalErrorNode();
+ if (!N)
+ continue;
+ if (!BT_capturedstackret)
+ BT_capturedstackret = llvm::make_unique<BuiltinBug>(
+ this, "Address of stack-allocated memory is captured");
+ SmallString<128> Buf;
+ llvm::raw_svector_ostream Out(Buf);
+ SourceRange Range = genName(Out, Region, C.getASTContext());
+ Out << " is captured by a returned block";
+ auto Report =
+ llvm::make_unique<BugReport>(*BT_capturedstackret, Out.str(), N);
+ if (Range.isValid())
+ Report->addRange(Range);
+ C.emitReport(std::move(Report));
+ }
+}
+
+void StackAddrEscapeChecker::checkPreCall(const CallEvent &Call,
+ CheckerContext &C) const {
+ if (!ChecksEnabled[CK_StackAddrAsyncEscapeChecker])
+ return;
+ if (!Call.isGlobalCFunction("dispatch_after") &&
+ !Call.isGlobalCFunction("dispatch_async"))
+ return;
+ for (unsigned Idx = 0, NumArgs = Call.getNumArgs(); Idx < NumArgs; ++Idx) {
+ if (const BlockDataRegion *B = dyn_cast_or_null<BlockDataRegion>(
+ Call.getArgSVal(Idx).getAsRegion()))
+ checkAsyncExecutedBlockCaptures(*B, C);
+ }
+}
+
void StackAddrEscapeChecker::checkPreStmt(const ReturnStmt *RS,
CheckerContext &C) const {
+ if (!ChecksEnabled[CK_StackAddrEscapeChecker])
+ return;
const Expr *RetE = RS->getRetValue();
if (!RetE)
@@ -127,25 +258,14 @@ void StackAddrEscapeChecker::checkPreStmt(const ReturnStmt *RS,
const LocationContext *LCtx = C.getLocationContext();
SVal V = C.getState()->getSVal(RetE, LCtx);
const MemRegion *R = V.getAsRegion();
-
if (!R)
return;
- const StackSpaceRegion *SS =
- dyn_cast_or_null<StackSpaceRegion>(R->getMemorySpace());
-
- if (!SS)
- return;
-
- // Return stack memory in an ancestor stack frame is fine.
- const StackFrameContext *CurFrame = LCtx->getCurrentStackFrame();
- const StackFrameContext *MemFrame = SS->getStackFrame();
- if (MemFrame != CurFrame)
- return;
+ if (const BlockDataRegion *B = dyn_cast<BlockDataRegion>(R))
+ checkReturnedBlockCaptures(*B, C);
- // Automatic reference counting automatically copies blocks.
- if (C.getASTContext().getLangOpts().ObjCAutoRefCount &&
- isa<BlockDataRegion>(R))
+ if (!isa<StackSpaceRegion>(R->getMemorySpace()) ||
+ isNotInCurrentFrame(R, C) || isArcManagedBlock(R, C))
return;
// Returning a record by value is fine. (In this case, the returned
@@ -169,7 +289,10 @@ void StackAddrEscapeChecker::checkPreStmt(const ReturnStmt *RS,
}
void StackAddrEscapeChecker::checkEndFunction(CheckerContext &Ctx) const {
- ProgramStateRef state = Ctx.getState();
+ if (!ChecksEnabled[CK_StackAddrEscapeChecker])
+ return;
+
+ ProgramStateRef State = Ctx.getState();
// Iterate over all bindings to global variables and see if it contains
// a memory region in the stack space.
@@ -177,82 +300,73 @@ void StackAddrEscapeChecker::checkEndFunction(CheckerContext &Ctx) const {
private:
CheckerContext &Ctx;
const StackFrameContext *CurSFC;
- public:
- SmallVector<std::pair<const MemRegion*, const MemRegion*>, 10> V;
- CallBack(CheckerContext &CC) :
- Ctx(CC),
- CurSFC(CC.getLocationContext()->getCurrentStackFrame())
- {}
+ public:
+ SmallVector<std::pair<const MemRegion *, const MemRegion *>, 10> V;
- bool HandleBinding(StoreManager &SMgr, Store store,
- const MemRegion *region, SVal val) override {
+ CallBack(CheckerContext &CC)
+ : Ctx(CC), CurSFC(CC.getLocationContext()->getCurrentStackFrame()) {}
- if (!isa<GlobalsSpaceRegion>(region->getMemorySpace()))
- return true;
+ bool HandleBinding(StoreManager &SMgr, Store S, const MemRegion *Region,
+ SVal Val) override {
- const MemRegion *vR = val.getAsRegion();
- if (!vR)
+ if (!isa<GlobalsSpaceRegion>(Region->getMemorySpace()))
return true;
-
- // Under automated retain release, it is okay to assign a block
- // directly to a global variable.
- if (Ctx.getASTContext().getLangOpts().ObjCAutoRefCount &&
- isa<BlockDataRegion>(vR))
- return true;
-
- if (const StackSpaceRegion *SSR =
- dyn_cast<StackSpaceRegion>(vR->getMemorySpace())) {
- // If the global variable holds a location in the current stack frame,
- // record the binding to emit a warning.
- if (SSR->getStackFrame() == CurSFC)
- V.push_back(std::make_pair(region, vR));
- }
-
+ const MemRegion *VR = Val.getAsRegion();
+ if (VR && isa<StackSpaceRegion>(VR->getMemorySpace()) &&
+ !isArcManagedBlock(VR, Ctx) && !isNotInCurrentFrame(VR, Ctx))
+ V.emplace_back(Region, VR);
return true;
}
};
- CallBack cb(Ctx);
- state->getStateManager().getStoreManager().iterBindings(state->getStore(),cb);
+ CallBack Cb(Ctx);
+ State->getStateManager().getStoreManager().iterBindings(State->getStore(),
+ Cb);
- if (cb.V.empty())
+ if (Cb.V.empty())
return;
// Generate an error node.
- ExplodedNode *N = Ctx.generateNonFatalErrorNode(state);
+ ExplodedNode *N = Ctx.generateNonFatalErrorNode(State);
if (!N)
return;
if (!BT_stackleak)
- BT_stackleak.reset(
- new BuiltinBug(this, "Stack address stored into global variable",
- "Stack address was saved into a global variable. "
- "This is dangerous because the address will become "
- "invalid after returning from the function"));
+ BT_stackleak = llvm::make_unique<BuiltinBug>(
+ this, "Stack address stored into global variable",
+ "Stack address was saved into a global variable. "
+ "This is dangerous because the address will become "
+ "invalid after returning from the function");
- for (unsigned i = 0, e = cb.V.size(); i != e; ++i) {
+ for (const auto &P : Cb.V) {
// Generate a report for this bug.
- SmallString<512> buf;
- llvm::raw_svector_ostream os(buf);
- SourceRange range = genName(os, cb.V[i].second, Ctx.getASTContext());
- os << " is still referred to by the ";
- if (isa<StaticGlobalSpaceRegion>(cb.V[i].first->getMemorySpace()))
- os << "static";
+ SmallString<128> Buf;
+ llvm::raw_svector_ostream Out(Buf);
+ SourceRange Range = genName(Out, P.second, Ctx.getASTContext());
+ Out << " is still referred to by the ";
+ if (isa<StaticGlobalSpaceRegion>(P.first->getMemorySpace()))
+ Out << "static";
else
- os << "global";
- os << " variable '";
- const VarRegion *VR = cast<VarRegion>(cb.V[i].first->getBaseRegion());
- os << *VR->getDecl()
- << "' upon returning to the caller. This will be a dangling reference";
- auto report = llvm::make_unique<BugReport>(*BT_stackleak, os.str(), N);
- if (range.isValid())
- report->addRange(range);
+ Out << "global";
+ Out << " variable '";
+ const VarRegion *VR = cast<VarRegion>(P.first->getBaseRegion());
+ Out << *VR->getDecl()
+ << "' upon returning to the caller. This will be a dangling reference";
+ auto Report = llvm::make_unique<BugReport>(*BT_stackleak, Out.str(), N);
+ if (Range.isValid())
+ Report->addRange(Range);
- Ctx.emitReport(std::move(report));
+ Ctx.emitReport(std::move(Report));
}
}
-void ento::registerStackAddrEscapeChecker(CheckerManager &mgr) {
- mgr.registerChecker<StackAddrEscapeChecker>();
-}
+#define REGISTER_CHECKER(name) \
+ void ento::register##name(CheckerManager &Mgr) { \
+ StackAddrEscapeChecker *Chk = \
+ Mgr.registerChecker<StackAddrEscapeChecker>(); \
+ Chk->ChecksEnabled[StackAddrEscapeChecker::CK_##name] = true; \
+ }
+
+REGISTER_CHECKER(StackAddrEscapeChecker)
+REGISTER_CHECKER(StackAddrAsyncEscapeChecker)
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
index f3c2ffc58662e..172ce346f1ba7 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
@@ -59,6 +59,11 @@ static bool isArrayIndexOutOfBounds(CheckerContext &C, const Expr *Ex) {
return StOutBound && !StInBound;
}
+static bool isShiftOverflow(const BinaryOperator *B, CheckerContext &C) {
+ return C.isGreaterOrEqual(
+ B->getRHS(), C.getASTContext().getIntWidth(B->getLHS()->getType()));
+}
+
void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
CheckerContext &C) const {
ProgramStateRef state = C.getState();
@@ -97,18 +102,50 @@ void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
}
if (Ex) {
- OS << "The " << (isLeft ? "left" : "right")
- << " operand of '"
+ OS << "The " << (isLeft ? "left" : "right") << " operand of '"
<< BinaryOperator::getOpcodeStr(B->getOpcode())
<< "' is a garbage value";
if (isArrayIndexOutOfBounds(C, Ex))
OS << " due to array index out of bounds";
- }
- else {
+ } else {
// Neither operand was undefined, but the result is undefined.
- OS << "The result of the '"
- << BinaryOperator::getOpcodeStr(B->getOpcode())
- << "' expression is undefined";
+ if ((B->getOpcode() == BinaryOperatorKind::BO_Shl ||
+ B->getOpcode() == BinaryOperatorKind::BO_Shr) &&
+ C.isNegative(B->getRHS())) {
+ OS << "The result of the "
+ << ((B->getOpcode() == BinaryOperatorKind::BO_Shl) ? "left"
+ : "right")
+ << " shift is undefined because the right operand is negative";
+ } else if ((B->getOpcode() == BinaryOperatorKind::BO_Shl ||
+ B->getOpcode() == BinaryOperatorKind::BO_Shr) &&
+ isShiftOverflow(B, C)) {
+
+ OS << "The result of the "
+ << ((B->getOpcode() == BinaryOperatorKind::BO_Shl) ? "left"
+ : "right")
+ << " shift is undefined due to shifting by ";
+
+ SValBuilder &SB = C.getSValBuilder();
+ const llvm::APSInt *I =
+ SB.getKnownValue(C.getState(), C.getSVal(B->getRHS()));
+ if (!I)
+ OS << "a value that is";
+ else if (I->isUnsigned())
+ OS << '\'' << I->getZExtValue() << "\', which is";
+ else
+ OS << '\'' << I->getSExtValue() << "\', which is";
+
+ OS << " greater or equal to the width of type '"
+ << B->getLHS()->getType().getAsString() << "'.";
+ } else if (B->getOpcode() == BinaryOperatorKind::BO_Shl &&
+ C.isNegative(B->getLHS())) {
+ OS << "The result of the left shift is undefined because the left "
+ "operand is negative";
+ } else {
+ OS << "The result of the '"
+ << BinaryOperator::getOpcodeStr(B->getOpcode())
+ << "' expression is undefined";
+ }
}
auto report = llvm::make_unique<BugReport>(*BT, OS.str(), N);
if (Ex) {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
index 7a31efc8cef88..c3dcf1fac197b 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
@@ -60,6 +60,14 @@ void UndefinedAssignmentChecker::checkBind(SVal location, SVal val,
const Expr *ex = nullptr;
while (StoreE) {
+ if (const UnaryOperator *U = dyn_cast<UnaryOperator>(StoreE)) {
+ str = "The expression is an uninitialized value. "
+ "The computed value will also be garbage";
+
+ ex = U->getSubExpr();
+ break;
+ }
+
if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) {
if (B->isCompoundAssignmentOp()) {
ProgramStateRef state = C.getState();
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
index ccd8e9a18b00f..6f21e868b1742 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
@@ -112,7 +112,7 @@ void UnreachableCodeChecker::checkEndAnalysis(ExplodedGraph &G,
continue;
// Check for false positives
- if (CB->size() > 0 && isInvalidPath(CB, *PM))
+ if (isInvalidPath(CB, *PM))
continue;
// It is good practice to always have a "default" label in a "switch", even
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
index b47762b915ce9..c5010f53785a8 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
@@ -14,279 +14,272 @@
#include "ClangSACheckers.h"
#include "clang/AST/DeclCXX.h"
-#include "clang/AST/StmtVisitor.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/Support/SaveAndRestore.h"
-#include "llvm/Support/raw_ostream.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
using namespace clang;
using namespace ento;
namespace {
+enum class ObjectState : bool { CtorCalled, DtorCalled };
+} // end namespace
+ // FIXME: Ascending over StackFrameContext maybe another method.
-class WalkAST : public StmtVisitor<WalkAST> {
- const CheckerBase *Checker;
- BugReporter &BR;
- AnalysisDeclContext *AC;
-
- /// The root constructor or destructor whose callees are being analyzed.
- const CXXMethodDecl *RootMethod = nullptr;
-
- /// Whether the checker should walk into bodies of called functions.
- /// Controlled by the "Interprocedural" analyzer-config option.
- bool IsInterprocedural = false;
-
- /// Whether the checker should only warn for calls to pure virtual functions
- /// (which is undefined behavior) or for all virtual functions (which may
- /// may result in unexpected behavior).
- bool ReportPureOnly = false;
-
- typedef const CallExpr * WorkListUnit;
- typedef SmallVector<WorkListUnit, 20> DFSWorkList;
-
- /// A vector representing the worklist which has a chain of CallExprs.
- DFSWorkList WList;
-
- // PreVisited : A CallExpr to this FunctionDecl is in the worklist, but the
- // body has not been visited yet.
- // PostVisited : A CallExpr to this FunctionDecl is in the worklist, and the
- // body has been visited.
- enum Kind { NotVisited,
- PreVisited, /**< A CallExpr to this FunctionDecl is in the
- worklist, but the body has not yet been
- visited. */
- PostVisited /**< A CallExpr to this FunctionDecl is in the
- worklist, and the body has been visited. */
- };
-
- /// A DenseMap that records visited states of FunctionDecls.
- llvm::DenseMap<const FunctionDecl *, Kind> VisitedFunctions;
+namespace llvm {
+template <> struct FoldingSetTrait<ObjectState> {
+ static inline void Profile(ObjectState X, FoldingSetNodeID &ID) {
+ ID.AddInteger(static_cast<int>(X));
+ }
+};
+} // end namespace llvm
- /// The CallExpr whose body is currently being visited. This is used for
- /// generating bug reports. This is null while visiting the body of a
- /// constructor or destructor.
- const CallExpr *visitingCallExpr;
+namespace {
+class VirtualCallChecker
+ : public Checker<check::BeginFunction, check::EndFunction, check::PreCall> {
+ mutable std::unique_ptr<BugType> BT;
public:
- WalkAST(const CheckerBase *checker, BugReporter &br, AnalysisDeclContext *ac,
- const CXXMethodDecl *rootMethod, bool isInterprocedural,
- bool reportPureOnly)
- : Checker(checker), BR(br), AC(ac), RootMethod(rootMethod),
- IsInterprocedural(isInterprocedural), ReportPureOnly(reportPureOnly),
- visitingCallExpr(nullptr) {
- // Walking should always start from either a constructor or a destructor.
- assert(isa<CXXConstructorDecl>(rootMethod) ||
- isa<CXXDestructorDecl>(rootMethod));
- }
+ // The flag to determine if pure virtual functions should be issued only.
+ DefaultBool IsPureOnly;
- bool hasWork() const { return !WList.empty(); }
+ void checkBeginFunction(CheckerContext &C) const;
+ void checkEndFunction(CheckerContext &C) const;
+ void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
- /// This method adds a CallExpr to the worklist and marks the callee as
- /// being PreVisited.
- void Enqueue(WorkListUnit WLUnit) {
- const FunctionDecl *FD = WLUnit->getDirectCallee();
- if (!FD || !FD->getBody())
- return;
- Kind &K = VisitedFunctions[FD];
- if (K != NotVisited)
- return;
- K = PreVisited;
- WList.push_back(WLUnit);
- }
+private:
+ void registerCtorDtorCallInState(bool IsBeginFunction,
+ CheckerContext &C) const;
+ void reportBug(StringRef Msg, bool PureError, const MemRegion *Reg,
+ CheckerContext &C) const;
- /// This method returns an item from the worklist without removing it.
- WorkListUnit Dequeue() {
- assert(!WList.empty());
- return WList.back();
- }
+ class VirtualBugVisitor : public BugReporterVisitorImpl<VirtualBugVisitor> {
+ private:
+ const MemRegion *ObjectRegion;
+ bool Found;
- void Execute() {
- while (hasWork()) {
- WorkListUnit WLUnit = Dequeue();
- const FunctionDecl *FD = WLUnit->getDirectCallee();
- assert(FD && FD->getBody());
+ public:
+ VirtualBugVisitor(const MemRegion *R) : ObjectRegion(R), Found(false) {}
- if (VisitedFunctions[FD] == PreVisited) {
- // If the callee is PreVisited, walk its body.
- // Visit the body.
- SaveAndRestore<const CallExpr *> SaveCall(visitingCallExpr, WLUnit);
- Visit(FD->getBody());
+ void Profile(llvm::FoldingSetNodeID &ID) const override {
+ static int X = 0;
+ ID.AddPointer(&X);
+ ID.AddPointer(ObjectRegion);
+ }
- // Mark the function as being PostVisited to indicate we have
- // scanned the body.
- VisitedFunctions[FD] = PostVisited;
- continue;
- }
+ std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR) override;
+ };
+};
+} // end namespace
- // Otherwise, the callee is PostVisited.
- // Remove it from the worklist.
- assert(VisitedFunctions[FD] == PostVisited);
- WList.pop_back();
- }
- }
+// GDM (generic data map) to the memregion of this for the ctor and dtor.
+REGISTER_MAP_WITH_PROGRAMSTATE(CtorDtorMap, const MemRegion *, ObjectState)
- // Stmt visitor methods.
- void VisitCallExpr(CallExpr *CE);
- void VisitCXXMemberCallExpr(CallExpr *CE);
- void VisitStmt(Stmt *S) { VisitChildren(S); }
- void VisitChildren(Stmt *S);
+std::shared_ptr<PathDiagnosticPiece>
+VirtualCallChecker::VirtualBugVisitor::VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR) {
+ // We need the last ctor/dtor which call the virtual function.
+ // The visitor walks the ExplodedGraph backwards.
+ if (Found)
+ return nullptr;
- void ReportVirtualCall(const CallExpr *CE, bool isPure);
+ ProgramStateRef State = N->getState();
+ const LocationContext *LCtx = N->getLocationContext();
+ const CXXConstructorDecl *CD =
+ dyn_cast_or_null<CXXConstructorDecl>(LCtx->getDecl());
+ const CXXDestructorDecl *DD =
+ dyn_cast_or_null<CXXDestructorDecl>(LCtx->getDecl());
-};
-} // end anonymous namespace
+ if (!CD && !DD)
+ return nullptr;
-//===----------------------------------------------------------------------===//
-// AST walking.
-//===----------------------------------------------------------------------===//
+ ProgramStateManager &PSM = State->getStateManager();
+ auto &SVB = PSM.getSValBuilder();
+ const auto *MD = dyn_cast<CXXMethodDecl>(LCtx->getDecl());
+ if (!MD)
+ return nullptr;
+ auto ThiSVal =
+ State->getSVal(SVB.getCXXThis(MD, LCtx->getCurrentStackFrame()));
+ const MemRegion *Reg = ThiSVal.castAs<loc::MemRegionVal>().getRegion();
+ if (!Reg)
+ return nullptr;
+ if (Reg != ObjectRegion)
+ return nullptr;
-void WalkAST::VisitChildren(Stmt *S) {
- for (Stmt *Child : S->children())
- if (Child)
- Visit(Child);
-}
+ const Stmt *S = PathDiagnosticLocation::getStmt(N);
+ if (!S)
+ return nullptr;
+ Found = true;
+
+ std::string InfoText;
+ if (CD)
+ InfoText = "This constructor of an object of type '" +
+ CD->getNameAsString() +
+ "' has not returned when the virtual method was called";
+ else
+ InfoText = "This destructor of an object of type '" +
+ DD->getNameAsString() +
+ "' has not returned when the virtual method was called";
-void WalkAST::VisitCallExpr(CallExpr *CE) {
- VisitChildren(CE);
- if (IsInterprocedural)
- Enqueue(CE);
+ // Generate the extra diagnostic.
+ PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
+ N->getLocationContext());
+ return std::make_shared<PathDiagnosticEventPiece>(Pos, InfoText, true);
}
-void WalkAST::VisitCXXMemberCallExpr(CallExpr *CE) {
- VisitChildren(CE);
- bool callIsNonVirtual = false;
+// The function to check if a callexpr is a virtual function.
+static bool isVirtualCall(const CallExpr *CE) {
+ bool CallIsNonVirtual = false;
- // Several situations to elide for checking.
- if (MemberExpr *CME = dyn_cast<MemberExpr>(CE->getCallee())) {
- // If the member access is fully qualified (i.e., X::F), then treat
- // this as a non-virtual call and do not warn.
+ if (const MemberExpr *CME = dyn_cast<MemberExpr>(CE->getCallee())) {
+ // The member access is fully qualified (i.e., X::F).
+ // Treat this as a non-virtual call and do not warn.
if (CME->getQualifier())
- callIsNonVirtual = true;
-
- if (Expr *base = CME->getBase()->IgnoreImpCasts()) {
- // Elide analyzing the call entirely if the base pointer is not 'this'.
- if (!isa<CXXThisExpr>(base))
- return;
+ CallIsNonVirtual = true;
- // If the most derived class is marked final, we know that now subclass
- // can override this member.
- if (base->getBestDynamicClassType()->hasAttr<FinalAttr>())
- callIsNonVirtual = true;
+ if (const Expr *Base = CME->getBase()) {
+ // The most derived class is marked final.
+ if (Base->getBestDynamicClassType()->hasAttr<FinalAttr>())
+ CallIsNonVirtual = true;
}
}
- // Get the callee.
const CXXMethodDecl *MD =
dyn_cast_or_null<CXXMethodDecl>(CE->getDirectCallee());
- if (MD && MD->isVirtual() && !callIsNonVirtual && !MD->hasAttr<FinalAttr>() &&
+ if (MD && MD->isVirtual() && !CallIsNonVirtual && !MD->hasAttr<FinalAttr>() &&
!MD->getParent()->hasAttr<FinalAttr>())
- ReportVirtualCall(CE, MD->isPure());
+ return true;
+ return false;
+}
- if (IsInterprocedural)
- Enqueue(CE);
+// The BeginFunction callback when enter a constructor or a destructor.
+void VirtualCallChecker::checkBeginFunction(CheckerContext &C) const {
+ registerCtorDtorCallInState(true, C);
}
-void WalkAST::ReportVirtualCall(const CallExpr *CE, bool isPure) {
- if (ReportPureOnly && !isPure)
+// The EndFunction callback when leave a constructor or a destructor.
+void VirtualCallChecker::checkEndFunction(CheckerContext &C) const {
+ registerCtorDtorCallInState(false, C);
+}
+
+void VirtualCallChecker::checkPreCall(const CallEvent &Call,
+ CheckerContext &C) const {
+ const auto MC = dyn_cast<CXXMemberCall>(&Call);
+ if (!MC)
return;
- SmallString<100> buf;
- llvm::raw_svector_ostream os(buf);
+ const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(Call.getDecl());
+ if (!MD)
+ return;
+ ProgramStateRef State = C.getState();
+ const CallExpr *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr());
- // FIXME: The interprocedural diagnostic experience here is not good.
- // Ultimately this checker should be re-written to be path sensitive.
- // For now, only diagnose intraprocedurally, by default.
- if (IsInterprocedural) {
- os << "Call Path : ";
- // Name of current visiting CallExpr.
- os << *CE->getDirectCallee();
+ if (IsPureOnly && !MD->isPure())
+ return;
+ if (!isVirtualCall(CE))
+ return;
- // Name of the CallExpr whose body is current being walked.
- if (visitingCallExpr)
- os << " <-- " << *visitingCallExpr->getDirectCallee();
- // Names of FunctionDecls in worklist with state PostVisited.
- for (SmallVectorImpl<const CallExpr *>::iterator I = WList.end(),
- E = WList.begin(); I != E; --I) {
- const FunctionDecl *FD = (*(I-1))->getDirectCallee();
- assert(FD);
- if (VisitedFunctions[FD] == PostVisited)
- os << " <-- " << *FD;
- }
+ const MemRegion *Reg = MC->getCXXThisVal().getAsRegion();
+ const ObjectState *ObState = State->get<CtorDtorMap>(Reg);
+ if (!ObState)
+ return;
+ // Check if a virtual method is called.
+ // The GDM of constructor and destructor should be true.
+ if (*ObState == ObjectState::CtorCalled) {
+ if (IsPureOnly && MD->isPure())
+ reportBug("Call to pure virtual function during construction", true, Reg,
+ C);
+ else if (!MD->isPure())
+ reportBug("Call to virtual function during construction", false, Reg, C);
+ else
+ reportBug("Call to pure virtual function during construction", false, Reg,
+ C);
+ }
- os << "\n";
+ if (*ObState == ObjectState::DtorCalled) {
+ if (IsPureOnly && MD->isPure())
+ reportBug("Call to pure virtual function during destruction", true, Reg,
+ C);
+ else if (!MD->isPure())
+ reportBug("Call to virtual function during destruction", false, Reg, C);
+ else
+ reportBug("Call to pure virtual function during construction", false, Reg,
+ C);
}
+}
- PathDiagnosticLocation CELoc =
- PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
- SourceRange R = CE->getCallee()->getSourceRange();
+void VirtualCallChecker::registerCtorDtorCallInState(bool IsBeginFunction,
+ CheckerContext &C) const {
+ const auto *LCtx = C.getLocationContext();
+ const auto *MD = dyn_cast_or_null<CXXMethodDecl>(LCtx->getDecl());
+ if (!MD)
+ return;
- os << "Call to ";
- if (isPure)
- os << "pure ";
+ ProgramStateRef State = C.getState();
+ auto &SVB = C.getSValBuilder();
- os << "virtual function during ";
+ // Enter a constructor, set the corresponding memregion be true.
+ if (isa<CXXConstructorDecl>(MD)) {
+ auto ThiSVal =
+ State->getSVal(SVB.getCXXThis(MD, LCtx->getCurrentStackFrame()));
+ const MemRegion *Reg = ThiSVal.getAsRegion();
+ if (IsBeginFunction)
+ State = State->set<CtorDtorMap>(Reg, ObjectState::CtorCalled);
+ else
+ State = State->remove<CtorDtorMap>(Reg);
- if (isa<CXXConstructorDecl>(RootMethod))
- os << "construction ";
- else
- os << "destruction ";
+ C.addTransition(State);
+ return;
+ }
- if (isPure)
- os << "has undefined behavior";
- else
- os << "will not dispatch to derived class";
+ // Enter a Destructor, set the corresponding memregion be true.
+ if (isa<CXXDestructorDecl>(MD)) {
+ auto ThiSVal =
+ State->getSVal(SVB.getCXXThis(MD, LCtx->getCurrentStackFrame()));
+ const MemRegion *Reg = ThiSVal.getAsRegion();
+ if (IsBeginFunction)
+ State = State->set<CtorDtorMap>(Reg, ObjectState::DtorCalled);
+ else
+ State = State->remove<CtorDtorMap>(Reg);
- BR.EmitBasicReport(AC->getDecl(), Checker,
- "Call to virtual function during construction or "
- "destruction",
- "C++ Object Lifecycle", os.str(), CELoc, R);
+ C.addTransition(State);
+ return;
+ }
}
-//===----------------------------------------------------------------------===//
-// VirtualCallChecker
-//===----------------------------------------------------------------------===//
-
-namespace {
-class VirtualCallChecker : public Checker<check::ASTDecl<CXXRecordDecl> > {
-public:
- DefaultBool isInterprocedural;
- DefaultBool isPureOnly;
-
- void checkASTDecl(const CXXRecordDecl *RD, AnalysisManager& mgr,
- BugReporter &BR) const {
- AnalysisDeclContext *ADC = mgr.getAnalysisDeclContext(RD);
+void VirtualCallChecker::reportBug(StringRef Msg, bool IsSink,
+ const MemRegion *Reg,
+ CheckerContext &C) const {
+ ExplodedNode *N;
+ if (IsSink)
+ N = C.generateErrorNode();
+ else
+ N = C.generateNonFatalErrorNode();
- // Check the constructors.
- for (const auto *I : RD->ctors()) {
- if (!I->isCopyOrMoveConstructor())
- if (Stmt *Body = I->getBody()) {
- WalkAST walker(this, BR, ADC, I, isInterprocedural, isPureOnly);
- walker.Visit(Body);
- walker.Execute();
- }
- }
+ if (!N)
+ return;
+ if (!BT)
+ BT.reset(new BugType(
+ this, "Call to virtual function during construction or destruction",
+ "C++ Object Lifecycle"));
- // Check the destructor.
- if (CXXDestructorDecl *DD = RD->getDestructor())
- if (Stmt *Body = DD->getBody()) {
- WalkAST walker(this, BR, ADC, DD, isInterprocedural, isPureOnly);
- walker.Visit(Body);
- walker.Execute();
- }
- }
-};
+ auto Reporter = llvm::make_unique<BugReport>(*BT, Msg, N);
+ Reporter->addVisitor(llvm::make_unique<VirtualBugVisitor>(Reg));
+ C.emitReport(std::move(Reporter));
}
void ento::registerVirtualCallChecker(CheckerManager &mgr) {
VirtualCallChecker *checker = mgr.registerChecker<VirtualCallChecker>();
- checker->isInterprocedural =
- mgr.getAnalyzerOptions().getBooleanOption("Interprocedural", false,
- checker);
- checker->isPureOnly =
- mgr.getAnalyzerOptions().getBooleanOption("PureOnly", false,
- checker);
+ checker->IsPureOnly =
+ mgr.getAnalyzerOptions().getBooleanOption("PureOnly", false, checker);
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp
index 83e67662e614c..1cc08f0d9fe75 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp
@@ -14,30 +14,25 @@ using namespace ento;
void AnalysisManager::anchor() { }
-AnalysisManager::AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags,
- const LangOptions &lang,
- const PathDiagnosticConsumers &PDC,
- StoreManagerCreator storemgr,
- ConstraintManagerCreator constraintmgr,
- CheckerManager *checkerMgr,
- AnalyzerOptions &Options,
- CodeInjector *injector)
- : AnaCtxMgr(Options.UnoptimizedCFG,
- Options.includeImplicitDtorsInCFG(),
- /*AddInitializers=*/true,
- Options.includeTemporaryDtorsInCFG(),
- Options.includeLifetimeInCFG(),
- Options.shouldSynthesizeBodies(),
- Options.shouldConditionalizeStaticInitializers(),
- /*addCXXNewAllocator=*/true,
- injector),
- Ctx(ctx),
- Diags(diags),
- LangOpts(lang),
- PathConsumers(PDC),
- CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr),
- CheckerMgr(checkerMgr),
- options(Options) {
+AnalysisManager::AnalysisManager(
+ ASTContext &ASTCtx, DiagnosticsEngine &diags, const LangOptions &lang,
+ const PathDiagnosticConsumers &PDC, StoreManagerCreator storemgr,
+ ConstraintManagerCreator constraintmgr, CheckerManager *checkerMgr,
+ AnalyzerOptions &Options, CodeInjector *injector)
+ : AnaCtxMgr(ASTCtx, Options.UnoptimizedCFG,
+ Options.includeImplicitDtorsInCFG(),
+ /*AddInitializers=*/true, Options.includeTemporaryDtorsInCFG(),
+ Options.includeLifetimeInCFG(),
+ // Adding LoopExit elements to the CFG is a requirement for loop
+ // unrolling.
+ Options.includeLoopExitInCFG() || Options.shouldUnrollLoops(),
+ Options.shouldSynthesizeBodies(),
+ Options.shouldConditionalizeStaticInitializers(),
+ /*addCXXNewAllocator=*/true,
+ injector),
+ Ctx(ASTCtx), Diags(diags), LangOpts(lang), PathConsumers(PDC),
+ CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr),
+ CheckerMgr(checkerMgr), options(Options) {
AnaCtxMgr.getCFGBuildOptions().setAllAlwaysAdd();
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
index 6f48fcb9e20ce..48e3e22af04ab 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
@@ -183,6 +183,11 @@ bool AnalyzerOptions::includeLifetimeInCFG() {
/* Default = */ false);
}
+bool AnalyzerOptions::includeLoopExitInCFG() {
+ return getBooleanOption(IncludeLoopExitInCFG, "cfg-loopexit",
+ /* Default = */ false);
+}
+
bool AnalyzerOptions::mayInlineCXXStandardLibrary() {
return getBooleanOption(InlineCXXStandardLibrary,
"c++-stdlib-inlining",
@@ -375,6 +380,12 @@ bool AnalyzerOptions::shouldWidenLoops() {
return WidenLoops.getValue();
}
+bool AnalyzerOptions::shouldUnrollLoops() {
+ if (!UnrollLoops.hasValue())
+ UnrollLoops = getBooleanOption("unroll-loops", /*Default=*/false);
+ return UnrollLoops.getValue();
+}
+
bool AnalyzerOptions::shouldDisplayNotesAsEvents() {
if (!DisplayNotesAsEvents.hasValue())
DisplayNotesAsEvents =
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
index ebbace4e33b38..ec7a7e9e4b1c8 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
@@ -225,6 +225,8 @@ BasicValueFactory::evalAPSInt(BinaryOperator::Opcode Op,
// test these conditions symbolically.
// FIXME: Expand these checks to include all undefined behavior.
+ if (V1.isSigned() && V1.isNegative())
+ return nullptr;
if (V2.isSigned() && V2.isNegative())
return nullptr;
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
index d8fca00681b4d..4a5d25fc56345 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -3310,6 +3310,78 @@ static const CFGBlock *findBlockForNode(const ExplodedNode *N) {
return nullptr;
}
+// Returns true if by simply looking at the block, we can be sure that it
+// results in a sink during analysis. This is useful to know when the analysis
+// was interrupted, and we try to figure out if it would sink eventually.
+// There may be many more reasons why a sink would appear during analysis
+// (eg. checkers may generate sinks arbitrarily), but here we only consider
+// sinks that would be obvious by looking at the CFG.
+static bool isImmediateSinkBlock(const CFGBlock *Blk) {
+ if (Blk->hasNoReturnElement())
+ return true;
+
+ // FIXME: Throw-expressions are currently generating sinks during analysis:
+ // they're not supported yet, and also often used for actually terminating
+ // the program. So we should treat them as sinks in this analysis as well,
+ // at least for now, but once we have better support for exceptions,
+ // we'd need to carefully handle the case when the throw is being
+ // immediately caught.
+ if (std::any_of(Blk->begin(), Blk->end(), [](const CFGElement &Elm) {
+ if (Optional<CFGStmt> StmtElm = Elm.getAs<CFGStmt>())
+ if (isa<CXXThrowExpr>(StmtElm->getStmt()))
+ return true;
+ return false;
+ }))
+ return true;
+
+ return false;
+}
+
+// Returns true if by looking at the CFG surrounding the node's program
+// point, we can be sure that any analysis starting from this point would
+// eventually end with a sink. We scan the child CFG blocks in a depth-first
+// manner and see if all paths eventually end up in an immediate sink block.
+static bool isInevitablySinking(const ExplodedNode *N) {
+ const CFG &Cfg = N->getCFG();
+
+ const CFGBlock *StartBlk = findBlockForNode(N);
+ if (!StartBlk)
+ return false;
+ if (isImmediateSinkBlock(StartBlk))
+ return true;
+
+ llvm::SmallVector<const CFGBlock *, 32> DFSWorkList;
+ llvm::SmallPtrSet<const CFGBlock *, 32> Visited;
+
+ DFSWorkList.push_back(StartBlk);
+ while (!DFSWorkList.empty()) {
+ const CFGBlock *Blk = DFSWorkList.back();
+ DFSWorkList.pop_back();
+ Visited.insert(Blk);
+
+ for (const auto &Succ : Blk->succs()) {
+ if (const CFGBlock *SuccBlk = Succ.getReachableBlock()) {
+ if (SuccBlk == &Cfg.getExit()) {
+ // If at least one path reaches the CFG exit, it means that control is
+ // returned to the caller. For now, say that we are not sure what
+ // happens next. If necessary, this can be improved to analyze
+ // the parent StackFrameContext's call site in a similar manner.
+ return false;
+ }
+
+ if (!isImmediateSinkBlock(SuccBlk) && !Visited.count(SuccBlk)) {
+ // If the block has reachable child blocks that aren't no-return,
+ // add them to the worklist.
+ DFSWorkList.push_back(SuccBlk);
+ }
+ }
+ }
+ }
+
+ // Nothing reached the exit. It can only mean one thing: there's no return.
+ return true;
+}
+
static BugReport *
FindReportInEquivalenceClass(BugReportEquivClass& EQ,
SmallVectorImpl<BugReport*> &bugReports) {
@@ -3360,15 +3432,10 @@ FindReportInEquivalenceClass(BugReportEquivClass& EQ,
// See if we are in a no-return CFG block. If so, treat this similarly
// to being post-dominated by a sink. This works better when the analysis
- // is incomplete and we have never reached a no-return function
- // we're post-dominated by.
- // This is not quite enough to handle the incomplete analysis case.
- // We may be post-dominated in subsequent blocks, or even
- // inter-procedurally. However, it is not clear if more complicated
- // cases are generally worth suppressing.
- if (const CFGBlock *B = findBlockForNode(errorNode))
- if (B->hasNoReturnElement())
- continue;
+ // is incomplete and we have never reached the no-return function call(s)
+ // that we'd inevitably bump into on this path.
+ if (isInevitablySinking(errorNode))
+ continue;
// At this point we know that 'N' is not a sink and it has at least one
// successor. Use a DFS worklist to find a non-sink end-of-path node.
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index d00182a871c1e..7304d789431ee 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -11,7 +11,7 @@
// enhance the diagnostics reported for a bug.
//
//===----------------------------------------------------------------------===//
-#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Analysis/CFGStmtMap.h"
@@ -42,48 +42,80 @@ bool bugreporter::isDeclRefExprToReference(const Expr *E) {
return false;
}
+/// Given that expression S represents a pointer that would be dereferenced,
+/// try to find a sub-expression from which the pointer came from.
+/// This is used for tracking down origins of a null or undefined value:
+/// "this is null because that is null because that is null" etc.
+/// We wipe away field and element offsets because they merely add offsets.
+/// We also wipe away all casts except lvalue-to-rvalue casts, because the
+/// latter represent an actual pointer dereference; however, we remove
+/// the final lvalue-to-rvalue cast before returning from this function
+/// because it demonstrates more clearly from where the pointer rvalue was
+/// loaded. Examples:
+/// x->y.z ==> x (lvalue)
+/// foo()->y.z ==> foo() (rvalue)
const Expr *bugreporter::getDerefExpr(const Stmt *S) {
- // Pattern match for a few useful cases:
- // a[0], p->f, *p
const Expr *E = dyn_cast<Expr>(S);
if (!E)
return nullptr;
- E = E->IgnoreParenCasts();
while (true) {
- if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E)) {
- assert(B->isAssignmentOp());
- E = B->getLHS()->IgnoreParenCasts();
- continue;
- }
- else if (const UnaryOperator *U = dyn_cast<UnaryOperator>(E)) {
- if (U->getOpcode() == UO_Deref)
- return U->getSubExpr()->IgnoreParenCasts();
- }
- else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
- if (ME->isImplicitAccess()) {
- return ME;
- } else if (ME->isArrow() || isDeclRefExprToReference(ME->getBase())) {
- return ME->getBase()->IgnoreParenCasts();
+ if (const CastExpr *CE = dyn_cast<CastExpr>(E)) {
+ if (CE->getCastKind() == CK_LValueToRValue) {
+ // This cast represents the load we're looking for.
+ break;
+ }
+ E = CE->getSubExpr();
+ } else if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E)) {
+ // Pointer arithmetic: '*(x + 2)' -> 'x') etc.
+ if (B->getType()->isPointerType()) {
+ if (B->getLHS()->getType()->isPointerType()) {
+ E = B->getLHS();
+ } else if (B->getRHS()->getType()->isPointerType()) {
+ E = B->getRHS();
+ } else {
+ break;
+ }
} else {
- // If we have a member expr with a dot, the base must have been
- // dereferenced.
- return getDerefExpr(ME->getBase());
+ // Probably more arithmetic can be pattern-matched here,
+ // but for now give up.
+ break;
+ }
+ } else if (const UnaryOperator *U = dyn_cast<UnaryOperator>(E)) {
+ if (U->getOpcode() == UO_Deref || U->getOpcode() == UO_AddrOf ||
+ (U->isIncrementDecrementOp() && U->getType()->isPointerType())) {
+ // Operators '*' and '&' don't actually mean anything.
+ // We look at casts instead.
+ E = U->getSubExpr();
+ } else {
+ // Probably more arithmetic can be pattern-matched here,
+ // but for now give up.
+ break;
}
}
- else if (const ObjCIvarRefExpr *IvarRef = dyn_cast<ObjCIvarRefExpr>(E)) {
- return IvarRef->getBase()->IgnoreParenCasts();
- }
- else if (const ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(E)) {
- return getDerefExpr(AE->getBase());
- }
- else if (isa<DeclRefExpr>(E)) {
- return E;
+ // Pattern match for a few useful cases: a[0], p->f, *p etc.
+ else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
+ E = ME->getBase();
+ } else if (const ObjCIvarRefExpr *IvarRef = dyn_cast<ObjCIvarRefExpr>(E)) {
+ E = IvarRef->getBase();
+ } else if (const ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(E)) {
+ E = AE->getBase();
+ } else if (const ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
+ E = PE->getSubExpr();
+ } else {
+ // Other arbitrary stuff.
+ break;
}
- break;
}
- return nullptr;
+ // Special case: remove the final lvalue-to-rvalue cast, but do not recurse
+ // deeper into the sub-expression. This way we return the lvalue from which
+ // our pointer rvalue was loaded.
+ if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E))
+ if (CE->getCastKind() == CK_LValueToRValue)
+ E = CE->getSubExpr();
+
+ return E;
}
const Stmt *bugreporter::GetDenomExpr(const ExplodedNode *N) {
@@ -1509,7 +1541,7 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond, const BinaryOperator *BExpr,
// For non-assignment operations, we require that we can understand
// both the LHS and RHS.
if (LhsString.empty() || RhsString.empty() ||
- !BinaryOperator::isComparisonOp(Op))
+ !BinaryOperator::isComparisonOp(Op) || Op == BO_Cmp)
return nullptr;
// Should we invert the strings if the LHS is not a variable name?
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CallEvent.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
index 1858bfd89637e..776369be9dbaa 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -21,6 +21,9 @@
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Debug.h"
+
+#define DEBUG_TYPE "static-analyzer-call-event"
using namespace clang;
using namespace ento;
@@ -97,9 +100,6 @@ bool CallEvent::hasNonNullArgumentsWithType(bool (*Condition)(QualType)) const {
for (CallEvent::param_type_iterator I = param_type_begin(),
E = param_type_end();
I != E && Idx < NumOfArgs; ++I, ++Idx) {
- if (NumOfArgs <= Idx)
- break;
-
// If the parameter is 0, it's harmless.
if (getArgSVal(Idx).isZeroConstant())
continue;
@@ -211,7 +211,9 @@ ProgramPoint CallEvent::getProgramPoint(bool IsPreVisit,
}
bool CallEvent::isCalled(const CallDescription &CD) const {
- assert(getKind() != CE_ObjCMessage && "Obj-C methods are not supported");
+ // FIXME: Add ObjC Message support.
+ if (getKind() == CE_ObjCMessage)
+ return false;
if (!CD.IsLookupDone) {
CD.IsLookupDone = true;
CD.II = &getState()->getStateManager().getContext().Idents.get(CD.FuncName);
@@ -346,6 +348,30 @@ ArrayRef<ParmVarDecl*> AnyFunctionCall::parameters() const {
return D->parameters();
}
+RuntimeDefinition AnyFunctionCall::getRuntimeDefinition() const {
+ const FunctionDecl *FD = getDecl();
+ // Note that the AnalysisDeclContext will have the FunctionDecl with
+ // the definition (if one exists).
+ if (FD) {
+ AnalysisDeclContext *AD =
+ getLocationContext()->getAnalysisDeclContext()->
+ getManager()->getContext(FD);
+ bool IsAutosynthesized;
+ Stmt* Body = AD->getBody(IsAutosynthesized);
+ DEBUG({
+ if (IsAutosynthesized)
+ llvm::dbgs() << "Using autosynthesized body for " << FD->getName()
+ << "\n";
+ });
+ if (Body) {
+ const Decl* Decl = AD->getDecl();
+ return RuntimeDefinition(Decl);
+ }
+ }
+
+ return RuntimeDefinition();
+}
+
void AnyFunctionCall::getInitialStackFrameContents(
const StackFrameContext *CalleeCtx,
BindingsTy &Bindings) const {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp
index 548b06ef91fce..61cbf3854bb21 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp
@@ -99,3 +99,35 @@ StringRef CheckerContext::getMacroNameOrSpelling(SourceLocation &Loc) {
return Lexer::getSpelling(Loc, buf, getSourceManager(), getLangOpts());
}
+/// Evaluate comparison and return true if it's known that condition is true
+static bool evalComparison(SVal LHSVal, BinaryOperatorKind ComparisonOp,
+ SVal RHSVal, ProgramStateRef State) {
+ if (LHSVal.isUnknownOrUndef())
+ return false;
+ ProgramStateManager &Mgr = State->getStateManager();
+ if (!LHSVal.getAs<NonLoc>()) {
+ LHSVal = Mgr.getStoreManager().getBinding(State->getStore(),
+ LHSVal.castAs<Loc>());
+ if (LHSVal.isUnknownOrUndef() || !LHSVal.getAs<NonLoc>())
+ return false;
+ }
+
+ SValBuilder &Bldr = Mgr.getSValBuilder();
+ SVal Eval = Bldr.evalBinOp(State, ComparisonOp, LHSVal, RHSVal,
+ Bldr.getConditionType());
+ if (Eval.isUnknownOrUndef())
+ return false;
+ ProgramStateRef StTrue, StFalse;
+ std::tie(StTrue, StFalse) = State->assume(Eval.castAs<DefinedSVal>());
+ return StTrue && !StFalse;
+}
+
+bool CheckerContext::isGreaterOrEqual(const Expr *E, unsigned long long Val) {
+ DefinedSVal V = getSValBuilder().makeIntVal(Val, getASTContext().LongLongTy);
+ return evalComparison(getSVal(E), BO_GE, V, getState());
+}
+
+bool CheckerContext::isNegative(const Expr *E) {
+ DefinedSVal V = getSValBuilder().makeIntVal(0, false);
+ return evalComparison(getSVal(E), BO_LT, V, getState());
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
index 4e2866c56f0ee..e2e9ddf5048eb 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
@@ -274,7 +274,8 @@ void CoreEngine::dispatchWorkItem(ExplodedNode* Pred, ProgramPoint Loc,
assert(Loc.getAs<PostStmt>() ||
Loc.getAs<PostInitializer>() ||
Loc.getAs<PostImplicitCall>() ||
- Loc.getAs<CallExitEnd>());
+ Loc.getAs<CallExitEnd>() ||
+ Loc.getAs<LoopExit>());
HandlePostStmt(WU.getBlock(), WU.getIndex(), Pred);
break;
}
@@ -566,7 +567,8 @@ void CoreEngine::enqueueStmtNode(ExplodedNode *N,
// Do not create extra nodes. Move to the next CFG element.
if (N->getLocation().getAs<PostInitializer>() ||
- N->getLocation().getAs<PostImplicitCall>()) {
+ N->getLocation().getAs<PostImplicitCall>()||
+ N->getLocation().getAs<LoopExit>()) {
WList->enqueue(N, Block, Idx+1);
return;
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp
index e2cb52cb417e2..c6acb9d1851ce 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp
@@ -13,7 +13,7 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
-#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "llvm/Support/raw_ostream.h"
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index eee5400fe1771..3be37e7ae301c 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -17,6 +17,7 @@
#include "PrettyStackTraceLocationContext.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/ParentMap.h"
+#include "clang/Analysis/CFGStmtMap.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/Basic/Builtins.h"
@@ -27,6 +28,7 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/raw_ostream.h"
@@ -362,6 +364,9 @@ void ExprEngine::processCFGElement(const CFGElement E, ExplodedNode *Pred,
case CFGElement::TemporaryDtor:
ProcessImplicitDtor(E.castAs<CFGImplicitDtor>(), Pred);
return;
+ case CFGElement::LoopExit:
+ ProcessLoopExit(E.castAs<CFGLoopExit>().getLoopStmt(), Pred);
+ return;
case CFGElement::LifetimeEnds:
return;
}
@@ -507,6 +512,24 @@ void ExprEngine::ProcessStmt(const CFGStmt S,
Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
}
+void ExprEngine::ProcessLoopExit(const Stmt* S, ExplodedNode *Pred) {
+ PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
+ S->getLocStart(),
+ "Error evaluating end of the loop");
+ ExplodedNodeSet Dst;
+ Dst.Add(Pred);
+ NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
+ ProgramStateRef NewState = Pred->getState();
+
+ if(AMgr.options.shouldUnrollLoops())
+ NewState = processLoopEnd(S, NewState);
+
+ LoopExit PP(S, Pred->getLocationContext());
+ Bldr.generateNode(PP, NewState, Pred);
+ // Enqueue the new nodes onto the work list.
+ Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
+}
+
void ExprEngine::ProcessInitializer(const CFGInitializer Init,
ExplodedNode *Pred) {
const CXXCtorInitializer *BMI = Init.getInitializer();
@@ -804,6 +827,21 @@ void ExprEngine::VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE,
}
}
+namespace {
+class CollectReachableSymbolsCallback final : public SymbolVisitor {
+ InvalidatedSymbols Symbols;
+
+public:
+ explicit CollectReachableSymbolsCallback(ProgramStateRef State) {}
+ const InvalidatedSymbols &getSymbols() const { return Symbols; }
+
+ bool VisitSymbol(SymbolRef Sym) override {
+ Symbols.insert(Sym);
+ return true;
+ }
+};
+} // end anonymous namespace
+
void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
ExplodedNodeSet &DstTop) {
PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
@@ -1080,8 +1118,29 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
SVal result = svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx,
resultType,
currBldrCtx->blockCount());
- ProgramStateRef state = N->getState()->BindExpr(Ex, LCtx, result);
- Bldr2.generateNode(S, N, state);
+ ProgramStateRef State = N->getState()->BindExpr(Ex, LCtx, result);
+
+ // Escape pointers passed into the list, unless it's an ObjC boxed
+ // expression which is not a boxable C structure.
+ if (!(isa<ObjCBoxedExpr>(Ex) &&
+ !cast<ObjCBoxedExpr>(Ex)->getSubExpr()
+ ->getType()->isRecordType()))
+ for (auto Child : Ex->children()) {
+ assert(Child);
+
+ SVal Val = State->getSVal(Child, LCtx);
+
+ CollectReachableSymbolsCallback Scanner =
+ State->scanReachableSymbols<CollectReachableSymbolsCallback>(
+ Val);
+ const InvalidatedSymbols &EscapedSymbols = Scanner.getSymbols();
+
+ State = getCheckerManager().runCheckersForPointerEscape(
+ State, EscapedSymbols,
+ /*CallEvent*/ nullptr, PSK_EscapeOther, nullptr);
+ }
+
+ Bldr2.generateNode(S, N, State);
}
getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this);
@@ -1091,7 +1150,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::ArraySubscriptExprClass:
Bldr.takeNodes(Pred);
- VisitLvalArraySubscriptExpr(cast<ArraySubscriptExpr>(S), Pred, Dst);
+ VisitArraySubscriptExpr(cast<ArraySubscriptExpr>(S), Pred, Dst);
Bldr.addNodes(Dst);
break;
@@ -1497,6 +1556,25 @@ void ExprEngine::processCFGBlockEntrance(const BlockEdge &L,
NodeBuilderWithSinks &nodeBuilder,
ExplodedNode *Pred) {
PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
+ // If we reach a loop which has a known bound (and meets
+ // other constraints) then consider completely unrolling it.
+ if(AMgr.options.shouldUnrollLoops()) {
+ unsigned maxBlockVisitOnPath = AMgr.options.maxBlockVisitOnPath;
+ const Stmt *Term = nodeBuilder.getContext().getBlock()->getTerminator();
+ if (Term) {
+ ProgramStateRef NewState = updateLoopStack(Term, AMgr.getASTContext(),
+ Pred, maxBlockVisitOnPath);
+ if (NewState != Pred->getState()) {
+ ExplodedNode *UpdatedNode = nodeBuilder.generateNode(NewState, Pred);
+ if (!UpdatedNode)
+ return;
+ Pred = UpdatedNode;
+ }
+ }
+ // Is we are inside an unrolled loop then no need the check the counters.
+ if(isUnrolledState(Pred->getState()))
+ return;
+ }
// If this block is terminated by a loop and it has already been visited the
// maximum number of times, widen the loop.
@@ -2030,10 +2108,12 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
ProgramPoint::PostLValueKind);
return;
}
- if (isa<FieldDecl>(D)) {
+ if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D)) {
// FIXME: Compute lvalue of field pointers-to-member.
// Right now we just use a non-null void pointer, so that it gives proper
// results in boolean contexts.
+ // FIXME: Maybe delegate this to the surrounding operator&.
+ // Note how this expression is lvalue, however pointer-to-member is NonLoc.
SVal V = svalBuilder.conjureSymbolVal(Ex, LCtx, getContext().VoidPtrTy,
currBldrCtx->blockCount());
state = state->assume(V.castAs<DefinedOrUnknownSVal>(), true);
@@ -2046,10 +2126,9 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
}
/// VisitArraySubscriptExpr - Transfer function for array accesses
-void ExprEngine::VisitLvalArraySubscriptExpr(const ArraySubscriptExpr *A,
+void ExprEngine::VisitArraySubscriptExpr(const ArraySubscriptExpr *A,
ExplodedNode *Pred,
ExplodedNodeSet &Dst){
-
const Expr *Base = A->getBase()->IgnoreParens();
const Expr *Idx = A->getIdx()->IgnoreParens();
@@ -2058,18 +2137,32 @@ void ExprEngine::VisitLvalArraySubscriptExpr(const ArraySubscriptExpr *A,
ExplodedNodeSet EvalSet;
StmtNodeBuilder Bldr(CheckerPreStmt, EvalSet, *currBldrCtx);
- assert(A->isGLValue() ||
- (!AMgr.getLangOpts().CPlusPlus &&
- A->getType().isCForbiddenLValueType()));
+
+ bool IsVectorType = A->getBase()->getType()->isVectorType();
+
+ // The "like" case is for situations where C standard prohibits the type to
+ // be an lvalue, e.g. taking the address of a subscript of an expression of
+ // type "void *".
+ bool IsGLValueLike = A->isGLValue() ||
+ (A->getType().isCForbiddenLValueType() && !AMgr.getLangOpts().CPlusPlus);
for (auto *Node : CheckerPreStmt) {
const LocationContext *LCtx = Node->getLocationContext();
ProgramStateRef state = Node->getState();
- SVal V = state->getLValue(A->getType(),
- state->getSVal(Idx, LCtx),
- state->getSVal(Base, LCtx));
- Bldr.generateNode(A, Node, state->BindExpr(A, LCtx, V), nullptr,
- ProgramPoint::PostLValueKind);
+
+ if (IsGLValueLike) {
+ SVal V = state->getLValue(A->getType(),
+ state->getSVal(Idx, LCtx),
+ state->getSVal(Base, LCtx));
+ Bldr.generateNode(A, Node, state->BindExpr(A, LCtx, V), nullptr,
+ ProgramPoint::PostLValueKind);
+ } else if (IsVectorType) {
+ // FIXME: non-glvalue vector reads are not modelled.
+ Bldr.generateNode(A, Node, state, nullptr);
+ } else {
+ llvm_unreachable("Array subscript should be an lValue when not \
+a vector and not a forbidden lvalue type");
+ }
}
getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, A, *this);
@@ -2195,21 +2288,6 @@ void ExprEngine::VisitAtomicExpr(const AtomicExpr *AE, ExplodedNode *Pred,
getCheckerManager().runCheckersForPostStmt(Dst, AfterInvalidateSet, AE, *this);
}
-namespace {
-class CollectReachableSymbolsCallback final : public SymbolVisitor {
- InvalidatedSymbols Symbols;
-
-public:
- CollectReachableSymbolsCallback(ProgramStateRef State) {}
- const InvalidatedSymbols &getSymbols() const { return Symbols; }
-
- bool VisitSymbol(SymbolRef Sym) override {
- Symbols.insert(Sym);
- return true;
- }
-};
-} // end anonymous namespace
-
// A value escapes in three possible cases:
// (1) We are binding to something that is not a memory region.
// (2) We are binding to a MemrRegion that does not have stack storage.
@@ -2666,6 +2744,12 @@ struct DOTGraphTraits<ExplodedNode*> :
Out << "Epsilon Point";
break;
+ case ProgramPoint::LoopExitKind: {
+ LoopExit LE = Loc.castAs<LoopExit>();
+ Out << "LoopExit: " << LE.getLoopStmt()->getStmtClassName();
+ break;
+ }
+
case ProgramPoint::PreImplicitCallKind: {
ImplicitCallPoint PC = Loc.castAs<ImplicitCallPoint>();
Out << "PreCall: ";
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 6f1e8391e67cf..3e7a50365f50c 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -20,6 +20,24 @@ using namespace clang;
using namespace ento;
using llvm::APSInt;
+/// \brief Optionally conjure and return a symbol for offset when processing
+/// an expression \p Expression.
+/// If \p Other is a location, conjure a symbol for \p Symbol
+/// (offset) if it is unknown so that memory arithmetic always
+/// results in an ElementRegion.
+/// \p Count The number of times the current basic block was visited.
+static SVal conjureOffsetSymbolOnLocation(
+ SVal Symbol, SVal Other, Expr* Expression, SValBuilder &svalBuilder,
+ unsigned Count, const LocationContext *LCtx) {
+ QualType Ty = Expression->getType();
+ if (Other.getAs<Loc>() &&
+ Ty->isIntegralOrEnumerationType() &&
+ Symbol.isUnknown()) {
+ return svalBuilder.conjureSymbolVal(Expression, LCtx, Ty, Count);
+ }
+ return Symbol;
+}
+
void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
@@ -63,24 +81,13 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
StmtNodeBuilder Bldr(*it, Tmp2, *currBldrCtx);
if (B->isAdditiveOp()) {
- // If one of the operands is a location, conjure a symbol for the other
- // one (offset) if it's unknown so that memory arithmetic always
- // results in an ElementRegion.
// TODO: This can be removed after we enable history tracking with
// SymSymExpr.
unsigned Count = currBldrCtx->blockCount();
- if (LeftV.getAs<Loc>() &&
- RHS->getType()->isIntegralOrEnumerationType() &&
- RightV.isUnknown()) {
- RightV = svalBuilder.conjureSymbolVal(RHS, LCtx, RHS->getType(),
- Count);
- }
- if (RightV.getAs<Loc>() &&
- LHS->getType()->isIntegralOrEnumerationType() &&
- LeftV.isUnknown()) {
- LeftV = svalBuilder.conjureSymbolVal(LHS, LCtx, LHS->getType(),
- Count);
- }
+ RightV = conjureOffsetSymbolOnLocation(
+ RightV, LeftV, RHS, svalBuilder, Count, LCtx);
+ LeftV = conjureOffsetSymbolOnLocation(
+ LeftV, RightV, LHS, svalBuilder, Count, LCtx);
}
// Although we don't yet model pointers-to-members, we do need to make
@@ -92,12 +99,10 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
// Process non-assignments except commas or short-circuited
// logical expressions (LAnd and LOr).
SVal Result = evalBinOp(state, Op, LeftV, RightV, B->getType());
- if (Result.isUnknown()) {
- Bldr.generateNode(B, *it, state);
- continue;
+ if (!Result.isUnknown()) {
+ state = state->BindExpr(B, LCtx, Result);
}
- state = state->BindExpr(B, LCtx, Result);
Bldr.generateNode(B, *it, state);
continue;
}
@@ -530,7 +535,7 @@ void ExprEngine::VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL,
const Expr *Init = CL->getInitializer();
SVal V = State->getSVal(CL->getInitializer(), LCtx);
- if (isa<CXXConstructExpr>(Init)) {
+ if (isa<CXXConstructExpr>(Init) || isa<CXXStdInitializerListExpr>(Init)) {
// No work needed. Just pass the value up to this expression.
} else {
assert(isa<InitListExpr>(Init));
@@ -628,6 +633,16 @@ void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred,
StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
ProgramStateRef state = Pred->getState();
+ if (B->getType()->isVectorType()) {
+ // FIXME: We do not model vector arithmetic yet. When adding support for
+ // that, note that the CFG-based reasoning below does not apply, because
+ // logical operators on vectors are not short-circuit. Currently they are
+ // modeled as short-circuit in Clang CFG but this is incorrect.
+ // Do not set the value for the expression. It'd be UnknownVal by default.
+ Bldr.generateNode(B, Pred, state);
+ return;
+ }
+
ExplodedNode *N = Pred;
while (!N->getLocation().getAs<BlockEntrance>()) {
ProgramPoint P = N->getLocation();
@@ -1028,7 +1043,14 @@ void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U,
// Propagate unknown and undefined values.
if (V2_untested.isUnknownOrUndef()) {
- Bldr.generateNode(U, *I, state->BindExpr(U, LCtx, V2_untested));
+ state = state->BindExpr(U, LCtx, V2_untested);
+
+ // Perform the store, so that the uninitialized value detection happens.
+ Bldr.takeNodes(*I);
+ ExplodedNodeSet Dst3;
+ evalStore(Dst3, U, U, *I, state, loc, V2_untested);
+ Bldr.addNodes(Dst3);
+
continue;
}
DefinedSVal V2 = V2_untested.castAs<DefinedSVal>();
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
index f0f6dd2e43e78..9b820e81e374f 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
@@ -44,8 +44,12 @@ class HTMLDiagnostics : public PathDiagnosticConsumer {
bool createdDir, noDir;
const Preprocessor &PP;
AnalyzerOptions &AnalyzerOpts;
+ const bool SupportsCrossFileDiagnostics;
public:
- HTMLDiagnostics(AnalyzerOptions &AnalyzerOpts, const std::string& prefix, const Preprocessor &pp);
+ HTMLDiagnostics(AnalyzerOptions &AnalyzerOpts,
+ const std::string& prefix,
+ const Preprocessor &pp,
+ bool supportsMultipleFiles);
~HTMLDiagnostics() override { FlushDiagnostics(nullptr); }
@@ -56,6 +60,10 @@ public:
return "HTMLDiagnostics";
}
+ bool supportsCrossFileDiagnostics() const override {
+ return SupportsCrossFileDiagnostics;
+ }
+
unsigned ProcessMacroPiece(raw_ostream &os,
const PathDiagnosticMacroPiece& P,
unsigned num);
@@ -69,21 +77,47 @@ public:
void ReportDiag(const PathDiagnostic& D,
FilesMade *filesMade);
+
+ // Generate the full HTML report
+ std::string GenerateHTML(const PathDiagnostic& D, Rewriter &R,
+ const SourceManager& SMgr, const PathPieces& path,
+ const char *declName);
+
+ // Add HTML header/footers to file specified by FID
+ void FinalizeHTML(const PathDiagnostic& D, Rewriter &R,
+ const SourceManager& SMgr, const PathPieces& path,
+ FileID FID, const FileEntry *Entry, const char *declName);
+
+ // Rewrite the file specified by FID with HTML formatting.
+ void RewriteFile(Rewriter &R, const SourceManager& SMgr,
+ const PathPieces& path, FileID FID);
};
} // end anonymous namespace
HTMLDiagnostics::HTMLDiagnostics(AnalyzerOptions &AnalyzerOpts,
const std::string& prefix,
- const Preprocessor &pp)
- : Directory(prefix), createdDir(false), noDir(false), PP(pp), AnalyzerOpts(AnalyzerOpts) {
-}
+ const Preprocessor &pp,
+ bool supportsMultipleFiles)
+ : Directory(prefix),
+ createdDir(false),
+ noDir(false),
+ PP(pp),
+ AnalyzerOpts(AnalyzerOpts),
+ SupportsCrossFileDiagnostics(supportsMultipleFiles) {}
void ento::createHTMLDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,
PathDiagnosticConsumers &C,
const std::string& prefix,
const Preprocessor &PP) {
- C.push_back(new HTMLDiagnostics(AnalyzerOpts, prefix, PP));
+ C.push_back(new HTMLDiagnostics(AnalyzerOpts, prefix, PP, true));
+}
+
+void ento::createHTMLSingleFileDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,
+ PathDiagnosticConsumers &C,
+ const std::string& prefix,
+ const Preprocessor &PP) {
+ C.push_back(new HTMLDiagnostics(AnalyzerOpts, prefix, PP, false));
}
//===----------------------------------------------------------------------===//
@@ -121,24 +155,24 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
// First flatten out the entire path to make it easier to use.
PathPieces path = D.path.flatten(/*ShouldFlattenMacros=*/false);
- // The path as already been prechecked that all parts of the path are
- // from the same file and that it is non-empty.
- const SourceManager &SMgr = path.front()->getLocation().getManager();
+ // The path as already been prechecked that the path is non-empty.
assert(!path.empty());
- FileID FID =
- path.front()->getLocation().asLocation().getExpansionLoc().getFileID();
- assert(FID.isValid());
+ const SourceManager &SMgr = path.front()->getLocation().getManager();
// Create a new rewriter to generate HTML.
Rewriter R(const_cast<SourceManager&>(SMgr), PP.getLangOpts());
+ // The file for the first path element is considered the main report file, it
+ // will usually be equivalent to SMgr.getMainFileID(); however, it might be a
+ // header when -analyzer-opt-analyze-headers is used.
+ FileID ReportFile = path.front()->getLocation().asLocation().getExpansionLoc().getFileID();
+
// Get the function/method name
SmallString<128> declName("unknown");
int offsetDecl = 0;
if (const Decl *DeclWithIssue = D.getDeclWithIssue()) {
- if (const NamedDecl *ND = dyn_cast<NamedDecl>(DeclWithIssue)) {
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(DeclWithIssue))
declName = ND->getDeclName().getAsString();
- }
if (const Stmt *Body = DeclWithIssue->getBody()) {
// Retrieve the relative position of the declaration which will be used
@@ -151,49 +185,144 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
}
}
- // Process the path.
- // Maintain the counts of extra note pieces separately.
- unsigned TotalPieces = path.size();
- unsigned TotalNotePieces =
- std::count_if(path.begin(), path.end(),
- [](const std::shared_ptr<PathDiagnosticPiece> &p) {
- return isa<PathDiagnosticNotePiece>(*p);
- });
+ std::string report = GenerateHTML(D, R, SMgr, path, declName.c_str());
+ if (report.empty()) {
+ llvm::errs() << "warning: no diagnostics generated for main file.\n";
+ return;
+ }
- unsigned TotalRegularPieces = TotalPieces - TotalNotePieces;
- unsigned NumRegularPieces = TotalRegularPieces;
- unsigned NumNotePieces = TotalNotePieces;
+ // Create a path for the target HTML file.
+ int FD;
+ SmallString<128> Model, ResultPath;
- for (auto I = path.rbegin(), E = path.rend(); I != E; ++I) {
- if (isa<PathDiagnosticNotePiece>(I->get())) {
- // This adds diagnostic bubbles, but not navigation.
- // Navigation through note pieces would be added later,
- // as a separate pass through the piece list.
- HandlePiece(R, FID, **I, NumNotePieces, TotalNotePieces);
- --NumNotePieces;
- } else {
- HandlePiece(R, FID, **I, NumRegularPieces, TotalRegularPieces);
- --NumRegularPieces;
- }
+ if (!AnalyzerOpts.shouldWriteStableReportFilename()) {
+ llvm::sys::path::append(Model, Directory, "report-%%%%%%.html");
+ if (std::error_code EC =
+ llvm::sys::fs::make_absolute(Model)) {
+ llvm::errs() << "warning: could not make '" << Model
+ << "' absolute: " << EC.message() << '\n';
+ return;
+ }
+ if (std::error_code EC =
+ llvm::sys::fs::createUniqueFile(Model, FD, ResultPath)) {
+ llvm::errs() << "warning: could not create file in '" << Directory
+ << "': " << EC.message() << '\n';
+ return;
+ }
+
+ } else {
+ int i = 1;
+ std::error_code EC;
+ do {
+ // Find a filename which is not already used
+ const FileEntry* Entry = SMgr.getFileEntryForID(ReportFile);
+ std::stringstream filename;
+ Model = "";
+ filename << "report-"
+ << llvm::sys::path::filename(Entry->getName()).str()
+ << "-" << declName.c_str()
+ << "-" << offsetDecl
+ << "-" << i << ".html";
+ llvm::sys::path::append(Model, Directory,
+ filename.str());
+ EC = llvm::sys::fs::openFileForWrite(Model,
+ FD,
+ llvm::sys::fs::F_RW |
+ llvm::sys::fs::F_Excl);
+ if (EC && EC != llvm::errc::file_exists) {
+ llvm::errs() << "warning: could not create file '" << Model
+ << "': " << EC.message() << '\n';
+ return;
+ }
+ i++;
+ } while (EC);
}
- // Add line numbers, header, footer, etc.
+ llvm::raw_fd_ostream os(FD, true);
- // unsigned FID = R.getSourceMgr().getMainFileID();
- html::EscapeText(R, FID);
- html::AddLineNumbers(R, FID);
+ if (filesMade)
+ filesMade->addDiagnostic(D, getName(),
+ llvm::sys::path::filename(ResultPath));
- // If we have a preprocessor, relex the file and syntax highlight.
- // We might not have a preprocessor if we come from a deserialized AST file,
- // for example.
+ // Emit the HTML to disk.
+ os << report;
+}
- html::SyntaxHighlight(R, FID, PP);
- html::HighlightMacros(R, FID, PP);
+std::string HTMLDiagnostics::GenerateHTML(const PathDiagnostic& D, Rewriter &R,
+ const SourceManager& SMgr, const PathPieces& path, const char *declName) {
+
+ // Rewrite source files as HTML for every new file the path crosses
+ std::vector<FileID> FileIDs;
+ for (auto I : path) {
+ FileID FID = I->getLocation().asLocation().getExpansionLoc().getFileID();
+ if (std::find(FileIDs.begin(), FileIDs.end(), FID) != FileIDs.end())
+ continue;
+
+ FileIDs.push_back(FID);
+ RewriteFile(R, SMgr, path, FID);
+ }
+
+ if (SupportsCrossFileDiagnostics && FileIDs.size() > 1) {
+ // Prefix file names, anchor tags, and nav cursors to every file
+ for (auto I = FileIDs.begin(), E = FileIDs.end(); I != E; I++) {
+ std::string s;
+ llvm::raw_string_ostream os(s);
+
+ if (I != FileIDs.begin())
+ os << "<hr class=divider>\n";
+
+ os << "<div id=File" << I->getHashValue() << ">\n";
- // Get the full directory name of the analyzed file.
+ // Left nav arrow
+ if (I != FileIDs.begin())
+ os << "<div class=FileNav><a href=\"#File" << (I - 1)->getHashValue()
+ << "\">&#x2190;</a></div>";
- const FileEntry* Entry = SMgr.getFileEntryForID(FID);
+ os << "<h4 class=FileName>" << SMgr.getFileEntryForID(*I)->getName()
+ << "</h4>\n";
+ // Right nav arrow
+ if (I + 1 != E)
+ os << "<div class=FileNav><a href=\"#File" << (I + 1)->getHashValue()
+ << "\">&#x2192;</a></div>";
+
+ os << "</div>\n";
+
+ R.InsertTextBefore(SMgr.getLocForStartOfFile(*I), os.str());
+ }
+
+ // Append files to the main report file in the order they appear in the path
+ for (auto I : llvm::make_range(FileIDs.begin() + 1, FileIDs.end())) {
+ std::string s;
+ llvm::raw_string_ostream os(s);
+
+ const RewriteBuffer *Buf = R.getRewriteBufferFor(I);
+ for (auto BI : *Buf)
+ os << BI;
+
+ R.InsertTextAfter(SMgr.getLocForEndOfFile(FileIDs[0]), os.str());
+ }
+ }
+
+ const RewriteBuffer *Buf = R.getRewriteBufferFor(FileIDs[0]);
+ if (!Buf)
+ return "";
+
+ // Add CSS, header, and footer.
+ const FileEntry* Entry = SMgr.getFileEntryForID(FileIDs[0]);
+ FinalizeHTML(D, R, SMgr, path, FileIDs[0], Entry, declName);
+
+ std::string file;
+ llvm::raw_string_ostream os(file);
+ for (auto BI : *Buf)
+ os << BI;
+
+ return os.str();
+}
+
+void HTMLDiagnostics::FinalizeHTML(const PathDiagnostic& D, Rewriter &R,
+ const SourceManager& SMgr, const PathPieces& path, FileID FID,
+ const FileEntry *Entry, const char *declName) {
// This is a cludge; basically we want to append either the full
// working directory if we have no directory information. This is
// a work in progress.
@@ -306,73 +435,48 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
R.InsertTextBefore(SMgr.getLocForStartOfFile(FID), os.str());
}
- // Add CSS, header, and footer.
-
html::AddHeaderFooterInternalBuiltinCSS(R, FID, Entry->getName());
+}
- // Get the rewrite buffer.
- const RewriteBuffer *Buf = R.getRewriteBufferFor(FID);
-
- if (!Buf) {
- llvm::errs() << "warning: no diagnostics generated for main file.\n";
- return;
- }
-
- // Create a path for the target HTML file.
- int FD;
- SmallString<128> Model, ResultPath;
+void HTMLDiagnostics::RewriteFile(Rewriter &R, const SourceManager& SMgr,
+ const PathPieces& path, FileID FID) {
+ // Process the path.
+ // Maintain the counts of extra note pieces separately.
+ unsigned TotalPieces = path.size();
+ unsigned TotalNotePieces =
+ std::count_if(path.begin(), path.end(),
+ [](const std::shared_ptr<PathDiagnosticPiece> &p) {
+ return isa<PathDiagnosticNotePiece>(*p);
+ });
- if (!AnalyzerOpts.shouldWriteStableReportFilename()) {
- llvm::sys::path::append(Model, Directory, "report-%%%%%%.html");
- if (std::error_code EC =
- llvm::sys::fs::make_absolute(Model)) {
- llvm::errs() << "warning: could not make '" << Model
- << "' absolute: " << EC.message() << '\n';
- return;
- }
- if (std::error_code EC =
- llvm::sys::fs::createUniqueFile(Model, FD, ResultPath)) {
- llvm::errs() << "warning: could not create file in '" << Directory
- << "': " << EC.message() << '\n';
- return;
- }
+ unsigned TotalRegularPieces = TotalPieces - TotalNotePieces;
+ unsigned NumRegularPieces = TotalRegularPieces;
+ unsigned NumNotePieces = TotalNotePieces;
- } else {
- int i = 1;
- std::error_code EC;
- do {
- // Find a filename which is not already used
- std::stringstream filename;
- Model = "";
- filename << "report-"
- << llvm::sys::path::filename(Entry->getName()).str()
- << "-" << declName.c_str()
- << "-" << offsetDecl
- << "-" << i << ".html";
- llvm::sys::path::append(Model, Directory,
- filename.str());
- EC = llvm::sys::fs::openFileForWrite(Model,
- FD,
- llvm::sys::fs::F_RW |
- llvm::sys::fs::F_Excl);
- if (EC && EC != llvm::errc::file_exists) {
- llvm::errs() << "warning: could not create file '" << Model
- << "': " << EC.message() << '\n';
- return;
- }
- i++;
- } while (EC);
+ for (auto I = path.rbegin(), E = path.rend(); I != E; ++I) {
+ if (isa<PathDiagnosticNotePiece>(I->get())) {
+ // This adds diagnostic bubbles, but not navigation.
+ // Navigation through note pieces would be added later,
+ // as a separate pass through the piece list.
+ HandlePiece(R, FID, **I, NumNotePieces, TotalNotePieces);
+ --NumNotePieces;
+ } else {
+ HandlePiece(R, FID, **I, NumRegularPieces, TotalRegularPieces);
+ --NumRegularPieces;
+ }
}
- llvm::raw_fd_ostream os(FD, true);
+ // Add line numbers, header, footer, etc.
- if (filesMade)
- filesMade->addDiagnostic(D, getName(),
- llvm::sys::path::filename(ResultPath));
+ html::EscapeText(R, FID);
+ html::AddLineNumbers(R, FID);
- // Emit the HTML to disk.
- for (RewriteBuffer::iterator I = Buf->begin(), E = Buf->end(); I!=E; ++I)
- os << *I;
+ // If we have a preprocessor, relex the file and syntax highlight.
+ // We might not have a preprocessor if we come from a deserialized AST file,
+ // for example.
+
+ html::SyntaxHighlight(R, FID, PP);
+ html::HighlightMacros(R, FID, PP);
}
void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID,
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/IssueHash.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/IssueHash.cpp
index abdea88b1db6f..274ebe7a941bc 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/IssueHash.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/IssueHash.cpp
@@ -33,6 +33,13 @@ static std::string GetSignature(const FunctionDecl *Target) {
return "";
std::string Signature;
+ // When a flow sensitive bug happens in templated code we should not generate
+ // distinct hash value for every instantiation. Use the signature from the
+ // primary template.
+ if (const FunctionDecl *InstantiatedFrom =
+ Target->getTemplateInstantiationPattern())
+ Target = InstantiatedFrom;
+
if (!isa<CXXConstructorDecl>(Target) && !isa<CXXDestructorDecl>(Target) &&
!isa<CXXConversionDecl>(Target))
Signature.append(Target->getReturnType().getAsString()).append(" ");
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
new file mode 100644
index 0000000000000..a8c4b05cea131
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
@@ -0,0 +1,294 @@
+//===--- LoopUnrolling.cpp - Unroll loops -----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// This file contains functions which are used to decide if a loop worth to be
+/// unrolled. Moreover, these functions manages the stack of loop which is
+/// tracked by the ProgramState.
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h"
+
+using namespace clang;
+using namespace ento;
+using namespace clang::ast_matchers;
+
+static const int MAXIMUM_STEP_UNROLLED = 128;
+
+struct LoopState {
+private:
+ enum Kind { Normal, Unrolled } K;
+ const Stmt *LoopStmt;
+ const LocationContext *LCtx;
+ unsigned maxStep;
+ LoopState(Kind InK, const Stmt *S, const LocationContext *L, unsigned N)
+ : K(InK), LoopStmt(S), LCtx(L), maxStep(N) {}
+
+public:
+ static LoopState getNormal(const Stmt *S, const LocationContext *L,
+ unsigned N) {
+ return LoopState(Normal, S, L, N);
+ }
+ static LoopState getUnrolled(const Stmt *S, const LocationContext *L,
+ unsigned N) {
+ return LoopState(Unrolled, S, L, N);
+ }
+ bool isUnrolled() const { return K == Unrolled; }
+ unsigned getMaxStep() const { return maxStep; }
+ const Stmt *getLoopStmt() const { return LoopStmt; }
+ const LocationContext *getLocationContext() const { return LCtx; }
+ bool operator==(const LoopState &X) const {
+ return K == X.K && LoopStmt == X.LoopStmt;
+ }
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddInteger(K);
+ ID.AddPointer(LoopStmt);
+ ID.AddPointer(LCtx);
+ ID.AddInteger(maxStep);
+ }
+};
+
+// The tracked stack of loops. The stack indicates that which loops the
+// simulated element contained by. The loops are marked depending if we decided
+// to unroll them.
+// TODO: The loop stack should not need to be in the program state since it is
+// lexical in nature. Instead, the stack of loops should be tracked in the
+// LocationContext.
+REGISTER_LIST_WITH_PROGRAMSTATE(LoopStack, LoopState)
+
+namespace clang {
+namespace ento {
+
+static bool isLoopStmt(const Stmt *S) {
+ return S && (isa<ForStmt>(S) || isa<WhileStmt>(S) || isa<DoStmt>(S));
+}
+
+ProgramStateRef processLoopEnd(const Stmt *LoopStmt, ProgramStateRef State) {
+ auto LS = State->get<LoopStack>();
+ if (!LS.isEmpty() && LS.getHead().getLoopStmt() == LoopStmt)
+ State = State->set<LoopStack>(LS.getTail());
+ return State;
+}
+
+static internal::Matcher<Stmt> simpleCondition(StringRef BindName) {
+ return binaryOperator(anyOf(hasOperatorName("<"), hasOperatorName(">"),
+ hasOperatorName("<="), hasOperatorName(">="),
+ hasOperatorName("!=")),
+ hasEitherOperand(ignoringParenImpCasts(declRefExpr(
+ to(varDecl(hasType(isInteger())).bind(BindName))))),
+ hasEitherOperand(ignoringParenImpCasts(
+ integerLiteral().bind("boundNum"))))
+ .bind("conditionOperator");
+}
+
+static internal::Matcher<Stmt>
+changeIntBoundNode(internal::Matcher<Decl> VarNodeMatcher) {
+ return anyOf(
+ unaryOperator(anyOf(hasOperatorName("--"), hasOperatorName("++")),
+ hasUnaryOperand(ignoringParenImpCasts(
+ declRefExpr(to(varDecl(VarNodeMatcher)))))),
+ binaryOperator(anyOf(hasOperatorName("="), hasOperatorName("+="),
+ hasOperatorName("/="), hasOperatorName("*="),
+ hasOperatorName("-=")),
+ hasLHS(ignoringParenImpCasts(
+ declRefExpr(to(varDecl(VarNodeMatcher)))))));
+}
+
+static internal::Matcher<Stmt>
+callByRef(internal::Matcher<Decl> VarNodeMatcher) {
+ return callExpr(forEachArgumentWithParam(
+ declRefExpr(to(varDecl(VarNodeMatcher))),
+ parmVarDecl(hasType(references(qualType(unless(isConstQualified())))))));
+}
+
+static internal::Matcher<Stmt>
+assignedToRef(internal::Matcher<Decl> VarNodeMatcher) {
+ return declStmt(hasDescendant(varDecl(
+ allOf(hasType(referenceType()),
+ hasInitializer(anyOf(
+ initListExpr(has(declRefExpr(to(varDecl(VarNodeMatcher))))),
+ declRefExpr(to(varDecl(VarNodeMatcher)))))))));
+}
+
+static internal::Matcher<Stmt>
+getAddrTo(internal::Matcher<Decl> VarNodeMatcher) {
+ return unaryOperator(
+ hasOperatorName("&"),
+ hasUnaryOperand(declRefExpr(hasDeclaration(VarNodeMatcher))));
+}
+
+static internal::Matcher<Stmt> hasSuspiciousStmt(StringRef NodeName) {
+ return hasDescendant(stmt(
+ anyOf(gotoStmt(), switchStmt(), returnStmt(),
+ // Escaping and not known mutation of the loop counter is handled
+ // by exclusion of assigning and address-of operators and
+ // pass-by-ref function calls on the loop counter from the body.
+ changeIntBoundNode(equalsBoundNode(NodeName)),
+ callByRef(equalsBoundNode(NodeName)),
+ getAddrTo(equalsBoundNode(NodeName)),
+ assignedToRef(equalsBoundNode(NodeName)))));
+}
+
+static internal::Matcher<Stmt> forLoopMatcher() {
+ return forStmt(
+ hasCondition(simpleCondition("initVarName")),
+ // Initialization should match the form: 'int i = 6' or 'i = 42'.
+ hasLoopInit(anyOf(
+ declStmt(hasSingleDecl(varDecl(
+ allOf(hasInitializer(integerLiteral().bind("initNum")),
+ equalsBoundNode("initVarName"))))),
+ binaryOperator(hasLHS(declRefExpr(to(
+ varDecl(equalsBoundNode("initVarName"))))),
+ hasRHS(integerLiteral().bind("initNum"))))),
+ // Incrementation should be a simple increment or decrement
+ // operator call.
+ hasIncrement(unaryOperator(
+ anyOf(hasOperatorName("++"), hasOperatorName("--")),
+ hasUnaryOperand(declRefExpr(
+ to(varDecl(allOf(equalsBoundNode("initVarName"),
+ hasType(isInteger())))))))),
+ unless(hasBody(hasSuspiciousStmt("initVarName")))).bind("forLoop");
+}
+
+static bool isPossiblyEscaped(const VarDecl *VD, ExplodedNode *N) {
+ // Global variables assumed as escaped variables.
+ if (VD->hasGlobalStorage())
+ return true;
+
+ while (!N->pred_empty()) {
+ const Stmt *S = PathDiagnosticLocation::getStmt(N);
+ if (!S) {
+ N = N->getFirstPred();
+ continue;
+ }
+
+ if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
+ for (const Decl *D : DS->decls()) {
+ // Once we reach the declaration of the VD we can return.
+ if (D->getCanonicalDecl() == VD)
+ return false;
+ }
+ }
+ // Check the usage of the pass-by-ref function calls and adress-of operator
+ // on VD and reference initialized by VD.
+ ASTContext &ASTCtx =
+ N->getLocationContext()->getAnalysisDeclContext()->getASTContext();
+ auto Match =
+ match(stmt(anyOf(callByRef(equalsNode(VD)), getAddrTo(equalsNode(VD)),
+ assignedToRef(equalsNode(VD)))),
+ *S, ASTCtx);
+ if (!Match.empty())
+ return true;
+
+ N = N->getFirstPred();
+ }
+ llvm_unreachable("Reached root without finding the declaration of VD");
+}
+
+bool shouldCompletelyUnroll(const Stmt *LoopStmt, ASTContext &ASTCtx,
+ ExplodedNode *Pred, unsigned &maxStep) {
+
+ if (!isLoopStmt(LoopStmt))
+ return false;
+
+ // TODO: Match the cases where the bound is not a concrete literal but an
+ // integer with known value
+ auto Matches = match(forLoopMatcher(), *LoopStmt, ASTCtx);
+ if (Matches.empty())
+ return false;
+
+ auto CounterVar = Matches[0].getNodeAs<VarDecl>("initVarName");
+ llvm::APInt BoundNum =
+ Matches[0].getNodeAs<IntegerLiteral>("boundNum")->getValue();
+ llvm::APInt InitNum =
+ Matches[0].getNodeAs<IntegerLiteral>("initNum")->getValue();
+ auto CondOp = Matches[0].getNodeAs<BinaryOperator>("conditionOperator");
+ if (InitNum.getBitWidth() != BoundNum.getBitWidth()) {
+ InitNum = InitNum.zextOrSelf(BoundNum.getBitWidth());
+ BoundNum = BoundNum.zextOrSelf(InitNum.getBitWidth());
+ }
+
+ if (CondOp->getOpcode() == BO_GE || CondOp->getOpcode() == BO_LE)
+ maxStep = (BoundNum - InitNum + 1).abs().getZExtValue();
+ else
+ maxStep = (BoundNum - InitNum).abs().getZExtValue();
+
+ // Check if the counter of the loop is not escaped before.
+ return !isPossiblyEscaped(CounterVar->getCanonicalDecl(), Pred);
+}
+
+bool madeNewBranch(ExplodedNode *N, const Stmt *LoopStmt) {
+ const Stmt *S = nullptr;
+ while (!N->pred_empty()) {
+ if (N->succ_size() > 1)
+ return true;
+
+ ProgramPoint P = N->getLocation();
+ if (Optional<BlockEntrance> BE = P.getAs<BlockEntrance>())
+ S = BE->getBlock()->getTerminator();
+
+ if (S == LoopStmt)
+ return false;
+
+ N = N->getFirstPred();
+ }
+
+ llvm_unreachable("Reached root without encountering the previous step");
+}
+
+// updateLoopStack is called on every basic block, therefore it needs to be fast
+ProgramStateRef updateLoopStack(const Stmt *LoopStmt, ASTContext &ASTCtx,
+ ExplodedNode *Pred, unsigned maxVisitOnPath) {
+ auto State = Pred->getState();
+ auto LCtx = Pred->getLocationContext();
+
+ if (!isLoopStmt(LoopStmt))
+ return State;
+
+ auto LS = State->get<LoopStack>();
+ if (!LS.isEmpty() && LoopStmt == LS.getHead().getLoopStmt() &&
+ LCtx == LS.getHead().getLocationContext()) {
+ if (LS.getHead().isUnrolled() && madeNewBranch(Pred, LoopStmt)) {
+ State = State->set<LoopStack>(LS.getTail());
+ State = State->add<LoopStack>(
+ LoopState::getNormal(LoopStmt, LCtx, maxVisitOnPath));
+ }
+ return State;
+ }
+ unsigned maxStep;
+ if (!shouldCompletelyUnroll(LoopStmt, ASTCtx, Pred, maxStep)) {
+ State = State->add<LoopStack>(
+ LoopState::getNormal(LoopStmt, LCtx, maxVisitOnPath));
+ return State;
+ }
+
+ unsigned outerStep = (LS.isEmpty() ? 1 : LS.getHead().getMaxStep());
+
+ unsigned innerMaxStep = maxStep * outerStep;
+ if (innerMaxStep > MAXIMUM_STEP_UNROLLED)
+ State = State->add<LoopStack>(
+ LoopState::getNormal(LoopStmt, LCtx, maxVisitOnPath));
+ else
+ State = State->add<LoopStack>(
+ LoopState::getUnrolled(LoopStmt, LCtx, innerMaxStep));
+ return State;
+}
+
+bool isUnrolledState(ProgramStateRef State) {
+ auto LS = State->get<LoopStack>();
+ if (LS.isEmpty() || !LS.getHead().isUnrolled())
+ return false;
+ return true;
+}
+}
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
index 7bc186d5b9941..cb8ba6de36265 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -18,7 +18,7 @@
#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/RecordLayout.h"
-#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/Support/BumpVector.h"
#include "clang/Basic/SourceManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
@@ -472,6 +472,8 @@ void ObjCStringRegion::dumpToStream(raw_ostream &os) const {
}
void SymbolicRegion::dumpToStream(raw_ostream &os) const {
+ if (isa<HeapSpaceRegion>(getSuperRegion()))
+ os << "Heap";
os << "SymRegion{" << sym << '}';
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
index d91786f749198..669748c0127ab 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
@@ -578,8 +578,10 @@ getLocationForCaller(const StackFrameContext *SFC,
}
case CFGElement::TemporaryDtor:
case CFGElement::NewAllocator:
- case CFGElement::LifetimeEnds:
llvm_unreachable("not yet implemented!");
+ case CFGElement::LifetimeEnds:
+ case CFGElement::LoopExit:
+ llvm_unreachable("CFGElement kind should not be on callsite!");
}
llvm_unreachable("Unknown CFGElement kind");
@@ -688,6 +690,15 @@ PathDiagnosticLocation::create(const ProgramPoint& P,
return getLocationForCaller(CEE->getCalleeContext(),
CEE->getLocationContext(),
SMng);
+ } else if (Optional<BlockEntrance> BE = P.getAs<BlockEntrance>()) {
+ CFGElement BlockFront = BE->getBlock()->front();
+ if (auto StmtElt = BlockFront.getAs<CFGStmt>()) {
+ return PathDiagnosticLocation(StmtElt->getStmt()->getLocStart(), SMng);
+ } else if (auto NewAllocElt = BlockFront.getAs<CFGNewAllocator>()) {
+ return PathDiagnosticLocation(
+ NewAllocElt->getAllocatorExpr()->getLocStart(), SMng);
+ }
+ llvm_unreachable("Unexpected CFG element at front of block");
} else {
llvm_unreachable("Unexpected ProgramPoint");
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PrettyStackTraceLocationContext.h b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PrettyStackTraceLocationContext.h
index e7cc23ca82345..4bb694819c2ab 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PrettyStackTraceLocationContext.h
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PrettyStackTraceLocationContext.h
@@ -10,7 +10,7 @@
#ifndef LLVM_CLANG_LIB_STATICANALYZER_CORE_PRETTYSTACKTRACELOCATIONCONTEXT_H
#define LLVM_CLANG_LIB_STATICANALYZER_CORE_PRETTYSTACKTRACELOCATIONCONTEXT_H
-#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
namespace clang {
namespace ento {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ProgramState.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ProgramState.cpp
index 3215c3ccd21e9..5b6b7339697f1 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ProgramState.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -260,7 +260,9 @@ SVal ProgramState::getSVal(Loc location, QualType T) const {
// be a constant value, use that value instead to lessen the burden
// on later analysis stages (so we have less symbolic values to reason
// about).
- if (!T.isNull()) {
+ // We only go into this branch if we can convert the APSInt value we have
+ // to the type of T, which is not always the case (e.g. for void).
+ if (!T.isNull() && (T->isIntegralOrEnumerationType() || Loc::isLocType(T))) {
if (SymbolRef sym = V.getAsSymbol()) {
if (const llvm::APSInt *Int = getStateManager()
.getConstraintManager()
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
index e0ad2d8ad45c2..5a4031c0b4a5f 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -354,7 +354,8 @@ private:
RangeSet getSymLERange(ProgramStateRef St, SymbolRef Sym,
const llvm::APSInt &Int,
const llvm::APSInt &Adjustment);
- RangeSet getSymLERange(const RangeSet &RS, const llvm::APSInt &Int,
+ RangeSet getSymLERange(llvm::function_ref<RangeSet()> RS,
+ const llvm::APSInt &Int,
const llvm::APSInt &Adjustment);
RangeSet getSymGERange(ProgramStateRef St, SymbolRef Sym,
const llvm::APSInt &Int,
@@ -395,7 +396,9 @@ bool RangeConstraintManager::canReasonAbout(SVal X) const {
}
if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(SE)) {
- if (BinaryOperator::isComparisonOp(SSE->getOpcode())) {
+ // FIXME: Handle <=> here.
+ if (BinaryOperator::isEqualityOp(SSE->getOpcode()) ||
+ BinaryOperator::isRelationalOp(SSE->getOpcode())) {
// We handle Loc <> Loc comparisons, but not (yet) NonLoc <> NonLoc.
if (Loc::isLocType(SSE->getLHS()->getType())) {
assert(Loc::isLocType(SSE->getRHS()->getType()));
@@ -460,6 +463,53 @@ RangeConstraintManager::removeDeadBindings(ProgramStateRef State,
return Changed ? State->set<ConstraintRange>(CR) : State;
}
+/// Return a range set subtracting zero from \p Domain.
+static RangeSet assumeNonZero(
+ BasicValueFactory &BV,
+ RangeSet::Factory &F,
+ SymbolRef Sym,
+ RangeSet Domain) {
+ APSIntType IntType = BV.getAPSIntType(Sym->getType());
+ return Domain.Intersect(BV, F, ++IntType.getZeroValue(),
+ --IntType.getZeroValue());
+}
+
+/// \brief Apply implicit constraints for bitwise OR- and AND-.
+/// For unsigned types, bitwise OR with a constant always returns
+/// a value greater-or-equal than the constant, and bitwise AND
+/// returns a value less-or-equal then the constant.
+///
+/// Pattern matches the expression \p Sym against those rule,
+/// and applies the required constraints.
+/// \p Input Previously established expression range set
+static RangeSet applyBitwiseConstraints(
+ BasicValueFactory &BV,
+ RangeSet::Factory &F,
+ RangeSet Input,
+ const SymIntExpr* SIE) {
+ QualType T = SIE->getType();
+ bool IsUnsigned = T->isUnsignedIntegerType();
+ const llvm::APSInt &RHS = SIE->getRHS();
+ const llvm::APSInt &Zero = BV.getAPSIntType(T).getZeroValue();
+ BinaryOperator::Opcode Operator = SIE->getOpcode();
+
+ // For unsigned types, the output of bitwise-or is bigger-or-equal than RHS.
+ if (Operator == BO_Or && IsUnsigned)
+ return Input.Intersect(BV, F, RHS, BV.getMaxValue(T));
+
+ // Bitwise-or with a non-zero constant is always non-zero.
+ if (Operator == BO_Or && RHS != Zero)
+ return assumeNonZero(BV, F, SIE, Input);
+
+ // For unsigned types, or positive RHS,
+ // bitwise-and output is always smaller-or-equal than RHS (assuming two's
+ // complement representation of signed types).
+ if (Operator == BO_And && (IsUnsigned || RHS >= Zero))
+ return Input.Intersect(BV, F, BV.getMinValue(T), RHS);
+
+ return Input;
+}
+
RangeSet RangeConstraintManager::getRange(ProgramStateRef State,
SymbolRef Sym) {
if (ConstraintRangeTy::data_type *V = State->get<ConstraintRange>(Sym))
@@ -472,12 +522,13 @@ RangeSet RangeConstraintManager::getRange(ProgramStateRef State,
RangeSet Result(F, BV.getMinValue(T), BV.getMaxValue(T));
- // Special case: references are known to be non-zero.
- if (T->isReferenceType()) {
- APSIntType IntType = BV.getAPSIntType(T);
- Result = Result.Intersect(BV, F, ++IntType.getZeroValue(),
- --IntType.getZeroValue());
- }
+ // References are known to be non-zero.
+ if (T->isReferenceType())
+ return assumeNonZero(BV, F, Sym, Result);
+
+ // Known constraints on ranges of bitwise expressions.
+ if (const SymIntExpr* SIE = dyn_cast<SymIntExpr>(Sym))
+ return applyBitwiseConstraints(BV, F, Result, SIE);
return Result;
}
@@ -637,9 +688,10 @@ RangeConstraintManager::assumeSymGE(ProgramStateRef St, SymbolRef Sym,
return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
}
-RangeSet RangeConstraintManager::getSymLERange(const RangeSet &RS,
- const llvm::APSInt &Int,
- const llvm::APSInt &Adjustment) {
+RangeSet RangeConstraintManager::getSymLERange(
+ llvm::function_ref<RangeSet()> RS,
+ const llvm::APSInt &Int,
+ const llvm::APSInt &Adjustment) {
// Before we do any real work, see if the value can even show up.
APSIntType AdjustmentType(Adjustment);
switch (AdjustmentType.testInRange(Int, true)) {
@@ -648,48 +700,27 @@ RangeSet RangeConstraintManager::getSymLERange(const RangeSet &RS,
case APSIntType::RTR_Within:
break;
case APSIntType::RTR_Above:
- return RS;
+ return RS();
}
// Special case for Int == Max. This is always feasible.
llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
llvm::APSInt Max = AdjustmentType.getMaxValue();
if (ComparisonVal == Max)
- return RS;
+ return RS();
llvm::APSInt Min = AdjustmentType.getMinValue();
llvm::APSInt Lower = Min - Adjustment;
llvm::APSInt Upper = ComparisonVal - Adjustment;
- return RS.Intersect(getBasicVals(), F, Lower, Upper);
+ return RS().Intersect(getBasicVals(), F, Lower, Upper);
}
RangeSet RangeConstraintManager::getSymLERange(ProgramStateRef St,
SymbolRef Sym,
const llvm::APSInt &Int,
const llvm::APSInt &Adjustment) {
- // Before we do any real work, see if the value can even show up.
- APSIntType AdjustmentType(Adjustment);
- switch (AdjustmentType.testInRange(Int, true)) {
- case APSIntType::RTR_Below:
- return F.getEmptySet();
- case APSIntType::RTR_Within:
- break;
- case APSIntType::RTR_Above:
- return getRange(St, Sym);
- }
-
- // Special case for Int == Max. This is always feasible.
- llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
- llvm::APSInt Max = AdjustmentType.getMaxValue();
- if (ComparisonVal == Max)
- return getRange(St, Sym);
-
- llvm::APSInt Min = AdjustmentType.getMinValue();
- llvm::APSInt Lower = Min - Adjustment;
- llvm::APSInt Upper = ComparisonVal - Adjustment;
-
- return getRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
+ return getSymLERange([&] { return getRange(St, Sym); }, Int, Adjustment);
}
ProgramStateRef
@@ -706,8 +737,8 @@ ProgramStateRef RangeConstraintManager::assumeSymWithinInclusiveRange(
RangeSet New = getSymGERange(State, Sym, From, Adjustment);
if (New.isEmpty())
return nullptr;
- New = getSymLERange(New, To, Adjustment);
- return New.isEmpty() ? nullptr : State->set<ConstraintRange>(Sym, New);
+ RangeSet Out = getSymLERange([&] { return New; }, To, Adjustment);
+ return Out.isEmpty() ? nullptr : State->set<ConstraintRange>(Sym, Out);
}
ProgramStateRef RangeConstraintManager::assumeSymOutsideInclusiveRange(
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp
index 1304116f4974b..55ff15806efe6 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp
@@ -33,7 +33,7 @@ ProgramStateRef RangedConstraintManager::assumeSym(ProgramStateRef State,
// We can only simplify expressions whose RHS is an integer.
BinaryOperator::Opcode op = SIE->getOpcode();
- if (BinaryOperator::isComparisonOp(op)) {
+ if (BinaryOperator::isComparisonOp(op) && op != BO_Cmp) {
if (!Assumption)
op = BinaryOperator::negateComparisonOp(op);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
index 11902f66df914..7f2a481c6b0d3 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -18,7 +18,7 @@
#include "clang/AST/Attr.h"
#include "clang/AST/CharUnits.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
-#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
@@ -134,7 +134,9 @@ namespace llvm {
};
} // end llvm namespace
+#ifndef NDEBUG
LLVM_DUMP_METHOD void BindingKey::dump() const { llvm::errs() << *this; }
+#endif
//===----------------------------------------------------------------------===//
// Actual Store type.
@@ -1393,17 +1395,17 @@ SVal RegionStoreManager::getBinding(RegionBindingsConstRef B, Loc L, QualType T)
return UnknownVal();
}
- if (isa<AllocaRegion>(MR) ||
- isa<SymbolicRegion>(MR) ||
- isa<CodeTextRegion>(MR)) {
+ if (!isa<TypedValueRegion>(MR)) {
if (T.isNull()) {
if (const TypedRegion *TR = dyn_cast<TypedRegion>(MR))
- T = TR->getLocationType();
- else {
- const SymbolicRegion *SR = cast<SymbolicRegion>(MR);
- T = SR->getSymbol()->getType();
- }
+ T = TR->getLocationType()->getPointeeType();
+ else if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR))
+ T = SR->getSymbol()->getType()->getPointeeType();
+ else if (isa<AllocaRegion>(MR))
+ T = Ctx.VoidTy;
}
+ assert(!T.isNull() && "Unable to auto-detect binding type!");
+ assert(!T->isVoidType() && "Attempting to dereference a void pointer!");
MR = GetElementZeroRegion(cast<SubRegion>(MR), T);
}
@@ -1859,11 +1861,18 @@ SVal RegionStoreManager::getBindingForVar(RegionBindingsConstRef B,
return svalBuilder.getRegionValueSymbolVal(R);
// Is 'VD' declared constant? If so, retrieve the constant value.
- if (VD->getType().isConstQualified())
- if (const Expr *Init = VD->getInit())
+ if (VD->getType().isConstQualified()) {
+ if (const Expr *Init = VD->getInit()) {
if (Optional<SVal> V = svalBuilder.getConstantVal(Init))
return *V;
+ // If the variable is const qualified and has an initializer but
+ // we couldn't evaluate initializer to a value, treat the value as
+ // unknown.
+ return UnknownVal();
+ }
+ }
+
// This must come after the check for constants because closure-captured
// constant variables may appear in UnknownSpaceRegion.
if (isa<UnknownSpaceRegion>(MS))
@@ -2085,15 +2094,12 @@ RegionStoreManager::bindArray(RegionBindingsConstRef B,
if (const ConstantArrayType* CAT = dyn_cast<ConstantArrayType>(AT))
Size = CAT->getSize().getZExtValue();
- // Check if the init expr is a string literal.
+ // Check if the init expr is a literal. If so, bind the rvalue instead.
+ // FIXME: It's not responsibility of the Store to transform this lvalue
+ // to rvalue. ExprEngine or maybe even CFG should do this before binding.
if (Optional<loc::MemRegionVal> MRV = Init.getAs<loc::MemRegionVal>()) {
- const StringRegion *S = cast<StringRegion>(MRV->getRegion());
-
- // Treat the string as a lazy compound value.
- StoreRef store(B.asStore(), *this);
- nonloc::LazyCompoundVal LCV = svalBuilder.makeLazyCompoundVal(store, S)
- .castAs<nonloc::LazyCompoundVal>();
- return bindAggregate(B, R, LCV);
+ SVal V = getBinding(B.asStore(), *MRV, R->getValueType());
+ return bindAggregate(B, R, V);
}
// Handle lazy compound values.
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SVals.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SVals.cpp
index 9f2af3ffa7097..a83421426a131 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SVals.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SVals.cpp
@@ -113,12 +113,12 @@ SymbolRef SVal::getLocSymbolInBase() const {
/// Casts are ignored during lookup.
/// \param IncludeBaseRegions The boolean that controls whether the search
/// should continue to the base regions if the region is not symbolic.
-SymbolRef SVal::getAsSymbol(bool IncludeBaseRegion) const {
+SymbolRef SVal::getAsSymbol(bool IncludeBaseRegions) const {
// FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
if (Optional<nonloc::SymbolVal> X = getAs<nonloc::SymbolVal>())
return X->getSymbol();
- return getAsLocSymbol(IncludeBaseRegion);
+ return getAsLocSymbol(IncludeBaseRegions);
}
/// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
index f09f9696f5add..94d29d5a6ba32 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
@@ -360,10 +360,18 @@ SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state,
Loc lhsL = lhs.castAs<nonloc::LocAsInteger>().getLoc();
switch (rhs.getSubKind()) {
case nonloc::LocAsIntegerKind:
+ // FIXME: at the moment the implementation
+ // of modeling "pointers as integers" is not complete.
+ if (!BinaryOperator::isComparisonOp(op))
+ return UnknownVal();
return evalBinOpLL(state, op, lhsL,
rhs.castAs<nonloc::LocAsInteger>().getLoc(),
resultTy);
case nonloc::ConcreteIntKind: {
+ // FIXME: at the moment the implementation
+ // of modeling "pointers as integers" is not complete.
+ if (!BinaryOperator::isComparisonOp(op))
+ return UnknownVal();
// Transform the integer into a location and compare.
// FIXME: This only makes sense for comparisons. If we want to, say,
// add 1 to a LocAsInteger, we'd better unpack the Loc and add to it,
@@ -671,7 +679,7 @@ SVal SimpleSValBuilder::evalBinOpLL(ProgramStateRef state,
if (SymbolRef rSym = rhs.getAsLocSymbol()) {
// We can only build expressions with symbols on the left,
// so we need a reversible operator.
- if (!BinaryOperator::isComparisonOp(op))
+ if (!BinaryOperator::isComparisonOp(op) || op == BO_Cmp)
return UnknownVal();
const llvm::APSInt &lVal = lhs.castAs<loc::ConcreteInt>().getValue();
@@ -718,9 +726,11 @@ SVal SimpleSValBuilder::evalBinOpLL(ProgramStateRef state,
if (Optional<loc::ConcreteInt> rInt = rhs.getAs<loc::ConcreteInt>()) {
// If one of the operands is a symbol and the other is a constant,
// build an expression for use by the constraint manager.
- if (SymbolRef lSym = lhs.getAsLocSymbol(true))
- return MakeSymIntVal(lSym, op, rInt->getValue(), resultTy);
-
+ if (SymbolRef lSym = lhs.getAsLocSymbol(true)) {
+ if (BinaryOperator::isComparisonOp(op))
+ return MakeSymIntVal(lSym, op, rInt->getValue(), resultTy);
+ return UnknownVal();
+ }
// Special case comparisons to NULL.
// This must come after the test if the LHS is a symbol, which is used to
// build constraints. The address of any non-symbolic region is guaranteed
@@ -912,6 +922,10 @@ SVal SimpleSValBuilder::evalBinOpLN(ProgramStateRef state,
if (rhs.isZeroConstant())
return lhs;
+ // Perserve the null pointer so that it can be found by the DerefChecker.
+ if (lhs.isZeroConstant())
+ return lhs;
+
// We are dealing with pointer arithmetic.
// Handle pointer arithmetic on constant values.
@@ -927,6 +941,8 @@ SVal SimpleSValBuilder::evalBinOpLN(ProgramStateRef state,
// Offset the increment by the pointer size.
llvm::APSInt Multiplicand(rightI.getBitWidth(), /* isUnsigned */ true);
+ QualType pointeeType = resultTy->getPointeeType();
+ Multiplicand = getContext().getTypeSizeInChars(pointeeType).getQuantity();
rightI *= Multiplicand;
// Compute the adjusted pointer.
@@ -1016,7 +1032,8 @@ SVal SimpleSValBuilder::simplifySVal(ProgramStateRef State, SVal V) {
SVB.getKnownValue(State, nonloc::SymbolVal(S)))
return Loc::isLocType(S->getType()) ? (SVal)SVB.makeIntLocVal(*I)
: (SVal)SVB.makeIntVal(*I);
- return nonloc::SymbolVal(S);
+ return Loc::isLocType(S->getType()) ? (SVal)SVB.makeLoc(S)
+ : nonloc::SymbolVal(S);
}
// TODO: Support SymbolCast. Support IntSymExpr when/if we actually
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Store.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Store.cpp
index 1af49f68cc055..173fdd8d0056b 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Store.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Store.cpp
@@ -440,7 +440,10 @@ SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset,
// value. See also the similar FIXME in getLValueFieldOrIvar().
if (Base.isUnknownOrUndef() || Base.getAs<loc::ConcreteInt>())
return Base;
-
+
+ if (Base.getAs<loc::GotoLabel>())
+ return UnknownVal();
+
const SubRegion *BaseRegion =
Base.castAs<loc::MemRegionVal>().getRegionAs<SubRegion>();
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
index 4be85661b645f..f2d5ee83f3cc7 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
@@ -31,14 +31,20 @@ void SymIntExpr::dumpToStream(raw_ostream &os) const {
os << '(';
getLHS()->dumpToStream(os);
os << ") "
- << BinaryOperator::getOpcodeStr(getOpcode()) << ' '
- << getRHS().getZExtValue();
+ << BinaryOperator::getOpcodeStr(getOpcode()) << ' ';
+ if (getRHS().isUnsigned())
+ os << getRHS().getZExtValue();
+ else
+ os << getRHS().getSExtValue();
if (getRHS().isUnsigned())
os << 'U';
}
void IntSymExpr::dumpToStream(raw_ostream &os) const {
- os << getLHS().getZExtValue();
+ if (getLHS().isUnsigned())
+ os << getLHS().getZExtValue();
+ else
+ os << getLHS().getSExtValue();
if (getLHS().isUnsigned())
os << 'U';
os << ' '
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index c47edc7d21256..fccea9ee53bf5 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -854,8 +854,7 @@ UbigraphViz::~UbigraphViz() {
Ubiviz = *Path;
const char *args[] = {Ubiviz.c_str(), Filename.c_str(), nullptr};
- if (llvm::sys::ExecuteAndWait(Ubiviz, &args[0], nullptr, nullptr, 0, 0,
- &ErrMsg)) {
+ if (llvm::sys::ExecuteAndWait(Ubiviz, &args[0], nullptr, {}, 0, 0, &ErrMsg)) {
llvm::errs() << "Error viewing graph: " << ErrMsg << "\n";
}
diff --git a/contrib/llvm/tools/clang/lib/Tooling/ASTDiff/ASTDiff.cpp b/contrib/llvm/tools/clang/lib/Tooling/ASTDiff/ASTDiff.cpp
new file mode 100644
index 0000000000000..6da0de7edf9a2
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Tooling/ASTDiff/ASTDiff.cpp
@@ -0,0 +1,1021 @@
+//===- ASTDiff.cpp - AST differencing implementation-----------*- C++ -*- -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains definitons for the AST differencing interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/ASTDiff/ASTDiff.h"
+
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/PriorityQueue.h"
+
+#include <limits>
+#include <memory>
+#include <unordered_set>
+
+using namespace llvm;
+using namespace clang;
+
+namespace clang {
+namespace diff {
+
+namespace {
+/// Maps nodes of the left tree to ones on the right, and vice versa.
+class Mapping {
+public:
+ Mapping() = default;
+ Mapping(Mapping &&Other) = default;
+ Mapping &operator=(Mapping &&Other) = default;
+
+ Mapping(size_t Size) {
+ SrcToDst = llvm::make_unique<NodeId[]>(Size);
+ DstToSrc = llvm::make_unique<NodeId[]>(Size);
+ }
+
+ void link(NodeId Src, NodeId Dst) {
+ SrcToDst[Src] = Dst, DstToSrc[Dst] = Src;
+ }
+
+ NodeId getDst(NodeId Src) const { return SrcToDst[Src]; }
+ NodeId getSrc(NodeId Dst) const { return DstToSrc[Dst]; }
+ bool hasSrc(NodeId Src) const { return getDst(Src).isValid(); }
+ bool hasDst(NodeId Dst) const { return getSrc(Dst).isValid(); }
+
+private:
+ std::unique_ptr<NodeId[]> SrcToDst, DstToSrc;
+};
+} // end anonymous namespace
+
+class ASTDiff::Impl {
+public:
+ SyntaxTree::Impl &T1, &T2;
+ Mapping TheMapping;
+
+ Impl(SyntaxTree::Impl &T1, SyntaxTree::Impl &T2,
+ const ComparisonOptions &Options);
+
+ /// Matches nodes one-by-one based on their similarity.
+ void computeMapping();
+
+ // Compute Change for each node based on similarity.
+ void computeChangeKinds(Mapping &M);
+
+ NodeId getMapped(const std::unique_ptr<SyntaxTree::Impl> &Tree,
+ NodeId Id) const {
+ if (&*Tree == &T1)
+ return TheMapping.getDst(Id);
+ assert(&*Tree == &T2 && "Invalid tree.");
+ return TheMapping.getSrc(Id);
+ }
+
+private:
+ // Returns true if the two subtrees are identical.
+ bool identical(NodeId Id1, NodeId Id2) const;
+
+ // Returns false if the nodes must not be mached.
+ bool isMatchingPossible(NodeId Id1, NodeId Id2) const;
+
+ // Returns true if the nodes' parents are matched.
+ bool haveSameParents(const Mapping &M, NodeId Id1, NodeId Id2) const;
+
+ // Uses an optimal albeit slow algorithm to compute a mapping between two
+ // subtrees, but only if both have fewer nodes than MaxSize.
+ void addOptimalMapping(Mapping &M, NodeId Id1, NodeId Id2) const;
+
+ // Computes the ratio of common descendants between the two nodes.
+ // Descendants are only considered to be equal when they are mapped in M.
+ double getJaccardSimilarity(const Mapping &M, NodeId Id1, NodeId Id2) const;
+
+ // Returns the node that has the highest degree of similarity.
+ NodeId findCandidate(const Mapping &M, NodeId Id1) const;
+
+ // Returns a mapping of identical subtrees.
+ Mapping matchTopDown() const;
+
+ // Tries to match any yet unmapped nodes, in a bottom-up fashion.
+ void matchBottomUp(Mapping &M) const;
+
+ const ComparisonOptions &Options;
+
+ friend class ZhangShashaMatcher;
+};
+
+/// Represents the AST of a TranslationUnit.
+class SyntaxTree::Impl {
+public:
+ Impl(SyntaxTree *Parent, ASTContext &AST);
+ /// Constructs a tree from an AST node.
+ Impl(SyntaxTree *Parent, Decl *N, ASTContext &AST);
+ Impl(SyntaxTree *Parent, Stmt *N, ASTContext &AST);
+ template <class T>
+ Impl(SyntaxTree *Parent,
+ typename std::enable_if<std::is_base_of<Stmt, T>::value, T>::type *Node,
+ ASTContext &AST)
+ : Impl(Parent, dyn_cast<Stmt>(Node), AST) {}
+ template <class T>
+ Impl(SyntaxTree *Parent,
+ typename std::enable_if<std::is_base_of<Decl, T>::value, T>::type *Node,
+ ASTContext &AST)
+ : Impl(Parent, dyn_cast<Decl>(Node), AST) {}
+
+ SyntaxTree *Parent;
+ ASTContext &AST;
+ PrintingPolicy TypePP;
+ /// Nodes in preorder.
+ std::vector<Node> Nodes;
+ std::vector<NodeId> Leaves;
+ // Maps preorder indices to postorder ones.
+ std::vector<int> PostorderIds;
+ std::vector<NodeId> NodesBfs;
+
+ int getSize() const { return Nodes.size(); }
+ NodeId getRootId() const { return 0; }
+ PreorderIterator begin() const { return getRootId(); }
+ PreorderIterator end() const { return getSize(); }
+
+ const Node &getNode(NodeId Id) const { return Nodes[Id]; }
+ Node &getMutableNode(NodeId Id) { return Nodes[Id]; }
+ bool isValidNodeId(NodeId Id) const { return Id >= 0 && Id < getSize(); }
+ void addNode(Node &N) { Nodes.push_back(N); }
+ int getNumberOfDescendants(NodeId Id) const;
+ bool isInSubtree(NodeId Id, NodeId SubtreeRoot) const;
+ int findPositionInParent(NodeId Id, bool Shifted = false) const;
+
+ std::string getRelativeName(const NamedDecl *ND,
+ const DeclContext *Context) const;
+ std::string getRelativeName(const NamedDecl *ND) const;
+
+ std::string getNodeValue(NodeId Id) const;
+ std::string getNodeValue(const Node &Node) const;
+ std::string getDeclValue(const Decl *D) const;
+ std::string getStmtValue(const Stmt *S) const;
+
+private:
+ void initTree();
+ void setLeftMostDescendants();
+};
+
+static bool isSpecializedNodeExcluded(const Decl *D) { return D->isImplicit(); }
+static bool isSpecializedNodeExcluded(const Stmt *S) { return false; }
+static bool isSpecializedNodeExcluded(CXXCtorInitializer *I) {
+ return !I->isWritten();
+}
+
+template <class T>
+static bool isNodeExcluded(const SourceManager &SrcMgr, T *N) {
+ if (!N)
+ return true;
+ SourceLocation SLoc = N->getSourceRange().getBegin();
+ if (SLoc.isValid()) {
+ // Ignore everything from other files.
+ if (!SrcMgr.isInMainFile(SLoc))
+ return true;
+ // Ignore macros.
+ if (SLoc != SrcMgr.getSpellingLoc(SLoc))
+ return true;
+ }
+ return isSpecializedNodeExcluded(N);
+}
+
+namespace {
+// Sets Height, Parent and Children for each node.
+struct PreorderVisitor : public RecursiveASTVisitor<PreorderVisitor> {
+ int Id = 0, Depth = 0;
+ NodeId Parent;
+ SyntaxTree::Impl &Tree;
+
+ PreorderVisitor(SyntaxTree::Impl &Tree) : Tree(Tree) {}
+
+ template <class T> std::tuple<NodeId, NodeId> PreTraverse(T *ASTNode) {
+ NodeId MyId = Id;
+ Tree.Nodes.emplace_back();
+ Node &N = Tree.getMutableNode(MyId);
+ N.Parent = Parent;
+ N.Depth = Depth;
+ N.ASTNode = DynTypedNode::create(*ASTNode);
+ assert(!N.ASTNode.getNodeKind().isNone() &&
+ "Expected nodes to have a valid kind.");
+ if (Parent.isValid()) {
+ Node &P = Tree.getMutableNode(Parent);
+ P.Children.push_back(MyId);
+ }
+ Parent = MyId;
+ ++Id;
+ ++Depth;
+ return std::make_tuple(MyId, Tree.getNode(MyId).Parent);
+ }
+ void PostTraverse(std::tuple<NodeId, NodeId> State) {
+ NodeId MyId, PreviousParent;
+ std::tie(MyId, PreviousParent) = State;
+ assert(MyId.isValid() && "Expecting to only traverse valid nodes.");
+ Parent = PreviousParent;
+ --Depth;
+ Node &N = Tree.getMutableNode(MyId);
+ N.RightMostDescendant = Id - 1;
+ assert(N.RightMostDescendant >= 0 &&
+ N.RightMostDescendant < Tree.getSize() &&
+ "Rightmost descendant must be a valid tree node.");
+ if (N.isLeaf())
+ Tree.Leaves.push_back(MyId);
+ N.Height = 1;
+ for (NodeId Child : N.Children)
+ N.Height = std::max(N.Height, 1 + Tree.getNode(Child).Height);
+ }
+ bool TraverseDecl(Decl *D) {
+ if (isNodeExcluded(Tree.AST.getSourceManager(), D))
+ return true;
+ auto SavedState = PreTraverse(D);
+ RecursiveASTVisitor<PreorderVisitor>::TraverseDecl(D);
+ PostTraverse(SavedState);
+ return true;
+ }
+ bool TraverseStmt(Stmt *S) {
+ if (S)
+ S = S->IgnoreImplicit();
+ if (isNodeExcluded(Tree.AST.getSourceManager(), S))
+ return true;
+ auto SavedState = PreTraverse(S);
+ RecursiveASTVisitor<PreorderVisitor>::TraverseStmt(S);
+ PostTraverse(SavedState);
+ return true;
+ }
+ bool TraverseType(QualType T) { return true; }
+ bool TraverseConstructorInitializer(CXXCtorInitializer *Init) {
+ if (isNodeExcluded(Tree.AST.getSourceManager(), Init))
+ return true;
+ auto SavedState = PreTraverse(Init);
+ RecursiveASTVisitor<PreorderVisitor>::TraverseConstructorInitializer(Init);
+ PostTraverse(SavedState);
+ return true;
+ }
+};
+} // end anonymous namespace
+
+SyntaxTree::Impl::Impl(SyntaxTree *Parent, ASTContext &AST)
+ : Parent(Parent), AST(AST), TypePP(AST.getLangOpts()) {
+ TypePP.AnonymousTagLocations = false;
+}
+
+SyntaxTree::Impl::Impl(SyntaxTree *Parent, Decl *N, ASTContext &AST)
+ : Impl(Parent, AST) {
+ PreorderVisitor PreorderWalker(*this);
+ PreorderWalker.TraverseDecl(N);
+ initTree();
+}
+
+SyntaxTree::Impl::Impl(SyntaxTree *Parent, Stmt *N, ASTContext &AST)
+ : Impl(Parent, AST) {
+ PreorderVisitor PreorderWalker(*this);
+ PreorderWalker.TraverseStmt(N);
+ initTree();
+}
+
+static std::vector<NodeId> getSubtreePostorder(const SyntaxTree::Impl &Tree,
+ NodeId Root) {
+ std::vector<NodeId> Postorder;
+ std::function<void(NodeId)> Traverse = [&](NodeId Id) {
+ const Node &N = Tree.getNode(Id);
+ for (NodeId Child : N.Children)
+ Traverse(Child);
+ Postorder.push_back(Id);
+ };
+ Traverse(Root);
+ return Postorder;
+}
+
+static std::vector<NodeId> getSubtreeBfs(const SyntaxTree::Impl &Tree,
+ NodeId Root) {
+ std::vector<NodeId> Ids;
+ size_t Expanded = 0;
+ Ids.push_back(Root);
+ while (Expanded < Ids.size())
+ for (NodeId Child : Tree.getNode(Ids[Expanded++]).Children)
+ Ids.push_back(Child);
+ return Ids;
+}
+
+void SyntaxTree::Impl::initTree() {
+ setLeftMostDescendants();
+ int PostorderId = 0;
+ PostorderIds.resize(getSize());
+ std::function<void(NodeId)> PostorderTraverse = [&](NodeId Id) {
+ for (NodeId Child : getNode(Id).Children)
+ PostorderTraverse(Child);
+ PostorderIds[Id] = PostorderId;
+ ++PostorderId;
+ };
+ PostorderTraverse(getRootId());
+ NodesBfs = getSubtreeBfs(*this, getRootId());
+}
+
+void SyntaxTree::Impl::setLeftMostDescendants() {
+ for (NodeId Leaf : Leaves) {
+ getMutableNode(Leaf).LeftMostDescendant = Leaf;
+ NodeId Parent, Cur = Leaf;
+ while ((Parent = getNode(Cur).Parent).isValid() &&
+ getNode(Parent).Children[0] == Cur) {
+ Cur = Parent;
+ getMutableNode(Cur).LeftMostDescendant = Leaf;
+ }
+ }
+}
+
+int SyntaxTree::Impl::getNumberOfDescendants(NodeId Id) const {
+ return getNode(Id).RightMostDescendant - Id + 1;
+}
+
+bool SyntaxTree::Impl::isInSubtree(NodeId Id, NodeId SubtreeRoot) const {
+ return Id >= SubtreeRoot && Id <= getNode(SubtreeRoot).RightMostDescendant;
+}
+
+int SyntaxTree::Impl::findPositionInParent(NodeId Id, bool Shifted) const {
+ NodeId Parent = getNode(Id).Parent;
+ if (Parent.isInvalid())
+ return 0;
+ const auto &Siblings = getNode(Parent).Children;
+ int Position = 0;
+ for (size_t I = 0, E = Siblings.size(); I < E; ++I) {
+ if (Shifted)
+ Position += getNode(Siblings[I]).Shift;
+ if (Siblings[I] == Id) {
+ Position += I;
+ return Position;
+ }
+ }
+ llvm_unreachable("Node not found in parent's children.");
+}
+
+// Returns the qualified name of ND. If it is subordinate to Context,
+// then the prefix of the latter is removed from the returned value.
+std::string
+SyntaxTree::Impl::getRelativeName(const NamedDecl *ND,
+ const DeclContext *Context) const {
+ std::string Val = ND->getQualifiedNameAsString();
+ std::string ContextPrefix;
+ if (!Context)
+ return Val;
+ if (auto *Namespace = dyn_cast<NamespaceDecl>(Context))
+ ContextPrefix = Namespace->getQualifiedNameAsString();
+ else if (auto *Record = dyn_cast<RecordDecl>(Context))
+ ContextPrefix = Record->getQualifiedNameAsString();
+ else if (AST.getLangOpts().CPlusPlus11)
+ if (auto *Tag = dyn_cast<TagDecl>(Context))
+ ContextPrefix = Tag->getQualifiedNameAsString();
+ // Strip the qualifier, if Val refers to somthing in the current scope.
+ // But leave one leading ':' in place, so that we know that this is a
+ // relative path.
+ if (!ContextPrefix.empty() && StringRef(Val).startswith(ContextPrefix))
+ Val = Val.substr(ContextPrefix.size() + 1);
+ return Val;
+}
+
+std::string SyntaxTree::Impl::getRelativeName(const NamedDecl *ND) const {
+ return getRelativeName(ND, ND->getDeclContext());
+}
+
+static const DeclContext *getEnclosingDeclContext(ASTContext &AST,
+ const Stmt *S) {
+ while (S) {
+ const auto &Parents = AST.getParents(*S);
+ if (Parents.empty())
+ return nullptr;
+ const auto &P = Parents[0];
+ if (const auto *D = P.get<Decl>())
+ return D->getDeclContext();
+ S = P.get<Stmt>();
+ }
+ return nullptr;
+}
+
+static std::string getInitializerValue(const CXXCtorInitializer *Init,
+ const PrintingPolicy &TypePP) {
+ if (Init->isAnyMemberInitializer())
+ return Init->getAnyMember()->getName();
+ if (Init->isBaseInitializer())
+ return QualType(Init->getBaseClass(), 0).getAsString(TypePP);
+ if (Init->isDelegatingInitializer())
+ return Init->getTypeSourceInfo()->getType().getAsString(TypePP);
+ llvm_unreachable("Unknown initializer type");
+}
+
+std::string SyntaxTree::Impl::getNodeValue(NodeId Id) const {
+ return getNodeValue(getNode(Id));
+}
+
+std::string SyntaxTree::Impl::getNodeValue(const Node &N) const {
+ const DynTypedNode &DTN = N.ASTNode;
+ if (auto *S = DTN.get<Stmt>())
+ return getStmtValue(S);
+ if (auto *D = DTN.get<Decl>())
+ return getDeclValue(D);
+ if (auto *Init = DTN.get<CXXCtorInitializer>())
+ return getInitializerValue(Init, TypePP);
+ llvm_unreachable("Fatal: unhandled AST node.\n");
+}
+
+std::string SyntaxTree::Impl::getDeclValue(const Decl *D) const {
+ std::string Value;
+ if (auto *V = dyn_cast<ValueDecl>(D))
+ return getRelativeName(V) + "(" + V->getType().getAsString(TypePP) + ")";
+ if (auto *N = dyn_cast<NamedDecl>(D))
+ Value += getRelativeName(N) + ";";
+ if (auto *T = dyn_cast<TypedefNameDecl>(D))
+ return Value + T->getUnderlyingType().getAsString(TypePP) + ";";
+ if (auto *T = dyn_cast<TypeDecl>(D))
+ if (T->getTypeForDecl())
+ Value +=
+ T->getTypeForDecl()->getCanonicalTypeInternal().getAsString(TypePP) +
+ ";";
+ if (auto *U = dyn_cast<UsingDirectiveDecl>(D))
+ return U->getNominatedNamespace()->getName();
+ if (auto *A = dyn_cast<AccessSpecDecl>(D)) {
+ CharSourceRange Range(A->getSourceRange(), false);
+ return Lexer::getSourceText(Range, AST.getSourceManager(),
+ AST.getLangOpts());
+ }
+ return Value;
+}
+
+std::string SyntaxTree::Impl::getStmtValue(const Stmt *S) const {
+ if (auto *U = dyn_cast<UnaryOperator>(S))
+ return UnaryOperator::getOpcodeStr(U->getOpcode());
+ if (auto *B = dyn_cast<BinaryOperator>(S))
+ return B->getOpcodeStr();
+ if (auto *M = dyn_cast<MemberExpr>(S))
+ return getRelativeName(M->getMemberDecl());
+ if (auto *I = dyn_cast<IntegerLiteral>(S)) {
+ SmallString<256> Str;
+ I->getValue().toString(Str, /*Radix=*/10, /*Signed=*/false);
+ return Str.str();
+ }
+ if (auto *F = dyn_cast<FloatingLiteral>(S)) {
+ SmallString<256> Str;
+ F->getValue().toString(Str);
+ return Str.str();
+ }
+ if (auto *D = dyn_cast<DeclRefExpr>(S))
+ return getRelativeName(D->getDecl(), getEnclosingDeclContext(AST, S));
+ if (auto *String = dyn_cast<StringLiteral>(S))
+ return String->getString();
+ if (auto *B = dyn_cast<CXXBoolLiteralExpr>(S))
+ return B->getValue() ? "true" : "false";
+ return "";
+}
+
+/// Identifies a node in a subtree by its postorder offset, starting at 1.
+struct SNodeId {
+ int Id = 0;
+
+ explicit SNodeId(int Id) : Id(Id) {}
+ explicit SNodeId() = default;
+
+ operator int() const { return Id; }
+ SNodeId &operator++() { return ++Id, *this; }
+ SNodeId &operator--() { return --Id, *this; }
+ SNodeId operator+(int Other) const { return SNodeId(Id + Other); }
+};
+
+class Subtree {
+private:
+ /// The parent tree.
+ const SyntaxTree::Impl &Tree;
+ /// Maps SNodeIds to original ids.
+ std::vector<NodeId> RootIds;
+ /// Maps subtree nodes to their leftmost descendants wtihin the subtree.
+ std::vector<SNodeId> LeftMostDescendants;
+
+public:
+ std::vector<SNodeId> KeyRoots;
+
+ Subtree(const SyntaxTree::Impl &Tree, NodeId SubtreeRoot) : Tree(Tree) {
+ RootIds = getSubtreePostorder(Tree, SubtreeRoot);
+ int NumLeaves = setLeftMostDescendants();
+ computeKeyRoots(NumLeaves);
+ }
+ int getSize() const { return RootIds.size(); }
+ NodeId getIdInRoot(SNodeId Id) const {
+ assert(Id > 0 && Id <= getSize() && "Invalid subtree node index.");
+ return RootIds[Id - 1];
+ }
+ const Node &getNode(SNodeId Id) const {
+ return Tree.getNode(getIdInRoot(Id));
+ }
+ SNodeId getLeftMostDescendant(SNodeId Id) const {
+ assert(Id > 0 && Id <= getSize() && "Invalid subtree node index.");
+ return LeftMostDescendants[Id - 1];
+ }
+ /// Returns the postorder index of the leftmost descendant in the subtree.
+ NodeId getPostorderOffset() const {
+ return Tree.PostorderIds[getIdInRoot(SNodeId(1))];
+ }
+ std::string getNodeValue(SNodeId Id) const {
+ return Tree.getNodeValue(getIdInRoot(Id));
+ }
+
+private:
+ /// Returns the number of leafs in the subtree.
+ int setLeftMostDescendants() {
+ int NumLeaves = 0;
+ LeftMostDescendants.resize(getSize());
+ for (int I = 0; I < getSize(); ++I) {
+ SNodeId SI(I + 1);
+ const Node &N = getNode(SI);
+ NumLeaves += N.isLeaf();
+ assert(I == Tree.PostorderIds[getIdInRoot(SI)] - getPostorderOffset() &&
+ "Postorder traversal in subtree should correspond to traversal in "
+ "the root tree by a constant offset.");
+ LeftMostDescendants[I] = SNodeId(Tree.PostorderIds[N.LeftMostDescendant] -
+ getPostorderOffset());
+ }
+ return NumLeaves;
+ }
+ void computeKeyRoots(int Leaves) {
+ KeyRoots.resize(Leaves);
+ std::unordered_set<int> Visited;
+ int K = Leaves - 1;
+ for (SNodeId I(getSize()); I > 0; --I) {
+ SNodeId LeftDesc = getLeftMostDescendant(I);
+ if (Visited.count(LeftDesc))
+ continue;
+ assert(K >= 0 && "K should be non-negative");
+ KeyRoots[K] = I;
+ Visited.insert(LeftDesc);
+ --K;
+ }
+ }
+};
+
+/// Implementation of Zhang and Shasha's Algorithm for tree edit distance.
+/// Computes an optimal mapping between two trees using only insertion,
+/// deletion and update as edit actions (similar to the Levenshtein distance).
+class ZhangShashaMatcher {
+ const ASTDiff::Impl &DiffImpl;
+ Subtree S1;
+ Subtree S2;
+ std::unique_ptr<std::unique_ptr<double[]>[]> TreeDist, ForestDist;
+
+public:
+ ZhangShashaMatcher(const ASTDiff::Impl &DiffImpl, const SyntaxTree::Impl &T1,
+ const SyntaxTree::Impl &T2, NodeId Id1, NodeId Id2)
+ : DiffImpl(DiffImpl), S1(T1, Id1), S2(T2, Id2) {
+ TreeDist = llvm::make_unique<std::unique_ptr<double[]>[]>(
+ size_t(S1.getSize()) + 1);
+ ForestDist = llvm::make_unique<std::unique_ptr<double[]>[]>(
+ size_t(S1.getSize()) + 1);
+ for (int I = 0, E = S1.getSize() + 1; I < E; ++I) {
+ TreeDist[I] = llvm::make_unique<double[]>(size_t(S2.getSize()) + 1);
+ ForestDist[I] = llvm::make_unique<double[]>(size_t(S2.getSize()) + 1);
+ }
+ }
+
+ std::vector<std::pair<NodeId, NodeId>> getMatchingNodes() {
+ std::vector<std::pair<NodeId, NodeId>> Matches;
+ std::vector<std::pair<SNodeId, SNodeId>> TreePairs;
+
+ computeTreeDist();
+
+ bool RootNodePair = true;
+
+ TreePairs.emplace_back(SNodeId(S1.getSize()), SNodeId(S2.getSize()));
+
+ while (!TreePairs.empty()) {
+ SNodeId LastRow, LastCol, FirstRow, FirstCol, Row, Col;
+ std::tie(LastRow, LastCol) = TreePairs.back();
+ TreePairs.pop_back();
+
+ if (!RootNodePair) {
+ computeForestDist(LastRow, LastCol);
+ }
+
+ RootNodePair = false;
+
+ FirstRow = S1.getLeftMostDescendant(LastRow);
+ FirstCol = S2.getLeftMostDescendant(LastCol);
+
+ Row = LastRow;
+ Col = LastCol;
+
+ while (Row > FirstRow || Col > FirstCol) {
+ if (Row > FirstRow &&
+ ForestDist[Row - 1][Col] + 1 == ForestDist[Row][Col]) {
+ --Row;
+ } else if (Col > FirstCol &&
+ ForestDist[Row][Col - 1] + 1 == ForestDist[Row][Col]) {
+ --Col;
+ } else {
+ SNodeId LMD1 = S1.getLeftMostDescendant(Row);
+ SNodeId LMD2 = S2.getLeftMostDescendant(Col);
+ if (LMD1 == S1.getLeftMostDescendant(LastRow) &&
+ LMD2 == S2.getLeftMostDescendant(LastCol)) {
+ NodeId Id1 = S1.getIdInRoot(Row);
+ NodeId Id2 = S2.getIdInRoot(Col);
+ assert(DiffImpl.isMatchingPossible(Id1, Id2) &&
+ "These nodes must not be matched.");
+ Matches.emplace_back(Id1, Id2);
+ --Row;
+ --Col;
+ } else {
+ TreePairs.emplace_back(Row, Col);
+ Row = LMD1;
+ Col = LMD2;
+ }
+ }
+ }
+ }
+ return Matches;
+ }
+
+private:
+ /// We use a simple cost model for edit actions, which seems good enough.
+ /// Simple cost model for edit actions. This seems to make the matching
+ /// algorithm perform reasonably well.
+ /// The values range between 0 and 1, or infinity if this edit action should
+ /// always be avoided.
+ static constexpr double DeletionCost = 1;
+ static constexpr double InsertionCost = 1;
+
+ double getUpdateCost(SNodeId Id1, SNodeId Id2) {
+ if (!DiffImpl.isMatchingPossible(S1.getIdInRoot(Id1), S2.getIdInRoot(Id2)))
+ return std::numeric_limits<double>::max();
+ return S1.getNodeValue(Id1) != S2.getNodeValue(Id2);
+ }
+
+ void computeTreeDist() {
+ for (SNodeId Id1 : S1.KeyRoots)
+ for (SNodeId Id2 : S2.KeyRoots)
+ computeForestDist(Id1, Id2);
+ }
+
+ void computeForestDist(SNodeId Id1, SNodeId Id2) {
+ assert(Id1 > 0 && Id2 > 0 && "Expecting offsets greater than 0.");
+ SNodeId LMD1 = S1.getLeftMostDescendant(Id1);
+ SNodeId LMD2 = S2.getLeftMostDescendant(Id2);
+
+ ForestDist[LMD1][LMD2] = 0;
+ for (SNodeId D1 = LMD1 + 1; D1 <= Id1; ++D1) {
+ ForestDist[D1][LMD2] = ForestDist[D1 - 1][LMD2] + DeletionCost;
+ for (SNodeId D2 = LMD2 + 1; D2 <= Id2; ++D2) {
+ ForestDist[LMD1][D2] = ForestDist[LMD1][D2 - 1] + InsertionCost;
+ SNodeId DLMD1 = S1.getLeftMostDescendant(D1);
+ SNodeId DLMD2 = S2.getLeftMostDescendant(D2);
+ if (DLMD1 == LMD1 && DLMD2 == LMD2) {
+ double UpdateCost = getUpdateCost(D1, D2);
+ ForestDist[D1][D2] =
+ std::min({ForestDist[D1 - 1][D2] + DeletionCost,
+ ForestDist[D1][D2 - 1] + InsertionCost,
+ ForestDist[D1 - 1][D2 - 1] + UpdateCost});
+ TreeDist[D1][D2] = ForestDist[D1][D2];
+ } else {
+ ForestDist[D1][D2] =
+ std::min({ForestDist[D1 - 1][D2] + DeletionCost,
+ ForestDist[D1][D2 - 1] + InsertionCost,
+ ForestDist[DLMD1][DLMD2] + TreeDist[D1][D2]});
+ }
+ }
+ }
+ }
+};
+
+ast_type_traits::ASTNodeKind Node::getType() const {
+ return ASTNode.getNodeKind();
+}
+
+StringRef Node::getTypeLabel() const { return getType().asStringRef(); }
+
+llvm::Optional<std::string> Node::getQualifiedIdentifier() const {
+ if (auto *ND = ASTNode.get<NamedDecl>()) {
+ if (ND->getDeclName().isIdentifier())
+ return ND->getQualifiedNameAsString();
+ }
+ return llvm::None;
+}
+
+llvm::Optional<StringRef> Node::getIdentifier() const {
+ if (auto *ND = ASTNode.get<NamedDecl>()) {
+ if (ND->getDeclName().isIdentifier())
+ return ND->getName();
+ }
+ return llvm::None;
+}
+
+namespace {
+// Compares nodes by their depth.
+struct HeightLess {
+ const SyntaxTree::Impl &Tree;
+ HeightLess(const SyntaxTree::Impl &Tree) : Tree(Tree) {}
+ bool operator()(NodeId Id1, NodeId Id2) const {
+ return Tree.getNode(Id1).Height < Tree.getNode(Id2).Height;
+ }
+};
+} // end anonymous namespace
+
+namespace {
+// Priority queue for nodes, sorted descendingly by their height.
+class PriorityList {
+ const SyntaxTree::Impl &Tree;
+ HeightLess Cmp;
+ std::vector<NodeId> Container;
+ PriorityQueue<NodeId, std::vector<NodeId>, HeightLess> List;
+
+public:
+ PriorityList(const SyntaxTree::Impl &Tree)
+ : Tree(Tree), Cmp(Tree), List(Cmp, Container) {}
+
+ void push(NodeId id) { List.push(id); }
+
+ std::vector<NodeId> pop() {
+ int Max = peekMax();
+ std::vector<NodeId> Result;
+ if (Max == 0)
+ return Result;
+ while (peekMax() == Max) {
+ Result.push_back(List.top());
+ List.pop();
+ }
+ // TODO this is here to get a stable output, not a good heuristic
+ std::sort(Result.begin(), Result.end());
+ return Result;
+ }
+ int peekMax() const {
+ if (List.empty())
+ return 0;
+ return Tree.getNode(List.top()).Height;
+ }
+ void open(NodeId Id) {
+ for (NodeId Child : Tree.getNode(Id).Children)
+ push(Child);
+ }
+};
+} // end anonymous namespace
+
+bool ASTDiff::Impl::identical(NodeId Id1, NodeId Id2) const {
+ const Node &N1 = T1.getNode(Id1);
+ const Node &N2 = T2.getNode(Id2);
+ if (N1.Children.size() != N2.Children.size() ||
+ !isMatchingPossible(Id1, Id2) ||
+ T1.getNodeValue(Id1) != T2.getNodeValue(Id2))
+ return false;
+ for (size_t Id = 0, E = N1.Children.size(); Id < E; ++Id)
+ if (!identical(N1.Children[Id], N2.Children[Id]))
+ return false;
+ return true;
+}
+
+bool ASTDiff::Impl::isMatchingPossible(NodeId Id1, NodeId Id2) const {
+ return Options.isMatchingAllowed(T1.getNode(Id1), T2.getNode(Id2));
+}
+
+bool ASTDiff::Impl::haveSameParents(const Mapping &M, NodeId Id1,
+ NodeId Id2) const {
+ NodeId P1 = T1.getNode(Id1).Parent;
+ NodeId P2 = T2.getNode(Id2).Parent;
+ return (P1.isInvalid() && P2.isInvalid()) ||
+ (P1.isValid() && P2.isValid() && M.getDst(P1) == P2);
+}
+
+void ASTDiff::Impl::addOptimalMapping(Mapping &M, NodeId Id1,
+ NodeId Id2) const {
+ if (std::max(T1.getNumberOfDescendants(Id1), T2.getNumberOfDescendants(Id2)) >
+ Options.MaxSize)
+ return;
+ ZhangShashaMatcher Matcher(*this, T1, T2, Id1, Id2);
+ std::vector<std::pair<NodeId, NodeId>> R = Matcher.getMatchingNodes();
+ for (const auto Tuple : R) {
+ NodeId Src = Tuple.first;
+ NodeId Dst = Tuple.second;
+ if (!M.hasSrc(Src) && !M.hasDst(Dst))
+ M.link(Src, Dst);
+ }
+}
+
+double ASTDiff::Impl::getJaccardSimilarity(const Mapping &M, NodeId Id1,
+ NodeId Id2) const {
+ int CommonDescendants = 0;
+ const Node &N1 = T1.getNode(Id1);
+ // Count the common descendants, excluding the subtree root.
+ for (NodeId Src = Id1 + 1; Src <= N1.RightMostDescendant; ++Src) {
+ NodeId Dst = M.getDst(Src);
+ CommonDescendants += int(Dst.isValid() && T2.isInSubtree(Dst, Id2));
+ }
+ // We need to subtract 1 to get the number of descendants excluding the root.
+ double Denominator = T1.getNumberOfDescendants(Id1) - 1 +
+ T2.getNumberOfDescendants(Id2) - 1 - CommonDescendants;
+ // CommonDescendants is less than the size of one subtree.
+ assert(Denominator >= 0 && "Expected non-negative denominator.");
+ if (Denominator == 0)
+ return 0;
+ return CommonDescendants / Denominator;
+}
+
+NodeId ASTDiff::Impl::findCandidate(const Mapping &M, NodeId Id1) const {
+ NodeId Candidate;
+ double HighestSimilarity = 0.0;
+ for (NodeId Id2 : T2) {
+ if (!isMatchingPossible(Id1, Id2))
+ continue;
+ if (M.hasDst(Id2))
+ continue;
+ double Similarity = getJaccardSimilarity(M, Id1, Id2);
+ if (Similarity >= Options.MinSimilarity && Similarity > HighestSimilarity) {
+ HighestSimilarity = Similarity;
+ Candidate = Id2;
+ }
+ }
+ return Candidate;
+}
+
+void ASTDiff::Impl::matchBottomUp(Mapping &M) const {
+ std::vector<NodeId> Postorder = getSubtreePostorder(T1, T1.getRootId());
+ for (NodeId Id1 : Postorder) {
+ if (Id1 == T1.getRootId() && !M.hasSrc(T1.getRootId()) &&
+ !M.hasDst(T2.getRootId())) {
+ if (isMatchingPossible(T1.getRootId(), T2.getRootId())) {
+ M.link(T1.getRootId(), T2.getRootId());
+ addOptimalMapping(M, T1.getRootId(), T2.getRootId());
+ }
+ break;
+ }
+ bool Matched = M.hasSrc(Id1);
+ const Node &N1 = T1.getNode(Id1);
+ bool MatchedChildren =
+ std::any_of(N1.Children.begin(), N1.Children.end(),
+ [&](NodeId Child) { return M.hasSrc(Child); });
+ if (Matched || !MatchedChildren)
+ continue;
+ NodeId Id2 = findCandidate(M, Id1);
+ if (Id2.isValid()) {
+ M.link(Id1, Id2);
+ addOptimalMapping(M, Id1, Id2);
+ }
+ }
+}
+
+Mapping ASTDiff::Impl::matchTopDown() const {
+ PriorityList L1(T1);
+ PriorityList L2(T2);
+
+ Mapping M(T1.getSize() + T2.getSize());
+
+ L1.push(T1.getRootId());
+ L2.push(T2.getRootId());
+
+ int Max1, Max2;
+ while (std::min(Max1 = L1.peekMax(), Max2 = L2.peekMax()) >
+ Options.MinHeight) {
+ if (Max1 > Max2) {
+ for (NodeId Id : L1.pop())
+ L1.open(Id);
+ continue;
+ }
+ if (Max2 > Max1) {
+ for (NodeId Id : L2.pop())
+ L2.open(Id);
+ continue;
+ }
+ std::vector<NodeId> H1, H2;
+ H1 = L1.pop();
+ H2 = L2.pop();
+ for (NodeId Id1 : H1) {
+ for (NodeId Id2 : H2) {
+ if (identical(Id1, Id2) && !M.hasSrc(Id1) && !M.hasDst(Id2)) {
+ for (int I = 0, E = T1.getNumberOfDescendants(Id1); I < E; ++I)
+ M.link(Id1 + I, Id2 + I);
+ }
+ }
+ }
+ for (NodeId Id1 : H1) {
+ if (!M.hasSrc(Id1))
+ L1.open(Id1);
+ }
+ for (NodeId Id2 : H2) {
+ if (!M.hasDst(Id2))
+ L2.open(Id2);
+ }
+ }
+ return M;
+}
+
+ASTDiff::Impl::Impl(SyntaxTree::Impl &T1, SyntaxTree::Impl &T2,
+ const ComparisonOptions &Options)
+ : T1(T1), T2(T2), Options(Options) {
+ computeMapping();
+ computeChangeKinds(TheMapping);
+}
+
+void ASTDiff::Impl::computeMapping() {
+ TheMapping = matchTopDown();
+ if (Options.StopAfterTopDown)
+ return;
+ matchBottomUp(TheMapping);
+}
+
+void ASTDiff::Impl::computeChangeKinds(Mapping &M) {
+ for (NodeId Id1 : T1) {
+ if (!M.hasSrc(Id1)) {
+ T1.getMutableNode(Id1).Change = Delete;
+ T1.getMutableNode(Id1).Shift -= 1;
+ }
+ }
+ for (NodeId Id2 : T2) {
+ if (!M.hasDst(Id2)) {
+ T2.getMutableNode(Id2).Change = Insert;
+ T2.getMutableNode(Id2).Shift -= 1;
+ }
+ }
+ for (NodeId Id1 : T1.NodesBfs) {
+ NodeId Id2 = M.getDst(Id1);
+ if (Id2.isInvalid())
+ continue;
+ if (!haveSameParents(M, Id1, Id2) ||
+ T1.findPositionInParent(Id1, true) !=
+ T2.findPositionInParent(Id2, true)) {
+ T1.getMutableNode(Id1).Shift -= 1;
+ T2.getMutableNode(Id2).Shift -= 1;
+ }
+ }
+ for (NodeId Id2 : T2.NodesBfs) {
+ NodeId Id1 = M.getSrc(Id2);
+ if (Id1.isInvalid())
+ continue;
+ Node &N1 = T1.getMutableNode(Id1);
+ Node &N2 = T2.getMutableNode(Id2);
+ if (Id1.isInvalid())
+ continue;
+ if (!haveSameParents(M, Id1, Id2) ||
+ T1.findPositionInParent(Id1, true) !=
+ T2.findPositionInParent(Id2, true)) {
+ N1.Change = N2.Change = Move;
+ }
+ if (T1.getNodeValue(Id1) != T2.getNodeValue(Id2)) {
+ N1.Change = N2.Change = (N1.Change == Move ? UpdateMove : Update);
+ }
+ }
+}
+
+ASTDiff::ASTDiff(SyntaxTree &T1, SyntaxTree &T2,
+ const ComparisonOptions &Options)
+ : DiffImpl(llvm::make_unique<Impl>(*T1.TreeImpl, *T2.TreeImpl, Options)) {}
+
+ASTDiff::~ASTDiff() = default;
+
+NodeId ASTDiff::getMapped(const SyntaxTree &SourceTree, NodeId Id) const {
+ return DiffImpl->getMapped(SourceTree.TreeImpl, Id);
+}
+
+SyntaxTree::SyntaxTree(ASTContext &AST)
+ : TreeImpl(llvm::make_unique<SyntaxTree::Impl>(
+ this, AST.getTranslationUnitDecl(), AST)) {}
+
+SyntaxTree::~SyntaxTree() = default;
+
+const ASTContext &SyntaxTree::getASTContext() const { return TreeImpl->AST; }
+
+const Node &SyntaxTree::getNode(NodeId Id) const {
+ return TreeImpl->getNode(Id);
+}
+
+int SyntaxTree::getSize() const { return TreeImpl->getSize(); }
+NodeId SyntaxTree::getRootId() const { return TreeImpl->getRootId(); }
+SyntaxTree::PreorderIterator SyntaxTree::begin() const {
+ return TreeImpl->begin();
+}
+SyntaxTree::PreorderIterator SyntaxTree::end() const { return TreeImpl->end(); }
+
+int SyntaxTree::findPositionInParent(NodeId Id) const {
+ return TreeImpl->findPositionInParent(Id);
+}
+
+std::pair<unsigned, unsigned>
+SyntaxTree::getSourceRangeOffsets(const Node &N) const {
+ const SourceManager &SrcMgr = TreeImpl->AST.getSourceManager();
+ SourceRange Range = N.ASTNode.getSourceRange();
+ SourceLocation BeginLoc = Range.getBegin();
+ SourceLocation EndLoc = Lexer::getLocForEndOfToken(
+ Range.getEnd(), /*Offset=*/0, SrcMgr, TreeImpl->AST.getLangOpts());
+ if (auto *ThisExpr = N.ASTNode.get<CXXThisExpr>()) {
+ if (ThisExpr->isImplicit())
+ EndLoc = BeginLoc;
+ }
+ unsigned Begin = SrcMgr.getFileOffset(SrcMgr.getExpansionLoc(BeginLoc));
+ unsigned End = SrcMgr.getFileOffset(SrcMgr.getExpansionLoc(EndLoc));
+ return {Begin, End};
+}
+
+std::string SyntaxTree::getNodeValue(NodeId Id) const {
+ return TreeImpl->getNodeValue(Id);
+}
+
+std::string SyntaxTree::getNodeValue(const Node &N) const {
+ return TreeImpl->getNodeValue(N);
+}
+
+} // end namespace diff
+} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Tooling/ArgumentsAdjusters.cpp b/contrib/llvm/tools/clang/lib/Tooling/ArgumentsAdjusters.cpp
index ac9fd3c5cade4..7068ec2c4010e 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/ArgumentsAdjusters.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/ArgumentsAdjusters.cpp
@@ -58,14 +58,14 @@ ArgumentsAdjuster getClangStripDependencyFileAdjuster() {
StringRef Arg = Args[i];
// All dependency-file options begin with -M. These include -MM,
// -MF, -MG, -MP, -MT, -MQ, -MD, and -MMD.
- if (!Arg.startswith("-M"))
+ if (!Arg.startswith("-M")) {
AdjustedArgs.push_back(Args[i]);
+ continue;
+ }
- if ((Arg == "-MF") || (Arg == "-MT") || (Arg == "-MQ") ||
- (Arg == "-MD") || (Arg == "-MMD")) {
- // Output is specified as -MX foo. Skip the next argument also.
+ if (Arg == "-MF" || Arg == "-MT" || Arg == "-MQ")
+ // These flags take an argument: -MX foo. Skip the next argument also.
++i;
- }
}
return AdjustedArgs;
};
@@ -96,6 +96,10 @@ ArgumentsAdjuster getInsertArgumentAdjuster(const char *Extra,
ArgumentsAdjuster combineAdjusters(ArgumentsAdjuster First,
ArgumentsAdjuster Second) {
+ if (!First)
+ return Second;
+ if (!Second)
+ return First;
return [First, Second](const CommandLineArguments &Args, StringRef File) {
return Second(First(Args, File), File);
};
diff --git a/contrib/llvm/tools/clang/lib/Tooling/CommonOptionsParser.cpp b/contrib/llvm/tools/clang/lib/Tooling/CommonOptionsParser.cpp
index 9e9689e6b2524..74ad4e83ee3f3 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/CommonOptionsParser.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/CommonOptionsParser.cpp
@@ -24,10 +24,9 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Support/CommandLine.h"
-#include "clang/Tooling/ArgumentsAdjusters.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
+#include "llvm/Support/CommandLine.h"
using namespace clang::tooling;
using namespace llvm;
@@ -54,80 +53,82 @@ const char *const CommonOptionsParser::HelpMessage =
"\tsuffix of a path in the compile command database.\n"
"\n";
-namespace {
-class ArgumentsAdjustingCompilations : public CompilationDatabase {
-public:
- ArgumentsAdjustingCompilations(
- std::unique_ptr<CompilationDatabase> Compilations)
- : Compilations(std::move(Compilations)) {}
-
- void appendArgumentsAdjuster(ArgumentsAdjuster Adjuster) {
- Adjusters.push_back(std::move(Adjuster));
- }
-
- std::vector<CompileCommand>
- getCompileCommands(StringRef FilePath) const override {
- return adjustCommands(Compilations->getCompileCommands(FilePath));
- }
+void ArgumentsAdjustingCompilations::appendArgumentsAdjuster(
+ ArgumentsAdjuster Adjuster) {
+ Adjusters.push_back(std::move(Adjuster));
+}
- std::vector<std::string> getAllFiles() const override {
- return Compilations->getAllFiles();
- }
+std::vector<CompileCommand> ArgumentsAdjustingCompilations::getCompileCommands(
+ StringRef FilePath) const {
+ return adjustCommands(Compilations->getCompileCommands(FilePath));
+}
- std::vector<CompileCommand> getAllCompileCommands() const override {
- return adjustCommands(Compilations->getAllCompileCommands());
- }
+std::vector<std::string>
+ArgumentsAdjustingCompilations::getAllFiles() const {
+ return Compilations->getAllFiles();
+}
-private:
- std::unique_ptr<CompilationDatabase> Compilations;
- std::vector<ArgumentsAdjuster> Adjusters;
+std::vector<CompileCommand>
+ArgumentsAdjustingCompilations::getAllCompileCommands() const {
+ return adjustCommands(Compilations->getAllCompileCommands());
+}
- std::vector<CompileCommand>
- adjustCommands(std::vector<CompileCommand> Commands) const {
- for (CompileCommand &Command : Commands)
- for (const auto &Adjuster : Adjusters)
- Command.CommandLine = Adjuster(Command.CommandLine, Command.Filename);
- return Commands;
- }
-};
-} // namespace
+std::vector<CompileCommand> ArgumentsAdjustingCompilations::adjustCommands(
+ std::vector<CompileCommand> Commands) const {
+ for (CompileCommand &Command : Commands)
+ for (const auto &Adjuster : Adjusters)
+ Command.CommandLine = Adjuster(Command.CommandLine, Command.Filename);
+ return Commands;
+}
-CommonOptionsParser::CommonOptionsParser(
+llvm::Error CommonOptionsParser::init(
int &argc, const char **argv, cl::OptionCategory &Category,
llvm::cl::NumOccurrencesFlag OccurrencesFlag, const char *Overview) {
- static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden);
+ static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden,
+ cl::sub(*cl::AllSubCommands));
static cl::opt<std::string> BuildPath("p", cl::desc("Build path"),
- cl::Optional, cl::cat(Category));
+ cl::Optional, cl::cat(Category),
+ cl::sub(*cl::AllSubCommands));
static cl::list<std::string> SourcePaths(
cl::Positional, cl::desc("<source0> [... <sourceN>]"), OccurrencesFlag,
- cl::cat(Category));
+ cl::cat(Category), cl::sub(*cl::AllSubCommands));
static cl::list<std::string> ArgsAfter(
"extra-arg",
cl::desc("Additional argument to append to the compiler command line"),
- cl::cat(Category));
+ cl::cat(Category), cl::sub(*cl::AllSubCommands));
static cl::list<std::string> ArgsBefore(
"extra-arg-before",
cl::desc("Additional argument to prepend to the compiler command line"),
- cl::cat(Category));
+ cl::cat(Category), cl::sub(*cl::AllSubCommands));
+
+ cl::ResetAllOptionOccurrences();
cl::HideUnrelatedOptions(Category);
std::string ErrorMessage;
Compilations =
FixedCompilationDatabase::loadFromCommandLine(argc, argv, ErrorMessage);
- if (!Compilations && !ErrorMessage.empty())
- llvm::errs() << ErrorMessage;
- cl::ParseCommandLineOptions(argc, argv, Overview);
+ if (!ErrorMessage.empty())
+ ErrorMessage.append("\n");
+ llvm::raw_string_ostream OS(ErrorMessage);
+ // Stop initializing if command-line option parsing failed.
+ if (!cl::ParseCommandLineOptions(argc, argv, Overview, &OS)) {
+ OS.flush();
+ return llvm::make_error<llvm::StringError>("[CommonOptionsParser]: " +
+ ErrorMessage,
+ llvm::inconvertibleErrorCode());
+ }
+
cl::PrintOptionValues();
SourcePathList = SourcePaths;
if ((OccurrencesFlag == cl::ZeroOrMore || OccurrencesFlag == cl::Optional) &&
SourcePathList.empty())
- return;
+ return llvm::Error::success();
if (!Compilations) {
if (!BuildPath.empty()) {
Compilations =
@@ -146,9 +147,34 @@ CommonOptionsParser::CommonOptionsParser(
auto AdjustingCompilations =
llvm::make_unique<ArgumentsAdjustingCompilations>(
std::move(Compilations));
- AdjustingCompilations->appendArgumentsAdjuster(
- getInsertArgumentAdjuster(ArgsBefore, ArgumentInsertPosition::BEGIN));
- AdjustingCompilations->appendArgumentsAdjuster(
+ Adjuster =
+ getInsertArgumentAdjuster(ArgsBefore, ArgumentInsertPosition::BEGIN);
+ Adjuster = combineAdjusters(
+ std::move(Adjuster),
getInsertArgumentAdjuster(ArgsAfter, ArgumentInsertPosition::END));
+ AdjustingCompilations->appendArgumentsAdjuster(Adjuster);
Compilations = std::move(AdjustingCompilations);
+ return llvm::Error::success();
+}
+
+llvm::Expected<CommonOptionsParser> CommonOptionsParser::create(
+ int &argc, const char **argv, llvm::cl::OptionCategory &Category,
+ llvm::cl::NumOccurrencesFlag OccurrencesFlag, const char *Overview) {
+ CommonOptionsParser Parser;
+ llvm::Error Err =
+ Parser.init(argc, argv, Category, OccurrencesFlag, Overview);
+ if (Err)
+ return std::move(Err);
+ return std::move(Parser);
+}
+
+CommonOptionsParser::CommonOptionsParser(
+ int &argc, const char **argv, cl::OptionCategory &Category,
+ llvm::cl::NumOccurrencesFlag OccurrencesFlag, const char *Overview) {
+ llvm::Error Err = init(argc, argv, Category, OccurrencesFlag, Overview);
+ if (Err) {
+ llvm::report_fatal_error(
+ "CommonOptionsParser: failed to parse command-line arguments. " +
+ llvm::toString(std::move(Err)));
+ }
}
diff --git a/contrib/llvm/tools/clang/lib/Tooling/CompilationDatabase.cpp b/contrib/llvm/tools/clang/lib/Tooling/CompilationDatabase.cpp
index 0e835579e04ed..92b76b157dcb0 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/CompilationDatabase.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/CompilationDatabase.cpp
@@ -10,6 +10,9 @@
// This file contains implementations of the CompilationDatabase base class
// and the FixedCompilationDatabase.
//
+// FIXME: Various functions that take a string &ErrorMessage should be upgraded
+// to Expected.
+//
//===----------------------------------------------------------------------===//
#include "clang/Tooling/CompilationDatabase.h"
@@ -26,6 +29,7 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/Option/Arg.h"
#include "llvm/Support/Host.h"
+#include "llvm/Support/LineIterator.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include <sstream>
@@ -108,6 +112,15 @@ CompilationDatabase::autoDetectFromDirectory(StringRef SourceDir,
return DB;
}
+std::vector<CompileCommand> CompilationDatabase::getAllCompileCommands() const {
+ std::vector<CompileCommand> Result;
+ for (const auto &File : getAllFiles()) {
+ auto C = getCompileCommands(File);
+ std::move(C.begin(), C.end(), std::back_inserter(Result));
+ }
+ return Result;
+}
+
CompilationDatabasePlugin::~CompilationDatabasePlugin() {}
namespace {
@@ -302,8 +315,22 @@ FixedCompilationDatabase::loadFromCommandLine(int &Argc,
std::vector<std::string> StrippedArgs;
if (!stripPositionalArgs(CommandLine, StrippedArgs, ErrorMsg))
return nullptr;
- return std::unique_ptr<FixedCompilationDatabase>(
- new FixedCompilationDatabase(Directory, StrippedArgs));
+ return llvm::make_unique<FixedCompilationDatabase>(Directory, StrippedArgs);
+}
+
+std::unique_ptr<FixedCompilationDatabase>
+FixedCompilationDatabase::loadFromFile(StringRef Path, std::string &ErrorMsg) {
+ ErrorMsg.clear();
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =
+ llvm::MemoryBuffer::getFile(Path);
+ if (std::error_code Result = File.getError()) {
+ ErrorMsg = "Error while opening fixed database: " + Result.message();
+ return nullptr;
+ }
+ std::vector<std::string> Args{llvm::line_iterator(**File),
+ llvm::line_iterator()};
+ return llvm::make_unique<FixedCompilationDatabase>(
+ llvm::sys::path::parent_path(Path), std::move(Args));
}
FixedCompilationDatabase::
@@ -324,15 +351,21 @@ FixedCompilationDatabase::getCompileCommands(StringRef FilePath) const {
return Result;
}
-std::vector<std::string>
-FixedCompilationDatabase::getAllFiles() const {
- return std::vector<std::string>();
-}
+namespace {
-std::vector<CompileCommand>
-FixedCompilationDatabase::getAllCompileCommands() const {
- return std::vector<CompileCommand>();
-}
+class FixedCompilationDatabasePlugin : public CompilationDatabasePlugin {
+ std::unique_ptr<CompilationDatabase>
+ loadFromDirectory(StringRef Directory, std::string &ErrorMessage) override {
+ SmallString<1024> DatabasePath(Directory);
+ llvm::sys::path::append(DatabasePath, "compile_flags.txt");
+ return FixedCompilationDatabase::loadFromFile(DatabasePath, ErrorMessage);
+ }
+};
+
+static CompilationDatabasePluginRegistry::Add<FixedCompilationDatabasePlugin>
+X("fixed-compilation-database", "Reads plain-text flags file");
+
+} // namespace
namespace clang {
namespace tooling {
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Core/Replacement.cpp b/contrib/llvm/tools/clang/lib/Tooling/Core/Replacement.cpp
index e194b59a6e2b1..6d4f3a3401425 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/Core/Replacement.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/Core/Replacement.cpp
@@ -503,7 +503,7 @@ calculateRangesAfterReplacements(const Replacements &Replaces,
std::string(R.getLength(), ' ')));
assert(!Err &&
"Replacements must not conflict since ranges have been merged.");
- (void)Err;
+ llvm::consumeError(std::move(Err));
}
return FakeReplaces.merge(Replaces).getAffectedRanges();
}
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Execution.cpp b/contrib/llvm/tools/clang/lib/Tooling/Execution.cpp
new file mode 100644
index 0000000000000..498d683f8924a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Tooling/Execution.cpp
@@ -0,0 +1,105 @@
+//===- lib/Tooling/Execution.cpp - Implements tool execution framework. ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/Execution.h"
+#include "clang/Tooling/ToolExecutorPluginRegistry.h"
+#include "clang/Tooling/Tooling.h"
+
+LLVM_INSTANTIATE_REGISTRY(clang::tooling::ToolExecutorPluginRegistry)
+
+namespace clang {
+namespace tooling {
+
+static llvm::cl::opt<std::string>
+ ExecutorName("executor", llvm::cl::desc("The name of the executor to use."),
+ llvm::cl::init("standalone"));
+
+void InMemoryToolResults::addResult(StringRef Key, StringRef Value) {
+ KVResults.push_back({Key.str(), Value.str()});
+}
+
+std::vector<std::pair<std::string, std::string>>
+InMemoryToolResults::AllKVResults() {
+ return KVResults;
+}
+
+void InMemoryToolResults::forEachResult(
+ llvm::function_ref<void(StringRef Key, StringRef Value)> Callback) {
+ for (const auto &KV : KVResults) {
+ Callback(KV.first, KV.second);
+ }
+}
+
+void ExecutionContext::reportResult(StringRef Key, StringRef Value) {
+ Results->addResult(Key, Value);
+}
+
+llvm::Error
+ToolExecutor::execute(std::unique_ptr<FrontendActionFactory> Action) {
+ return execute(std::move(Action), ArgumentsAdjuster());
+}
+
+llvm::Error ToolExecutor::execute(std::unique_ptr<FrontendActionFactory> Action,
+ ArgumentsAdjuster Adjuster) {
+ std::vector<
+ std::pair<std::unique_ptr<FrontendActionFactory>, ArgumentsAdjuster>>
+ Actions;
+ Actions.emplace_back(std::move(Action), std::move(Adjuster));
+ return execute(Actions);
+}
+
+namespace internal {
+llvm::Expected<std::unique_ptr<ToolExecutor>>
+createExecutorFromCommandLineArgsImpl(int &argc, const char **argv,
+ llvm::cl::OptionCategory &Category,
+ const char *Overview) {
+ auto OptionsParser =
+ CommonOptionsParser::create(argc, argv, Category, llvm::cl::ZeroOrMore,
+ /*Overview=*/Overview);
+ if (!OptionsParser)
+ return OptionsParser.takeError();
+ for (auto I = ToolExecutorPluginRegistry::begin(),
+ E = ToolExecutorPluginRegistry::end();
+ I != E; ++I) {
+ if (I->getName() != ExecutorName) {
+ continue;
+ }
+ std::unique_ptr<ToolExecutorPlugin> Plugin(I->instantiate());
+ llvm::Expected<std::unique_ptr<ToolExecutor>> Executor =
+ Plugin->create(*OptionsParser);
+ if (!Executor) {
+ return llvm::make_error<llvm::StringError>(
+ llvm::Twine("Failed to create '") + I->getName() +
+ "': " + llvm::toString(Executor.takeError()) + "\n",
+ llvm::inconvertibleErrorCode());
+ }
+ return std::move(*Executor);
+ }
+ return llvm::make_error<llvm::StringError>(
+ llvm::Twine("Executor \"") + ExecutorName + "\" is not registered.",
+ llvm::inconvertibleErrorCode());
+}
+} // end namespace internal
+
+llvm::Expected<std::unique_ptr<ToolExecutor>>
+createExecutorFromCommandLineArgs(int &argc, const char **argv,
+ llvm::cl::OptionCategory &Category,
+ const char *Overview) {
+ return internal::createExecutorFromCommandLineArgsImpl(argc, argv, Category,
+ Overview);
+}
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the StandaloneToolExecutorPlugin.
+extern volatile int StandaloneToolExecutorAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED StandaloneToolExecutorAnchorDest =
+ StandaloneToolExecutorAnchorSource;
+
+} // end namespace tooling
+} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Refactoring/ASTSelection.cpp b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/ASTSelection.cpp
new file mode 100644
index 0000000000000..7123fc32cec9b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/ASTSelection.cpp
@@ -0,0 +1,453 @@
+//===--- ASTSelection.cpp - Clang refactoring library ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/Refactoring/ASTSelection.h"
+#include "clang/AST/LexicallyOrderedRecursiveASTVisitor.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/Support/SaveAndRestore.h"
+
+using namespace clang;
+using namespace tooling;
+using ast_type_traits::DynTypedNode;
+
+namespace {
+
+CharSourceRange getLexicalDeclRange(Decl *D, const SourceManager &SM,
+ const LangOptions &LangOpts) {
+ if (!isa<ObjCImplDecl>(D))
+ return CharSourceRange::getTokenRange(D->getSourceRange());
+ // Objective-C implementation declarations end at the '@' instead of the 'end'
+ // keyword. Use the lexer to find the location right after 'end'.
+ SourceRange R = D->getSourceRange();
+ SourceLocation LocAfterEnd = Lexer::findLocationAfterToken(
+ R.getEnd(), tok::raw_identifier, SM, LangOpts,
+ /*SkipTrailingWhitespaceAndNewLine=*/false);
+ return LocAfterEnd.isValid()
+ ? CharSourceRange::getCharRange(R.getBegin(), LocAfterEnd)
+ : CharSourceRange::getTokenRange(R);
+}
+
+/// Constructs the tree of selected AST nodes that either contain the location
+/// of the cursor or overlap with the selection range.
+class ASTSelectionFinder
+ : public LexicallyOrderedRecursiveASTVisitor<ASTSelectionFinder> {
+public:
+ ASTSelectionFinder(SourceRange Selection, FileID TargetFile,
+ const ASTContext &Context)
+ : LexicallyOrderedRecursiveASTVisitor(Context.getSourceManager()),
+ SelectionBegin(Selection.getBegin()),
+ SelectionEnd(Selection.getBegin() == Selection.getEnd()
+ ? SourceLocation()
+ : Selection.getEnd()),
+ TargetFile(TargetFile), Context(Context) {
+ // The TU decl is the root of the selected node tree.
+ SelectionStack.push_back(
+ SelectedASTNode(DynTypedNode::create(*Context.getTranslationUnitDecl()),
+ SourceSelectionKind::None));
+ }
+
+ Optional<SelectedASTNode> getSelectedASTNode() {
+ assert(SelectionStack.size() == 1 && "stack was not popped");
+ SelectedASTNode Result = std::move(SelectionStack.back());
+ SelectionStack.pop_back();
+ if (Result.Children.empty())
+ return None;
+ return std::move(Result);
+ }
+
+ bool TraversePseudoObjectExpr(PseudoObjectExpr *E) {
+ // Avoid traversing the semantic expressions. They should be handled by
+ // looking through the appropriate opaque expressions in order to build
+ // a meaningful selection tree.
+ llvm::SaveAndRestore<bool> LookThrough(LookThroughOpaqueValueExprs, true);
+ return TraverseStmt(E->getSyntacticForm());
+ }
+
+ bool TraverseOpaqueValueExpr(OpaqueValueExpr *E) {
+ if (!LookThroughOpaqueValueExprs)
+ return true;
+ llvm::SaveAndRestore<bool> LookThrough(LookThroughOpaqueValueExprs, false);
+ return TraverseStmt(E->getSourceExpr());
+ }
+
+ bool TraverseDecl(Decl *D) {
+ if (isa<TranslationUnitDecl>(D))
+ return LexicallyOrderedRecursiveASTVisitor::TraverseDecl(D);
+ if (D->isImplicit())
+ return true;
+
+ // Check if this declaration is written in the file of interest.
+ const SourceRange DeclRange = D->getSourceRange();
+ const SourceManager &SM = Context.getSourceManager();
+ SourceLocation FileLoc;
+ if (DeclRange.getBegin().isMacroID() && !DeclRange.getEnd().isMacroID())
+ FileLoc = DeclRange.getEnd();
+ else
+ FileLoc = SM.getSpellingLoc(DeclRange.getBegin());
+ if (SM.getFileID(FileLoc) != TargetFile)
+ return true;
+
+ SourceSelectionKind SelectionKind =
+ selectionKindFor(getLexicalDeclRange(D, SM, Context.getLangOpts()));
+ SelectionStack.push_back(
+ SelectedASTNode(DynTypedNode::create(*D), SelectionKind));
+ LexicallyOrderedRecursiveASTVisitor::TraverseDecl(D);
+ popAndAddToSelectionIfSelected(SelectionKind);
+
+ if (DeclRange.getEnd().isValid() &&
+ SM.isBeforeInTranslationUnit(SelectionEnd.isValid() ? SelectionEnd
+ : SelectionBegin,
+ DeclRange.getEnd())) {
+ // Stop early when we've reached a declaration after the selection.
+ return false;
+ }
+ return true;
+ }
+
+ bool TraverseStmt(Stmt *S) {
+ if (!S)
+ return true;
+ if (auto *Opaque = dyn_cast<OpaqueValueExpr>(S))
+ return TraverseOpaqueValueExpr(Opaque);
+ // Avoid selecting implicit 'this' expressions.
+ if (auto *TE = dyn_cast<CXXThisExpr>(S)) {
+ if (TE->isImplicit())
+ return true;
+ }
+ // FIXME (Alex Lorenz): Improve handling for macro locations.
+ SourceSelectionKind SelectionKind =
+ selectionKindFor(CharSourceRange::getTokenRange(S->getSourceRange()));
+ SelectionStack.push_back(
+ SelectedASTNode(DynTypedNode::create(*S), SelectionKind));
+ LexicallyOrderedRecursiveASTVisitor::TraverseStmt(S);
+ popAndAddToSelectionIfSelected(SelectionKind);
+ return true;
+ }
+
+private:
+ void popAndAddToSelectionIfSelected(SourceSelectionKind SelectionKind) {
+ SelectedASTNode Node = std::move(SelectionStack.back());
+ SelectionStack.pop_back();
+ if (SelectionKind != SourceSelectionKind::None || !Node.Children.empty())
+ SelectionStack.back().Children.push_back(std::move(Node));
+ }
+
+ SourceSelectionKind selectionKindFor(CharSourceRange Range) {
+ SourceLocation End = Range.getEnd();
+ const SourceManager &SM = Context.getSourceManager();
+ if (Range.isTokenRange())
+ End = Lexer::getLocForEndOfToken(End, 0, SM, Context.getLangOpts());
+ if (!SourceLocation::isPairOfFileLocations(Range.getBegin(), End))
+ return SourceSelectionKind::None;
+ if (!SelectionEnd.isValid()) {
+ // Do a quick check when the selection is of length 0.
+ if (SM.isPointWithin(SelectionBegin, Range.getBegin(), End))
+ return SourceSelectionKind::ContainsSelection;
+ return SourceSelectionKind::None;
+ }
+ bool HasStart = SM.isPointWithin(SelectionBegin, Range.getBegin(), End);
+ bool HasEnd = SM.isPointWithin(SelectionEnd, Range.getBegin(), End);
+ if (HasStart && HasEnd)
+ return SourceSelectionKind::ContainsSelection;
+ if (SM.isPointWithin(Range.getBegin(), SelectionBegin, SelectionEnd) &&
+ SM.isPointWithin(End, SelectionBegin, SelectionEnd))
+ return SourceSelectionKind::InsideSelection;
+ // Ensure there's at least some overlap with the 'start'/'end' selection
+ // types.
+ if (HasStart && SelectionBegin != End)
+ return SourceSelectionKind::ContainsSelectionStart;
+ if (HasEnd && SelectionEnd != Range.getBegin())
+ return SourceSelectionKind::ContainsSelectionEnd;
+
+ return SourceSelectionKind::None;
+ }
+
+ const SourceLocation SelectionBegin, SelectionEnd;
+ FileID TargetFile;
+ const ASTContext &Context;
+ std::vector<SelectedASTNode> SelectionStack;
+ /// Controls whether we can traverse through the OpaqueValueExpr. This is
+ /// typically enabled during the traversal of syntactic form for
+ /// PseudoObjectExprs.
+ bool LookThroughOpaqueValueExprs = false;
+};
+
+} // end anonymous namespace
+
+Optional<SelectedASTNode>
+clang::tooling::findSelectedASTNodes(const ASTContext &Context,
+ SourceRange SelectionRange) {
+ assert(SelectionRange.isValid() &&
+ SourceLocation::isPairOfFileLocations(SelectionRange.getBegin(),
+ SelectionRange.getEnd()) &&
+ "Expected a file range");
+ FileID TargetFile =
+ Context.getSourceManager().getFileID(SelectionRange.getBegin());
+ assert(Context.getSourceManager().getFileID(SelectionRange.getEnd()) ==
+ TargetFile &&
+ "selection range must span one file");
+
+ ASTSelectionFinder Visitor(SelectionRange, TargetFile, Context);
+ Visitor.TraverseDecl(Context.getTranslationUnitDecl());
+ return Visitor.getSelectedASTNode();
+}
+
+static const char *selectionKindToString(SourceSelectionKind Kind) {
+ switch (Kind) {
+ case SourceSelectionKind::None:
+ return "none";
+ case SourceSelectionKind::ContainsSelection:
+ return "contains-selection";
+ case SourceSelectionKind::ContainsSelectionStart:
+ return "contains-selection-start";
+ case SourceSelectionKind::ContainsSelectionEnd:
+ return "contains-selection-end";
+ case SourceSelectionKind::InsideSelection:
+ return "inside";
+ }
+ llvm_unreachable("invalid selection kind");
+}
+
+static void dump(const SelectedASTNode &Node, llvm::raw_ostream &OS,
+ unsigned Indent = 0) {
+ OS.indent(Indent * 2);
+ if (const Decl *D = Node.Node.get<Decl>()) {
+ OS << D->getDeclKindName() << "Decl";
+ if (const auto *ND = dyn_cast<NamedDecl>(D))
+ OS << " \"" << ND->getNameAsString() << '"';
+ } else if (const Stmt *S = Node.Node.get<Stmt>()) {
+ OS << S->getStmtClassName();
+ }
+ OS << ' ' << selectionKindToString(Node.SelectionKind) << "\n";
+ for (const auto &Child : Node.Children)
+ dump(Child, OS, Indent + 1);
+}
+
+void SelectedASTNode::dump(llvm::raw_ostream &OS) const { ::dump(*this, OS); }
+
+/// Returns true if the given node has any direct children with the following
+/// selection kind.
+///
+/// Note: The direct children also include children of direct children with the
+/// "None" selection kind.
+static bool hasAnyDirectChildrenWithKind(const SelectedASTNode &Node,
+ SourceSelectionKind Kind) {
+ assert(Kind != SourceSelectionKind::None && "invalid predicate!");
+ for (const auto &Child : Node.Children) {
+ if (Child.SelectionKind == Kind)
+ return true;
+ if (Child.SelectionKind == SourceSelectionKind::None)
+ return hasAnyDirectChildrenWithKind(Child, Kind);
+ }
+ return false;
+}
+
+namespace {
+struct SelectedNodeWithParents {
+ SelectedNodeWithParents(SelectedNodeWithParents &&) = default;
+ SelectedNodeWithParents &operator=(SelectedNodeWithParents &&) = default;
+ SelectedASTNode::ReferenceType Node;
+ llvm::SmallVector<SelectedASTNode::ReferenceType, 8> Parents;
+
+ /// Canonicalizes the given selection by selecting different related AST nodes
+ /// when it makes sense to do so.
+ void canonicalize();
+};
+
+enum SelectionCanonicalizationAction { KeepSelection, SelectParent };
+
+/// Returns the canonicalization action which should be applied to the
+/// selected statement.
+SelectionCanonicalizationAction
+getSelectionCanonizalizationAction(const Stmt *S, const Stmt *Parent) {
+ // Select the parent expression when:
+ // - The string literal in ObjC string literal is selected, e.g.:
+ // @"test" becomes @"test"
+ // ~~~~~~ ~~~~~~~
+ if (isa<StringLiteral>(S) && isa<ObjCStringLiteral>(Parent))
+ return SelectParent;
+ // The entire call should be selected when just the member expression
+ // that refers to the method or the decl ref that refers to the function
+ // is selected.
+ // f.call(args) becomes f.call(args)
+ // ~~~~ ~~~~~~~~~~~~
+ // func(args) becomes func(args)
+ // ~~~~ ~~~~~~~~~~
+ else if (const auto *CE = dyn_cast<CallExpr>(Parent)) {
+ if ((isa<MemberExpr>(S) || isa<DeclRefExpr>(S)) &&
+ CE->getCallee()->IgnoreImpCasts() == S)
+ return SelectParent;
+ }
+ // FIXME: Syntactic form -> Entire pseudo-object expr.
+ return KeepSelection;
+}
+
+} // end anonymous namespace
+
+void SelectedNodeWithParents::canonicalize() {
+ const Stmt *S = Node.get().Node.get<Stmt>();
+ assert(S && "non statement selection!");
+ const Stmt *Parent = Parents[Parents.size() - 1].get().Node.get<Stmt>();
+ if (!Parent)
+ return;
+
+ // Look through the implicit casts in the parents.
+ unsigned ParentIndex = 1;
+ for (; (ParentIndex + 1) <= Parents.size() && isa<ImplicitCastExpr>(Parent);
+ ++ParentIndex) {
+ const Stmt *NewParent =
+ Parents[Parents.size() - ParentIndex - 1].get().Node.get<Stmt>();
+ if (!NewParent)
+ break;
+ Parent = NewParent;
+ }
+
+ switch (getSelectionCanonizalizationAction(S, Parent)) {
+ case SelectParent:
+ Node = Parents[Parents.size() - ParentIndex];
+ for (; ParentIndex != 0; --ParentIndex)
+ Parents.pop_back();
+ break;
+ case KeepSelection:
+ break;
+ }
+}
+
+/// Finds the set of bottom-most selected AST nodes that are in the selection
+/// tree with the specified selection kind.
+///
+/// For example, given the following selection tree:
+///
+/// FunctionDecl "f" contains-selection
+/// CompoundStmt contains-selection [#1]
+/// CallExpr inside
+/// ImplicitCastExpr inside
+/// DeclRefExpr inside
+/// IntegerLiteral inside
+/// IntegerLiteral inside
+/// FunctionDecl "f2" contains-selection
+/// CompoundStmt contains-selection [#2]
+/// CallExpr inside
+/// ImplicitCastExpr inside
+/// DeclRefExpr inside
+/// IntegerLiteral inside
+/// IntegerLiteral inside
+///
+/// This function will find references to nodes #1 and #2 when searching for the
+/// \c ContainsSelection kind.
+static void findDeepestWithKind(
+ const SelectedASTNode &ASTSelection,
+ llvm::SmallVectorImpl<SelectedNodeWithParents> &MatchingNodes,
+ SourceSelectionKind Kind,
+ llvm::SmallVectorImpl<SelectedASTNode::ReferenceType> &ParentStack) {
+ if (ASTSelection.Node.get<DeclStmt>()) {
+ // Select the entire decl stmt when any of its child declarations is the
+ // bottom-most.
+ for (const auto &Child : ASTSelection.Children) {
+ if (!hasAnyDirectChildrenWithKind(Child, Kind)) {
+ MatchingNodes.push_back(SelectedNodeWithParents{
+ std::cref(ASTSelection), {ParentStack.begin(), ParentStack.end()}});
+ return;
+ }
+ }
+ } else {
+ if (!hasAnyDirectChildrenWithKind(ASTSelection, Kind)) {
+ // This node is the bottom-most.
+ MatchingNodes.push_back(SelectedNodeWithParents{
+ std::cref(ASTSelection), {ParentStack.begin(), ParentStack.end()}});
+ return;
+ }
+ }
+ // Search in the children.
+ ParentStack.push_back(std::cref(ASTSelection));
+ for (const auto &Child : ASTSelection.Children)
+ findDeepestWithKind(Child, MatchingNodes, Kind, ParentStack);
+ ParentStack.pop_back();
+}
+
+static void findDeepestWithKind(
+ const SelectedASTNode &ASTSelection,
+ llvm::SmallVectorImpl<SelectedNodeWithParents> &MatchingNodes,
+ SourceSelectionKind Kind) {
+ llvm::SmallVector<SelectedASTNode::ReferenceType, 16> ParentStack;
+ findDeepestWithKind(ASTSelection, MatchingNodes, Kind, ParentStack);
+}
+
+Optional<CodeRangeASTSelection>
+CodeRangeASTSelection::create(SourceRange SelectionRange,
+ const SelectedASTNode &ASTSelection) {
+ // Code range is selected when the selection range is not empty.
+ if (SelectionRange.getBegin() == SelectionRange.getEnd())
+ return None;
+ llvm::SmallVector<SelectedNodeWithParents, 4> ContainSelection;
+ findDeepestWithKind(ASTSelection, ContainSelection,
+ SourceSelectionKind::ContainsSelection);
+ // We are looking for a selection in one body of code, so let's focus on
+ // one matching result.
+ if (ContainSelection.size() != 1)
+ return None;
+ SelectedNodeWithParents &Selected = ContainSelection[0];
+ if (!Selected.Node.get().Node.get<Stmt>())
+ return None;
+ const Stmt *CodeRangeStmt = Selected.Node.get().Node.get<Stmt>();
+ if (!isa<CompoundStmt>(CodeRangeStmt)) {
+ Selected.canonicalize();
+ return CodeRangeASTSelection(Selected.Node, Selected.Parents,
+ /*AreChildrenSelected=*/false);
+ }
+ // FIXME (Alex L): First selected SwitchCase means that first case statement.
+ // is selected actually
+ // (See https://github.com/apple/swift-clang & CompoundStmtRange).
+
+ // FIXME (Alex L): Tweak selection rules for compound statements, see:
+ // https://github.com/apple/swift-clang/blob/swift-4.1-branch/lib/Tooling/
+ // Refactor/ASTSlice.cpp#L513
+ // The user selected multiple statements in a compound statement.
+ Selected.Parents.push_back(Selected.Node);
+ return CodeRangeASTSelection(Selected.Node, Selected.Parents,
+ /*AreChildrenSelected=*/true);
+}
+
+static bool isFunctionLikeDeclaration(const Decl *D) {
+ // FIXME (Alex L): Test for BlockDecl.
+ return isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D);
+}
+
+bool CodeRangeASTSelection::isInFunctionLikeBodyOfCode() const {
+ bool IsPrevCompound = false;
+ // Scan through the parents (bottom-to-top) and check if the selection is
+ // contained in a compound statement that's a body of a function/method
+ // declaration.
+ for (const auto &Parent : llvm::reverse(Parents)) {
+ const DynTypedNode &Node = Parent.get().Node;
+ if (const auto *D = Node.get<Decl>()) {
+ if (isFunctionLikeDeclaration(D))
+ return IsPrevCompound;
+ // Stop the search at any type declaration to avoid returning true for
+ // expressions in type declarations in functions, like:
+ // function foo() { struct X {
+ // int m = /*selection:*/ 1 + 2 /*selection end*/; }; };
+ if (isa<TypeDecl>(D))
+ return false;
+ }
+ IsPrevCompound = Node.get<CompoundStmt>() != nullptr;
+ }
+ return false;
+}
+
+const Decl *CodeRangeASTSelection::getFunctionLikeNearestParent() const {
+ for (const auto &Parent : llvm::reverse(Parents)) {
+ const DynTypedNode &Node = Parent.get().Node;
+ if (const auto *D = Node.get<Decl>()) {
+ if (isFunctionLikeDeclaration(D))
+ return D;
+ }
+ }
+ return nullptr;
+}
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Refactoring/ASTSelectionRequirements.cpp b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/ASTSelectionRequirements.cpp
new file mode 100644
index 0000000000000..c0232c5da4429
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/ASTSelectionRequirements.cpp
@@ -0,0 +1,48 @@
+//===--- ASTSelectionRequirements.cpp - Clang refactoring library ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h"
+
+using namespace clang;
+using namespace tooling;
+
+Expected<SelectedASTNode>
+ASTSelectionRequirement::evaluate(RefactoringRuleContext &Context) const {
+ // FIXME: Memoize so that selection is evaluated only once.
+ Expected<SourceRange> Range =
+ SourceRangeSelectionRequirement::evaluate(Context);
+ if (!Range)
+ return Range.takeError();
+
+ Optional<SelectedASTNode> Selection =
+ findSelectedASTNodes(Context.getASTContext(), *Range);
+ if (!Selection)
+ return Context.createDiagnosticError(
+ Range->getBegin(), diag::err_refactor_selection_invalid_ast);
+ return std::move(*Selection);
+}
+
+Expected<CodeRangeASTSelection> CodeRangeASTSelectionRequirement::evaluate(
+ RefactoringRuleContext &Context) const {
+ // FIXME: Memoize so that selection is evaluated only once.
+ Expected<SelectedASTNode> ASTSelection =
+ ASTSelectionRequirement::evaluate(Context);
+ if (!ASTSelection)
+ return ASTSelection.takeError();
+ std::unique_ptr<SelectedASTNode> StoredSelection =
+ llvm::make_unique<SelectedASTNode>(std::move(*ASTSelection));
+ Optional<CodeRangeASTSelection> CodeRange = CodeRangeASTSelection::create(
+ Context.getSelectionRange(), *StoredSelection);
+ if (!CodeRange)
+ return Context.createDiagnosticError(
+ Context.getSelectionRange().getBegin(),
+ diag::err_refactor_selection_invalid_ast);
+ Context.setASTSelection(std::move(StoredSelection));
+ return std::move(*CodeRange);
+}
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Refactoring/AtomicChange.cpp b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/AtomicChange.cpp
index 79dd346acf72f..e4cc6a5617b65 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/Refactoring/AtomicChange.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/AtomicChange.cpp
@@ -83,6 +83,116 @@ template <> struct MappingTraits<clang::tooling::AtomicChange> {
namespace clang {
namespace tooling {
+namespace {
+
+// Returns true if there is any line that violates \p ColumnLimit in range
+// [Start, End].
+bool violatesColumnLimit(llvm::StringRef Code, unsigned ColumnLimit,
+ unsigned Start, unsigned End) {
+ auto StartPos = Code.rfind('\n', Start);
+ StartPos = (StartPos == llvm::StringRef::npos) ? 0 : StartPos + 1;
+
+ auto EndPos = Code.find("\n", End);
+ if (EndPos == llvm::StringRef::npos)
+ EndPos = Code.size();
+
+ llvm::SmallVector<llvm::StringRef, 8> Lines;
+ Code.substr(StartPos, EndPos - StartPos).split(Lines, '\n');
+ for (llvm::StringRef Line : Lines)
+ if (Line.size() > ColumnLimit)
+ return true;
+ return false;
+}
+
+std::vector<Range>
+getRangesForFormating(llvm::StringRef Code, unsigned ColumnLimit,
+ ApplyChangesSpec::FormatOption Format,
+ const clang::tooling::Replacements &Replaces) {
+ // kNone suppresses formatting entirely.
+ if (Format == ApplyChangesSpec::kNone)
+ return {};
+ std::vector<clang::tooling::Range> Ranges;
+ // This works assuming that replacements are ordered by offset.
+ // FIXME: use `getAffectedRanges()` to calculate when it does not include '\n'
+ // at the end of an insertion in affected ranges.
+ int Offset = 0;
+ for (const clang::tooling::Replacement &R : Replaces) {
+ int Start = R.getOffset() + Offset;
+ int End = Start + R.getReplacementText().size();
+ if (!R.getReplacementText().empty() &&
+ R.getReplacementText().back() == '\n' && R.getLength() == 0 &&
+ R.getOffset() > 0 && R.getOffset() <= Code.size() &&
+ Code[R.getOffset() - 1] == '\n')
+ // If we are inserting at the start of a line and the replacement ends in
+ // a newline, we don't need to format the subsequent line.
+ --End;
+ Offset += R.getReplacementText().size() - R.getLength();
+
+ if (Format == ApplyChangesSpec::kAll ||
+ violatesColumnLimit(Code, ColumnLimit, Start, End))
+ Ranges.emplace_back(Start, End - Start);
+ }
+ return Ranges;
+}
+
+inline llvm::Error make_string_error(const llvm::Twine &Message) {
+ return llvm::make_error<llvm::StringError>(Message,
+ llvm::inconvertibleErrorCode());
+}
+
+// Creates replacements for inserting/deleting #include headers.
+llvm::Expected<Replacements>
+createReplacementsForHeaders(llvm::StringRef FilePath, llvm::StringRef Code,
+ llvm::ArrayRef<AtomicChange> Changes,
+ const format::FormatStyle &Style) {
+ // Create header insertion/deletion replacements to be cleaned up
+ // (i.e. converted to real insertion/deletion replacements).
+ Replacements HeaderReplacements;
+ for (const auto &Change : Changes) {
+ for (llvm::StringRef Header : Change.getInsertedHeaders()) {
+ std::string EscapedHeader =
+ Header.startswith("<") || Header.startswith("\"")
+ ? Header.str()
+ : ("\"" + Header + "\"").str();
+ std::string ReplacementText = "#include " + EscapedHeader;
+ // Offset UINT_MAX and length 0 indicate that the replacement is a header
+ // insertion.
+ llvm::Error Err = HeaderReplacements.add(
+ tooling::Replacement(FilePath, UINT_MAX, 0, ReplacementText));
+ if (Err)
+ return std::move(Err);
+ }
+ for (const std::string &Header : Change.getRemovedHeaders()) {
+ // Offset UINT_MAX and length 1 indicate that the replacement is a header
+ // deletion.
+ llvm::Error Err =
+ HeaderReplacements.add(Replacement(FilePath, UINT_MAX, 1, Header));
+ if (Err)
+ return std::move(Err);
+ }
+ }
+
+ // cleanupAroundReplacements() converts header insertions/deletions into
+ // actual replacements that add/remove headers at the right location.
+ return clang::format::cleanupAroundReplacements(Code, HeaderReplacements,
+ Style);
+}
+
+// Combine replacements in all Changes as a `Replacements`. This ignores the
+// file path in all replacements and replaces them with \p FilePath.
+llvm::Expected<Replacements>
+combineReplacementsInChanges(llvm::StringRef FilePath,
+ llvm::ArrayRef<AtomicChange> Changes) {
+ Replacements Replaces;
+ for (const auto &Change : Changes)
+ for (const auto &R : Change.getReplacements())
+ if (auto Err = Replaces.add(Replacement(
+ FilePath, R.getOffset(), R.getLength(), R.getReplacementText())))
+ return std::move(Err);
+ return Replaces;
+}
+
+} // end namespace
AtomicChange::AtomicChange(const SourceManager &SM,
SourceLocation KeyPosition) {
@@ -105,6 +215,15 @@ AtomicChange::AtomicChange(std::string Key, std::string FilePath,
RemovedHeaders(std::move(RemovedHeaders)), Replaces(std::move(Replaces)) {
}
+bool AtomicChange::operator==(const AtomicChange &Other) const {
+ if (Key != Other.Key || FilePath != Other.FilePath || Error != Other.Error)
+ return false;
+ if (!(Replaces == Other.Replaces))
+ return false;
+ // FXIME: Compare header insertions/removals.
+ return true;
+}
+
std::string AtomicChange::toYAMLString() {
std::string YamlContent;
llvm::raw_string_ostream YamlContentStream(YamlContent);
@@ -173,5 +292,74 @@ void AtomicChange::removeHeader(llvm::StringRef Header) {
RemovedHeaders.push_back(Header);
}
+llvm::Expected<std::string>
+applyAtomicChanges(llvm::StringRef FilePath, llvm::StringRef Code,
+ llvm::ArrayRef<AtomicChange> Changes,
+ const ApplyChangesSpec &Spec) {
+ llvm::Expected<Replacements> HeaderReplacements =
+ createReplacementsForHeaders(FilePath, Code, Changes, Spec.Style);
+ if (!HeaderReplacements)
+ return make_string_error(
+ "Failed to create replacements for header changes: " +
+ llvm::toString(HeaderReplacements.takeError()));
+
+ llvm::Expected<Replacements> Replaces =
+ combineReplacementsInChanges(FilePath, Changes);
+ if (!Replaces)
+ return make_string_error("Failed to combine replacements in all changes: " +
+ llvm::toString(Replaces.takeError()));
+
+ Replacements AllReplaces = std::move(*Replaces);
+ for (const auto &R : *HeaderReplacements) {
+ llvm::Error Err = AllReplaces.add(R);
+ if (Err)
+ return make_string_error(
+ "Failed to combine existing replacements with header replacements: " +
+ llvm::toString(std::move(Err)));
+ }
+
+ if (Spec.Cleanup) {
+ llvm::Expected<Replacements> CleanReplaces =
+ format::cleanupAroundReplacements(Code, AllReplaces, Spec.Style);
+ if (!CleanReplaces)
+ return make_string_error("Failed to cleanup around replacements: " +
+ llvm::toString(CleanReplaces.takeError()));
+ AllReplaces = std::move(*CleanReplaces);
+ }
+
+ // Apply all replacements.
+ llvm::Expected<std::string> ChangedCode =
+ applyAllReplacements(Code, AllReplaces);
+ if (!ChangedCode)
+ return make_string_error("Failed to apply all replacements: " +
+ llvm::toString(ChangedCode.takeError()));
+
+ // Sort inserted headers. This is done even if other formatting is turned off
+ // as incorrectly sorted headers are always just wrong, it's not a matter of
+ // taste.
+ Replacements HeaderSortingReplacements = format::sortIncludes(
+ Spec.Style, *ChangedCode, AllReplaces.getAffectedRanges(), FilePath);
+ ChangedCode = applyAllReplacements(*ChangedCode, HeaderSortingReplacements);
+ if (!ChangedCode)
+ return make_string_error(
+ "Failed to apply replacements for sorting includes: " +
+ llvm::toString(ChangedCode.takeError()));
+
+ AllReplaces = AllReplaces.merge(HeaderSortingReplacements);
+
+ std::vector<Range> FormatRanges = getRangesForFormating(
+ *ChangedCode, Spec.Style.ColumnLimit, Spec.Format, AllReplaces);
+ if (!FormatRanges.empty()) {
+ Replacements FormatReplacements =
+ format::reformat(Spec.Style, *ChangedCode, FormatRanges, FilePath);
+ ChangedCode = applyAllReplacements(*ChangedCode, FormatReplacements);
+ if (!ChangedCode)
+ return make_string_error(
+ "Failed to apply replacements for formatting changed code: " +
+ llvm::toString(ChangedCode.takeError()));
+ }
+ return ChangedCode;
+}
+
} // end namespace tooling
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Extract/Extract.cpp b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Extract/Extract.cpp
new file mode 100644
index 0000000000000..b0847a7400481
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Extract/Extract.cpp
@@ -0,0 +1,199 @@
+//===--- Extract.cpp - Clang refactoring library --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Implements the "extract" refactoring that can pull code into
+/// new functions, methods or declare new variables.
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/Refactoring/Extract/Extract.h"
+#include "SourceExtraction.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/Rewrite/Core/Rewriter.h"
+
+namespace clang {
+namespace tooling {
+
+namespace {
+
+/// Returns true if \c E is a simple literal or a reference expression that
+/// should not be extracted.
+bool isSimpleExpression(const Expr *E) {
+ if (!E)
+ return false;
+ switch (E->IgnoreParenCasts()->getStmtClass()) {
+ case Stmt::DeclRefExprClass:
+ case Stmt::PredefinedExprClass:
+ case Stmt::IntegerLiteralClass:
+ case Stmt::FloatingLiteralClass:
+ case Stmt::ImaginaryLiteralClass:
+ case Stmt::CharacterLiteralClass:
+ case Stmt::StringLiteralClass:
+ return true;
+ default:
+ return false;
+ }
+}
+
+SourceLocation computeFunctionExtractionLocation(const Decl *D) {
+ if (isa<CXXMethodDecl>(D)) {
+ // Code from method that is defined in class body should be extracted to a
+ // function defined just before the class.
+ while (const auto *RD = dyn_cast<CXXRecordDecl>(D->getLexicalDeclContext()))
+ D = RD;
+ }
+ return D->getLocStart();
+}
+
+} // end anonymous namespace
+
+const RefactoringDescriptor &ExtractFunction::describe() {
+ static const RefactoringDescriptor Descriptor = {
+ "extract-function",
+ "Extract Function",
+ "(WIP action; use with caution!) Extracts code into a new function",
+ };
+ return Descriptor;
+}
+
+Expected<ExtractFunction>
+ExtractFunction::initiate(RefactoringRuleContext &Context,
+ CodeRangeASTSelection Code,
+ Optional<std::string> DeclName) {
+ // We would like to extract code out of functions/methods/blocks.
+ // Prohibit extraction from things like global variable / field
+ // initializers and other top-level expressions.
+ if (!Code.isInFunctionLikeBodyOfCode())
+ return Context.createDiagnosticError(
+ diag::err_refactor_code_outside_of_function);
+
+ if (Code.size() == 1) {
+ // Avoid extraction of simple literals and references.
+ if (isSimpleExpression(dyn_cast<Expr>(Code[0])))
+ return Context.createDiagnosticError(
+ diag::err_refactor_extract_simple_expression);
+
+ // Property setters can't be extracted.
+ if (const auto *PRE = dyn_cast<ObjCPropertyRefExpr>(Code[0])) {
+ if (!PRE->isMessagingGetter())
+ return Context.createDiagnosticError(
+ diag::err_refactor_extract_prohibited_expression);
+ }
+ }
+
+ return ExtractFunction(std::move(Code), DeclName);
+}
+
+// FIXME: Support C++ method extraction.
+// FIXME: Support Objective-C method extraction.
+Expected<AtomicChanges>
+ExtractFunction::createSourceReplacements(RefactoringRuleContext &Context) {
+ const Decl *ParentDecl = Code.getFunctionLikeNearestParent();
+ assert(ParentDecl && "missing parent");
+
+ // Compute the source range of the code that should be extracted.
+ SourceRange ExtractedRange(Code[0]->getLocStart(),
+ Code[Code.size() - 1]->getLocEnd());
+ // FIXME (Alex L): Add code that accounts for macro locations.
+
+ ASTContext &AST = Context.getASTContext();
+ SourceManager &SM = AST.getSourceManager();
+ const LangOptions &LangOpts = AST.getLangOpts();
+ Rewriter ExtractedCodeRewriter(SM, LangOpts);
+
+ // FIXME: Capture used variables.
+
+ // Compute the return type.
+ QualType ReturnType = AST.VoidTy;
+ // FIXME (Alex L): Account for the return statement in extracted code.
+ // FIXME (Alex L): Check for lexical expression instead.
+ bool IsExpr = Code.size() == 1 && isa<Expr>(Code[0]);
+ if (IsExpr) {
+ // FIXME (Alex L): Get a more user-friendly type if needed.
+ ReturnType = cast<Expr>(Code[0])->getType();
+ }
+
+ // FIXME: Rewrite the extracted code performing any required adjustments.
+
+ // FIXME: Capture any field if necessary (method -> function extraction).
+
+ // FIXME: Sort captured variables by name.
+
+ // FIXME: Capture 'this' / 'self' if necessary.
+
+ // FIXME: Compute the actual parameter types.
+
+ // Compute the location of the extracted declaration.
+ SourceLocation ExtractedDeclLocation =
+ computeFunctionExtractionLocation(ParentDecl);
+ // FIXME: Adjust the location to account for any preceding comments.
+
+ // FIXME: Adjust with PP awareness like in Sema to get correct 'bool'
+ // treatment.
+ PrintingPolicy PP = AST.getPrintingPolicy();
+ // FIXME: PP.UseStdFunctionForLambda = true;
+ PP.SuppressStrongLifetime = true;
+ PP.SuppressLifetimeQualifiers = true;
+ PP.SuppressUnwrittenScope = true;
+
+ ExtractionSemicolonPolicy Semicolons = ExtractionSemicolonPolicy::compute(
+ Code[Code.size() - 1], ExtractedRange, SM, LangOpts);
+ AtomicChange Change(SM, ExtractedDeclLocation);
+ // Create the replacement for the extracted declaration.
+ {
+ std::string ExtractedCode;
+ llvm::raw_string_ostream OS(ExtractedCode);
+ // FIXME: Use 'inline' in header.
+ OS << "static ";
+ ReturnType.print(OS, PP, DeclName);
+ OS << '(';
+ // FIXME: Arguments.
+ OS << ')';
+
+ // Function body.
+ OS << " {\n";
+ if (IsExpr && !ReturnType->isVoidType())
+ OS << "return ";
+ OS << ExtractedCodeRewriter.getRewrittenText(ExtractedRange);
+ if (Semicolons.isNeededInExtractedFunction())
+ OS << ';';
+ OS << "\n}\n\n";
+ auto Err = Change.insert(SM, ExtractedDeclLocation, OS.str());
+ if (Err)
+ return std::move(Err);
+ }
+
+ // Create the replacement for the call to the extracted declaration.
+ {
+ std::string ReplacedCode;
+ llvm::raw_string_ostream OS(ReplacedCode);
+
+ OS << DeclName << '(';
+ // FIXME: Forward arguments.
+ OS << ')';
+ if (Semicolons.isNeededInOriginalFunction())
+ OS << ';';
+
+ auto Err = Change.replace(
+ SM, CharSourceRange::getTokenRange(ExtractedRange), OS.str());
+ if (Err)
+ return std::move(Err);
+ }
+
+ // FIXME: Add support for assocciated symbol location to AtomicChange to mark
+ // the ranges of the name of the extracted declaration.
+ return AtomicChanges{std::move(Change)};
+}
+
+} // end namespace tooling
+} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
new file mode 100644
index 0000000000000..7fd8cc2d3c7fb
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
@@ -0,0 +1,112 @@
+//===--- SourceExtraction.cpp - Clang refactoring library -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SourceExtraction.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtObjC.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang;
+
+namespace {
+
+/// Returns true if the token at the given location is a semicolon.
+bool isSemicolonAtLocation(SourceLocation TokenLoc, const SourceManager &SM,
+ const LangOptions &LangOpts) {
+ return Lexer::getSourceText(
+ CharSourceRange::getTokenRange(TokenLoc, TokenLoc), SM,
+ LangOpts) == ";";
+}
+
+/// Returns true if there should be a semicolon after the given statement.
+bool isSemicolonRequiredAfter(const Stmt *S) {
+ if (isa<CompoundStmt>(S))
+ return false;
+ if (const auto *If = dyn_cast<IfStmt>(S))
+ return isSemicolonRequiredAfter(If->getElse() ? If->getElse()
+ : If->getThen());
+ if (const auto *While = dyn_cast<WhileStmt>(S))
+ return isSemicolonRequiredAfter(While->getBody());
+ if (const auto *For = dyn_cast<ForStmt>(S))
+ return isSemicolonRequiredAfter(For->getBody());
+ if (const auto *CXXFor = dyn_cast<CXXForRangeStmt>(S))
+ return isSemicolonRequiredAfter(CXXFor->getBody());
+ if (const auto *ObjCFor = dyn_cast<ObjCForCollectionStmt>(S))
+ return isSemicolonRequiredAfter(ObjCFor->getBody());
+ switch (S->getStmtClass()) {
+ case Stmt::SwitchStmtClass:
+ case Stmt::CXXTryStmtClass:
+ case Stmt::ObjCAtSynchronizedStmtClass:
+ case Stmt::ObjCAutoreleasePoolStmtClass:
+ case Stmt::ObjCAtTryStmtClass:
+ return false;
+ default:
+ return true;
+ }
+}
+
+/// Returns true if the two source locations are on the same line.
+bool areOnSameLine(SourceLocation Loc1, SourceLocation Loc2,
+ const SourceManager &SM) {
+ return !Loc1.isMacroID() && !Loc2.isMacroID() &&
+ SM.getSpellingLineNumber(Loc1) == SM.getSpellingLineNumber(Loc2);
+}
+
+} // end anonymous namespace
+
+namespace clang {
+namespace tooling {
+
+ExtractionSemicolonPolicy
+ExtractionSemicolonPolicy::compute(const Stmt *S, SourceRange &ExtractedRange,
+ const SourceManager &SM,
+ const LangOptions &LangOpts) {
+ auto neededInExtractedFunction = []() {
+ return ExtractionSemicolonPolicy(true, false);
+ };
+ auto neededInOriginalFunction = []() {
+ return ExtractionSemicolonPolicy(false, true);
+ };
+
+ /// The extracted expression should be terminated with a ';'. The call to
+ /// the extracted function will replace this expression, so it won't need
+ /// a terminating ';'.
+ if (isa<Expr>(S))
+ return neededInExtractedFunction();
+
+ /// Some statements don't need to be terminated with ';'. The call to the
+ /// extracted function will be a standalone statement, so it should be
+ /// terminated with a ';'.
+ bool NeedsSemi = isSemicolonRequiredAfter(S);
+ if (!NeedsSemi)
+ return neededInOriginalFunction();
+
+ /// Some statements might end at ';'. The extraction will move that ';', so
+ /// the call to the extracted function should be terminated with a ';'.
+ SourceLocation End = ExtractedRange.getEnd();
+ if (isSemicolonAtLocation(End, SM, LangOpts))
+ return neededInOriginalFunction();
+
+ /// Other statements should generally have a trailing ';'. We can try to find
+ /// it and move it together it with the extracted code.
+ Optional<Token> NextToken = Lexer::findNextToken(End, SM, LangOpts);
+ if (NextToken && NextToken->is(tok::semi) &&
+ areOnSameLine(NextToken->getLocation(), End, SM)) {
+ ExtractedRange.setEnd(NextToken->getLocation());
+ return neededInOriginalFunction();
+ }
+
+ /// Otherwise insert semicolons in both places.
+ return ExtractionSemicolonPolicy(true, true);
+}
+
+} // end namespace tooling
+} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Extract/SourceExtraction.h b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Extract/SourceExtraction.h
new file mode 100644
index 0000000000000..4b4bd8b477ff4
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Extract/SourceExtraction.h
@@ -0,0 +1,52 @@
+//===--- SourceExtraction.cpp - Clang refactoring library -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H
+#define LLVM_CLANG_LIB_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H
+
+#include "clang/Basic/LLVM.h"
+
+namespace clang {
+
+class LangOptions;
+class SourceManager;
+class SourceRange;
+class Stmt;
+
+namespace tooling {
+
+/// Determines which semicolons should be inserted during extraction.
+class ExtractionSemicolonPolicy {
+public:
+ bool isNeededInExtractedFunction() const {
+ return IsNeededInExtractedFunction;
+ }
+
+ bool isNeededInOriginalFunction() const { return IsNeededInOriginalFunction; }
+
+ /// Returns the semicolon insertion policy that is needed for extraction of
+ /// the given statement from the given source range.
+ static ExtractionSemicolonPolicy compute(const Stmt *S,
+ SourceRange &ExtractedRange,
+ const SourceManager &SM,
+ const LangOptions &LangOpts);
+
+private:
+ ExtractionSemicolonPolicy(bool IsNeededInExtractedFunction,
+ bool IsNeededInOriginalFunction)
+ : IsNeededInExtractedFunction(IsNeededInExtractedFunction),
+ IsNeededInOriginalFunction(IsNeededInOriginalFunction) {}
+ bool IsNeededInExtractedFunction;
+ bool IsNeededInOriginalFunction;
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Refactoring/RefactoringActions.cpp b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/RefactoringActions.cpp
new file mode 100644
index 0000000000000..37a1639cb4464
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/RefactoringActions.cpp
@@ -0,0 +1,114 @@
+//===--- RefactoringActions.cpp - Constructs refactoring actions ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/Refactoring/Extract/Extract.h"
+#include "clang/Tooling/Refactoring/RefactoringAction.h"
+#include "clang/Tooling/Refactoring/RefactoringOptions.h"
+#include "clang/Tooling/Refactoring/Rename/RenamingAction.h"
+
+namespace clang {
+namespace tooling {
+
+namespace {
+
+class DeclNameOption final : public OptionalRefactoringOption<std::string> {
+public:
+ StringRef getName() const { return "name"; }
+ StringRef getDescription() const {
+ return "Name of the extracted declaration";
+ }
+};
+
+// FIXME: Rewrite the Actions to avoid duplication of descriptions/names with
+// rules.
+class ExtractRefactoring final : public RefactoringAction {
+public:
+ StringRef getCommand() const override { return "extract"; }
+
+ StringRef getDescription() const override {
+ return "(WIP action; use with caution!) Extracts code into a new function";
+ }
+
+ /// Returns a set of refactoring actions rules that are defined by this
+ /// action.
+ RefactoringActionRules createActionRules() const override {
+ RefactoringActionRules Rules;
+ Rules.push_back(createRefactoringActionRule<ExtractFunction>(
+ CodeRangeASTSelectionRequirement(),
+ OptionRequirement<DeclNameOption>()));
+ return Rules;
+ }
+};
+
+class OldQualifiedNameOption : public RequiredRefactoringOption<std::string> {
+public:
+ StringRef getName() const override { return "old-qualified-name"; }
+ StringRef getDescription() const override {
+ return "The old qualified name to be renamed";
+ }
+};
+
+class NewQualifiedNameOption : public RequiredRefactoringOption<std::string> {
+public:
+ StringRef getName() const override { return "new-qualified-name"; }
+ StringRef getDescription() const override {
+ return "The new qualified name to change the symbol to";
+ }
+};
+
+class NewNameOption : public RequiredRefactoringOption<std::string> {
+public:
+ StringRef getName() const override { return "new-name"; }
+ StringRef getDescription() const override {
+ return "The new name to change the symbol to";
+ }
+};
+
+// FIXME: Rewrite the Actions to avoid duplication of descriptions/names with
+// rules.
+class LocalRename final : public RefactoringAction {
+public:
+ StringRef getCommand() const override { return "local-rename"; }
+
+ StringRef getDescription() const override {
+ return "Finds and renames symbols in code with no indexer support";
+ }
+
+ /// Returns a set of refactoring actions rules that are defined by this
+ /// action.
+ RefactoringActionRules createActionRules() const override {
+ RefactoringActionRules Rules;
+ Rules.push_back(createRefactoringActionRule<RenameOccurrences>(
+ SourceRangeSelectionRequirement(), OptionRequirement<NewNameOption>()));
+ // FIXME: Use NewNameOption.
+ Rules.push_back(createRefactoringActionRule<QualifiedRenameRule>(
+ OptionRequirement<OldQualifiedNameOption>(),
+ OptionRequirement<NewQualifiedNameOption>()));
+ return Rules;
+ }
+};
+
+} // end anonymous namespace
+
+std::vector<std::unique_ptr<RefactoringAction>> createRefactoringActions() {
+ std::vector<std::unique_ptr<RefactoringAction>> Actions;
+
+ Actions.push_back(llvm::make_unique<LocalRename>());
+ Actions.push_back(llvm::make_unique<ExtractRefactoring>());
+
+ return Actions;
+}
+
+RefactoringActionRules RefactoringAction::createActiveActionRules() {
+ // FIXME: Filter out rules that are not supported by a particular client.
+ return createActionRules();
+}
+
+} // end namespace tooling
+} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/RenamingAction.cpp b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/RenamingAction.cpp
index de6aba944a4aa..c8ed9dd19a8e8 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/RenamingAction.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/RenamingAction.cpp
@@ -22,8 +22,17 @@
#include "clang/Lex/Preprocessor.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Refactoring.h"
+#include "clang/Tooling/Refactoring/RefactoringAction.h"
+#include "clang/Tooling/Refactoring/RefactoringDiagnostic.h"
+#include "clang/Tooling/Refactoring/RefactoringOptions.h"
+#include "clang/Tooling/Refactoring/Rename/SymbolName.h"
+#include "clang/Tooling/Refactoring/Rename/USRFinder.h"
+#include "clang/Tooling/Refactoring/Rename/USRFindingAction.h"
#include "clang/Tooling/Refactoring/Rename/USRLocFinder.h"
#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Error.h"
#include <string>
#include <vector>
@@ -32,6 +41,143 @@ using namespace llvm;
namespace clang {
namespace tooling {
+namespace {
+
+Expected<SymbolOccurrences>
+findSymbolOccurrences(const NamedDecl *ND, RefactoringRuleContext &Context) {
+ std::vector<std::string> USRs =
+ getUSRsForDeclaration(ND, Context.getASTContext());
+ std::string PrevName = ND->getNameAsString();
+ return getOccurrencesOfUSRs(USRs, PrevName,
+ Context.getASTContext().getTranslationUnitDecl());
+}
+
+} // end anonymous namespace
+
+const RefactoringDescriptor &RenameOccurrences::describe() {
+ static const RefactoringDescriptor Descriptor = {
+ "local-rename",
+ "Rename",
+ "Finds and renames symbols in code with no indexer support",
+ };
+ return Descriptor;
+}
+
+Expected<RenameOccurrences>
+RenameOccurrences::initiate(RefactoringRuleContext &Context,
+ SourceRange SelectionRange, std::string NewName) {
+ const NamedDecl *ND =
+ getNamedDeclAt(Context.getASTContext(), SelectionRange.getBegin());
+ if (!ND)
+ return Context.createDiagnosticError(
+ SelectionRange.getBegin(), diag::err_refactor_selection_no_symbol);
+ return RenameOccurrences(getCanonicalSymbolDeclaration(ND),
+ std::move(NewName));
+}
+
+Expected<AtomicChanges>
+RenameOccurrences::createSourceReplacements(RefactoringRuleContext &Context) {
+ Expected<SymbolOccurrences> Occurrences = findSymbolOccurrences(ND, Context);
+ if (!Occurrences)
+ return Occurrences.takeError();
+ // FIXME: Verify that the new name is valid.
+ SymbolName Name(NewName);
+ return createRenameReplacements(
+ *Occurrences, Context.getASTContext().getSourceManager(), Name);
+}
+
+Expected<QualifiedRenameRule>
+QualifiedRenameRule::initiate(RefactoringRuleContext &Context,
+ std::string OldQualifiedName,
+ std::string NewQualifiedName) {
+ const NamedDecl *ND =
+ getNamedDeclFor(Context.getASTContext(), OldQualifiedName);
+ if (!ND)
+ return llvm::make_error<llvm::StringError>("Could not find symbol " +
+ OldQualifiedName,
+ llvm::errc::invalid_argument);
+ return QualifiedRenameRule(ND, std::move(NewQualifiedName));
+}
+
+const RefactoringDescriptor &QualifiedRenameRule::describe() {
+ static const RefactoringDescriptor Descriptor = {
+ /*Name=*/"local-qualified-rename",
+ /*Title=*/"Qualified Rename",
+ /*Description=*/
+ R"(Finds and renames qualified symbols in code within a translation unit.
+It is used to move/rename a symbol to a new namespace/name:
+ * Supported symbols: classes, class members, functions, enums, and type alias.
+ * Renames all symbol occurrences from the old qualified name to the new
+ qualified name. All symbol references will be correctly qualified; For
+ symbol definitions, only name will be changed.
+For example, rename "A::Foo" to "B::Bar":
+ Old code:
+ namespace foo {
+ class A {};
+ }
+
+ namespace bar {
+ void f(foo::A a) {}
+ }
+
+ New code after rename:
+ namespace foo {
+ class B {};
+ }
+
+ namespace bar {
+ void f(B b) {}
+ })"
+ };
+ return Descriptor;
+}
+
+Expected<AtomicChanges>
+QualifiedRenameRule::createSourceReplacements(RefactoringRuleContext &Context) {
+ auto USRs = getUSRsForDeclaration(ND, Context.getASTContext());
+ assert(!USRs.empty());
+ return tooling::createRenameAtomicChanges(
+ USRs, NewQualifiedName, Context.getASTContext().getTranslationUnitDecl());
+}
+
+Expected<std::vector<AtomicChange>>
+createRenameReplacements(const SymbolOccurrences &Occurrences,
+ const SourceManager &SM, const SymbolName &NewName) {
+ // FIXME: A true local rename can use just one AtomicChange.
+ std::vector<AtomicChange> Changes;
+ for (const auto &Occurrence : Occurrences) {
+ ArrayRef<SourceRange> Ranges = Occurrence.getNameRanges();
+ assert(NewName.getNamePieces().size() == Ranges.size() &&
+ "Mismatching number of ranges and name pieces");
+ AtomicChange Change(SM, Ranges[0].getBegin());
+ for (const auto &Range : llvm::enumerate(Ranges)) {
+ auto Error =
+ Change.replace(SM, CharSourceRange::getCharRange(Range.value()),
+ NewName.getNamePieces()[Range.index()]);
+ if (Error)
+ return std::move(Error);
+ }
+ Changes.push_back(std::move(Change));
+ }
+ return std::move(Changes);
+}
+
+/// Takes each atomic change and inserts its replacements into the set of
+/// replacements that belong to the appropriate file.
+static void convertChangesToFileReplacements(
+ ArrayRef<AtomicChange> AtomicChanges,
+ std::map<std::string, tooling::Replacements> *FileToReplaces) {
+ for (const auto &AtomicChange : AtomicChanges) {
+ for (const auto &Replace : AtomicChange.getReplacements()) {
+ llvm::Error Err = (*FileToReplaces)[Replace.getFilePath()].add(Replace);
+ if (Err) {
+ llvm::errs() << "Renaming failed in " << Replace.getFilePath() << "! "
+ << llvm::toString(std::move(Err)) << "\n";
+ }
+ }
+ }
+}
+
class RenamingASTConsumer : public ASTConsumer {
public:
RenamingASTConsumer(
@@ -44,37 +190,42 @@ public:
FileToReplaces(FileToReplaces), PrintLocations(PrintLocations) {}
void HandleTranslationUnit(ASTContext &Context) override {
- for (unsigned I = 0; I < NewNames.size(); ++I)
+ for (unsigned I = 0; I < NewNames.size(); ++I) {
+ // If the previous name was not found, ignore this rename request.
+ if (PrevNames[I].empty())
+ continue;
+
HandleOneRename(Context, NewNames[I], PrevNames[I], USRList[I]);
+ }
}
void HandleOneRename(ASTContext &Context, const std::string &NewName,
const std::string &PrevName,
const std::vector<std::string> &USRs) {
const SourceManager &SourceMgr = Context.getSourceManager();
- std::vector<SourceLocation> RenamingCandidates;
- std::vector<SourceLocation> NewCandidates;
- NewCandidates = tooling::getLocationsOfUSRs(
+ SymbolOccurrences Occurrences = tooling::getOccurrencesOfUSRs(
USRs, PrevName, Context.getTranslationUnitDecl());
- RenamingCandidates.insert(RenamingCandidates.end(), NewCandidates.begin(),
- NewCandidates.end());
-
- unsigned PrevNameLen = PrevName.length();
- for (const auto &Loc : RenamingCandidates) {
- if (PrintLocations) {
- FullSourceLoc FullLoc(Loc, SourceMgr);
- errs() << "clang-rename: renamed at: " << SourceMgr.getFilename(Loc)
+ if (PrintLocations) {
+ for (const auto &Occurrence : Occurrences) {
+ FullSourceLoc FullLoc(Occurrence.getNameRanges()[0].getBegin(),
+ SourceMgr);
+ errs() << "clang-rename: renamed at: " << SourceMgr.getFilename(FullLoc)
<< ":" << FullLoc.getSpellingLineNumber() << ":"
<< FullLoc.getSpellingColumnNumber() << "\n";
}
- // FIXME: better error handling.
- tooling::Replacement Replace(SourceMgr, Loc, PrevNameLen, NewName);
- llvm::Error Err = FileToReplaces[Replace.getFilePath()].add(Replace);
- if (Err)
- llvm::errs() << "Renaming failed in " << Replace.getFilePath() << "! "
- << llvm::toString(std::move(Err)) << "\n";
}
+ // FIXME: Support multi-piece names.
+ // FIXME: better error handling (propagate error out).
+ SymbolName NewNameRef(NewName);
+ Expected<std::vector<AtomicChange>> Change =
+ createRenameReplacements(Occurrences, SourceMgr, NewNameRef);
+ if (!Change) {
+ llvm::errs() << "Failed to create renaming replacements for '" << PrevName
+ << "'! " << llvm::toString(Change.takeError()) << "\n";
+ return;
+ }
+ convertChangesToFileReplacements(*Change, &FileToReplaces);
}
private:
@@ -103,15 +254,7 @@ public:
// ready.
auto AtomicChanges = tooling::createRenameAtomicChanges(
USRList[I], NewNames[I], Context.getTranslationUnitDecl());
- for (const auto AtomicChange : AtomicChanges) {
- for (const auto &Replace : AtomicChange.getReplacements()) {
- llvm::Error Err = FileToReplaces[Replace.getFilePath()].add(Replace);
- if (Err) {
- llvm::errs() << "Renaming failed in " << Replace.getFilePath()
- << "! " << llvm::toString(std::move(Err)) << "\n";
- }
- }
- }
+ convertChangesToFileReplacements(AtomicChanges, &FileToReplaces);
}
}
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/SymbolOccurrences.cpp b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/SymbolOccurrences.cpp
new file mode 100644
index 0000000000000..ea64b2c1aa8c7
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/SymbolOccurrences.cpp
@@ -0,0 +1,37 @@
+//===--- SymbolOccurrences.cpp - Clang refactoring library ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/Refactoring/Rename/SymbolOccurrences.h"
+#include "clang/Tooling/Refactoring/Rename/SymbolName.h"
+#include "llvm/ADT/STLExtras.h"
+
+using namespace clang;
+using namespace tooling;
+
+SymbolOccurrence::SymbolOccurrence(const SymbolName &Name, OccurrenceKind Kind,
+ ArrayRef<SourceLocation> Locations)
+ : Kind(Kind) {
+ ArrayRef<std::string> NamePieces = Name.getNamePieces();
+ assert(Locations.size() == NamePieces.size() &&
+ "mismatching number of locations and lengths");
+ assert(!Locations.empty() && "no locations");
+ if (Locations.size() == 1) {
+ RangeOrNumRanges = SourceRange(
+ Locations[0], Locations[0].getLocWithOffset(NamePieces[0].size()));
+ return;
+ }
+ MultipleRanges = llvm::make_unique<SourceRange[]>(Locations.size());
+ RangeOrNumRanges.setBegin(
+ SourceLocation::getFromRawEncoding(Locations.size()));
+ for (const auto &Loc : llvm::enumerate(Locations)) {
+ MultipleRanges[Loc.index()] = SourceRange(
+ Loc.value(),
+ Loc.value().getLocWithOffset(NamePieces[Loc.index()].size()));
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
index 2769802ad2bc6..40b70d8a05902 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
@@ -39,6 +39,21 @@ using namespace llvm;
namespace clang {
namespace tooling {
+const NamedDecl *getCanonicalSymbolDeclaration(const NamedDecl *FoundDecl) {
+ // If FoundDecl is a constructor or destructor, we want to instead take
+ // the Decl of the corresponding class.
+ if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(FoundDecl))
+ FoundDecl = CtorDecl->getParent();
+ else if (const auto *DtorDecl = dyn_cast<CXXDestructorDecl>(FoundDecl))
+ FoundDecl = DtorDecl->getParent();
+ // FIXME: (Alex L): Canonicalize implicit template instantions, just like
+ // the indexer does it.
+
+ // Note: please update the declaration's doc comment every time the
+ // canonicalization rules are changed.
+ return FoundDecl;
+}
+
namespace {
// \brief NamedDeclFindingConsumer should delegate finding USRs of given Decl to
// AdditionalUSRFinder. AdditionalUSRFinder adds USRs of ctor and dtor if given
@@ -58,6 +73,7 @@ public:
if (checkIfOverriddenFunctionAscends(OverriddenMethod))
USRSet.insert(getUSRForDecl(OverriddenMethod));
}
+ addUSRsOfInstantiatedMethods(MethodDecl);
} else if (const auto *RecordDecl = dyn_cast<CXXRecordDecl>(FoundDecl)) {
handleCXXRecordDecl(RecordDecl);
} else if (const auto *TemplateDecl =
@@ -69,9 +85,13 @@ public:
return std::vector<std::string>(USRSet.begin(), USRSet.end());
}
+ bool shouldVisitTemplateInstantiations() const { return true; }
+
bool VisitCXXMethodDecl(const CXXMethodDecl *MethodDecl) {
if (MethodDecl->isVirtual())
OverriddenMethods.push_back(MethodDecl);
+ if (MethodDecl->getInstantiatedFromMemberFunction())
+ InstantiatedMethods.push_back(MethodDecl);
return true;
}
@@ -122,6 +142,20 @@ private:
addUSRsOfOverridenFunctions(OverriddenMethod);
}
+ void addUSRsOfInstantiatedMethods(const CXXMethodDecl *MethodDecl) {
+ // For renaming a class template method, all references of the instantiated
+ // member methods should be renamed too, so add USRs of the instantiated
+ // methods to the USR set.
+ USRSet.insert(getUSRForDecl(MethodDecl));
+ if (const auto *FT = MethodDecl->getInstantiatedFromMemberFunction())
+ USRSet.insert(getUSRForDecl(FT));
+ for (const auto *Method : InstantiatedMethods) {
+ if (USRSet.find(getUSRForDecl(
+ Method->getInstantiatedFromMemberFunction())) != USRSet.end())
+ USRSet.insert(getUSRForDecl(Method));
+ }
+ }
+
bool checkIfOverriddenFunctionAscends(const CXXMethodDecl *MethodDecl) {
for (const auto &OverriddenMethod : MethodDecl->overridden_methods()) {
if (USRSet.find(getUSRForDecl(OverriddenMethod)) != USRSet.end())
@@ -135,10 +169,17 @@ private:
ASTContext &Context;
std::set<std::string> USRSet;
std::vector<const CXXMethodDecl *> OverriddenMethods;
+ std::vector<const CXXMethodDecl *> InstantiatedMethods;
std::vector<const ClassTemplatePartialSpecializationDecl *> PartialSpecs;
};
} // namespace
+std::vector<std::string> getUSRsForDeclaration(const NamedDecl *ND,
+ ASTContext &Context) {
+ AdditionalUSRFinder Finder(ND, Context);
+ return Finder.Find();
+}
+
class NamedDeclFindingConsumer : public ASTConsumer {
public:
NamedDeclFindingConsumer(ArrayRef<unsigned> SymbolOffsets,
@@ -183,8 +224,11 @@ private:
return false;
}
- if (Force)
+ if (Force) {
+ SpellingNames.push_back(std::string());
+ USRList.push_back(std::vector<std::string>());
return true;
+ }
unsigned CouldNotFindSymbolNamed = Engine.getCustomDiagID(
DiagnosticsEngine::Error, "clang-rename could not find symbol %0");
@@ -193,13 +237,7 @@ private:
return false;
}
- // If FoundDecl is a constructor or destructor, we want to instead take
- // the Decl of the corresponding class.
- if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(FoundDecl))
- FoundDecl = CtorDecl->getParent();
- else if (const auto *DtorDecl = dyn_cast<CXXDestructorDecl>(FoundDecl))
- FoundDecl = DtorDecl->getParent();
-
+ FoundDecl = getCanonicalSymbolDeclaration(FoundDecl);
SpellingNames.push_back(FoundDecl->getNameAsString());
AdditionalUSRFinder Finder(FoundDecl, Context);
USRList.push_back(Finder.Find());
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp
index dc21a94610cbb..c77304a17332b 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp
@@ -23,6 +23,7 @@
#include "clang/Lex/Lexer.h"
#include "clang/Tooling/Core/Lookup.h"
#include "clang/Tooling/Refactoring/RecursiveSymbolVisitor.h"
+#include "clang/Tooling/Refactoring/Rename/SymbolName.h"
#include "clang/Tooling/Refactoring/Rename/USRFinder.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
@@ -38,6 +39,17 @@ namespace tooling {
namespace {
+// Returns true if the given Loc is valid for edit. We don't edit the
+// SourceLocations that are valid or in temporary buffer.
+bool IsValidEditLoc(const clang::SourceManager& SM, clang::SourceLocation Loc) {
+ if (Loc.isInvalid())
+ return false;
+ const clang::FullSourceLoc FullLoc(Loc, SM);
+ std::pair<clang::FileID, unsigned> FileIdAndOffset =
+ FullLoc.getSpellingLoc().getDecomposedLoc();
+ return SM.getFileEntryForID(FileIdAndOffset.first) != nullptr;
+}
+
// \brief This visitor recursively searches for all instances of a USR in a
// translation unit and stores them for later usage.
class USRLocFindingASTVisitor
@@ -68,11 +80,9 @@ public:
// Non-visitors:
- // \brief Returns a list of unique locations. Duplicate or overlapping
- // locations are erroneous and should be reported!
- const std::vector<clang::SourceLocation> &getLocationsFound() const {
- return LocationsFound;
- }
+ /// \brief Returns a set of unique symbol occurrences. Duplicate or
+ /// overlapping occurrences are erroneous and should be reported!
+ SymbolOccurrences takeOccurrences() { return std::move(Occurrences); }
private:
void checkAndAddLocation(SourceLocation Loc) {
@@ -82,17 +92,18 @@ private:
StringRef TokenName =
Lexer::getSourceText(CharSourceRange::getTokenRange(BeginLoc, EndLoc),
Context.getSourceManager(), Context.getLangOpts());
- size_t Offset = TokenName.find(PrevName);
+ size_t Offset = TokenName.find(PrevName.getNamePieces()[0]);
// The token of the source location we find actually has the old
// name.
if (Offset != StringRef::npos)
- LocationsFound.push_back(BeginLoc.getLocWithOffset(Offset));
+ Occurrences.emplace_back(PrevName, SymbolOccurrence::MatchingSymbol,
+ BeginLoc.getLocWithOffset(Offset));
}
const std::set<std::string> USRSet;
- const std::string PrevName;
- std::vector<clang::SourceLocation> LocationsFound;
+ const SymbolName PrevName;
+ SymbolOccurrences Occurrences;
const ASTContext &Context;
};
@@ -160,13 +171,14 @@ public:
const Decl *Context;
// The nested name being replaced (can be nullptr).
const NestedNameSpecifier *Specifier;
+ // Determine whether the prefix qualifiers of the NewName should be ignored.
+ // Normally, we set it to true for the symbol declaration and definition to
+ // avoid adding prefix qualifiers.
+ // For example, if it is true and NewName is "a::b::foo", then the symbol
+ // occurrence which the RenameInfo points to will be renamed to "foo".
+ bool IgnorePrefixQualifers;
};
- // FIXME: Currently, prefix qualifiers will be added to the renamed symbol
- // definition (e.g. "class Foo {};" => "class b::Bar {};" when renaming
- // "a::Foo" to "b::Bar").
- // For renaming declarations/definitions, prefix qualifiers should be filtered
- // out.
bool VisitNamedDecl(const NamedDecl *Decl) {
// UsingDecl has been handled in other place.
if (llvm::isa<UsingDecl>(Decl))
@@ -180,19 +192,129 @@ public:
return true;
if (isInUSRSet(Decl)) {
- RenameInfo Info = {Decl->getLocation(), Decl->getLocation(), nullptr,
- nullptr, nullptr};
- RenameInfos.push_back(Info);
+ // For the case of renaming an alias template, we actually rename the
+ // underlying alias declaration of the template.
+ if (const auto* TAT = dyn_cast<TypeAliasTemplateDecl>(Decl))
+ Decl = TAT->getTemplatedDecl();
+
+ auto StartLoc = Decl->getLocation();
+ auto EndLoc = StartLoc;
+ if (IsValidEditLoc(Context.getSourceManager(), StartLoc)) {
+ RenameInfo Info = {StartLoc,
+ EndLoc,
+ /*FromDecl=*/nullptr,
+ /*Context=*/nullptr,
+ /*Specifier=*/nullptr,
+ /*IgnorePrefixQualifers=*/true};
+ RenameInfos.push_back(Info);
+ }
}
return true;
}
- bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
+ bool VisitMemberExpr(const MemberExpr *Expr) {
const NamedDecl *Decl = Expr->getFoundDecl();
+ auto StartLoc = Expr->getMemberLoc();
+ auto EndLoc = Expr->getMemberLoc();
if (isInUSRSet(Decl)) {
- RenameInfo Info = {Expr->getSourceRange().getBegin(),
- Expr->getSourceRange().getEnd(), Decl,
- getClosestAncestorDecl(*Expr), Expr->getQualifier()};
+ RenameInfos.push_back({StartLoc, EndLoc,
+ /*FromDecl=*/nullptr,
+ /*Context=*/nullptr,
+ /*Specifier=*/nullptr,
+ /*IgnorePrefixQualifiers=*/true});
+ }
+ return true;
+ }
+
+ bool VisitCXXConstructorDecl(const CXXConstructorDecl *CD) {
+ // Fix the constructor initializer when renaming class members.
+ for (const auto *Initializer : CD->inits()) {
+ // Ignore implicit initializers.
+ if (!Initializer->isWritten())
+ continue;
+
+ if (const FieldDecl *FD = Initializer->getMember()) {
+ if (isInUSRSet(FD)) {
+ auto Loc = Initializer->getSourceLocation();
+ RenameInfos.push_back({Loc, Loc,
+ /*FromDecl=*/nullptr,
+ /*Context=*/nullptr,
+ /*Specifier=*/nullptr,
+ /*IgnorePrefixQualifiers=*/true});
+ }
+ }
+ }
+ return true;
+ }
+
+ bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
+ const NamedDecl *Decl = Expr->getFoundDecl();
+ // Get the underlying declaration of the shadow declaration introduced by a
+ // using declaration.
+ if (auto *UsingShadow = llvm::dyn_cast<UsingShadowDecl>(Decl)) {
+ Decl = UsingShadow->getTargetDecl();
+ }
+
+ auto StartLoc = Expr->getLocStart();
+ // For template function call expressions like `foo<int>()`, we want to
+ // restrict the end of location to just before the `<` character.
+ SourceLocation EndLoc = Expr->hasExplicitTemplateArgs()
+ ? Expr->getLAngleLoc().getLocWithOffset(-1)
+ : Expr->getLocEnd();
+
+ if (const auto *MD = llvm::dyn_cast<CXXMethodDecl>(Decl)) {
+ if (isInUSRSet(MD)) {
+ // Handle renaming static template class methods, we only rename the
+ // name without prefix qualifiers and restrict the source range to the
+ // name.
+ RenameInfos.push_back({EndLoc, EndLoc,
+ /*FromDecl=*/nullptr,
+ /*Context=*/nullptr,
+ /*Specifier=*/nullptr,
+ /*IgnorePrefixQualifiers=*/true});
+ return true;
+ }
+ }
+
+ // In case of renaming an enum declaration, we have to explicitly handle
+ // unscoped enum constants referenced in expressions (e.g.
+ // "auto r = ns1::ns2::Green" where Green is an enum constant of an unscoped
+ // enum decl "ns1::ns2::Color") as these enum constants cannot be caught by
+ // TypeLoc.
+ if (const auto *T = llvm::dyn_cast<EnumConstantDecl>(Decl)) {
+ // FIXME: Handle the enum constant without prefix qualifiers (`a = Green`)
+ // when renaming an unscoped enum declaration with a new namespace.
+ if (!Expr->hasQualifier())
+ return true;
+
+ if (const auto *ED =
+ llvm::dyn_cast_or_null<EnumDecl>(getClosestAncestorDecl(*T))) {
+ if (ED->isScoped())
+ return true;
+ Decl = ED;
+ }
+ // The current fix would qualify "ns1::ns2::Green" as
+ // "ns1::ns2::Color::Green".
+ //
+ // Get the EndLoc of the replacement by moving 1 character backward (
+ // to exclude the last '::').
+ //
+ // ns1::ns2::Green;
+ // ^ ^^
+ // BeginLoc |EndLoc of the qualifier
+ // new EndLoc
+ EndLoc = Expr->getQualifierLoc().getEndLoc().getLocWithOffset(-1);
+ assert(EndLoc.isValid() &&
+ "The enum constant should have prefix qualifers.");
+ }
+ if (isInUSRSet(Decl) &&
+ IsValidEditLoc(Context.getSourceManager(), StartLoc)) {
+ RenameInfo Info = {StartLoc,
+ EndLoc,
+ Decl,
+ getClosestAncestorDecl(*Expr),
+ Expr->getQualifier(),
+ /*IgnorePrefixQualifers=*/false};
RenameInfos.push_back(Info);
}
@@ -212,16 +334,16 @@ public:
bool VisitNestedNameSpecifierLocations(NestedNameSpecifierLoc NestedLoc) {
if (!NestedLoc.getNestedNameSpecifier()->getAsType())
return true;
- if (IsTypeAliasWhichWillBeRenamedElsewhere(NestedLoc.getTypeLoc()))
- return true;
if (const auto *TargetDecl =
getSupportedDeclFromTypeLoc(NestedLoc.getTypeLoc())) {
if (isInUSRSet(TargetDecl)) {
RenameInfo Info = {NestedLoc.getBeginLoc(),
EndLocationForType(NestedLoc.getTypeLoc()),
- TargetDecl, getClosestAncestorDecl(NestedLoc),
- NestedLoc.getNestedNameSpecifier()->getPrefix()};
+ TargetDecl,
+ getClosestAncestorDecl(NestedLoc),
+ NestedLoc.getNestedNameSpecifier()->getPrefix(),
+ /*IgnorePrefixQualifers=*/false};
RenameInfos.push_back(Info);
}
}
@@ -229,9 +351,6 @@ public:
}
bool VisitTypeLoc(TypeLoc Loc) {
- if (IsTypeAliasWhichWillBeRenamedElsewhere(Loc))
- return true;
-
auto Parents = Context.getParents(Loc);
TypeLoc ParentTypeLoc;
if (!Parents.empty()) {
@@ -265,10 +384,18 @@ public:
if (!ParentTypeLoc.isNull() &&
isInUSRSet(getSupportedDeclFromTypeLoc(ParentTypeLoc)))
return true;
- RenameInfo Info = {StartLocationForType(Loc), EndLocationForType(Loc),
- TargetDecl, getClosestAncestorDecl(Loc),
- GetNestedNameForType(Loc)};
- RenameInfos.push_back(Info);
+
+ auto StartLoc = StartLocationForType(Loc);
+ auto EndLoc = EndLocationForType(Loc);
+ if (IsValidEditLoc(Context.getSourceManager(), StartLoc)) {
+ RenameInfo Info = {StartLoc,
+ EndLoc,
+ TargetDecl,
+ getClosestAncestorDecl(Loc),
+ GetNestedNameForType(Loc),
+ /*IgnorePrefixQualifers=*/false};
+ RenameInfos.push_back(Info);
+ }
return true;
}
}
@@ -292,13 +419,20 @@ public:
if (!ParentTypeLoc.isNull() &&
llvm::isa<ElaboratedType>(ParentTypeLoc.getType()))
TargetLoc = ParentTypeLoc;
- RenameInfo Info = {
- StartLocationForType(TargetLoc), EndLocationForType(TargetLoc),
- TemplateSpecType->getTemplateName().getAsTemplateDecl(),
- getClosestAncestorDecl(
- ast_type_traits::DynTypedNode::create(TargetLoc)),
- GetNestedNameForType(TargetLoc)};
- RenameInfos.push_back(Info);
+
+ auto StartLoc = StartLocationForType(TargetLoc);
+ auto EndLoc = EndLocationForType(TargetLoc);
+ if (IsValidEditLoc(Context.getSourceManager(), StartLoc)) {
+ RenameInfo Info = {
+ StartLoc,
+ EndLoc,
+ TemplateSpecType->getTemplateName().getAsTemplateDecl(),
+ getClosestAncestorDecl(
+ ast_type_traits::DynTypedNode::create(TargetLoc)),
+ GetNestedNameForType(TargetLoc),
+ /*IgnorePrefixQualifers=*/false};
+ RenameInfos.push_back(Info);
+ }
}
}
return true;
@@ -313,40 +447,16 @@ public:
}
private:
- // FIXME: This method may not be suitable for renaming other types like alias
- // types. Need to figure out a way to handle it.
- bool IsTypeAliasWhichWillBeRenamedElsewhere(TypeLoc TL) const {
- while (!TL.isNull()) {
- // SubstTemplateTypeParm is the TypeLocation class for a substituted type
- // inside a template expansion so we ignore these. For example:
- //
- // template<typename T> struct S {
- // T t; // <-- this T becomes a TypeLoc(int) with class
- // // SubstTemplateTypeParm when S<int> is instantiated
- // }
- if (TL.getTypeLocClass() == TypeLoc::SubstTemplateTypeParm)
- return true;
-
- // Typedef is the TypeLocation class for a type which is a typedef to the
- // type we want to replace. We ignore the use of the typedef as we will
- // replace the definition of it. For example:
- //
- // typedef int T;
- // T a; // <--- This T is a TypeLoc(int) with class Typedef.
- if (TL.getTypeLocClass() == TypeLoc::Typedef)
- return true;
- TL = TL.getNextTypeLoc();
- }
- return false;
- }
-
// Get the supported declaration from a given typeLoc. If the declaration type
// is not supported, returns nullptr.
- //
- // FIXME: support more types, e.g. enum, type alias.
const NamedDecl *getSupportedDeclFromTypeLoc(TypeLoc Loc) {
+ if (const auto* TT = Loc.getType()->getAs<clang::TypedefType>())
+ return TT->getDecl();
if (const auto *RD = Loc.getType()->getAsCXXRecordDecl())
return RD;
+ if (const auto *ED =
+ llvm::dyn_cast_or_null<EnumDecl>(Loc.getType()->getAsTagDecl()))
+ return ED;
return nullptr;
}
@@ -391,12 +501,11 @@ private:
} // namespace
-std::vector<SourceLocation>
-getLocationsOfUSRs(const std::vector<std::string> &USRs, StringRef PrevName,
- Decl *Decl) {
+SymbolOccurrences getOccurrencesOfUSRs(ArrayRef<std::string> USRs,
+ StringRef PrevName, Decl *Decl) {
USRLocFindingASTVisitor Visitor(USRs, PrevName, Decl->getASTContext());
Visitor.TraverseDecl(Decl);
- return Visitor.getLocationsFound();
+ return Visitor.takeOccurrences();
}
std::vector<tooling::AtomicChange>
@@ -424,18 +533,43 @@ createRenameAtomicChanges(llvm::ArrayRef<std::string> USRs,
for (const auto &RenameInfo : Finder.getRenameInfos()) {
std::string ReplacedName = NewName.str();
- if (RenameInfo.FromDecl && RenameInfo.Context) {
- if (!llvm::isa<clang::TranslationUnitDecl>(
- RenameInfo.Context->getDeclContext())) {
- ReplacedName = tooling::replaceNestedName(
- RenameInfo.Specifier, RenameInfo.Context->getDeclContext(),
- RenameInfo.FromDecl,
- NewName.startswith("::") ? NewName.str() : ("::" + NewName).str());
+ if (RenameInfo.IgnorePrefixQualifers) {
+ // Get the name without prefix qualifiers from NewName.
+ size_t LastColonPos = NewName.find_last_of(':');
+ if (LastColonPos != std::string::npos)
+ ReplacedName = NewName.substr(LastColonPos + 1);
+ } else {
+ if (RenameInfo.FromDecl && RenameInfo.Context) {
+ if (!llvm::isa<clang::TranslationUnitDecl>(
+ RenameInfo.Context->getDeclContext())) {
+ ReplacedName = tooling::replaceNestedName(
+ RenameInfo.Specifier, RenameInfo.Context->getDeclContext(),
+ RenameInfo.FromDecl,
+ NewName.startswith("::") ? NewName.str()
+ : ("::" + NewName).str());
+ } else {
+ // This fixes the case where type `T` is a parameter inside a function
+ // type (e.g. `std::function<void(T)>`) and the DeclContext of `T`
+ // becomes the translation unit. As a workaround, we simply use
+ // fully-qualified name here for all references whose `DeclContext` is
+ // the translation unit and ignore the possible existence of
+ // using-decls (in the global scope) that can shorten the replaced
+ // name.
+ llvm::StringRef ActualName = Lexer::getSourceText(
+ CharSourceRange::getTokenRange(
+ SourceRange(RenameInfo.Begin, RenameInfo.End)),
+ SM, TranslationUnitDecl->getASTContext().getLangOpts());
+ // Add the leading "::" back if the name written in the code contains
+ // it.
+ if (ActualName.startswith("::") && !NewName.startswith("::")) {
+ ReplacedName = "::" + NewName.str();
+ }
+ }
}
+ // If the NewName contains leading "::", add it back.
+ if (NewName.startswith("::") && NewName.substr(2) == ReplacedName)
+ ReplacedName = NewName.str();
}
- // If the NewName contains leading "::", add it back.
- if (NewName.startswith("::") && NewName.substr(2) == ReplacedName)
- ReplacedName = NewName.str();
Replace(RenameInfo.Begin, RenameInfo.End, ReplacedName);
}
diff --git a/contrib/llvm/tools/clang/lib/Tooling/StandaloneExecution.cpp b/contrib/llvm/tools/clang/lib/Tooling/StandaloneExecution.cpp
new file mode 100644
index 0000000000000..eea8e39d134c2
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Tooling/StandaloneExecution.cpp
@@ -0,0 +1,91 @@
+//===- lib/Tooling/Execution.cpp - Standalone clang action execution. -----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/StandaloneExecution.h"
+#include "clang/Tooling/ToolExecutorPluginRegistry.h"
+
+namespace clang {
+namespace tooling {
+
+static llvm::Error make_string_error(const llvm::Twine &Message) {
+ return llvm::make_error<llvm::StringError>(Message,
+ llvm::inconvertibleErrorCode());
+}
+
+const char *StandaloneToolExecutor::ExecutorName = "StandaloneToolExecutor";
+
+static ArgumentsAdjuster getDefaultArgumentsAdjusters() {
+ return combineAdjusters(
+ getClangStripOutputAdjuster(),
+ combineAdjusters(getClangSyntaxOnlyAdjuster(),
+ getClangStripDependencyFileAdjuster()));
+}
+
+StandaloneToolExecutor::StandaloneToolExecutor(
+ const CompilationDatabase &Compilations,
+ llvm::ArrayRef<std::string> SourcePaths,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps)
+ : Tool(Compilations, SourcePaths), Context(&Results),
+ ArgsAdjuster(getDefaultArgumentsAdjusters()) {
+ // Use self-defined default argument adjusters instead of the default
+ // adjusters that come with the old `ClangTool`.
+ Tool.clearArgumentsAdjusters();
+}
+
+StandaloneToolExecutor::StandaloneToolExecutor(
+ CommonOptionsParser Options,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps)
+ : OptionsParser(std::move(Options)),
+ Tool(OptionsParser->getCompilations(), OptionsParser->getSourcePathList(),
+ PCHContainerOps),
+ Context(&Results), ArgsAdjuster(getDefaultArgumentsAdjusters()) {
+ Tool.clearArgumentsAdjusters();
+}
+
+llvm::Error StandaloneToolExecutor::execute(
+ llvm::ArrayRef<
+ std::pair<std::unique_ptr<FrontendActionFactory>, ArgumentsAdjuster>>
+ Actions) {
+ if (Actions.empty())
+ return make_string_error("No action to execute.");
+
+ if (Actions.size() != 1)
+ return make_string_error(
+ "Only support executing exactly 1 action at this point.");
+
+ auto &Action = Actions.front();
+ Tool.appendArgumentsAdjuster(Action.second);
+ Tool.appendArgumentsAdjuster(ArgsAdjuster);
+ if (Tool.run(Action.first.get()))
+ return make_string_error("Failed to run action.");
+
+ return llvm::Error::success();
+}
+
+class StandaloneToolExecutorPlugin : public ToolExecutorPlugin {
+public:
+ llvm::Expected<std::unique_ptr<ToolExecutor>>
+ create(CommonOptionsParser &OptionsParser) override {
+ if (OptionsParser.getSourcePathList().empty())
+ return make_string_error(
+ "[StandaloneToolExecutorPlugin] No positional argument found.");
+ return llvm::make_unique<StandaloneToolExecutor>(std::move(OptionsParser));
+ }
+};
+
+static ToolExecutorPluginRegistry::Add<StandaloneToolExecutorPlugin>
+ X("standalone", "Runs FrontendActions on a set of files provided "
+ "via positional arguments.");
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the plugin.
+volatile int StandaloneToolExecutorAnchorSource = 0;
+
+} // end namespace tooling
+} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Tooling.cpp b/contrib/llvm/tools/clang/lib/Tooling/Tooling.cpp
index 662f02dca2a66..4fbfa4f004736 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/Tooling.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/Tooling.cpp
@@ -29,6 +29,7 @@
#include "llvm/Config/llvm-config.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
@@ -190,11 +191,12 @@ void addTargetAndModeForProgramName(std::vector<std::string> &CommandLine,
}
auto TargetMode =
clang::driver::ToolChain::getTargetAndModeFromProgramName(InvokedAs);
- if (!AlreadyHasMode && !TargetMode.second.empty()) {
- CommandLine.insert(++CommandLine.begin(), TargetMode.second);
+ if (!AlreadyHasMode && TargetMode.DriverMode) {
+ CommandLine.insert(++CommandLine.begin(), TargetMode.DriverMode);
}
- if (!AlreadyHasTarget && !TargetMode.first.empty()) {
- CommandLine.insert(++CommandLine.begin(), {"-target", TargetMode.first});
+ if (!AlreadyHasTarget && TargetMode.TargetIsValid) {
+ CommandLine.insert(++CommandLine.begin(), {"-target",
+ TargetMode.TargetPrefix});
}
}
}
@@ -346,11 +348,7 @@ void ClangTool::mapVirtualFile(StringRef FilePath, StringRef Content) {
}
void ClangTool::appendArgumentsAdjuster(ArgumentsAdjuster Adjuster) {
- if (ArgsAdjuster)
- ArgsAdjuster =
- combineAdjusters(std::move(ArgsAdjuster), std::move(Adjuster));
- else
- ArgsAdjuster = std::move(Adjuster);
+ ArgsAdjuster = combineAdjusters(std::move(ArgsAdjuster), std::move(Adjuster));
}
void ClangTool::clearArgumentsAdjusters() {
diff --git a/contrib/llvm/tools/clang/tools/clang-format/ClangFormat.cpp b/contrib/llvm/tools/clang/tools/clang-format/ClangFormat.cpp
index 14bff19a1a0c6..b7179ffd64163 100644
--- a/contrib/llvm/tools/clang/tools/clang-format/ClangFormat.cpp
+++ b/contrib/llvm/tools/clang/tools/clang-format/ClangFormat.cpp
@@ -102,6 +102,10 @@ static cl::opt<bool> SortIncludes(
"SortIncludes style flag"),
cl::cat(ClangFormatCategory));
+static cl::opt<bool>
+ Verbose("verbose", cl::desc("If set, shows the list of processed files"),
+ cl::cat(ClangFormatCategory));
+
static cl::list<std::string> FileNames(cl::Positional, cl::desc("[<file> ...]"),
cl::cat(ClangFormatCategory));
@@ -285,7 +289,7 @@ static bool format(StringRef FileName) {
"xml:space='preserve' incomplete_format='"
<< (Status.FormatComplete ? "false" : "true") << "'";
if (!Status.FormatComplete)
- outs() << " line=" << Status.Line;
+ outs() << " line='" << Status.Line << "'";
outs() << ">\n";
if (Cursor.getNumOccurrences() != 0)
outs() << "<cursor>"
@@ -328,8 +332,7 @@ static bool format(StringRef FileName) {
} // namespace format
} // namespace clang
-static void PrintVersion() {
- raw_ostream &OS = outs();
+static void PrintVersion(raw_ostream &OS) {
OS << clang::getClangToolFullVersion("clang-format") << '\n';
}
@@ -348,8 +351,10 @@ int main(int argc, const char **argv) {
"together with <file>s, the files are edited in-place. Otherwise, the\n"
"result is written to the standard output.\n");
- if (Help)
+ if (Help) {
cl::PrintHelpMessage();
+ return 0;
+ }
if (DumpConfig) {
llvm::Expected<clang::format::FormatStyle> FormatStyle =
@@ -366,23 +371,19 @@ int main(int argc, const char **argv) {
}
bool Error = false;
- switch (FileNames.size()) {
- case 0:
+ if (FileNames.empty()) {
Error = clang::format::format("-");
- break;
- case 1:
- Error = clang::format::format(FileNames[0]);
- break;
- default:
- if (!Offsets.empty() || !Lengths.empty() || !LineRanges.empty()) {
- errs() << "error: -offset, -length and -lines can only be used for "
- "single file.\n";
- return 1;
- }
- for (unsigned i = 0; i < FileNames.size(); ++i)
- Error |= clang::format::format(FileNames[i]);
- break;
+ return Error ? 1 : 0;
+ }
+ if (FileNames.size() != 1 && (!Offsets.empty() || !Lengths.empty() || !LineRanges.empty())) {
+ errs() << "error: -offset, -length and -lines can only be used for "
+ "single file.\n";
+ return 1;
+ }
+ for (const auto &FileName : FileNames) {
+ if (Verbose)
+ errs() << "Formatting " << FileName << "\n";
+ Error |= clang::format::format(FileName);
}
return Error ? 1 : 0;
}
-
diff --git a/contrib/llvm/tools/clang/tools/driver/cc1as_main.cpp b/contrib/llvm/tools/clang/tools/driver/cc1as_main.cpp
index 2fc2b508ef21b..9b90562af903a 100644
--- a/contrib/llvm/tools/clang/tools/driver/cc1as_main.cpp
+++ b/contrib/llvm/tools/clang/tools/driver/cc1as_main.cpp
@@ -356,7 +356,7 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,
PIC = false;
}
- MOFI->InitMCObjectFileInfo(Triple(Opts.Triple), PIC, CodeModel::Default, Ctx);
+ MOFI->InitMCObjectFileInfo(Triple(Opts.Triple), PIC, Ctx);
if (Opts.SaveTemporaryLabels)
Ctx.setAllowTemporaryLabels(false);
if (Opts.GenDwarfForAssembly)
@@ -419,8 +419,8 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,
Opts.CPU, Options);
Triple T(Opts.Triple);
Str.reset(TheTarget->createMCObjectStreamer(
- T, Ctx, *MAB, *Out, CE, *STI, Opts.RelaxAll,
- Opts.IncrementalLinkerCompatible,
+ T, Ctx, std::unique_ptr<MCAsmBackend>(MAB), *Out, std::unique_ptr<MCCodeEmitter>(CE), *STI,
+ Opts.RelaxAll, Opts.IncrementalLinkerCompatible,
/*DWARFMustBeAtTheEnd*/ true));
Str.get()->InitSections(Opts.NoExecStack);
}
@@ -504,7 +504,8 @@ int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
if (Asm.ShowHelp) {
std::unique_ptr<OptTable> Opts(driver::createDriverOptTable());
Opts->PrintHelp(llvm::outs(), "clang -cc1as", "Clang Integrated Assembler",
- /*Include=*/driver::options::CC1AsOption, /*Exclude=*/0);
+ /*Include=*/driver::options::CC1AsOption, /*Exclude=*/0,
+ /*ShowAllAliases=*/false);
return 0;
}
diff --git a/contrib/llvm/tools/clang/tools/driver/driver.cpp b/contrib/llvm/tools/clang/tools/driver/driver.cpp
index 9f37c428ff932..fa757da9535c2 100644
--- a/contrib/llvm/tools/clang/tools/driver/driver.cpp
+++ b/contrib/llvm/tools/clang/tools/driver/driver.cpp
@@ -206,23 +206,26 @@ extern int cc1_main(ArrayRef<const char *> Argv, const char *Argv0,
extern int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0,
void *MainAddr);
-static void insertTargetAndModeArgs(StringRef Target, StringRef Mode,
+static void insertTargetAndModeArgs(const ParsedClangName &NameParts,
SmallVectorImpl<const char *> &ArgVector,
std::set<std::string> &SavedStrings) {
- if (!Mode.empty()) {
+ // Put target and mode arguments at the start of argument list so that
+ // arguments specified in command line could override them. Avoid putting
+ // them at index 0, as an option like '-cc1' must remain the first.
+ auto InsertionPoint = ArgVector.begin();
+ if (InsertionPoint != ArgVector.end())
+ ++InsertionPoint;
+
+ if (NameParts.DriverMode) {
// Add the mode flag to the arguments.
- auto it = ArgVector.begin();
- if (it != ArgVector.end())
- ++it;
- ArgVector.insert(it, GetStableCStr(SavedStrings, Mode));
+ ArgVector.insert(InsertionPoint,
+ GetStableCStr(SavedStrings, NameParts.DriverMode));
}
- if (!Target.empty()) {
- auto it = ArgVector.begin();
- if (it != ArgVector.end())
- ++it;
- const char *arr[] = {"-target", GetStableCStr(SavedStrings, Target)};
- ArgVector.insert(it, std::begin(arr), std::end(arr));
+ if (NameParts.TargetIsValid) {
+ const char *arr[] = {"-target", GetStableCStr(SavedStrings,
+ NameParts.TargetPrefix)};
+ ArgVector.insert(InsertionPoint, std::begin(arr), std::end(arr));
}
}
@@ -330,9 +333,7 @@ int main(int argc_, const char **argv_) {
}
llvm::InitializeAllTargets();
- std::string ProgName = argv[0];
- std::pair<std::string, std::string> TargetAndMode =
- ToolChain::getTargetAndModeFromProgramName(ProgName);
+ auto TargetAndMode = ToolChain::getTargetAndModeFromProgramName(argv[0]);
llvm::BumpPtrAllocator A;
llvm::StringSaver Saver(A);
@@ -345,7 +346,7 @@ int main(int argc_, const char **argv_) {
// Finally, our -cc1 tools don't care which tokenization mode we use because
// response files written by clang will tokenize the same way in either mode.
bool ClangCLMode = false;
- if (TargetAndMode.second == "--driver-mode=cl" ||
+ if (StringRef(TargetAndMode.DriverMode).equals("--driver-mode=cl") ||
std::find_if(argv.begin(), argv.end(), [](const char *F) {
return F && strcmp(F, "--driver-mode=cl") == 0;
}) != argv.end()) {
@@ -454,9 +455,9 @@ int main(int argc_, const char **argv_) {
Driver TheDriver(Path, llvm::sys::getDefaultTargetTriple(), Diags);
SetInstallDir(argv, TheDriver, CanonicalPrefixes);
+ TheDriver.setTargetAndMode(TargetAndMode);
- insertTargetAndModeArgs(TargetAndMode.first, TargetAndMode.second, argv,
- SavedStrings);
+ insertTargetAndModeArgs(TargetAndMode, argv, SavedStrings);
SetBackdoorDriverOutputsFromEnvVars(TheDriver);
diff --git a/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp b/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp
index b6d2988964b48..70ce15f5a24ed 100644
--- a/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp
+++ b/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -56,9 +56,9 @@ public:
V(Spelling.getValueAsString("Variety")),
N(Spelling.getValueAsString("Name")) {
- assert(V != "GCC" && "Given a GCC spelling, which means this hasn't been"
- "flattened!");
- if (V == "CXX11" || V == "Pragma")
+ assert(V != "GCC" && V != "Clang" &&
+ "Given a GCC spelling, which means this hasn't been flattened!");
+ if (V == "CXX11" || V == "C2x" || V == "Pragma")
NS = Spelling.getValueAsString("Namespace");
bool Unset;
K = Spelling.getValueAsBitOrUnset("KnownToGCC", Unset);
@@ -78,11 +78,15 @@ GetFlattenedSpellings(const Record &Attr) {
std::vector<FlattenedSpelling> Ret;
for (const auto &Spelling : Spellings) {
- if (Spelling->getValueAsString("Variety") == "GCC") {
+ StringRef Variety = Spelling->getValueAsString("Variety");
+ StringRef Name = Spelling->getValueAsString("Name");
+ if (Variety == "GCC") {
// Gin up two new spelling objects to add into the list.
- Ret.emplace_back("GNU", Spelling->getValueAsString("Name"), "", true);
- Ret.emplace_back("CXX11", Spelling->getValueAsString("Name"), "gnu",
- true);
+ Ret.emplace_back("GNU", Name, "", true);
+ Ret.emplace_back("CXX11", Name, "gnu", true);
+ } else if (Variety == "Clang") {
+ Ret.emplace_back("GNU", Name, "", false);
+ Ret.emplace_back("CXX11", Name, "clang", false);
} else
Ret.push_back(FlattenedSpelling(*Spelling));
}
@@ -490,6 +494,17 @@ namespace {
OS << "}\n";
}
+ void writeASTVisitorTraversal(raw_ostream &OS) const override {
+ StringRef Name = getUpperName();
+ OS << " if (A->is" << Name << "Expr()) {\n"
+ << " if (!getDerived().TraverseStmt(A->get" << Name << "Expr()))\n"
+ << " return false;\n"
+ << " } else if (auto *TSI = A->get" << Name << "Type()) {\n"
+ << " if (!getDerived().TraverseTypeLoc(TSI->getTypeLoc()))\n"
+ << " return false;\n"
+ << " }\n";
+ }
+
void writeCloneArgs(raw_ostream &OS) const override {
OS << "is" << getLowerName() << "Expr, is" << getLowerName()
<< "Expr ? static_cast<void*>(" << getLowerName()
@@ -630,6 +645,10 @@ namespace {
<< "A->" << getLowerName() << "_size()";
}
+ void writeASTVisitorTraversal(raw_ostream &OS) const override {
+ // FIXME: Traverse the elements.
+ }
+
void writeCtorBody(raw_ostream &OS) const override {
OS << " std::copy(" << getUpperName() << ", " << getUpperName()
<< " + " << ArgSizeName << ", " << ArgName << ");\n";
@@ -1153,6 +1172,12 @@ namespace {
OS << " }";
}
+ void writeASTVisitorTraversal(raw_ostream &OS) const override {
+ OS << " if (auto *TSI = A->get" << getUpperName() << "Loc())\n";
+ OS << " if (!getDerived().TraverseTypeLoc(TSI->getTypeLoc()))\n";
+ OS << " return false;\n";
+ }
+
void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
OS << "A->get" << getUpperName() << "Loc()";
}
@@ -1305,7 +1330,7 @@ writePrettyPrintFunction(Record &R,
if (Variety == "GNU") {
Prefix = " __attribute__((";
Suffix = "))";
- } else if (Variety == "CXX11") {
+ } else if (Variety == "CXX11" || Variety == "C2x") {
Prefix = " [[";
Suffix = "]]";
std::string Namespace = Spellings[I].nameSpace();
@@ -1419,7 +1444,7 @@ static void writeAttrAccessorDefinition(const Record &R, raw_ostream &OS) {
assert(!SpellingList.empty() &&
"Attribute with empty spelling list can't have accessors!");
for (const auto *Accessor : Accessors) {
- std::string Name = Accessor->getValueAsString("Name");
+ const StringRef Name = Accessor->getValueAsString("Name");
std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Accessor);
OS << " bool " << Name << "() const { return SpellingListIndex == ";
@@ -1568,7 +1593,7 @@ struct AttributeSubjectMatchRule {
// Abstract rules are used only for sub-rules
bool isAbstractRule() const { return getSubjects().empty(); }
- std::string getName() const {
+ StringRef getName() const {
return (Constraint ? Constraint : MetaSubject)->getValueAsString("Name");
}
@@ -1800,13 +1825,11 @@ PragmaClangAttributeSupport::generateStrictConformsTo(const Record &Attr,
// Generate a function that constructs a set of matching rules that describe
// to which declarations the attribute should apply to.
std::string FnName = "matchRulesFor" + Attr.getName().str();
- std::stringstream SS;
- SS << "static void " << FnName << "(llvm::SmallVectorImpl<std::pair<"
+ OS << "static void " << FnName << "(llvm::SmallVectorImpl<std::pair<"
<< AttributeSubjectMatchRule::EnumName
<< ", bool>> &MatchRules, const LangOptions &LangOpts) {\n";
if (Attr.isValueUnset("Subjects")) {
- SS << "}\n\n";
- OS << SS.str();
+ OS << "}\n\n";
return FnName;
}
const Record *SubjectObj = Attr.getValueAsDef("Subjects");
@@ -1819,24 +1842,23 @@ PragmaClangAttributeSupport::generateStrictConformsTo(const Record &Attr,
// The rule might be language specific, so only subtract it from the given
// rules if the specific language options are specified.
std::vector<Record *> LangOpts = Rule.getLangOpts();
- SS << " MatchRules.push_back(std::make_pair(" << Rule.getEnumValue()
+ OS << " MatchRules.push_back(std::make_pair(" << Rule.getEnumValue()
<< ", /*IsSupported=*/";
if (!LangOpts.empty()) {
for (auto I = LangOpts.begin(), E = LangOpts.end(); I != E; ++I) {
- std::string Part = (*I)->getValueAsString("Name");
+ const StringRef Part = (*I)->getValueAsString("Name");
if ((*I)->getValueAsBit("Negated"))
- SS << "!";
- SS << "LangOpts." + Part;
+ OS << "!";
+ OS << "LangOpts." << Part;
if (I + 1 != E)
- SS << " || ";
+ OS << " || ";
}
} else
- SS << "true";
- SS << "));\n";
+ OS << "true";
+ OS << "));\n";
}
}
- SS << "}\n\n";
- OS << SS.str();
+ OS << "}\n\n";
return FnName;
}
@@ -1892,7 +1914,8 @@ void PragmaClangAttributeSupport::generateParsingHelpers(raw_ostream &OS) {
continue;
std::string SubRuleFunction;
if (SubMatchRules.count(Rule.MetaSubject))
- SubRuleFunction = "isAttributeSubjectMatchSubRuleFor_" + Rule.getName();
+ SubRuleFunction =
+ ("isAttributeSubjectMatchSubRuleFor_" + Rule.getName()).str();
else
SubRuleFunction = "defaultIsAttributeSubjectMatchSubRuleFor";
OS << " Case(\"" << Rule.getName() << "\", std::make_pair("
@@ -2695,10 +2718,14 @@ static void GenerateHasAttrSpellingStringSwitch(
// If this is the C++11 variety, also add in the LangOpts test.
if (Variety == "CXX11")
Test += " && LangOpts.CPlusPlus11";
+ else if (Variety == "C2x")
+ Test += " && LangOpts.DoubleSquareBracketAttributes";
} else if (Variety == "CXX11")
// C++11 mode should be checked against LangOpts, which is presumed to be
// present in the caller.
Test = "LangOpts.CPlusPlus11";
+ else if (Variety == "C2x")
+ Test = "LangOpts.DoubleSquareBracketAttributes";
std::string TestStr =
!Test.empty() ? Test + " ? " + llvm::itostr(Version) + " : 0" : "1";
@@ -2719,7 +2746,7 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
// and declspecs. Then generate a big switch statement for each of them.
std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
std::vector<Record *> Declspec, Microsoft, GNU, Pragma;
- std::map<std::string, std::vector<Record *>> CXX;
+ std::map<std::string, std::vector<Record *>> CXX, C2x;
// Walk over the list of all attributes, and split them out based on the
// spelling variety.
@@ -2735,6 +2762,8 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
Microsoft.push_back(R);
else if (Variety == "CXX11")
CXX[SI.nameSpace()].push_back(R);
+ else if (Variety == "C2x")
+ C2x[SI.nameSpace()].push_back(R);
else if (Variety == "Pragma")
Pragma.push_back(R);
}
@@ -2754,20 +2783,25 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
OS << "case AttrSyntax::Pragma:\n";
OS << " return llvm::StringSwitch<int>(Name)\n";
GenerateHasAttrSpellingStringSwitch(Pragma, OS, "Pragma");
- OS << "case AttrSyntax::CXX: {\n";
- // C++11-style attributes are further split out based on the Scope.
- for (auto I = CXX.cbegin(), E = CXX.cend(); I != E; ++I) {
- if (I != CXX.begin())
- OS << " else ";
- if (I->first.empty())
- OS << "if (!Scope || Scope->getName() == \"\") {\n";
- else
- OS << "if (Scope->getName() == \"" << I->first << "\") {\n";
- OS << " return llvm::StringSwitch<int>(Name)\n";
- GenerateHasAttrSpellingStringSwitch(I->second, OS, "CXX11", I->first);
- OS << "}";
- }
- OS << "\n}\n";
+ auto fn = [&OS](const char *Spelling, const char *Variety,
+ const std::map<std::string, std::vector<Record *>> &List) {
+ OS << "case AttrSyntax::" << Variety << ": {\n";
+ // C++11-style attributes are further split out based on the Scope.
+ for (auto I = List.cbegin(), E = List.cend(); I != E; ++I) {
+ if (I != List.cbegin())
+ OS << " else ";
+ if (I->first.empty())
+ OS << "if (!Scope || Scope->getName() == \"\") {\n";
+ else
+ OS << "if (Scope->getName() == \"" << I->first << "\") {\n";
+ OS << " return llvm::StringSwitch<int>(Name)\n";
+ GenerateHasAttrSpellingStringSwitch(I->second, OS, Spelling, I->first);
+ OS << "}";
+ }
+ OS << "\n} break;\n";
+ };
+ fn("CXX11", "CXX", CXX);
+ fn("C2x", "C", C2x);
OS << "}\n";
}
@@ -2788,10 +2822,11 @@ void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) {
<< StringSwitch<unsigned>(Spellings[I].variety())
.Case("GNU", 0)
.Case("CXX11", 1)
- .Case("Declspec", 2)
- .Case("Microsoft", 3)
- .Case("Keyword", 4)
- .Case("Pragma", 5)
+ .Case("C2x", 2)
+ .Case("Declspec", 3)
+ .Case("Microsoft", 4)
+ .Case("Keyword", 5)
+ .Case("Pragma", 6)
.Default(0)
<< " && Scope == \"" << Spellings[I].nameSpace() << "\")\n"
<< " return " << I << ";\n";
@@ -2965,7 +3000,7 @@ static bool isArgVariadic(const Record &R, StringRef AttrName) {
return createArgument(R, AttrName)->isVariadic();
}
-static void emitArgInfo(const Record &R, std::stringstream &OS) {
+static void emitArgInfo(const Record &R, raw_ostream &OS) {
// This function will count the number of arguments specified for the
// attribute and emit the number of required arguments followed by the
// number of optional arguments.
@@ -2994,136 +3029,72 @@ static void GenerateDefaultAppertainsTo(raw_ostream &OS) {
OS << "}\n\n";
}
+static std::string GetDiagnosticSpelling(const Record &R) {
+ std::string Ret = R.getValueAsString("DiagSpelling");
+ if (!Ret.empty())
+ return Ret;
+
+ // If we couldn't find the DiagSpelling in this object, we can check to see
+ // if the object is one that has a base, and if it is, loop up to the Base
+ // member recursively.
+ std::string Super = R.getSuperClasses().back().first->getName();
+ if (Super == "DDecl" || Super == "DStmt")
+ return GetDiagnosticSpelling(*R.getValueAsDef("Base"));
+
+ return "";
+}
+
static std::string CalculateDiagnostic(const Record &S) {
// If the SubjectList object has a custom diagnostic associated with it,
// return that directly.
- std::string CustomDiag = S.getValueAsString("CustomDiag");
+ const StringRef CustomDiag = S.getValueAsString("CustomDiag");
if (!CustomDiag.empty())
- return CustomDiag;
-
- // Given the list of subjects, determine what diagnostic best fits.
- enum {
- Func = 1U << 0,
- Var = 1U << 1,
- ObjCMethod = 1U << 2,
- Param = 1U << 3,
- Class = 1U << 4,
- GenericRecord = 1U << 5,
- Type = 1U << 6,
- ObjCIVar = 1U << 7,
- ObjCProp = 1U << 8,
- ObjCInterface = 1U << 9,
- Block = 1U << 10,
- Namespace = 1U << 11,
- Field = 1U << 12,
- CXXMethod = 1U << 13,
- ObjCProtocol = 1U << 14,
- Enum = 1U << 15,
- Named = 1U << 16,
- };
- uint32_t SubMask = 0;
+ return ("\"" + Twine(CustomDiag) + "\"").str();
+ std::vector<std::string> DiagList;
std::vector<Record *> Subjects = S.getValueAsListOfDefs("Subjects");
for (const auto *Subject : Subjects) {
const Record &R = *Subject;
- std::string Name;
-
- if (R.isSubClassOf("SubsetSubject")) {
- PrintError(R.getLoc(), "SubsetSubjects should use a custom diagnostic");
- // As a fallback, look through the SubsetSubject to see what its base
- // type is, and use that. This needs to be updated if SubsetSubjects
- // are allowed within other SubsetSubjects.
- Name = R.getValueAsDef("Base")->getName();
- } else
- Name = R.getName();
-
- uint32_t V = StringSwitch<uint32_t>(Name)
- .Case("Function", Func)
- .Case("Var", Var)
- .Case("ObjCMethod", ObjCMethod)
- .Case("ParmVar", Param)
- .Case("TypedefName", Type)
- .Case("ObjCIvar", ObjCIVar)
- .Case("ObjCProperty", ObjCProp)
- .Case("Record", GenericRecord)
- .Case("ObjCInterface", ObjCInterface)
- .Case("ObjCProtocol", ObjCProtocol)
- .Case("Block", Block)
- .Case("CXXRecord", Class)
- .Case("Namespace", Namespace)
- .Case("Field", Field)
- .Case("CXXMethod", CXXMethod)
- .Case("Enum", Enum)
- .Case("Named", Named)
- .Default(0);
- if (!V) {
- // Something wasn't in our mapping, so be helpful and let the developer
- // know about it.
- PrintFatalError(R.getLoc(), "Unknown subject type: " + R.getName());
- return "";
+ // Get the diagnostic text from the Decl or Stmt node given.
+ std::string V = GetDiagnosticSpelling(R);
+ if (V.empty()) {
+ PrintError(R.getLoc(),
+ "Could not determine diagnostic spelling for the node: " +
+ R.getName() + "; please add one to DeclNodes.td");
+ } else {
+ // The node may contain a list of elements itself, so split the elements
+ // by a comma, and trim any whitespace.
+ SmallVector<StringRef, 2> Frags;
+ llvm::SplitString(V, Frags, ",");
+ for (auto Str : Frags) {
+ DiagList.push_back(Str.trim());
+ }
}
-
- SubMask |= V;
}
- switch (SubMask) {
- // For the simple cases where there's only a single entry in the mask, we
- // don't have to resort to bit fiddling.
- case Func: return "ExpectedFunction";
- case Var: return "ExpectedVariable";
- case Param: return "ExpectedParameter";
- case Class: return "ExpectedClass";
- case Enum: return "ExpectedEnum";
- case CXXMethod:
- // FIXME: Currently, this maps to ExpectedMethod based on existing code,
- // but should map to something a bit more accurate at some point.
- case ObjCMethod: return "ExpectedMethod";
- case Type: return "ExpectedType";
- case ObjCInterface: return "ExpectedObjectiveCInterface";
- case ObjCProtocol: return "ExpectedObjectiveCProtocol";
-
- // "GenericRecord" means struct, union or class; check the language options
- // and if not compiling for C++, strip off the class part. Note that this
- // relies on the fact that the context for this declares "Sema &S".
- case GenericRecord:
- return "(S.getLangOpts().CPlusPlus ? ExpectedStructOrUnionOrClass : "
- "ExpectedStructOrUnion)";
- case Func | ObjCMethod | Block: return "ExpectedFunctionMethodOrBlock";
- case Func | ObjCMethod | Class: return "ExpectedFunctionMethodOrClass";
- case Func | Param:
- case Func | ObjCMethod | Param: return "ExpectedFunctionMethodOrParameter";
- case Func | ObjCMethod: return "ExpectedFunctionOrMethod";
- case Func | Var: return "ExpectedVariableOrFunction";
-
- // If not compiling for C++, the class portion does not apply.
- case Func | Var | Class:
- return "(S.getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass : "
- "ExpectedVariableOrFunction)";
-
- case Func | Var | Class | ObjCInterface:
- return "(S.getLangOpts().CPlusPlus"
- " ? ((S.getLangOpts().ObjC1 || S.getLangOpts().ObjC2)"
- " ? ExpectedFunctionVariableClassOrObjCInterface"
- " : ExpectedFunctionVariableOrClass)"
- " : ((S.getLangOpts().ObjC1 || S.getLangOpts().ObjC2)"
- " ? ExpectedFunctionVariableOrObjCInterface"
- " : ExpectedVariableOrFunction))";
+ if (DiagList.empty()) {
+ PrintFatalError(S.getLoc(),
+ "Could not deduce diagnostic argument for Attr subjects");
+ return "";
+ }
- case ObjCMethod | ObjCProp: return "ExpectedMethodOrProperty";
- case Func | ObjCMethod | ObjCProp:
- return "ExpectedFunctionOrMethodOrProperty";
- case ObjCProtocol | ObjCInterface:
- return "ExpectedObjectiveCInterfaceOrProtocol";
- case Field | Var: return "ExpectedFieldOrGlobalVar";
+ // FIXME: this is not particularly good for localization purposes and ideally
+ // should be part of the diagnostics engine itself with some sort of list
+ // specifier.
- case Named:
- return "ExpectedNamedDecl";
- }
+ // A single member of the list can be returned directly.
+ if (DiagList.size() == 1)
+ return '"' + DiagList.front() + '"';
- PrintFatalError(S.getLoc(),
- "Could not deduce diagnostic argument for Attr subjects");
+ if (DiagList.size() == 2)
+ return '"' + DiagList[0] + " and " + DiagList[1] + '"';
- return "";
+ // If there are more than two in the list, we serialize the first N - 1
+ // elements with a comma. This leaves the string in the state: foo, bar,
+ // baz (but misses quux). We can then add ", and " for the last element
+ // manually.
+ std::string Diag = llvm::join(DiagList.begin(), DiagList.end() - 1, ", ");
+ return '"' + Diag + ", and " + *(DiagList.end() - 1) + '"';
}
static std::string GetSubjectWithSuffix(const Record *R) {
@@ -3210,8 +3181,8 @@ static std::string GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) {
}
SS << ") {\n";
SS << " S.Diag(Attr.getLoc(), diag::";
- SS << (Warn ? "warn_attribute_wrong_decl_type" :
- "err_attribute_wrong_decl_type");
+ SS << (Warn ? "warn_attribute_wrong_decl_type_str" :
+ "err_attribute_wrong_decl_type_str");
SS << ")\n";
SS << " << Attr.getName() << ";
SS << CalculateDiagnostic(*SubjectObj) << ";\n";
@@ -3281,12 +3252,13 @@ static std::string GenerateLangOptRequirements(const Record &R,
// codegen efficiency).
std::string FnName = "check", Test;
for (auto I = LangOpts.begin(), E = LangOpts.end(); I != E; ++I) {
- std::string Part = (*I)->getValueAsString("Name");
+ const StringRef Part = (*I)->getValueAsString("Name");
if ((*I)->getValueAsBit("Negated")) {
FnName += "Not";
Test += "!";
}
- Test += "S.LangOpts." + Part;
+ Test += "S.LangOpts.";
+ Test += Part;
if (I + 1 != E)
Test += " || ";
FnName += Part;
@@ -3342,7 +3314,7 @@ static std::string GenerateTargetRequirements(const Record &Attr,
// applies to multiple target architectures. In order for the attribute to be
// considered valid, all of its architectures need to be included.
if (!Attr.isValueUnset("ParseKind")) {
- std::string APK = Attr.getValueAsString("ParseKind");
+ const StringRef APK = Attr.getValueAsString("ParseKind");
for (const auto &I : Dupes) {
if (I.first == APK) {
std::vector<StringRef> DA =
@@ -3438,7 +3410,8 @@ void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
// another mapping. At the same time, generate the AttrInfoMap object
// contents. Due to the reliance on generated code, use separate streams so
// that code will not be interleaved.
- std::stringstream SS;
+ std::string Buffer;
+ raw_string_ostream SS {Buffer};
for (auto I = Attrs.begin(), E = Attrs.end(); I != E; ++I) {
// TODO: If the attribute's kind appears in the list of duplicates, that is
// because it is a target-specific attribute that appears multiple times.
@@ -3484,7 +3457,7 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {
std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
std::vector<StringMatcher::StringPair> GNU, Declspec, Microsoft, CXX11,
- Keywords, Pragma;
+ Keywords, Pragma, C2x;
std::set<std::string> Seen;
for (const auto *A : Attrs) {
const Record &Attr = *A;
@@ -3522,6 +3495,10 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {
Matches = &CXX11;
Spelling += S.nameSpace();
Spelling += "::";
+ } else if (Variety == "C2x") {
+ Matches = &C2x;
+ Spelling += S.nameSpace();
+ Spelling += "::";
} else if (Variety == "GNU")
Matches = &GNU;
else if (Variety == "Declspec")
@@ -3560,6 +3537,8 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {
StringMatcher("Name", Microsoft, OS).Emit();
OS << " } else if (AttributeList::AS_CXX11 == Syntax) {\n";
StringMatcher("Name", CXX11, OS).Emit();
+ OS << " } else if (AttributeList::AS_C2x == Syntax) {\n";
+ StringMatcher("Name", C2x, OS).Emit();
OS << " } else if (AttributeList::AS_Keyword == Syntax || ";
OS << "AttributeList::AS_ContextSensitiveKeyword == Syntax) {\n";
StringMatcher("Name", Keywords, OS).Emit();
@@ -3624,20 +3603,25 @@ class DocumentationData {
public:
const Record *Documentation;
const Record *Attribute;
+ std::string Heading;
+ unsigned SupportedSpellings;
- DocumentationData(const Record &Documentation, const Record &Attribute)
- : Documentation(&Documentation), Attribute(&Attribute) {}
+ DocumentationData(const Record &Documentation, const Record &Attribute,
+ const std::pair<std::string, unsigned> HeadingAndKinds)
+ : Documentation(&Documentation), Attribute(&Attribute),
+ Heading(std::move(HeadingAndKinds.first)),
+ SupportedSpellings(HeadingAndKinds.second) {}
};
static void WriteCategoryHeader(const Record *DocCategory,
raw_ostream &OS) {
- const std::string &Name = DocCategory->getValueAsString("Name");
- OS << Name << "\n" << std::string(Name.length(), '=') << "\n";
+ const StringRef Name = DocCategory->getValueAsString("Name");
+ OS << Name << "\n" << std::string(Name.size(), '=') << "\n";
// If there is content, print that as well.
- std::string ContentStr = DocCategory->getValueAsString("Content");
+ const StringRef ContentStr = DocCategory->getValueAsString("Content");
// Trim leading and trailing newlines and spaces.
- OS << StringRef(ContentStr).trim();
+ OS << ContentStr.trim();
OS << "\n\n";
}
@@ -3645,22 +3629,24 @@ static void WriteCategoryHeader(const Record *DocCategory,
enum SpellingKind {
GNU = 1 << 0,
CXX11 = 1 << 1,
- Declspec = 1 << 2,
- Microsoft = 1 << 3,
- Keyword = 1 << 4,
- Pragma = 1 << 5
+ C2x = 1 << 2,
+ Declspec = 1 << 3,
+ Microsoft = 1 << 4,
+ Keyword = 1 << 5,
+ Pragma = 1 << 6
};
-static void WriteDocumentation(RecordKeeper &Records,
- const DocumentationData &Doc, raw_ostream &OS) {
+static std::pair<std::string, unsigned>
+GetAttributeHeadingAndSpellingKinds(const Record &Documentation,
+ const Record &Attribute) {
// FIXME: there is no way to have a per-spelling category for the attribute
// documentation. This may not be a limiting factor since the spellings
// should generally be consistently applied across the category.
- std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Doc.Attribute);
+ std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attribute);
// Determine the heading to be used for this attribute.
- std::string Heading = Doc.Documentation->getValueAsString("Heading");
+ std::string Heading = Documentation.getValueAsString("Heading");
bool CustomHeading = !Heading.empty();
if (Heading.empty()) {
// If there's only one spelling, we can simply use that.
@@ -3682,7 +3668,7 @@ static void WriteDocumentation(RecordKeeper &Records,
// If the heading is still empty, it is an error.
if (Heading.empty())
- PrintFatalError(Doc.Attribute->getLoc(),
+ PrintFatalError(Attribute.getLoc(),
"This attribute requires a heading to be specified");
// Gather a list of unique spellings; this is not the same as the semantic
@@ -3695,6 +3681,7 @@ static void WriteDocumentation(RecordKeeper &Records,
SpellingKind Kind = StringSwitch<SpellingKind>(I.variety())
.Case("GNU", GNU)
.Case("CXX11", CXX11)
+ .Case("C2x", C2x)
.Case("Declspec", Declspec)
.Case("Microsoft", Microsoft)
.Case("Keyword", Keyword)
@@ -3704,7 +3691,7 @@ static void WriteDocumentation(RecordKeeper &Records,
SupportedSpellings |= Kind;
std::string Name;
- if (Kind == CXX11 && !I.nameSpace().empty())
+ if ((Kind == CXX11 || Kind == C2x) && !I.nameSpace().empty())
Name = I.nameSpace() + "::";
Name += I.name();
@@ -3724,27 +3711,33 @@ static void WriteDocumentation(RecordKeeper &Records,
}
Heading += ")";
}
- OS << Heading << "\n" << std::string(Heading.length(), '-') << "\n";
-
if (!SupportedSpellings)
- PrintFatalError(Doc.Attribute->getLoc(),
+ PrintFatalError(Attribute.getLoc(),
"Attribute has no supported spellings; cannot be "
"documented");
+ return std::make_pair(std::move(Heading), SupportedSpellings);
+}
+
+static void WriteDocumentation(RecordKeeper &Records,
+ const DocumentationData &Doc, raw_ostream &OS) {
+ OS << Doc.Heading << "\n" << std::string(Doc.Heading.length(), '-') << "\n";
// List what spelling syntaxes the attribute supports.
OS << ".. csv-table:: Supported Syntaxes\n";
- OS << " :header: \"GNU\", \"C++11\", \"__declspec\", \"Keyword\",";
+ OS << " :header: \"GNU\", \"C++11\", \"C2x\", \"__declspec\", \"Keyword\",";
OS << " \"Pragma\", \"Pragma clang attribute\"\n\n";
OS << " \"";
- if (SupportedSpellings & GNU) OS << "X";
+ if (Doc.SupportedSpellings & GNU) OS << "X";
+ OS << "\",\"";
+ if (Doc.SupportedSpellings & CXX11) OS << "X";
OS << "\",\"";
- if (SupportedSpellings & CXX11) OS << "X";
+ if (Doc.SupportedSpellings & C2x) OS << "X";
OS << "\",\"";
- if (SupportedSpellings & Declspec) OS << "X";
+ if (Doc.SupportedSpellings & Declspec) OS << "X";
OS << "\",\"";
- if (SupportedSpellings & Keyword) OS << "X";
+ if (Doc.SupportedSpellings & Keyword) OS << "X";
OS << "\", \"";
- if (SupportedSpellings & Pragma) OS << "X";
+ if (Doc.SupportedSpellings & Pragma) OS << "X";
OS << "\", \"";
if (getPragmaAttributeSupport(Records).isAttributedSupported(*Doc.Attribute))
OS << "X";
@@ -3756,16 +3749,16 @@ static void WriteDocumentation(RecordKeeper &Records,
OS << "This attribute has been deprecated, and may be removed in a future "
<< "version of Clang.";
const Record &Deprecated = *Doc.Documentation->getValueAsDef("Deprecated");
- std::string Replacement = Deprecated.getValueAsString("Replacement");
+ const StringRef Replacement = Deprecated.getValueAsString("Replacement");
if (!Replacement.empty())
OS << " This attribute has been superseded by ``"
<< Replacement << "``.";
OS << "\n\n";
}
- std::string ContentStr = Doc.Documentation->getValueAsString("Content");
+ const StringRef ContentStr = Doc.Documentation->getValueAsString("Content");
// Trim leading and trailing newlines and spaces.
- OS << StringRef(ContentStr).trim();
+ OS << ContentStr.trim();
OS << "\n\n\n";
}
@@ -3794,23 +3787,29 @@ void EmitClangAttrDocs(RecordKeeper &Records, raw_ostream &OS) {
// If the category is "undocumented", then there cannot be any other
// documentation categories (otherwise, the attribute would become
// documented).
- std::string Cat = Category->getValueAsString("Name");
+ const StringRef Cat = Category->getValueAsString("Name");
bool Undocumented = Cat == "Undocumented";
if (Undocumented && Docs.size() > 1)
PrintFatalError(Doc.getLoc(),
"Attribute is \"Undocumented\", but has multiple "
- "documentation categories");
+ "documentation categories");
if (!Undocumented)
- SplitDocs[Category].push_back(DocumentationData(Doc, Attr));
+ SplitDocs[Category].push_back(DocumentationData(
+ Doc, Attr, GetAttributeHeadingAndSpellingKinds(Doc, Attr)));
}
}
// Having split the attributes out based on what documentation goes where,
// we can begin to generate sections of documentation.
- for (const auto &I : SplitDocs) {
+ for (auto &I : SplitDocs) {
WriteCategoryHeader(I.first, OS);
+ std::sort(I.second.begin(), I.second.end(),
+ [](const DocumentationData &D1, const DocumentationData &D2) {
+ return D1.Heading < D2.Heading;
+ });
+
// Walk over each of the attributes in the category and write out their
// documentation.
for (const auto &Doc : I.second)
diff --git a/contrib/llvm/tools/clang/utils/TableGen/ClangDataCollectorsEmitter.cpp b/contrib/llvm/tools/clang/utils/TableGen/ClangDataCollectorsEmitter.cpp
new file mode 100644
index 0000000000000..4079efc808231
--- /dev/null
+++ b/contrib/llvm/tools/clang/utils/TableGen/ClangDataCollectorsEmitter.cpp
@@ -0,0 +1,18 @@
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenBackend.h"
+
+using namespace llvm;
+
+namespace clang {
+void EmitClangDataCollectors(RecordKeeper &RK, raw_ostream &OS) {
+ const auto &Defs = RK.getClasses();
+ for (const auto &Entry : Defs) {
+ Record &R = *Entry.second;
+ OS << "DEF_ADD_DATA(" << R.getName() << ", {\n";
+ auto Code = R.getValue("Code")->getValue();
+ OS << Code->getAsUnquotedString() << "}\n)";
+ OS << "\n";
+ }
+ OS << "#undef DEF_ADD_DATA\n";
+}
+} // end namespace clang
diff --git a/contrib/llvm/tools/clang/utils/TableGen/TableGen.cpp b/contrib/llvm/tools/clang/utils/TableGen/TableGen.cpp
index 781518ddbc312..840b330a732c1 100644
--- a/contrib/llvm/tools/clang/utils/TableGen/TableGen.cpp
+++ b/contrib/llvm/tools/clang/utils/TableGen/TableGen.cpp
@@ -57,6 +57,7 @@ enum ActionType {
GenAttrDocs,
GenDiagDocs,
GenOptDocs,
+ GenDataCollectors,
GenTestPragmaAttributeSupportedAttributes
};
@@ -147,6 +148,8 @@ cl::opt<ActionType> Action(
clEnumValN(GenDiagDocs, "gen-diag-docs",
"Generate diagnostic documentation"),
clEnumValN(GenOptDocs, "gen-opt-docs", "Generate option documentation"),
+ clEnumValN(GenDataCollectors, "gen-clang-data-collectors",
+ "Generate data collectors for AST nodes"),
clEnumValN(GenTestPragmaAttributeSupportedAttributes,
"gen-clang-test-pragma-attribute-supported-attributes",
"Generate a list of attributes supported by #pragma clang "
@@ -262,6 +265,9 @@ bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
case GenOptDocs:
EmitClangOptDocs(Records, OS);
break;
+ case GenDataCollectors:
+ EmitClangDataCollectors(Records, OS);
+ break;
case GenTestPragmaAttributeSupportedAttributes:
EmitTestPragmaAttributeSupportedAttributes(Records, OS);
break;
diff --git a/contrib/llvm/tools/clang/utils/TableGen/TableGenBackends.h b/contrib/llvm/tools/clang/utils/TableGen/TableGenBackends.h
index e1b7d0ec63be3..342c889ca47a6 100644
--- a/contrib/llvm/tools/clang/utils/TableGen/TableGenBackends.h
+++ b/contrib/llvm/tools/clang/utils/TableGen/TableGenBackends.h
@@ -75,6 +75,8 @@ void EmitClangAttrDocs(RecordKeeper &Records, raw_ostream &OS);
void EmitClangDiagDocs(RecordKeeper &Records, raw_ostream &OS);
void EmitClangOptDocs(RecordKeeper &Records, raw_ostream &OS);
+void EmitClangDataCollectors(RecordKeeper &Records, raw_ostream &OS);
+
void EmitTestPragmaAttributeSupportedAttributes(RecordKeeper &Records,
raw_ostream &OS);